From e2dd2c2d694521279d886c7d51585781769a9a85 Mon Sep 17 00:00:00 2001 From: Alfrix Date: Fri, 19 Oct 2018 09:28:44 -0300 Subject: [PATCH 001/234] Remove Enable from main labels --- intl/msg_hash_us.h | 98 +++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 6b4c968fcd..c3d26aa4b2 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -297,7 +297,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE, - "Audio Enable" + "Audio" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_FILTER_DIR, @@ -445,7 +445,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BLUETOOTH_ENABLE, - "Bluetooth Enable" + "Bluetooth" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BUILDBOT_ASSETS_URL, @@ -789,7 +789,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_DPI_OVERRIDE_ENABLE, - "DPI Override Enable" + "DPI Override" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_DPI_OVERRIDE_VALUE, @@ -817,7 +817,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_ENABLE, - "Enable Achievements" + "Achievements" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ENTRY_HOVER_COLOR, @@ -905,7 +905,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_HISTORY_LIST_ENABLE, - "History List Enable" + "History List" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_HISTORY_TAB, @@ -1029,7 +1029,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_AUTODETECT_ENABLE, - "Autoconfig Enable" + "Autoconfig" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_AXIS_THRESHOLD, @@ -1089,7 +1089,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_ICADE_ENABLE, - "Keyboard Gamepad Mapping Enable" + "Keyboard Gamepad Mapping" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_A, @@ -1233,7 +1233,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY, - "Enable hotkeys" + "Hotkeys" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_FAST_FORWARD_HOLD_KEY, @@ -1397,7 +1397,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_REMAP_BINDS_ENABLE, - "Remap Binds Enable" + "Remap Binds for this core" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_SAVE_AUTOCONFIG, @@ -1409,15 +1409,15 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_SMALL_KEYBOARD_ENABLE, - "Small Keyboard Enable" + "Small Keyboard" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_TOUCH_ENABLE, - "Touch Enable" + "Touch" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_TURBO_ENABLE, - "Turbo enable" + "Turbo" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD, @@ -1713,7 +1713,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE, - "Netplay Enable" + "Netplay" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_CLIENT, @@ -1737,7 +1737,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_MODE, - "Netplay Client Enable" + "Netplay Client" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_NICKNAME, @@ -1813,7 +1813,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_SPECTATOR_MODE_ENABLE, - "Netplay Spectator Enable" + "Netplay Spectator" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_TCP_UDP_PORT, @@ -2204,7 +2204,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_RECORD_ENABLE, - "Enable Recording" + "Recording Support" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_RECORD_PATH, @@ -2284,7 +2284,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_REWIND_ENABLE, - "Rewind Enable" + "Rewind Support" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEAT_APPLY_AFTER_TOGGLE, @@ -2360,7 +2360,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SAMBA_ENABLE, - "SAMBA Enable" + "SAMBA" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SAVEFILE_DIRECTORY, @@ -2536,7 +2536,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SSH_ENABLE, - "SSH Enable" + "SSH" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_START_CORE, @@ -2572,7 +2572,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_BGM_ENABLE, - "System BGM Enable" + "System BGM" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_DIRECTORY, @@ -2960,7 +2960,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_UI_COMPANION_ENABLE, - "UI Companion Enable" + "UI Companion" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_UI_COMPANION_START_ON_BOOT, @@ -2972,7 +2972,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_DESKTOP_MENU_ENABLE, - "Enable desktop menu (restart)" + "Desktop menu (restart)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_UI_MENUBAR_ENABLE, @@ -3116,7 +3116,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_FONT_ENABLE, - "Enable Onscreen Notifications" + "Onscreen Notifications" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_FONT_PATH, @@ -3152,7 +3152,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_GPU_SCREENSHOT, - "GPU Screenshot Enable" + "GPU Screenshot" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC, @@ -3244,7 +3244,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_SHARED_CONTEXT, - "Enable Hardware Shared Context" + "Hardware Shared Context" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_SMOOTH, @@ -3252,7 +3252,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_SOFT_FILTER, - "Soft Filter Enable" + "Soft Filter" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_SWAP_INTERVAL, @@ -3448,7 +3448,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_XMB_SHADOWS_ENABLE, - "Icon Shadows Enable" + "Icon Shadows" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_HISTORY, @@ -4621,7 +4621,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_ENABLE, - "Enable audio output." + "Enable or disable audio output." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_MAX_TIMING_SKEW, @@ -4765,7 +4765,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETWORK_USER_REMOTE_ENABLE, - "User %d Remote Enable" + "User %d Remote" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BATTERY_LEVEL_ENABLE, @@ -4986,7 +4986,8 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_ENABLE, - "Enable rewinding. This will take a performance hit when playing." + "Enable or disable rewind support.\n" + "Beware that this causes a performance hit when playing." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_APPLY_AFTER_TOGGLE, @@ -5119,7 +5120,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_PERFCNT_ENABLE, - "Enable performance counters for RetroArch (and cores)." + "Enable or disable performance counters for RetroArch (and cores)." ) MSG_HASH( MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_SAVE, @@ -5143,7 +5144,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE, - "Enable input auto-detection. Will attempt to autoconfigure joypads, Plug-and-Play style." + "If enabled attempts to autoconfigure controllers, Plug-and-Play style." ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL, @@ -5231,7 +5232,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_OVERLAY_ENABLE, - "Enable the overlay." + "Enable or disable the overlay." ) MSG_HASH( MENU_ENUM_SUBLABEL_OVERLAY_PRESET, @@ -5283,15 +5284,15 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_STDIN_CMD_ENABLE, - "Enable stdin command interface." + "stdin command interface." ) MSG_HASH( MENU_ENUM_SUBLABEL_MOUSE_ENABLE, - "Enable mouse controls inside the menu." + "Enable or disable mouse controls inside the menu." ) MSG_HASH( MENU_ENUM_SUBLABEL_POINTER_ENABLE, - "Enable touch controls inside the menu." + "Enable or disable touch controls inside the menu." ) MSG_HASH( MENU_ENUM_SUBLABEL_THUMBNAILS, @@ -5395,15 +5396,15 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_AUTO_REMAPS_ENABLE, - "Enable customized controls by default at startup." + "Load customized controls at startup." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUTO_OVERRIDES_ENABLE, - "Enable customized configuration by default at startup." + "Load customized configuration at startup." ) MSG_HASH( MENU_ENUM_SUBLABEL_GAME_SPECIFIC_OPTIONS, - "Enable customized core options by default at startup." + "Load customized core options by default at startup." ) MSG_HASH( MENU_ENUM_SUBLABEL_CORE_ENABLE, @@ -5583,7 +5584,8 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, - "Enable drop shadows for all icons. This will have a minor performance hit." + "Draw drop shadows for all icons.\n" + "This will have a minor performance hit." ) MSG_HASH( MENU_ENUM_SUBLABEL_MATERIALUI_MENU_COLOR_THEME, @@ -5980,7 +5982,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_XMB_MAIN_MENU_ENABLE_SETTINGS, - "Enable Settings Tab" + "Settings Tab" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS_PASSWORD, @@ -6184,7 +6186,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_ENABLE, - "Notification Background Enable" + "Notification Background" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_RED, @@ -6212,7 +6214,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_ENABLE_KIOSK_MODE, - "Enable Kiosk Mode" + "Kiosk Mode" ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_ENABLE_KIOSK_MODE, @@ -6328,15 +6330,15 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, - "Enable border filler" + "Border filler" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, - "Enable border filler thickness" + "Border filler thickness" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, - "Enable background filler thickness" + "Background filler thickness" ) MSG_HASH( MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, @@ -6380,7 +6382,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU, - "Enable menu audio" + "Menu audio" ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_ENABLE_MENU, @@ -6780,7 +6782,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_DISCORD_ALLOW, - "Enable Discord Rich Presence" + "Discord Rich Presence" ) MSG_HASH( MENU_ENUM_SUBLABEL_DISCORD_ALLOW, From d2f472ba7a684f14c252373cd3ee950d803dd6a0 Mon Sep 17 00:00:00 2001 From: Alfrix Date: Fri, 19 Oct 2018 09:42:22 -0300 Subject: [PATCH 002/234] Rework some sublabels --- intl/msg_hash_us.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index c3d26aa4b2..3798787444 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -3504,27 +3504,30 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, - "Enable or disable achievements. For more information, visit http://retroachievements.org" + "Enable or disable achievements.\n" + "For more information, visit http://retroachievements.org" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, - "Enable or disable unofficial achievements and/or beta features for testing purposes." + "Use unofficial achievements and/or beta features for testing purposes." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, - "Enable or disable savestates, cheats, rewind, pause, and slow-motion for all games." + "Double the amount of points earned.\n" + "Disables savestates, cheats, rewind, pause, and slow-motion for all games." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_LEADERBOARDS_ENABLE, - "Enable or disable in-game leaderboards. Has no effect if Hardcore Mode is disabled." + "Game specific leaderboards.\n" + "Has no effect if Hardcore Mode is disabled." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE, - "Enable or disable badge display in the Achievement List." + "Display badges in the Achievement List." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_VERBOSE_ENABLE, - "Enable or disable OSD verbosity for achievements." + "Show more information in the notifications." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_AUTO_SCREENSHOT, From cb7df5a66546f25417bc319595133fd689a178be Mon Sep 17 00:00:00 2001 From: Alfrix Date: Fri, 19 Oct 2018 09:50:21 -0300 Subject: [PATCH 003/234] Remove driver from main labels at the driver menu --- intl/msg_hash_us.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 3798787444..9117b07c37 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -289,7 +289,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_DRIVER, - "Audio Driver" + "Audio" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_DSP_PLUGIN, @@ -329,7 +329,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_DRIVER, - "Audio Resampler Driver" + "Audio Resampler" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_SETTINGS, @@ -461,7 +461,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CAMERA_DRIVER, - "Camera Driver" + "Camera" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEAT, @@ -797,7 +797,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_DRIVER_SETTINGS, - "Driver" + "Drivers" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_DUMMY_ON_CORE_SHUTDOWN, @@ -1077,7 +1077,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_DRIVER, - "Input Driver" + "Input" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_DUTY_CYCLE, @@ -1441,7 +1441,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_JOYPAD_DRIVER, - "Joypad Driver" + "Joypad" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_LAKKA_SERVICES, @@ -1561,7 +1561,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_LOCATION_DRIVER, - "Location Driver" + "Location" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_LOGGING_SETTINGS, @@ -1621,7 +1621,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_DRIVER, - "Menu Driver" + "Menu" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_ENUM_THROTTLE_FRAMERATE, @@ -2196,11 +2196,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_RECORD_DRIVER, - "Record Driver" + "Record" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MIDI_DRIVER, - "MIDI Driver" + "MIDI" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_RECORD_ENABLE, @@ -3100,7 +3100,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_DRIVER, - "Video Driver" + "Video" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_FILTER, @@ -3316,7 +3316,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_WIFI_DRIVER, - "Wi-Fi Driver" + "Wi-Fi" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS, From 50880e643509b5ad10fc3b729c9cf5ff0cafab45 Mon Sep 17 00:00:00 2001 From: Alfrix Date: Fri, 19 Oct 2018 10:01:35 -0300 Subject: [PATCH 004/234] Remove audio from main labels at the audio menu --- intl/msg_hash_us.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 9117b07c37..ef816f552e 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -285,7 +285,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_DEVICE, - "Audio Device" + "Device" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_DRIVER, @@ -293,7 +293,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_DSP_PLUGIN, - "Audio DSP Plugin" + "DSP Plugin" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE, @@ -313,15 +313,15 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MAX_TIMING_SKEW, - "Audio Maximum Timing Skew" + "Maximum Timing Skew" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MUTE, - "Audio Mute" + "Mute" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_OUTPUT_RATE, - "Audio Output Rate (Hz)" + "Output Rate (Hz)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_RATE_CONTROL_DELTA, @@ -337,11 +337,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_SYNC, - "Audio Sync" + "Synchronization" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_VOLUME, - "Audio Volume Level (dB)" + "Volume Gain (dB)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_WASAPI_EXCLUSIVE_MODE, @@ -5889,11 +5889,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_VOLUME, - "Audio Mixer Volume Level (dB)" + "Mixer Volume Gain (dB)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_MUTE, - "Audio Mixer Mute" + "Mixer Mute" ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_MIXER_MUTE, @@ -6305,7 +6305,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, - "Audio Resampler Quality" + "Resampler Quality" ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, @@ -6385,7 +6385,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU, - "Menu audio" + "Menu Sound" ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_ENABLE_MENU, From 605113a20aa0b162b0b51479ae5053f939061dad Mon Sep 17 00:00:00 2001 From: Alfrix Date: Fri, 19 Oct 2018 10:11:28 -0300 Subject: [PATCH 005/234] Remove input from main labels at the input menu --- intl/msg_hash_us.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index ef816f552e..a00e2eecf5 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1085,7 +1085,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BINDS, - "Input Hotkey Binds" + "Hotkey Binds" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_ICADE_ENABLE, @@ -1425,7 +1425,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_USER_BINDS, - "Input User %u Binds" + "User %u Binds" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_LATENCY_SETTINGS, From d5c56e460133bd64a78191d075767147e1d105ba Mon Sep 17 00:00:00 2001 From: Alfrix Date: Sat, 20 Oct 2018 14:29:28 -0300 Subject: [PATCH 006/234] Rework sublabels to avoid the unhelpful enable/disable --- intl/msg_hash_us.h | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index a00e2eecf5..009c1897c9 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -3504,7 +3504,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, - "Enable or disable achievements.\n" + "Compete to earn custom-made achievements in classic games.\n" "For more information, visit http://retroachievements.org" ) MSG_HASH( @@ -3603,7 +3603,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_BLUETOOTH_ENABLE, - "Enable or disable bluetooth." + "Determines the state of Bluetooth." ) MSG_HASH( MENU_ENUM_SUBLABEL_CONFIG_SAVE_ON_EXIT, @@ -3647,7 +3647,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_LOG_VERBOSITY, - "Enable or disable logging to the terminal." + "Log events to the terminal." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY, @@ -3667,7 +3667,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_SAMBA_ENABLE, - "Enable or disable network sharing of your folders." + "Share network folders through the SMB protocol." ) MSG_HASH( MENU_ENUM_SUBLABEL_SERVICES_SETTINGS, @@ -3679,7 +3679,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_SSH_ENABLE, - "Enable or disable remote command line access." + "Use SSH to access the command line remotely." ) MSG_HASH( MENU_ENUM_SUBLABEL_SUSPEND_SCREENSAVER_ENABLE, @@ -4624,7 +4624,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_ENABLE, - "Enable or disable audio output." + "Determines if audio is outputted." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_MAX_TIMING_SKEW, @@ -4744,11 +4744,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition." + "Window managers use composition to apply visual effects, detect unresponsive windows, amongst other things." ) MSG_HASH( MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, - "Enable or disable recent playlist for games, images, music, and videos." + "Maintain a playlist of recently used games, images, music, and videos." ) MSG_HASH( MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -4989,7 +4989,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_ENABLE, - "Enable or disable rewind support.\n" + "Made a mistake? Rewind and try again.\n" "Beware that this causes a performance hit when playing." ) MSG_HASH( @@ -5123,7 +5123,8 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_PERFCNT_ENABLE, - "Enable or disable performance counters for RetroArch (and cores)." + "Performance counters for RetroArch (and cores).\n" + "The counter data can help determine system bottlenecks and fine-tune system and application performance" ) MSG_HASH( MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_SAVE, @@ -5235,7 +5236,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_OVERLAY_ENABLE, - "Enable or disable the overlay." + "Overlays are used for borders and on-screen controls" ) MSG_HASH( MENU_ENUM_SUBLABEL_OVERLAY_PRESET, @@ -5291,11 +5292,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_MOUSE_ENABLE, - "Enable or disable mouse controls inside the menu." + "Allows the menu to be controlled with the mouse." ) MSG_HASH( MENU_ENUM_SUBLABEL_POINTER_ENABLE, - "Enable or disable touch controls inside the menu." + "Allows the menu to be controlled with screen touches." ) MSG_HASH( MENU_ENUM_SUBLABEL_THUMBNAILS, @@ -5981,7 +5982,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_MATERIALUI_ICONS_ENABLE, - "Enable/disable the menu icons shown at the lefthand side of the menu entries." + "Show icons at the left of the menu entries." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_XMB_MAIN_MENU_ENABLE_SETTINGS, @@ -6385,11 +6386,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU, - "Menu Sound" + "Mixer" ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_ENABLE_MENU, - "Enable or disable menu sound." + "Play simultaneous audio streams even in the menu." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_SETTINGS, @@ -6789,7 +6790,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_DISCORD_ALLOW, - "Enable or disable Discord Rich Presence support.\n" + "Allows the discord app to show more data about the content played.\n" "NOTE: It will not work with the browser version, only with the native desktop client." ) MSG_HASH( From 4260f9ffbca16cae7e30339502f7622f6aab784f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sat, 5 Jan 2019 00:39:59 -0500 Subject: [PATCH 007/234] Hash full Lynx file content --- cheevos/cheevos.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index 04dd23b153..35bce37199 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -2615,7 +2615,7 @@ static int cheevos_iterate(coro_t *coro) { {SNES_MD5, "SNES (discards header)", snes_exts}, {GENESIS_MD5, "Genesis (6Mb padding)", genesis_exts}, - {LYNX_MD5, "Atari Lynx (only first 512 bytes)", lynx_exts}, + {LYNX_MD5, "Atari Lynx (discards header)", lynx_exts}, {NES_MD5, "NES (discards header)", NULL}, {GENERIC_MD5, "Generic (plain content)", NULL}, {FILENAME_MD5, "Generic (filename)", NULL} @@ -2955,16 +2955,21 @@ found: *************************************************************************/ CORO_SUB(LYNX_MD5) - if (coro->len < 0x0240) + /* Checks for the existence of a headered Lynx file. + Unheadered files fall back to GENERIC_MD5. */ + + const int lynx_header_len = 0x40; + + if (coro->len <= lynx_header_len || + memcmp("LYNX", (void *)coro->data, 5) != 0) { coro->gameid = 0; CORO_RET(); } MD5_Init(&coro->md5); - - coro->offset = 0x0040; - coro->count = 0x0200; + coro->offset = lynx_header_len; + coro->count = coro->len - lynx_header_len; CORO_GOSUB(EVAL_MD5); MD5_Final(coro->hash, &coro->md5); From cdbfec7348583fc94602a64830017d2d27c2d920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 15 Jan 2019 12:18:58 -0500 Subject: [PATCH 008/234] Make SNES_HEADER_LEN snake case --- cheevos/cheevos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index 35bce37199..c698b1e6e4 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -2571,7 +2571,7 @@ enum static int cheevos_iterate(coro_t *coro) { - const int SNES_HEADER_LEN = 0x200; + const int snes_header_len = 0x200; ssize_t num_read = 0; size_t to_read = 4096; uint8_t *buffer = NULL; @@ -2904,7 +2904,7 @@ found: /* Checks for the existence of a headered SNES file. Unheadered files fall back to GENERIC_MD5. */ - if (coro->len < 0x2000 || coro->len % 0x2000 != SNES_HEADER_LEN) + if (coro->len < 0x2000 || coro->len % 0x2000 != snes_header_len) { coro->gameid = 0; CORO_RET(); From b1de87555193cf56de38ceb984f862e29405dc1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 15 Jan 2019 12:19:25 -0500 Subject: [PATCH 009/234] Define lynx_header_len at the function head --- cheevos/cheevos.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index c698b1e6e4..92891c4b70 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -2572,6 +2572,7 @@ enum static int cheevos_iterate(coro_t *coro) { const int snes_header_len = 0x200; + const int lynx_header_len = 0x40; ssize_t num_read = 0; size_t to_read = 4096; uint8_t *buffer = NULL; @@ -2958,8 +2959,6 @@ found: /* Checks for the existence of a headered Lynx file. Unheadered files fall back to GENERIC_MD5. */ - const int lynx_header_len = 0x40; - if (coro->len <= lynx_header_len || memcmp("LYNX", (void *)coro->data, 5) != 0) { From b7cc124070514c591388845b4b972788193b7954 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sun, 6 Jan 2019 14:49:26 +0100 Subject: [PATCH 010/234] (UWP) Base StorageFile implementation --- griffin/griffin.c | 2 + .../include/vfs/vfs_implementation.h | 8 + .../vfs/vfs_implementation_uwp.cpp | 605 ++++++++++++++++++ .../RetroArch-msvc2017-UWP.vcxproj | 3 + .../RetroArch-msvc2017-UWP.vcxproj.filters | 6 + 5 files changed, 624 insertions(+) create mode 100644 libretro-common/vfs/vfs_implementation_uwp.cpp diff --git a/griffin/griffin.c b/griffin/griffin.c index d4ebac5a2b..d2c609c86f 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -926,7 +926,9 @@ FILE #include "../libretro-common/streams/file_stream_transforms.c" #include "../libretro-common/streams/interface_stream.c" #include "../libretro-common/streams/memory_stream.c" +#ifndef __WINRT__ #include "../libretro-common/vfs/vfs_implementation.c" +#endif #include "../list_special.c" #include "../libretro-common/string/stdstring.c" #include "../libretro-common/file/nbio/nbio_stdio.c" diff --git a/libretro-common/include/vfs/vfs_implementation.h b/libretro-common/include/vfs/vfs_implementation.h index afc2e22213..9f49f2640d 100644 --- a/libretro-common/include/vfs/vfs_implementation.h +++ b/libretro-common/include/vfs/vfs_implementation.h @@ -44,6 +44,10 @@ typedef struct retro_vfs_dir_handle libretro_vfs_implementation_dir; typedef struct libretro_vfs_implementation_dir libretro_vfs_implementation_dir; #endif +#ifdef __cplusplus +extern "C" { +#endif + libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints); int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream); @@ -84,4 +88,8 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream); int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream); +#ifdef __cplusplus +} +#endif + #endif diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp new file mode 100644 index 0000000000..5293a13f41 --- /dev/null +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -0,0 +1,605 @@ +/* Copyright (C) 2018-2019 The RetroArch team +* +* --------------------------------------------------------------------------------------- +* The following license statement only applies to this file (vfs_implementation_uwp.cpp). +* --------------------------------------------------------------------------------------- +* +* Permission is hereby granted, free of charge, +* to any person obtaining a copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +* and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Windows::Foundation::Collections; +using namespace Windows::Storage; +using namespace Windows::Storage::Streams; +using namespace Windows::Storage::FileProperties; + +#ifdef RARCH_INTERNAL +#ifndef VFS_FRONTEND +#define VFS_FRONTEND +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + /* Dear Microsoft + * I really appreciate all the effort you took to not provide any + * synchronous file APIs and block all attempts to synchronously + * wait for the results of async tasks for "smooth user experience", + * but I'm not going to run and rewrite all RetroArch cores for + * async I/O. I hope you like this hack I made instead. + */ + template + T RunAsync(std::function()> func) + { + bool finished = false; + Platform::Exception^ exception = nullptr; + T result; + func().then([&](concurrency::task t) { + try + { + result = t.get(); + } + catch (Platform::Exception^ exception_) + { + exception = exception_; + } + finished = true; + }); + + while (!finished) + Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); + + if (exception != nullptr) + throw exception; + return result; + } + + template + T RunAsyncAndCatchErrors(std::function()> func, T valueOnError) + { + try + { + return RunAsync(func); + } + catch (Platform::Exception^ e) + { + return valueOnError; + } + } + + + void windowsize_path(wchar_t* path) + { + /* UWP deals with paths containing / instead of \ way worse than normal Windows */ + /* and RetroArch may sometimes mix them (e.g. on archive extraction) */ + if (!path) + return; + while (*path) + { + if (*path == '/') + *path = '\\'; + ++path; + } + } +} + +#ifdef VFS_FRONTEND +struct retro_vfs_file_handle +#else +struct libretro_vfs_implementation_file +#endif +{ + IRandomAccessStream^ fp; + char* orig_path; +}; + +libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints) +{ + if (!path || !*path) + return NULL; + + if (!path_is_absolute(path)) + { + RARCH_WARN("Something tried to access files from current directory ('%s'). This is not allowed on UWP.\n", path); + return NULL; + } + + if (path_char_is_slash(path[strlen(path) - 1])) + { + RARCH_WARN("Trying to open a directory as file?! ('%s')\n", path); + return NULL; + } + + char* dirpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_basedir(dirpath, path, PATH_MAX_LENGTH); + wchar_t *dirpath_wide = utf8_to_utf16_string_alloc(dirpath); + windowsize_path(dirpath_wide); + Platform::String^ dirpath_str = ref new Platform::String(dirpath_wide); + free(dirpath_wide); + free(dirpath); + + char* filename = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_base(filename, path, PATH_MAX_LENGTH); + wchar_t *filename_wide = utf8_to_utf16_string_alloc(filename); + Platform::String^ filename_str = ref new Platform::String(filename_wide); + free(filename_wide); + free(filename); + + retro_assert(!dirpath_str->IsEmpty() && !filename_str->IsEmpty()); + + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(dirpath_str)).then([&](StorageFolder^ dir) { + if (mode == RETRO_VFS_FILE_ACCESS_READ) + return dir->GetFileAsync(filename_str); + else + return dir->CreateFileAsync(filename_str, (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ? + CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting); + }).then([&](StorageFile^ file) { + FileAccessMode accessMode = mode == RETRO_VFS_FILE_ACCESS_READ ? + FileAccessMode::Read : FileAccessMode::ReadWrite; + return file->OpenAsync(accessMode); + }).then([&](IRandomAccessStream^ fpstream) { + libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream)); + if (!stream) + return (libretro_vfs_implementation_file*)NULL; + + stream->orig_path = strdup(path); + stream->fp = fpstream; + stream->fp->Seek(0); + return stream; + }); + }, NULL); +} + +int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream || !stream->fp) + return -1; + + /* Apparently, this is how you close a file in WinRT */ + /* Yes, really */ + stream->fp = nullptr; + + return 0; +} + +int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream) +{ + return false; /* TODO */ +} + +int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream || !stream->fp) + return 0; + return stream->fp->Size; +} + +int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, int64_t length) +{ + if (!stream || !stream->fp) + return -1; + stream->fp->Size = length; + return 0; +} + +int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream || !stream->fp) + return -1; + return stream->fp->Position; +} + +int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position) +{ + if (!stream || !stream->fp) + return -1; + + switch (seek_position) + { + case RETRO_VFS_SEEK_POSITION_START: + stream->fp->Seek(offset); + break; + + case RETRO_VFS_SEEK_POSITION_CURRENT: + stream->fp->Seek(stream->fp->Position + offset); + break; + + case RETRO_VFS_SEEK_POSITION_END: + stream->fp->Seek(stream->fp->Size - offset); + break; + } + + return 0; +} + +/* This is some pure magic and I have absolutely no idea how it works */ +/* Wraps a raw buffer into a WinRT object */ +/* https://stackoverflow.com/questions/10520335/how-to-wrap-a-char-buffer-in-a-winrt-ibuffer-in-c */ +class NativeBuffer : + public Microsoft::WRL::RuntimeClass, + ABI::Windows::Storage::Streams::IBuffer, + Windows::Storage::Streams::IBufferByteAccess> +{ +public: + virtual ~NativeBuffer() + { + } + + HRESULT __stdcall RuntimeClassInitialize(byte *buffer, uint32_t capacity, uint32_t length) + { + m_buffer = buffer; + m_capacity = capacity; + m_length = length; + return S_OK; + } + + HRESULT __stdcall Buffer(byte **value) + { + if (m_buffer == nullptr) + return E_INVALIDARG; + *value = m_buffer; + return S_OK; + } + + HRESULT __stdcall get_Capacity(uint32_t *value) + { + *value = m_capacity; + return S_OK; + } + + HRESULT __stdcall get_Length(uint32_t *value) + { + *value = m_length; + return S_OK; + } + + HRESULT __stdcall put_Length(uint32_t value) + { + if (value > m_capacity) + return E_INVALIDARG; + m_length = value; + return S_OK; + } + +private: + byte *m_buffer; + uint32_t m_capacity; + uint32_t m_length; +}; + +IBuffer^ CreateNativeBuffer(void* buf, uint32_t capacity, uint32_t length) +{ + Microsoft::WRL::ComPtr nativeBuffer; + Microsoft::WRL::Details::MakeAndInitialize(&nativeBuffer, (byte *)buf, capacity, length); + auto iinspectable = (IInspectable *)reinterpret_cast(nativeBuffer.Get()); + IBuffer ^buffer = reinterpret_cast(iinspectable); + return buffer; +} + +int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void *s, uint64_t len) +{ + if (!stream || !stream->fp || !s) + return -1; + + IBuffer^ buffer = CreateNativeBuffer(s, len, 0); + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) { + retro_assert(buf == buffer); + return (int64_t)buffer->Length; + }); + }, -1); +} + +int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len) +{ + if (!stream || !stream->fp || !s) + return -1; + + IBuffer^ buffer = CreateNativeBuffer(const_cast(s), len, len); + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) { + return (int64_t)written; + }); + }, -1); +} + +int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream || !stream->fp) + return -1; + + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(stream->fp->FlushAsync()).then([&](bool this_value_is_not_even_documented_wtf) { + /* The bool value may be reporting an error or something, but just leave it alone for now */ + /* https://github.com/MicrosoftDocs/winrt-api/issues/841 */ + return 0; + }); + }, -1); +} + +int retro_vfs_file_remove_impl(const char *path) +{ + if (!path || !*path) + return -1; + + wchar_t *path_wide = utf8_to_utf16_string_alloc(path); + windowsize_path(path_wide); + Platform::String^ path_str = ref new Platform::String(path_wide); + free(path_wide); + + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(StorageFile::GetFileFromPathAsync(path_str)).then([&](StorageFile^ file) { + return file->DeleteAsync(StorageDeleteOption::PermanentDelete); + }).then([&]() { + return 0; + }); + }, -1); +} + +/* TODO: this may not work if trying to move a directory */ +int retro_vfs_file_rename_impl(const char *old_path, const char *new_path) +{ + if (!old_path || !*old_path || !new_path || !*new_path) + return -1; + + wchar_t* old_path_wide = utf8_to_utf16_string_alloc(old_path); + Platform::String^ old_path_str = ref new Platform::String(old_path_wide); + free(old_path_wide); + + char* new_dir_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_basedir(new_dir_path, new_path, PATH_MAX_LENGTH); + wchar_t *new_dir_path_wide = utf8_to_utf16_string_alloc(new_dir_path); + windowsize_path(new_dir_path_wide); + Platform::String^ new_dir_path_str = ref new Platform::String(new_dir_path_wide); + free(new_dir_path_wide); + free(new_dir_path); + + char* new_file_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_base(new_file_name, new_path, PATH_MAX_LENGTH); + wchar_t *new_file_name_wide = utf8_to_utf16_string_alloc(new_file_name); + Platform::String^ new_file_name_str = ref new Platform::String(new_file_name_wide); + free(new_file_name_wide); + free(new_file_name); + + retro_assert(!old_path_str->IsEmpty() && !new_dir_path_str->IsEmpty() && !new_file_name_str->IsEmpty()); + + return RunAsyncAndCatchErrors([&]() { + concurrency::task old_file_task = concurrency::create_task(StorageFile::GetFileFromPathAsync(old_path_str)); + concurrency::task new_dir_task = concurrency::create_task(StorageFolder::GetFolderFromPathAsync(new_dir_path_str)); + return concurrency::create_task([&] { + /* Run these two tasks in parallel */ + /* TODO: There may be some cleaner way to express this */ + concurrency::task_group group; + group.run([&] { return old_file_task; }); + group.run([&] { return new_dir_task; }); + group.wait(); + }).then([&]() { + return old_file_task.get()->MoveAsync(new_dir_task.get(), new_file_name_str, NameCollisionOption::ReplaceExisting); + }).then([&]() { + return 0; + }); + }, -1); +} + +const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream) +{ + /* should never happen, do something noisy so caller can be fixed */ + if (!stream) + abort(); + return stream->orig_path; +} + + +/* This is ugly, but I can't figure out a better way and there may be no better way... */ +static IStorageItem^ GetFileOrFolderFromPath(Platform::String^ path) +{ + if (!path || path->IsEmpty()) + return nullptr; + + if (*(path->End() - 1) == '\\') + { + /* Ends with a slash, so it's definitely a directory */ + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path)); + }, nullptr); + } + else + { + /* No final slash - probably a file (since RetroArch usually slash-terminates dirs), but there is a chance it's a directory */ + IStorageItem^ item; + item = RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(StorageFile::GetFileFromPathAsync(path)); + }, nullptr); + if (!item) + { + item = RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path)); + }, nullptr); + } + return item; + } +} + +int retro_vfs_stat_impl(const char *path, int32_t *size) +{ + if (!path || !*path) + return 0; + + wchar_t *path_wide = utf8_to_utf16_string_alloc(path); + windowsize_path(path_wide); + Platform::String^ path_str = ref new Platform::String(path_wide); + free(path_wide); + + IStorageItem^ item = GetFileOrFolderFromPath(path_str); + if (!item) + return 0; + + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(item->GetBasicPropertiesAsync()).then([&](BasicProperties^ properties) { + if (size) + *size = properties->Size; + return item->IsOfType(StorageItemTypes::Folder) ? RETRO_VFS_STAT_IS_VALID | RETRO_VFS_STAT_IS_DIRECTORY : RETRO_VFS_STAT_IS_VALID; + }); + }, 0); +} + +int retro_vfs_mkdir_impl(const char *dir) +{ + if (!dir || !*dir) + return -1; + + char* dir_local = strdup(dir); + /* If the path ends with a slash, we have to remove it for basename to work */ + char* tmp = dir_local + strlen(dir_local) - 1; + if (path_char_is_slash(*tmp)) + *tmp = 0; + + char* dir_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_base(dir_name, dir_local, PATH_MAX_LENGTH); + wchar_t *dir_name_wide = utf8_to_utf16_string_alloc(dir_name); + Platform::String^ dir_name_str = ref new Platform::String(dir_name_wide); + free(dir_name_wide); + free(dir_name); + + char* parent_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_parent_dir(parent_path, dir_local, PATH_MAX_LENGTH); + wchar_t *parent_path_wide = utf8_to_utf16_string_alloc(parent_path); + windowsize_path(parent_path_wide); + Platform::String^ parent_path_str = ref new Platform::String(parent_path_wide); + free(parent_path_wide); + free(parent_path); + + retro_assert(!dir_name_str->IsEmpty() && !parent_path_str->IsEmpty()); + + free(dir_local); + + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(parent_path_str)).then([&](StorageFolder^ parent) { + return parent->CreateFolderAsync(dir_name_str); + }).then([&](concurrency::task new_dir) { + try + { + new_dir.get(); + } + catch (Platform::COMException^ e) + { + if (e->HResult == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + return -2; + throw; + } + return 0; + }); + }, -1); +} + +#ifdef VFS_FRONTEND +struct retro_vfs_dir_handle +#else +struct libretro_vfs_implementation_dir +#endif +{ + IVectorView^ directory; + IIterator^ entry; + char *entry_name; +}; + +libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden) +{ + libretro_vfs_implementation_dir *rdir; + + if (!name || !*name) + return NULL; + + rdir = (libretro_vfs_implementation_dir*)calloc(1, sizeof(*rdir)); + if (!rdir) + return NULL; + + wchar_t *name_wide = utf8_to_utf16_string_alloc(name); + windowsize_path(name_wide); + Platform::String^ name_str = ref new Platform::String(name_wide); + free(name_wide); + + rdir->directory = RunAsyncAndCatchErrors^>([&]() { + return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(name_str)).then([&](StorageFolder^ folder) { + return folder->GetItemsAsync(); + }); + }, nullptr); + + if (rdir->directory) + return rdir; + + free(rdir); + return NULL; +} + +bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir) +{ + if (!rdir->entry) + { + rdir->entry = rdir->directory->First(); + return rdir->entry->HasCurrent; + } + else + { + return rdir->entry->MoveNext(); + } +} + +const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir) +{ + if (rdir->entry_name) + free(rdir->entry_name); + rdir->entry_name = utf16_to_utf8_string_alloc(rdir->entry->Current->Name->Data()); + return rdir->entry_name; +} + +bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir) +{ + return rdir->entry->Current->IsOfType(StorageItemTypes::Folder); +} + +int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir) +{ + if (!rdir) + return -1; + + if (rdir->entry_name) + free(rdir->entry_name); + rdir->entry = nullptr; + rdir->directory = nullptr; + + free(rdir); + return 0; +} diff --git a/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj b/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj index 1f21ca7a6c..4d8b42ab77 100644 --- a/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj +++ b/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj @@ -282,6 +282,9 @@ + + + diff --git a/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj.filters b/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj.filters index 3fcb574ea4..dd9507e079 100644 --- a/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj.filters +++ b/pkg/msvc-uwp/RetroArch-msvc2017-UWP/RetroArch-msvc2017-UWP.vcxproj.filters @@ -10,6 +10,9 @@ {c3155604-6d38-494a-bfe0-861cef871cb2} + + {d41660c5-7f5b-442c-b5d7-03e6e9af8172} + @@ -40,6 +43,9 @@ griffin + + libretro-common-uwp + From 9188cc1a730f663600211e5090933028e23f7c18 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sun, 13 Jan 2019 18:13:21 +0100 Subject: [PATCH 011/234] (UWP) Add broadFileSystemAccess support --- frontend/drivers/platform_uwp.c | 39 ++++++++++++++----- intl/msg_hash_us.c | 5 +++ intl/msg_hash_us.h | 8 ++++ menu/cbs/menu_cbs_ok.c | 18 +++++++++ menu/cbs/menu_cbs_sublabel.c | 4 ++ msg_hash.h | 2 + .../Package.appxmanifest | 3 +- uwp/uwp_func.h | 2 + uwp/uwp_main.cpp | 5 +++ 9 files changed, 76 insertions(+), 10 deletions(-) diff --git a/frontend/drivers/platform_uwp.c b/frontend/drivers/platform_uwp.c index b6fa41002c..dfbc113928 100644 --- a/frontend/drivers/platform_uwp.c +++ b/frontend/drivers/platform_uwp.c @@ -271,18 +271,39 @@ static int frontend_uwp_parse_drive_list(void *data, bool load_content) enum msg_hash_enums enum_idx = load_content ? MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR : MSG_UNKNOWN; - /* TODO (krzys_h): UWP storage sandboxing */ - char *home_dir = (char*)malloc( - PATH_MAX_LENGTH * sizeof(char)); + char drive[] = " :\\"; + char *home_dir = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + bool have_any_drives = false; - fill_pathname_home_dir(home_dir, - PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_home_dir(home_dir, PATH_MAX_LENGTH * sizeof(char)); + + for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++) + { + if (path_is_valid(drive)) + { + menu_entries_append_enum(list, + drive, + msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), + enum_idx, + FILE_TYPE_DIRECTORY, 0, 0); + have_any_drives = true; + } + } menu_entries_append_enum(list, - home_dir, - msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), - enum_idx, - FILE_TYPE_DIRECTORY, 0, 0); + home_dir, + msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), + enum_idx, + FILE_TYPE_DIRECTORY, 0, 0); + + if (!have_any_drives && string_is_equal(uwp_device_family, "Windows.Desktop")) + { + menu_entries_append_enum(list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FILE_BROWSER_OPEN_UWP_PERMISSIONS), + msg_hash_to_str(MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS), + MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS, + MENU_SETTING_ACTION, 0, 0); + } free(home_dir); #endif diff --git a/intl/msg_hash_us.c b/intl/msg_hash_us.c index 6f46d28063..b273e76090 100644 --- a/intl/msg_hash_us.c +++ b/intl/msg_hash_us.c @@ -390,6 +390,11 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len) snprintf(s, len, "Go back to the parent directory."); break; + case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS: + snprintf(s, len, + "Open Windows permission settings to enable \n" + "the broadFileSystemAccess capability."); + break; case MENU_ENUM_LABEL_FILE_BROWSER_SHADER_PRESET: snprintf(s, len, "Shader preset file."); diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 0615dca690..6fc52c51ca 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2044,6 +2044,14 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY, "Parent directory" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_FILE_BROWSER_OPEN_UWP_PERMISSIONS, + "Enable external file access" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS, + "Open Windows file access permissions settings" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_PAUSE_LIBRETRO, "Pause when menu activated" diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 55f1a1bc66..22a3358bc7 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -79,6 +79,10 @@ #include "../../record/record_driver.h" +#ifdef __WINRT__ +#include "../../uwp/uwp_func.h" +#endif + enum { ACTION_OK_LOAD_PRESET = 0, @@ -3965,6 +3969,17 @@ default_action_ok_func(action_ok_push_accounts_youtube_list, ACTION_OK_DL_ACCOUN default_action_ok_func(action_ok_push_accounts_twitch_list, ACTION_OK_DL_ACCOUNTS_TWITCH_LIST) default_action_ok_func(action_ok_open_archive, ACTION_OK_DL_OPEN_ARCHIVE) +static int action_ok_open_uwp_permission_settings(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ +#ifdef __WINRT__ + uwp_open_broadfilesystemaccess_settings(); +#else + retro_assert(false); +#endif + return 0; +} + static int action_ok_shader_pass(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { @@ -5465,6 +5480,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS: BIND_ACTION_OK(cbs, action_ok_menu_file_browser_list); break; + case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS: + BIND_ACTION_OK(cbs, action_ok_open_uwp_permission_settings); + break; case MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS: BIND_ACTION_OK(cbs, action_ok_retro_achievements_list); break; diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 1bd69f3765..8d0c9d76e7 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -334,6 +334,7 @@ default_sublabel_macro(action_bind_sublabel_goto_images, default_sublabel_macro(action_bind_sublabel_goto_music, MENU_ENUM_SUBLABEL_GOTO_MUSIC) default_sublabel_macro(action_bind_sublabel_goto_video, MENU_ENUM_SUBLABEL_GOTO_VIDEO) default_sublabel_macro(action_bind_sublabel_menu_filebrowser_settings, MENU_ENUM_SUBLABEL_MENU_FILE_BROWSER_SETTINGS) +default_sublabel_macro(action_bind_sublabel_menu_filebrowser_open_uwp_permissions, MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS) default_sublabel_macro(action_bind_sublabel_auto_remaps_enable, MENU_ENUM_SUBLABEL_AUTO_REMAPS_ENABLE) default_sublabel_macro(action_bind_sublabel_auto_overrides_enable, MENU_ENUM_SUBLABEL_AUTO_OVERRIDES_ENABLE) default_sublabel_macro(action_bind_sublabel_game_specific_options, MENU_ENUM_SUBLABEL_GAME_SPECIFIC_OPTIONS) @@ -1379,6 +1380,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_filebrowser_settings); break; + case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_filebrowser_open_uwp_permissions); + break; case MENU_ENUM_LABEL_ADD_TO_FAVORITES: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_add_to_favorites); break; diff --git a/msg_hash.h b/msg_hash.h index a1226afcd2..c6501869d3 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -823,6 +823,8 @@ enum msg_hash_enums MENU_LABEL(PARENT_DIRECTORY), + MENU_LABEL(FILE_BROWSER_OPEN_UWP_PERMISSIONS), + MENU_ENUM_LABEL_CONTENT_ACTIONS, /* Menu settings */ diff --git a/pkg/msvc-uwp/RetroArch-msvc2017-UWP/Package.appxmanifest b/pkg/msvc-uwp/RetroArch-msvc2017-UWP/Package.appxmanifest index e1d4376bbd..1d99be534b 100644 --- a/pkg/msvc-uwp/RetroArch-msvc2017-UWP/Package.appxmanifest +++ b/pkg/msvc-uwp/RetroArch-msvc2017-UWP/Package.appxmanifest @@ -1,5 +1,5 @@ - + @@ -25,5 +25,6 @@ + diff --git a/uwp/uwp_func.h b/uwp/uwp_func.h index ecab3b8a03..65e663d3de 100644 --- a/uwp/uwp_func.h +++ b/uwp/uwp_func.h @@ -26,6 +26,8 @@ extern char uwp_dir_install[PATH_MAX_LENGTH]; extern char uwp_dir_data[PATH_MAX_LENGTH]; extern char uwp_device_family[128]; +void uwp_open_broadfilesystemaccess_settings(void); + void* uwp_get_corewindow(void); void uwp_input_next_frame(void); diff --git a/uwp/uwp_main.cpp b/uwp/uwp_main.cpp index bc1c9b5e13..30b2b8b5a2 100644 --- a/uwp/uwp_main.cpp +++ b/uwp/uwp_main.cpp @@ -627,4 +627,9 @@ extern "C" { return 0; } + + void uwp_open_broadfilesystemaccess_settings(void) + { + Windows::System::Launcher::LaunchUriAsync(ref new Uri("ms-settings:privacy-broadfilesystemaccess")); + } } From c8510378dc953c5ecf064fa2bc67e882780a8ab6 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Mon, 14 Jan 2019 21:30:20 +0100 Subject: [PATCH 012/234] (UWP) Error if trying to use VFS on cores that don't support it --- core.h | 2 ++ dynamic.c | 1 + intl/msg_hash_us.h | 4 ++++ .../vfs/vfs_implementation_uwp.cpp | 12 +++++++++++ msg_hash.h | 1 + tasks/task_content.c | 21 ++++++++++++++++++- uwp/uwp_func.h | 1 + 7 files changed, 41 insertions(+), 1 deletion(-) diff --git a/core.h b/core.h index 06cdbac698..40d0a193d4 100644 --- a/core.h +++ b/core.h @@ -65,6 +65,8 @@ typedef struct rarch_system_info const char *input_desc_btn[MAX_USERS][RARCH_FIRST_META_KEY]; char valid_extensions[255]; + bool supports_vfs; + struct retro_disk_control_callback disk_control_cb; struct retro_location_callback location_cb; diff --git a/dynamic.c b/dynamic.c index a6d3074013..eceba94e22 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1960,6 +1960,7 @@ bool rarch_environment_cb(unsigned cmd, void *data) RARCH_LOG("Core requested VFS version >= v%d, providing v%d\n", vfs_iface_info->required_interface_version, supported_vfs_version); vfs_iface_info->required_interface_version = supported_vfs_version; vfs_iface_info->iface = &vfs_iface; + system->supports_vfs = true; } else { diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 6fc52c51ca..6b1323e3a8 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -4143,6 +4143,10 @@ MSG_HASH( MSG_ERROR_LIBRETRO_CORE_REQUIRES_SPECIAL_CONTENT, "Libretro core requires special content, but none were provided." ) +MSG_HASH( + MSG_ERROR_LIBRETRO_CORE_REQUIRES_VFS, + "Loading content from here requires VFS, but core does not support it" +) MSG_HASH( MSG_ERROR_PARSING_ARGUMENTS, "Error parsing arguments." diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index 5293a13f41..b1eee0cf0a 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -49,6 +49,7 @@ using namespace Windows::Storage::FileProperties; #include #include #include +#include namespace { @@ -603,3 +604,14 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir) free(rdir); return 0; } + +bool uwp_is_path_accessible_using_standard_io(char *path) +{ + char *relative_path_abbrev = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + fill_pathname_abbreviate_special(relative_path_abbrev, path, PATH_MAX_LENGTH * sizeof(char)); + + bool result = strlen(relative_path_abbrev) >= 2 && (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~') && path_char_is_slash(relative_path_abbrev[1]); + + free(relative_path_abbrev); + return result; +} diff --git a/msg_hash.h b/msg_hash.h index c6501869d3..7f87dfba60 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -260,6 +260,7 @@ enum msg_hash_enums MSG_COMPILED_AGAINST_API, MSG_ERROR_LIBRETRO_CORE_REQUIRES_SPECIAL_CONTENT, MSG_ERROR_LIBRETRO_CORE_REQUIRES_CONTENT, + MSG_ERROR_LIBRETRO_CORE_REQUIRES_VFS, MSG_SEVERAL_PATCHES_ARE_EXPLICITLY_DEFINED, MSG_DID_NOT_FIND_A_VALID_CONTENT_PATCH, MSG_FAILED_TO_ALLOCATE_MEMORY_FOR_PATCHED_CONTENT, diff --git a/tasks/task_content.c b/tasks/task_content.c index 3445f69383..dee66b7cd8 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -39,6 +39,10 @@ #endif #endif +#ifdef __WINRT__ +#include +#endif + #ifdef HAVE_CONFIG_H #include "../config.h" #endif @@ -557,6 +561,7 @@ static bool content_file_load( retro_ctx_load_content_info_t load_info; size_t msg_size = 1024 * sizeof(char); char *msg = (char*)malloc(msg_size); + rarch_system_info_t *system = runloop_get_system_info(); msg[0] = '\0'; @@ -605,7 +610,6 @@ static bool content_file_load( } else { - #ifdef HAVE_COMPRESSION if ( !content_ctx->block_extract && need_fullpath @@ -617,6 +621,21 @@ static bool content_file_load( error_string)) goto error; #endif + +#ifdef __WINRT__ + /* TODO: When support for the 'actual' VFS is added, there will need to be some more logic here */ + if (!system->supports_vfs && !uwp_is_path_accessible_using_standard_io(path)) + { + strlcpy(msg, + msg_hash_to_str(MSG_ERROR_LIBRETRO_CORE_REQUIRES_VFS), + msg_size + ); + *error_string = strdup(msg); + goto error; + } +#endif + + RARCH_LOG("%s\n", msg_hash_to_str(MSG_CONTENT_LOADING_SKIPPED_IMPLEMENTATION_WILL_DO_IT)); content_rom_crc = file_crc32(0, path); RARCH_LOG("CRC32: 0x%x .\n", (unsigned)content_rom_crc); diff --git a/uwp/uwp_func.h b/uwp/uwp_func.h index 65e663d3de..d137909c04 100644 --- a/uwp/uwp_func.h +++ b/uwp/uwp_func.h @@ -27,6 +27,7 @@ extern char uwp_dir_data[PATH_MAX_LENGTH]; extern char uwp_device_family[128]; void uwp_open_broadfilesystemaccess_settings(void); +bool uwp_is_path_accessible_using_standard_io(char *path); void* uwp_get_corewindow(void); From a116bb908e54a033a0f0c80235f7f5b03bc546a9 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Mon, 14 Jan 2019 22:43:29 +0100 Subject: [PATCH 013/234] (UWP) Support access through the file picker --- frontend/drivers/platform_uwp.c | 19 +- intl/msg_hash_us.c | 5 + intl/msg_hash_us.h | 8 + .../vfs/vfs_implementation_uwp.cpp | 219 ++++++++++++++---- menu/cbs/menu_cbs_ok.c | 25 ++ menu/cbs/menu_cbs_sublabel.c | 4 + msg_hash.h | 1 + uwp/uwp_func.h | 2 + 8 files changed, 239 insertions(+), 44 deletions(-) diff --git a/frontend/drivers/platform_uwp.c b/frontend/drivers/platform_uwp.c index dfbc113928..7c5205f72d 100644 --- a/frontend/drivers/platform_uwp.c +++ b/frontend/drivers/platform_uwp.c @@ -279,7 +279,7 @@ static int frontend_uwp_parse_drive_list(void *data, bool load_content) for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++) { - if (path_is_valid(drive)) + if (uwp_drive_exists(drive)) { menu_entries_append_enum(list, drive, @@ -296,13 +296,22 @@ static int frontend_uwp_parse_drive_list(void *data, bool load_content) enum_idx, FILE_TYPE_DIRECTORY, 0, 0); - if (!have_any_drives && string_is_equal(uwp_device_family, "Windows.Desktop")) + if (!have_any_drives) { menu_entries_append_enum(list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FILE_BROWSER_OPEN_UWP_PERMISSIONS), - msg_hash_to_str(MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS), - MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FILE_BROWSER_OPEN_PICKER), + msg_hash_to_str(MENU_ENUM_LABEL_FILE_BROWSER_OPEN_PICKER), + MENU_ENUM_LABEL_FILE_BROWSER_OPEN_PICKER, MENU_SETTING_ACTION, 0, 0); + + if (string_is_equal(uwp_device_family, "Windows.Desktop")) + { + menu_entries_append_enum(list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FILE_BROWSER_OPEN_UWP_PERMISSIONS), + msg_hash_to_str(MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS), + MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS, + MENU_SETTING_ACTION, 0, 0); + } } free(home_dir); diff --git a/intl/msg_hash_us.c b/intl/msg_hash_us.c index b273e76090..6905970494 100644 --- a/intl/msg_hash_us.c +++ b/intl/msg_hash_us.c @@ -395,6 +395,11 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len) "Open Windows permission settings to enable \n" "the broadFileSystemAccess capability."); break; + case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_PICKER: + snprintf(s, len, + "Open the system file picker to access \n" + "additional directories."); + break; case MENU_ENUM_LABEL_FILE_BROWSER_SHADER_PRESET: snprintf(s, len, "Shader preset file."); diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 6b1323e3a8..0a39e2c700 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2052,6 +2052,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS, "Open Windows file access permissions settings" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_FILE_BROWSER_OPEN_PICKER, + "Open..." +) +MSG_HASH( + MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_PICKER, + "Open another directory using the system file picker" +) MSG_HASH( MENU_ENUM_LABEL_VALUE_PAUSE_LIBRETRO, "Pause when menu activated" diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index b1eee0cf0a..4a8b174c24 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -27,8 +27,10 @@ #include #include #include +#include #include +using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::Storage; using namespace Windows::Storage::Streams; @@ -78,8 +80,13 @@ namespace finished = true; }); + /* Don't stall the UI thread - prevents a deadlock */ + Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread(); while (!finished) - Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); + { + if (corewindow) + corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); + } if (exception != nullptr) throw exception; @@ -115,6 +122,146 @@ namespace } } +namespace +{ + /* Damn you, UWP, why no functions for that either */ + template + concurrency::task GetItemFromPathAsync(Platform::String^ path) + { + static_assert(false, "StorageFile and StorageFolder only"); + } + template<> + concurrency::task GetItemFromPathAsync(Platform::String^ path) + { + return concurrency::create_task(StorageFile::GetFileFromPathAsync(path)); + } + template<> + concurrency::task GetItemFromPathAsync(Platform::String^ path) + { + return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path)); + } + + template + concurrency::task GetItemInFolderFromPathAsync(StorageFolder^ folder, Platform::String^ path) + { + static_assert(false, "StorageFile and StorageFolder only"); + } + template<> + concurrency::task GetItemInFolderFromPathAsync(StorageFolder^ folder, Platform::String^ path) + { + if (path->IsEmpty()) + retro_assert(false); /* Attempt to read a folder as a file - this really should have been caught earlier */ + return concurrency::create_task(folder->GetFileAsync(path)); + } + template<> + concurrency::task GetItemInFolderFromPathAsync(StorageFolder^ folder, Platform::String^ path) + { + if (path->IsEmpty()) + return concurrency::create_task(concurrency::create_async([folder]() { return folder; })); + return concurrency::create_task(folder->GetFolderAsync(path)); + } +} + +namespace +{ + /* A list of all StorageFolder objects returned using from the file picker */ + Platform::Collections::Vector accessible_directories; + + concurrency::task TriggerPickerAddDialog() + { + auto folderPicker = ref new Windows::Storage::Pickers::FolderPicker(); + folderPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::Desktop; + folderPicker->FileTypeFilter->Append("*"); + + return concurrency::create_task(folderPicker->PickSingleFolderAsync()).then([](StorageFolder^ folder) { + if (folder == nullptr) + throw ref new Platform::Exception(E_ABORT, L"Operation cancelled by user"); + + /* TODO: check for duplicates */ + accessible_directories.Append(folder); + return folder->Path; + }); + } + + template + concurrency::task LocateStorageItem(Platform::String^ path) + { + /* Look for a matching directory we can use */ + for each (StorageFolder^ folder in accessible_directories) + { + std::wstring folder_path = folder->Path->Data(); + /* Could be C:\ or C:\Users\somebody - remove the trailing slash to unify them */ + if (folder_path[folder_path.size() - 1] == '\\') + folder_path.erase(folder_path.size() - 1); + std::wstring file_path = path->Data(); + if (file_path.find(folder_path) == 0) + { + /* Found a match */ + file_path = file_path.length() > folder_path.length() ? file_path.substr(folder_path.length() + 1) : L""; + return concurrency::create_task(GetItemInFolderFromPathAsync(folder, ref new Platform::String(file_path.data()))); + } + } + + /* No matches - try accessing directly, and fallback to user prompt */ + return concurrency::create_task(GetItemFromPathAsync(path)).then([path](concurrency::task item) { + try + { + T^ storageItem = item.get(); + return concurrency::create_task(concurrency::create_async([storageItem]() { return storageItem; })); + } + catch (Platform::AccessDeniedException^ e) + { + Windows::UI::Popups::MessageDialog^ dialog = + ref new Windows::UI::Popups::MessageDialog("Path \"" + path + "\" is not currently accessible. Please open any containing directory to access it."); + dialog->Commands->Append(ref new Windows::UI::Popups::UICommand("Open file picker")); + dialog->Commands->Append(ref new Windows::UI::Popups::UICommand("Cancel")); + return concurrency::create_task(dialog->ShowAsync()).then([path](Windows::UI::Popups::IUICommand^ cmd) { + if (cmd->Label == "Open file picker") + { + return TriggerPickerAddDialog().then([path](Platform::String^ added_path) { + /* Retry */ + return LocateStorageItem(path); + }); + } + else + { + throw ref new Platform::Exception(E_ABORT, L"Operation cancelled by user"); + } + }); + } + }); + } + + IStorageItem^ LocateStorageFileOrFolder(Platform::String^ path) + { + if (!path || path->IsEmpty()) + return nullptr; + + if (*(path->End() - 1) == '\\') + { + /* Ends with a slash, so it's definitely a directory */ + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(LocateStorageItem(path)); + }, nullptr); + } + else + { + /* No final slash - probably a file (since RetroArch usually slash-terminates dirs), but there is still a chance it's a directory */ + IStorageItem^ item; + item = RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(LocateStorageItem(path)); + }, nullptr); + if (!item) + { + item = RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(LocateStorageItem(path)); + }, nullptr); + } + return item; + } + } +} + #ifdef VFS_FRONTEND struct retro_vfs_file_handle #else @@ -160,7 +307,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns retro_assert(!dirpath_str->IsEmpty() && !filename_str->IsEmpty()); return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(dirpath_str)).then([&](StorageFolder^ dir) { + return concurrency::create_task(LocateStorageItem(dirpath_str)).then([&](StorageFolder^ dir) { if (mode == RETRO_VFS_FILE_ACCESS_READ) return dir->GetFileAsync(filename_str); else @@ -361,7 +508,7 @@ int retro_vfs_file_remove_impl(const char *path) free(path_wide); return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(StorageFile::GetFileFromPathAsync(path_str)).then([&](StorageFile^ file) { + return concurrency::create_task(LocateStorageItem(path_str)).then([&](StorageFile^ file) { return file->DeleteAsync(StorageDeleteOption::PermanentDelete); }).then([&]() { return 0; @@ -397,8 +544,8 @@ int retro_vfs_file_rename_impl(const char *old_path, const char *new_path) retro_assert(!old_path_str->IsEmpty() && !new_dir_path_str->IsEmpty() && !new_file_name_str->IsEmpty()); return RunAsyncAndCatchErrors([&]() { - concurrency::task old_file_task = concurrency::create_task(StorageFile::GetFileFromPathAsync(old_path_str)); - concurrency::task new_dir_task = concurrency::create_task(StorageFolder::GetFolderFromPathAsync(new_dir_path_str)); + concurrency::task old_file_task = concurrency::create_task(LocateStorageItem(old_path_str)); + concurrency::task new_dir_task = concurrency::create_task(LocateStorageItem(new_dir_path_str)); return concurrency::create_task([&] { /* Run these two tasks in parallel */ /* TODO: There may be some cleaner way to express this */ @@ -422,37 +569,6 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea return stream->orig_path; } - -/* This is ugly, but I can't figure out a better way and there may be no better way... */ -static IStorageItem^ GetFileOrFolderFromPath(Platform::String^ path) -{ - if (!path || path->IsEmpty()) - return nullptr; - - if (*(path->End() - 1) == '\\') - { - /* Ends with a slash, so it's definitely a directory */ - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path)); - }, nullptr); - } - else - { - /* No final slash - probably a file (since RetroArch usually slash-terminates dirs), but there is a chance it's a directory */ - IStorageItem^ item; - item = RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(StorageFile::GetFileFromPathAsync(path)); - }, nullptr); - if (!item) - { - item = RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path)); - }, nullptr); - } - return item; - } -} - int retro_vfs_stat_impl(const char *path, int32_t *size) { if (!path || !*path) @@ -463,7 +579,7 @@ int retro_vfs_stat_impl(const char *path, int32_t *size) Platform::String^ path_str = ref new Platform::String(path_wide); free(path_wide); - IStorageItem^ item = GetFileOrFolderFromPath(path_str); + IStorageItem^ item = LocateStorageFileOrFolder(path_str); if (!item) return 0; @@ -507,7 +623,7 @@ int retro_vfs_mkdir_impl(const char *dir) free(dir_local); return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(parent_path_str)).then([&](StorageFolder^ parent) { + return concurrency::create_task(LocateStorageItem(parent_path_str)).then([&](StorageFolder^ parent) { return parent->CreateFolderAsync(dir_name_str); }).then([&](concurrency::task new_dir) { try @@ -553,7 +669,7 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i free(name_wide); rdir->directory = RunAsyncAndCatchErrors^>([&]() { - return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(name_str)).then([&](StorageFolder^ folder) { + return concurrency::create_task(LocateStorageItem(name_str)).then([&](StorageFolder^ folder) { return folder->GetItemsAsync(); }); }, nullptr); @@ -615,3 +731,28 @@ bool uwp_is_path_accessible_using_standard_io(char *path) free(relative_path_abbrev); return result; } + +bool uwp_drive_exists(const char *path) +{ + if (!path || !*path) + return 0; + + wchar_t *path_wide = utf8_to_utf16_string_alloc(path); + Platform::String^ path_str = ref new Platform::String(path_wide); + free(path_wide); + + return RunAsyncAndCatchErrors([&]() { + return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path_str)).then([](StorageFolder^ properties) { + return true; + }); + }, false); +} + +char* uwp_trigger_picker(void) +{ + return RunAsyncAndCatchErrors([&]() { + return TriggerPickerAddDialog().then([](Platform::String^ path) { + return utf16_to_utf8_string_alloc(path->Data()); + }); + }, NULL); +} diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 22a3358bc7..8fb64ca3fe 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -3980,6 +3980,28 @@ static int action_ok_open_uwp_permission_settings(const char *path, return 0; } +static int action_ok_open_picker(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ + char* new_path; + int ret; +#ifdef __WINRT__ + new_path = uwp_trigger_picker(); + if (!new_path) + return 0; /* User aborted */ +#else + retro_assert(false); +#endif + + ret = generic_action_ok_displaylist_push(path, new_path, + msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES), + type, idx, + entry_idx, ACTION_OK_DL_CONTENT_LIST); + + free(new_path); + return ret; +} + static int action_ok_shader_pass(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { @@ -5483,6 +5505,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS: BIND_ACTION_OK(cbs, action_ok_open_uwp_permission_settings); break; + case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_PICKER: + BIND_ACTION_OK(cbs, action_ok_open_picker); + break; case MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS: BIND_ACTION_OK(cbs, action_ok_retro_achievements_list); break; diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 8d0c9d76e7..520edfe59b 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -335,6 +335,7 @@ default_sublabel_macro(action_bind_sublabel_goto_music, default_sublabel_macro(action_bind_sublabel_goto_video, MENU_ENUM_SUBLABEL_GOTO_VIDEO) default_sublabel_macro(action_bind_sublabel_menu_filebrowser_settings, MENU_ENUM_SUBLABEL_MENU_FILE_BROWSER_SETTINGS) default_sublabel_macro(action_bind_sublabel_menu_filebrowser_open_uwp_permissions, MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS) +default_sublabel_macro(action_bind_sublabel_menu_filebrowser_open_picker, MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_PICKER) default_sublabel_macro(action_bind_sublabel_auto_remaps_enable, MENU_ENUM_SUBLABEL_AUTO_REMAPS_ENABLE) default_sublabel_macro(action_bind_sublabel_auto_overrides_enable, MENU_ENUM_SUBLABEL_AUTO_OVERRIDES_ENABLE) default_sublabel_macro(action_bind_sublabel_game_specific_options, MENU_ENUM_SUBLABEL_GAME_SPECIFIC_OPTIONS) @@ -1383,6 +1384,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_filebrowser_open_uwp_permissions); break; + case MENU_ENUM_LABEL_FILE_BROWSER_OPEN_PICKER: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_filebrowser_open_picker); + break; case MENU_ENUM_LABEL_ADD_TO_FAVORITES: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_add_to_favorites); break; diff --git a/msg_hash.h b/msg_hash.h index 7f87dfba60..a73ada2a02 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -825,6 +825,7 @@ enum msg_hash_enums MENU_LABEL(PARENT_DIRECTORY), MENU_LABEL(FILE_BROWSER_OPEN_UWP_PERMISSIONS), + MENU_LABEL(FILE_BROWSER_OPEN_PICKER), MENU_ENUM_LABEL_CONTENT_ACTIONS, diff --git a/uwp/uwp_func.h b/uwp/uwp_func.h index d137909c04..a48382fbe6 100644 --- a/uwp/uwp_func.h +++ b/uwp/uwp_func.h @@ -28,6 +28,8 @@ extern char uwp_device_family[128]; void uwp_open_broadfilesystemaccess_settings(void); bool uwp_is_path_accessible_using_standard_io(char *path); +bool uwp_drive_exists(const char *path); +char* uwp_trigger_picker(void); void* uwp_get_corewindow(void); From 4461d329003f4a1060b149394abdae677267cf29 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Wed, 16 Jan 2019 23:54:12 +0100 Subject: [PATCH 014/234] (UWP) Fallback to a file copy when core doesn't support VFS --- intl/msg_hash_us.h | 2 +- tasks/task_content.c | 84 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 0a39e2c700..3599f9d964 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -4153,7 +4153,7 @@ MSG_HASH( ) MSG_HASH( MSG_ERROR_LIBRETRO_CORE_REQUIRES_VFS, - "Loading content from here requires VFS, but core does not support it" + "Core does not support VFS, and loading from a local copy failed" ) MSG_HASH( MSG_ERROR_PARSING_ARGUMENTS, diff --git a/tasks/task_content.c b/tasks/task_content.c index dee66b7cd8..22619d41f5 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -562,6 +562,7 @@ static bool content_file_load( size_t msg_size = 1024 * sizeof(char); char *msg = (char*)malloc(msg_size); rarch_system_info_t *system = runloop_get_system_info(); + bool used_vfs_fallback_copy = false; msg[0] = '\0'; @@ -626,12 +627,71 @@ static bool content_file_load( /* TODO: When support for the 'actual' VFS is added, there will need to be some more logic here */ if (!system->supports_vfs && !uwp_is_path_accessible_using_standard_io(path)) { - strlcpy(msg, - msg_hash_to_str(MSG_ERROR_LIBRETRO_CORE_REQUIRES_VFS), - msg_size - ); - *error_string = strdup(msg); - goto error; + /* Fallback to a file copy into an accessible directory */ + + union string_list_elem_attr attributes; + size_t new_basedir_size = PATH_MAX_LENGTH * sizeof(char); + size_t new_path_size = PATH_MAX_LENGTH * sizeof(char); + char *new_basedir = (char*)malloc(new_basedir_size); + char *new_path = (char*)malloc(new_path_size); + char* buf; + int64_t len; + + new_path[0] = '\0'; + new_basedir[0] = '\0'; + attributes.i = 0; + + RARCH_LOG("Core does not support VFS - copying to cache directory\n"); + + if (!string_is_empty(content_ctx->directory_cache)) + strlcpy(new_basedir, content_ctx->directory_cache, new_basedir_size); + if (string_is_empty(new_basedir) || !path_is_directory(new_basedir) || !uwp_is_path_accessible_using_standard_io(new_basedir)) + { + RARCH_WARN("Tried copying to cache directory, but " + "cache directory was not set or found. " + "Setting cache directory to root of " + "writable app directory...\n"); + strlcpy(new_basedir, uwp_dir_data, new_basedir_size); + } + + fill_pathname_join(new_path, new_basedir, + path_basename(path), new_path_size); + + /* TODO: This may fail on very large files... but copying large files is not a good idea anyway */ + if (!filestream_read_file(path, &buf, &len)) + { + snprintf(msg, + msg_size, + "%s \"%s\". (during copy read)\n", + msg_hash_to_str(MSG_COULD_NOT_READ_CONTENT_FILE), + path); + *error_string = strdup(msg); + goto error; + } + if (!filestream_write_file(new_path, buf, len)) + { + free(buf); + snprintf(msg, + msg_size, + "%s \"%s\". (during copy write)\n", + msg_hash_to_str(MSG_COULD_NOT_READ_CONTENT_FILE), + path); + *error_string = strdup(msg); + goto error; + } + free(buf); + + string_list_append(additional_path_allocs, new_path, attributes); + info[i].path = + additional_path_allocs->elems[additional_path_allocs->size - 1].data; + + string_list_append(content_ctx->temporary_content, + new_path, attributes); + + free(new_basedir); + free(new_path); + + used_vfs_fallback_copy = true; } #endif @@ -649,9 +709,19 @@ static bool content_file_load( if (!core_load_game(&load_info)) { - snprintf(msg, + if (used_vfs_fallback_copy) + { + /* This is probably going to fail on multifile ROMs etc. so give a visible explanation of what is likely wrong */ + snprintf(msg, + msg_size, + "%s.", msg_hash_to_str(MSG_ERROR_LIBRETRO_CORE_REQUIRES_VFS)); + } + else + { + snprintf(msg, msg_size, "%s.", msg_hash_to_str(MSG_FAILED_TO_LOAD_CONTENT)); + } *error_string = strdup(msg); goto error; } From 4b859fd09713a5ea6d3b85ace7516f70f414e5d7 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Fri, 18 Jan 2019 16:15:05 +0000 Subject: [PATCH 015/234] (RGUI) Add rudimentary playlist thumbnail support --- menu/cbs/menu_cbs_scan.c | 12 +- menu/drivers/rgui.c | 819 +++++++++++++++++++++++++++++++-------- menu/menu_setting.c | 5 +- 3 files changed, 665 insertions(+), 171 deletions(-) diff --git a/menu/cbs/menu_cbs_scan.c b/menu/cbs/menu_cbs_scan.c index 150f226fa3..6f1490a90e 100644 --- a/menu/cbs/menu_cbs_scan.c +++ b/menu/cbs/menu_cbs_scan.c @@ -118,9 +118,15 @@ int action_switch_thumbnail(const char *path, } else { - settings->uints.menu_thumbnails++; - if (settings->uints.menu_thumbnails > 3) - settings->uints.menu_thumbnails = 1; + /* RGUI is a special case where thumbnail 'switch' corresponds to + * toggling thumbnail view on/off. For other menu drivers, we + * cycle through available thumbnail types. */ + if(!string_is_equal(settings->arrays.menu_driver, "rgui")) + { + settings->uints.menu_thumbnails++; + if (settings->uints.menu_thumbnails > 3) + settings->uints.menu_thumbnails = 1; + } menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); } diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 48cb9d0e00..580c8ee9d5 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -48,6 +48,13 @@ #include "../../configuration.h" #include "../../gfx/drivers_font_renderer/bitmap.h" +/* Thumbnail additions */ +#include +#if defined(HAVE_RPNG) +#include +#include +#endif + #define RGUI_TERM_START_X(width) (width / 21) #define RGUI_TERM_START_Y(height) (height / 9) #define RGUI_TERM_WIDTH(width) (((width - RGUI_TERM_START_X(width) - RGUI_TERM_START_X(width)) / (FONT_WIDTH_STRIDE))) @@ -409,8 +416,33 @@ typedef struct char *msgbox; unsigned color_theme; rgui_colors_t colors; + bool is_playlist_entry; + bool show_thumbnail; + char *thumbnail_system; + char *thumbnail_content; + char *thumbnail_path; } rgui_t; +#define THUMB_MAX_WIDTH 320 +#define THUMB_MAX_HEIGHT 240 + +typedef struct +{ + unsigned width; + unsigned height; + bool is_valid; + char *path; + uint16_t data[THUMB_MAX_WIDTH * THUMB_MAX_HEIGHT]; +} thumbnail_t; + +static thumbnail_t thumbnail = { + 0, + 0, + false, + NULL, + {0} +}; + static uint16_t *rgui_framebuf_data = NULL; #if defined(PS2) @@ -422,21 +454,24 @@ static uint16_t argb32_to_abgr1555(uint32_t col) unsigned r = (col >> 16) & 0xff; unsigned g = (col >> 8) & 0xff; unsigned b = col & 0xff; - /* Background and border colours are normally semi-transparent - * (so we can see suspended content when opening the quick menu). - * When no content is loaded, the 'image' behind the RGUI background - * and border is black - which has the effect of darkening the - * perceived background/border colours. All the preset theme (and - * default 'custom') colour values have been adjusted to account for - * this, but abgr1555 only has a 1 bit alpha channel. This means all - * colours become fully opaque, and consequently backgrounds/borders - * become abnormally bright. - * We therefore have to darken each RGB value according to the alpha - * component of the input colour... */ - float a_factor = (float)a * (1.0 / 255.0); - r = (unsigned)(((float)r * a_factor) + 0.5) & 0xff; - g = (unsigned)(((float)g * a_factor) + 0.5) & 0xff; - b = (unsigned)(((float)b * a_factor) + 0.5) & 0xff; + if (a < 0xff) + { + /* Background and border colours are normally semi-transparent + * (so we can see suspended content when opening the quick menu). + * When no content is loaded, the 'image' behind the RGUI background + * and border is black - which has the effect of darkening the + * perceived background/border colours. All the preset theme (and + * default 'custom') colour values have been adjusted to account for + * this, but abgr1555 only has a 1 bit alpha channel. This means all + * colours become fully opaque, and consequently backgrounds/borders + * become abnormally bright. + * We therefore have to darken each RGB value according to the alpha + * component of the input colour... */ + float a_factor = (float)a * (1.0 / 255.0); + r = (unsigned)(((float)r * a_factor) + 0.5) & 0xff; + g = (unsigned)(((float)g * a_factor) + 0.5) & 0xff; + b = (unsigned)(((float)b * a_factor) + 0.5) & 0xff; + } /* Convert from 8 bit to 5 bit */ r = r >> 3; g = g >> 3; @@ -456,30 +491,33 @@ static uint16_t argb32_to_rgb5a3(uint32_t col) unsigned r = (col >> 16) & 0xff; unsigned g = (col >> 8) & 0xff; unsigned b = col & 0xff; - /* Gekko platforms only have a 3 bit alpha channel, which - * is one bit less than all 'standard' target platforms. - * As a result, Gekko colours are effectively ~6-7% less - * transparent than expected, which causes backgrounds and - * borders to appear too bright. We therefore have to darken - * each RGB component according to the difference between Gekko - * alpha and normal 4 bit alpha values... */ - unsigned a4 = a >> 4; unsigned a3 = a >> 5; - float a_factor = 1.0; - if (a3 > 0) + if (a < 0xff) { - /* Avoid divide by zero errors... */ - a_factor = ((float)a4 * (1.0 / 15.0)) / ((float)a3 * (1.0 / 7.0)); + /* Gekko platforms only have a 3 bit alpha channel, which + * is one bit less than all 'standard' target platforms. + * As a result, Gekko colours are effectively ~6-7% less + * transparent than expected, which causes backgrounds and + * borders to appear too bright. We therefore have to darken + * each RGB component according to the difference between Gekko + * alpha and normal 4 bit alpha values... */ + unsigned a4 = a >> 4; + float a_factor = 1.0; + if (a3 > 0) + { + /* Avoid divide by zero errors... */ + a_factor = ((float)a4 * (1.0 / 15.0)) / ((float)a3 * (1.0 / 7.0)); + } + r = (unsigned)(((float)r * a_factor) + 0.5); + g = (unsigned)(((float)g * a_factor) + 0.5); + b = (unsigned)(((float)b * a_factor) + 0.5); + /* a_factor can actually be greater than 1. This will never happen + * with the current preset theme colour values, but users can set + * any custom values they like, so we have to play it safe... */ + r = (r <= 0xff) ? r : 0xff; + g = (g <= 0xff) ? g : 0xff; + b = (b <= 0xff) ? b : 0xff; } - r = (unsigned)(((float)r * a_factor) + 0.5); - g = (unsigned)(((float)g * a_factor) + 0.5); - b = (unsigned)(((float)b * a_factor) + 0.5); - /* a_factor can actually be greater than 1. This will never happen - * with the current preset theme colour values, but users can set - * any custom values they like, so we have to play it safe... */ - r = (r <= 0xff) ? r : 0xff; - g = (g <= 0xff) ? g : 0xff; - b = (b <= 0xff) ? b : 0xff; /* Convert RGB from 8 bit to 4 bit */ r = r >> 4; g = g >> 4; @@ -518,6 +556,200 @@ static uint16_t argb32_to_rgba4444(uint32_t col) #endif +/* From rpng_test.c */ +static bool rpng_load_image_argb(const char *path, uint32_t **data, + unsigned *width, unsigned *height) +{ + /* Check for RPNG support... + * > This seems to be the cleanest place to do it - saves having + * to litter the code with '#if defined(HAVE_RPNG)' all over the + * place... */ +#if defined(HAVE_RPNG) + int retval; + size_t file_len; + bool ret = true; + rpng_t *rpng = NULL; + void *ptr = NULL; + struct nbio_t* handle = (struct nbio_t*)nbio_open(path, NBIO_READ); + + if (!handle) + goto end; + + nbio_begin_read(handle); + + while (!nbio_iterate(handle)); + + ptr = nbio_get_ptr(handle, &file_len); + + if (!ptr) + { + ret = false; + goto end; + } + + rpng = rpng_alloc(); + + if (!rpng) + { + ret = false; + goto end; + } + + if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) + { + ret = false; + goto end; + } + + if (!rpng_start(rpng)) + { + ret = false; + goto end; + } + + while (rpng_iterate_image(rpng)); + + if (!rpng_is_valid(rpng)) + { + ret = false; + goto end; + } + + do + { + retval = rpng_process_image(rpng, + (void**)data, file_len, width, height); + }while(retval == IMAGE_PROCESS_NEXT); + + if (retval == IMAGE_PROCESS_ERROR || retval == IMAGE_PROCESS_ERROR_END) + ret = false; + +end: + if (handle) + nbio_free(handle); + if (rpng) + rpng_free(rpng); + rpng = NULL; + if (!ret) + free(*data); + return ret; +#else + return false; +#endif +} + +static void load_thumbnail(const char *path) +{ + unsigned width, height; + uint32_t *png_data = NULL; + unsigned x, y, index; + unsigned x_offset, y_offset; + + /* Do nothing if current thumbnail path hasn't changed */ + if (!string_is_empty(thumbnail.path) && !string_is_empty(thumbnail.path)) + { + if (string_is_equal(thumbnail.path, path)) { + return; + } + } + + /* 'Reset' current thumbnail */ + thumbnail.width = 0; + thumbnail.height = 0; + thumbnail.is_valid = false; + free(thumbnail.path); + thumbnail.path = NULL; + + /* Ensure that new path is valid... */ + if (!string_is_empty(path)) + { + thumbnail.path = strdup(path); + if (filestream_exists(path)) + { + /* Load image */ + if (rpng_load_image_argb(path, &png_data, &width, &height)) + { + /* Have to crop image if larger than max allowed size... */ + if (width > THUMB_MAX_WIDTH) { + x_offset = (width - THUMB_MAX_WIDTH) >> 1; + thumbnail.width = THUMB_MAX_WIDTH; + } else { + x_offset = 0; + thumbnail.width = width; + } + if (height > THUMB_MAX_HEIGHT) { + y_offset = (height - THUMB_MAX_HEIGHT) >> 1; + thumbnail.height = THUMB_MAX_HEIGHT; + } else { + y_offset = 0; + thumbnail.height = height; + } + + /* Copy (cropped) image to thumbnail buffer, performing + * pixel format conversion */ + for (x = 0; x < thumbnail.width; x++) { + for (y = 0; y < thumbnail.height; y++) { + thumbnail.data[x + (y * thumbnail.width)] = + argb32_to_pixel_platform_format(png_data[(x + x_offset) + ((y + y_offset) * width)]); + } + } + + thumbnail.is_valid = true; + + free(png_data); + png_data = NULL; + } + } + } +} + +static void rgui_render_thumbnail(void) +{ + size_t fb_pitch; + unsigned fb_width, fb_height; + unsigned x, y; + unsigned fb_x_offset, fb_y_offset; + unsigned thumb_x_offset, thumb_y_offset; + unsigned width, height; + + if (thumbnail.is_valid && rgui_framebuf_data) + { + menu_display_get_fb_size(&fb_width, &fb_height, &fb_pitch); + + /* Ensure that thumbnail is centred + * > Have to perform some stupid tests here because we + * cannot assume fb_width and fb_height are constant and + * >= thumbnail.width and thumbnail.height (even though + * they are...) */ + if (thumbnail.width <= fb_width) { + thumb_x_offset = 0; + fb_x_offset = (fb_width - thumbnail.width) >> 1; + width = thumbnail.width; + } else { + thumb_x_offset = (thumbnail.width - fb_width) >> 1; + fb_x_offset = 0; + width = fb_width; + } + if (thumbnail.height <= fb_height) { + thumb_y_offset = 0; + fb_y_offset = (fb_height - thumbnail.height) >> 1; + height = thumbnail.height; + } else { + thumb_y_offset = (thumbnail.height - fb_height) >> 1; + fb_y_offset = 0; + height = fb_height; + } + + /* Copy thumbnail to framebuffer */ + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + rgui_framebuf_data[(y + fb_y_offset) * (fb_pitch >> 1) + (x + fb_x_offset)] = + thumbnail.data[(x + thumb_x_offset) + ((y + thumb_y_offset) * thumbnail.width)]; + } + } + } +} + static const rgui_theme_t *get_theme(rgui_t *rgui) { switch (rgui->color_theme) @@ -796,16 +1028,20 @@ static void rgui_render_background(rgui_t *rgui) dst += pitch_in_pixels * 4; } - if (rgui_framebuf_data) + /* Skip drawing border if we are currently showing a thumbnail */ + if (!rgui->show_thumbnail || !rgui->is_playlist_entry || !thumbnail.is_valid) { - settings_t *settings = config_get_ptr(); - - if (settings->bools.menu_rgui_border_filler_enable) + if (rgui_framebuf_data) { - rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, 5, fb_width - 10, 5, rgui_border_filler); - rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, fb_height - 10, fb_width - 10, 5, rgui_border_filler); - rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, 5, 5, fb_height - 10, rgui_border_filler); - rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, fb_width - 10, 5, 5, fb_height - 10, rgui_border_filler); + settings_t *settings = config_get_ptr(); + + if (settings->bools.menu_rgui_border_filler_enable) + { + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, 5, fb_width - 10, 5, rgui_border_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, fb_height - 10, fb_width - 10, 5, rgui_border_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, 5, 5, fb_height - 10, rgui_border_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, fb_width - 10, 5, 5, fb_height - 10, rgui_border_filler); + } } } } @@ -1052,139 +1288,174 @@ static void rgui_render(void *data, bool is_idle) rgui_render_background(rgui); - menu_entries_get_title(title, sizeof(title)); - - ticker.s = title_buf; - ticker.len = RGUI_TERM_WIDTH(fb_width) - 10; - ticker.idx = frame_count / RGUI_TERM_START_X(fb_width); - ticker.str = title; - ticker.selected = true; - - menu_animation_ticker(&ticker); - - if (menu_entries_ctl(MENU_ENTRIES_CTL_SHOW_BACK, NULL)) + if (rgui->show_thumbnail && rgui->is_playlist_entry && thumbnail.is_valid) { - char back_buf[32]; - char back_msg[32]; - - back_buf[0] = back_msg[0] = '\0'; - - strlcpy(back_buf, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_BACK), sizeof(back_buf)); - string_to_upper(back_buf); - if (rgui_framebuf_data) - blit_line( - RGUI_TERM_START_X(fb_width), - RGUI_TERM_START_X(fb_width), - back_msg, - rgui->colors.title_color); - } - - string_to_upper(title_buf); - - if (rgui_framebuf_data) - blit_line( - (int)(RGUI_TERM_START_X(fb_width) + (RGUI_TERM_WIDTH(fb_width) - - utf8len(title_buf)) * FONT_WIDTH_STRIDE / 2), - RGUI_TERM_START_X(fb_width), - title_buf, rgui->colors.title_color); - - if (settings->bools.menu_core_enable && - menu_entries_get_core_title(title_msg, sizeof(title_msg)) == 0) - { - if (rgui_framebuf_data) - blit_line( - RGUI_TERM_START_X(fb_width), - (RGUI_TERM_HEIGHT(fb_width, fb_height) * FONT_HEIGHT_STRIDE) + - RGUI_TERM_START_Y(fb_height) + 2, title_msg, rgui->colors.hover_color); - } - - if (settings->bools.menu_timedate_enable) - { - menu_display_ctx_datetime_t datetime; - char timedate[255]; - - timedate[0] = '\0'; - - datetime.s = timedate; - datetime.len = sizeof(timedate); - datetime.time_mode = 4; - - menu_display_timedate(&datetime); - - if (rgui_framebuf_data) - blit_line( - RGUI_TERM_WIDTH(fb_width) * FONT_WIDTH_STRIDE - RGUI_TERM_START_X(fb_width), - (RGUI_TERM_HEIGHT(fb_width, fb_height) * FONT_HEIGHT_STRIDE) + - RGUI_TERM_START_Y(fb_height) + 2, timedate, rgui->colors.hover_color); - } - - x = RGUI_TERM_START_X(fb_width); - y = RGUI_TERM_START_Y(fb_height); - - menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i); - - for (; i < end; i++, y += FONT_HEIGHT_STRIDE) - { - menu_entry_t entry; menu_animation_ctx_ticker_t ticker; - char entry_value[255]; - char message[255]; - char entry_title_buf[255]; - char type_str_buf[255]; - char *entry_path = NULL; - unsigned entry_spacing = 0; - size_t entry_title_buf_utf8len = 0; - size_t entry_title_buf_len = 0; - bool entry_selected = menu_entry_is_currently_selected((unsigned)i); - size_t selection = menu_navigation_get_selection(); - - if (i > (selection + 100)) - continue; - - entry_value[0] = '\0'; - message[0] = '\0'; - entry_title_buf[0] = '\0'; - type_str_buf[0] = '\0'; - - menu_entry_init(&entry); - menu_entry_get(&entry, 0, (unsigned)i, NULL, true); - - entry_spacing = menu_entry_get_spacing(&entry); - menu_entry_get_value(&entry, entry_value, sizeof(entry_value)); - entry_path = menu_entry_get_rich_label(&entry); - - ticker.s = entry_title_buf; - ticker.len = RGUI_TERM_WIDTH(fb_width) - (entry_spacing + 1 + 2); + char thumbnail_title_buf[255]; + unsigned title_x, title_width; + thumbnail_title_buf[0] = '\0'; + + /* Draw thumbnail */ + rgui_render_thumbnail(); + + /* Format thumbnail title */ + ticker.s = thumbnail_title_buf; + ticker.len = RGUI_TERM_WIDTH(fb_width) - 10; ticker.idx = frame_count / RGUI_TERM_START_X(fb_width); - ticker.str = entry_path; - ticker.selected = entry_selected; + ticker.str = rgui->thumbnail_content; + ticker.selected = true; + menu_animation_ticker(&ticker); + + title_width = utf8len(thumbnail_title_buf) * FONT_WIDTH_STRIDE; + title_x = RGUI_TERM_START_X(fb_width) + ((RGUI_TERM_WIDTH(fb_width) * FONT_WIDTH_STRIDE) - title_width) / 2; + + if (rgui_framebuf_data) + { + /* Draw thumbnail title background */ + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, + title_x - 5, 0, title_width + 10, FONT_HEIGHT_STRIDE, rgui_bg_filler); + + /* Draw thumbnail title */ + blit_line((int)title_x, 0, thumbnail_title_buf, rgui->colors.hover_color); + } + } + else + { + /* No thumbnail - render usual text */ + menu_entries_get_title(title, sizeof(title)); + + ticker.s = title_buf; + ticker.len = RGUI_TERM_WIDTH(fb_width) - 10; + ticker.idx = frame_count / RGUI_TERM_START_X(fb_width); + ticker.str = title; + ticker.selected = true; menu_animation_ticker(&ticker); - ticker.s = type_str_buf; - ticker.len = entry_spacing; - ticker.str = entry_value; + if (menu_entries_ctl(MENU_ENTRIES_CTL_SHOW_BACK, NULL)) + { + char back_buf[32]; + char back_msg[32]; - menu_animation_ticker(&ticker); + back_buf[0] = back_msg[0] = '\0'; - entry_title_buf_utf8len = utf8len(entry_title_buf); - entry_title_buf_len = strlen(entry_title_buf); + strlcpy(back_buf, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_BACK), sizeof(back_buf)); + string_to_upper(back_buf); + if (rgui_framebuf_data) + blit_line( + RGUI_TERM_START_X(fb_width), + RGUI_TERM_START_X(fb_width), + back_msg, + rgui->colors.title_color); + } - snprintf(message, sizeof(message), "%c %-*.*s %-.*s", - entry_selected ? '>' : ' ', - (int)(RGUI_TERM_WIDTH(fb_width) - (entry_spacing + 1 + 2) - entry_title_buf_utf8len + entry_title_buf_len), - (int)(RGUI_TERM_WIDTH(fb_width) - (entry_spacing + 1 + 2) - entry_title_buf_utf8len + entry_title_buf_len), - entry_title_buf, - entry_spacing, - type_str_buf); + string_to_upper(title_buf); if (rgui_framebuf_data) - blit_line(x, y, message, - entry_selected ? rgui->colors.hover_color : rgui->colors.normal_color); + blit_line( + (int)(RGUI_TERM_START_X(fb_width) + (RGUI_TERM_WIDTH(fb_width) + - utf8len(title_buf)) * FONT_WIDTH_STRIDE / 2), + RGUI_TERM_START_X(fb_width), + title_buf, rgui->colors.title_color); - menu_entry_free(&entry); - if (!string_is_empty(entry_path)) - free(entry_path); + if (settings->bools.menu_core_enable && + menu_entries_get_core_title(title_msg, sizeof(title_msg)) == 0) + { + if (rgui_framebuf_data) + blit_line( + RGUI_TERM_START_X(fb_width), + (RGUI_TERM_HEIGHT(fb_width, fb_height) * FONT_HEIGHT_STRIDE) + + RGUI_TERM_START_Y(fb_height) + 2, title_msg, rgui->colors.hover_color); + } + + if (settings->bools.menu_timedate_enable) + { + menu_display_ctx_datetime_t datetime; + char timedate[255]; + + timedate[0] = '\0'; + + datetime.s = timedate; + datetime.len = sizeof(timedate); + datetime.time_mode = 4; + + menu_display_timedate(&datetime); + + if (rgui_framebuf_data) + blit_line( + RGUI_TERM_WIDTH(fb_width) * FONT_WIDTH_STRIDE - RGUI_TERM_START_X(fb_width), + (RGUI_TERM_HEIGHT(fb_width, fb_height) * FONT_HEIGHT_STRIDE) + + RGUI_TERM_START_Y(fb_height) + 2, timedate, rgui->colors.hover_color); + } + + x = RGUI_TERM_START_X(fb_width); + y = RGUI_TERM_START_Y(fb_height); + + menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i); + + for (; i < end; i++, y += FONT_HEIGHT_STRIDE) + { + menu_entry_t entry; + menu_animation_ctx_ticker_t ticker; + char entry_value[255]; + char message[255]; + char entry_title_buf[255]; + char type_str_buf[255]; + char *entry_path = NULL; + unsigned entry_spacing = 0; + size_t entry_title_buf_utf8len = 0; + size_t entry_title_buf_len = 0; + bool entry_selected = menu_entry_is_currently_selected((unsigned)i); + size_t selection = menu_navigation_get_selection(); + + if (i > (selection + 100)) + continue; + + entry_value[0] = '\0'; + message[0] = '\0'; + entry_title_buf[0] = '\0'; + type_str_buf[0] = '\0'; + + menu_entry_init(&entry); + menu_entry_get(&entry, 0, (unsigned)i, NULL, true); + + entry_spacing = menu_entry_get_spacing(&entry); + menu_entry_get_value(&entry, entry_value, sizeof(entry_value)); + entry_path = menu_entry_get_rich_label(&entry); + + ticker.s = entry_title_buf; + ticker.len = RGUI_TERM_WIDTH(fb_width) - (entry_spacing + 1 + 2); + ticker.idx = frame_count / RGUI_TERM_START_X(fb_width); + ticker.str = entry_path; + ticker.selected = entry_selected; + + menu_animation_ticker(&ticker); + + ticker.s = type_str_buf; + ticker.len = entry_spacing; + ticker.str = entry_value; + + menu_animation_ticker(&ticker); + + entry_title_buf_utf8len = utf8len(entry_title_buf); + entry_title_buf_len = strlen(entry_title_buf); + + snprintf(message, sizeof(message), "%c %-*.*s %-.*s", + entry_selected ? '>' : ' ', + (int)(RGUI_TERM_WIDTH(fb_width) - (entry_spacing + 1 + 2) - entry_title_buf_utf8len + entry_title_buf_len), + (int)(RGUI_TERM_WIDTH(fb_width) - (entry_spacing + 1 + 2) - entry_title_buf_utf8len + entry_title_buf_len), + entry_title_buf, + entry_spacing, + type_str_buf); + + if (rgui_framebuf_data) + blit_line(x, y, message, + entry_selected ? rgui->colors.hover_color : rgui->colors.normal_color); + + menu_entry_free(&entry); + if (!string_is_empty(entry_path)) + free(entry_path); + } } if (menu_input_dialog_get_display_kb()) @@ -1276,6 +1547,9 @@ static void *rgui_init(void **userdata, bool video_is_threaded) rgui->last_width = fb_width; rgui->last_height = fb_height; + /* Ensure that we start with thumbnails disabled */ + rgui->show_thumbnail = false; + return menu; error: @@ -1289,6 +1563,17 @@ static void rgui_free(void *data) { const uint8_t *font_fb; bool fb_font_inited = false; + rgui_t *rgui = (rgui_t*)data; + + if (rgui) + { + if (!string_is_empty(rgui->thumbnail_system)) + free(rgui->thumbnail_system); + if (!string_is_empty(rgui->thumbnail_content)) + free(rgui->thumbnail_content); + if (!string_is_empty(rgui->thumbnail_path)) + free(rgui->thumbnail_path); + } fb_font_inited = menu_display_get_font_data_init(); font_fb = menu_display_get_font_framebuffer(); @@ -1298,6 +1583,11 @@ static void rgui_free(void *data) fb_font_inited = false; menu_display_set_font_data_init(fb_font_inited); + + rgui_framebuffer_free(); + + if (!string_is_empty(thumbnail.path)) + free(thumbnail.path); } static void rgui_set_texture(void) @@ -1329,6 +1619,187 @@ static void rgui_navigation_clear(void *data, bool pending_push) rgui->scroll_y = 0; } +static const char *rgui_thumbnail_ident() +{ + char folder = 0; + settings_t *settings = config_get_ptr(); + + folder = settings->uints.menu_thumbnails; + + switch (folder) + { + case 1: + return "Named_Snaps"; + case 2: + return "Named_Titles"; + case 3: + return "Named_Boxarts"; + case 0: + default: + break; + } + + return msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF); +} + +static void rgui_update_thumbnail_path(void *userdata) +{ + rgui_t *rgui = (rgui_t*)userdata; + settings_t *settings = config_get_ptr(); + char new_path[PATH_MAX_LENGTH] = {0}; + const char *thumbnail_base_dir = settings->paths.directory_thumbnails; + const char *thumb_ident = rgui_thumbnail_ident(); + + if (!string_is_empty(rgui->thumbnail_path)) + { + free(rgui->thumbnail_path); + rgui->thumbnail_path = NULL; + } + + /* NB: The following is copied directly from xmb.c (xmb_update_thumbnail_path()) */ + if (!string_is_equal(thumb_ident, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) && + !string_is_empty(thumbnail_base_dir) && + !string_is_empty(rgui->thumbnail_system) && + !string_is_empty(rgui->thumbnail_content)) + { + /* Append thumbnail system directory */ + fill_pathname_join(new_path, thumbnail_base_dir, rgui->thumbnail_system, sizeof(new_path)); + + if (!string_is_empty(new_path)) + { + char *tmp_new2 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + tmp_new2[0] = '\0'; + + /* Append Named_Snaps/Named_Boxarts/Named_Titles */ + fill_pathname_join(tmp_new2, new_path, thumb_ident, PATH_MAX_LENGTH * sizeof(char)); + + strlcpy(new_path, tmp_new2, PATH_MAX_LENGTH * sizeof(char)); + free(tmp_new2); + tmp_new2 = NULL; + + if (!string_is_empty(new_path)) + { + /* Scrub characters that are not cross-platform and/or violate the + * No-Intro filename standard: + * http://datomatic.no-intro.org/stuff/The%20Official%20No-Intro%20Convention%20(20071030).zip + * Replace these characters in the entry name with underscores. + */ + char *scrub_char_pointer = NULL; + char *tmp_new = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + char *tmp = strdup(rgui->thumbnail_content); + + tmp_new[0] = '\0'; + + while((scrub_char_pointer = strpbrk(tmp, "&*/:`\"<>?\\|"))) + { + *scrub_char_pointer = '_'; + } + + fill_pathname_join(tmp_new, new_path, tmp, PATH_MAX_LENGTH * sizeof(char)); + + if (!string_is_empty(tmp_new)) + { + strlcpy(new_path, tmp_new, sizeof(new_path)); + } + + free(tmp_new); + tmp_new = NULL; + free(tmp); + tmp = NULL; + + /* Append png extension */ + if (!string_is_empty(new_path)) + { + strlcat(new_path, file_path_str(FILE_PATH_PNG_EXTENSION), sizeof(new_path)); + + if (!string_is_empty(new_path)) + { + rgui->thumbnail_path = strdup(new_path); + } + } + } + } + } +} + +static void rgui_set_thumbnail_system(void *userdata, char *s, size_t len) +{ + rgui_t *rgui = (rgui_t*)userdata; + if (!rgui) + return; + if (!string_is_empty(rgui->thumbnail_system)) + free(rgui->thumbnail_system); + rgui->thumbnail_system = strdup(s); +} + +static void rgui_update_thumbnail_content(void *userdata) +{ + rgui_t *rgui = (rgui_t*)userdata; + playlist_t *playlist = NULL; + char title[255]; + size_t selection = menu_navigation_get_selection(); + + if (!rgui) + return; + + /* Check whether current selection is a playlist entry + * (i.e. whether we should be looking for a thumbnail image) */ + rgui->is_playlist_entry = false; + title[0] = '\0'; + menu_entries_get_title(title, sizeof(title)); + if (!string_is_empty(rgui->thumbnail_system)) + { + /* An ugly but effective test... */ + if (strstr(path_basename(title), rgui->thumbnail_system) != NULL) + { + /* Get label of currently selected playlist entry + * > This is pretty nasty, but I can't see any other way of doing + * it (entry.path gives us almost what we need, but it's tainted + * with the core name, which is too difficult to remove...) */ + playlist = playlist_get_cached(); + if (playlist) + { + if (selection < playlist_get_size(playlist)) + { + const char *label = NULL; + playlist_get_index(playlist, selection, NULL, &label, NULL, NULL, NULL, NULL); + + if (!string_is_empty(rgui->thumbnail_content)) + { + free(rgui->thumbnail_content); + rgui->thumbnail_content = NULL; + } + + if (!string_is_empty(label)) + { + rgui->thumbnail_content = strdup(label); + rgui->is_playlist_entry = true; + } + } + } + } + } +} + +static void rgui_update_thumbnail_image(void *userdata) +{ + rgui_t *rgui = (rgui_t*)userdata; + if (!rgui) + return; + + rgui->show_thumbnail = !rgui->show_thumbnail; + + if (rgui->show_thumbnail) + { + rgui_update_thumbnail_content(rgui); + if (rgui->is_playlist_entry) + { + rgui_update_thumbnail_path(rgui); + load_thumbnail(rgui->thumbnail_path); + } + } +} + static void rgui_navigation_set(void *data, bool scroll) { size_t start, fb_pitch; @@ -1336,6 +1807,20 @@ static void rgui_navigation_set(void *data, bool scroll) bool do_set_start = false; size_t end = menu_entries_get_size(); size_t selection = menu_navigation_get_selection(); + rgui_t *rgui = (rgui_t*)data; + + if (!rgui) + return; + + if (rgui->show_thumbnail) + { + rgui_update_thumbnail_content(rgui); + if (rgui->is_playlist_entry) + { + rgui_update_thumbnail_path(rgui); + load_thumbnail(rgui->thumbnail_path); + } + } if (!scroll) return; @@ -1475,8 +1960,8 @@ menu_ctx_driver_t menu_ctx_rgui = { rgui_environ, rgui_pointer_tap, NULL, - NULL, - NULL, + rgui_update_thumbnail_image, + rgui_set_thumbnail_system, NULL, NULL, NULL, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 9fac37f45f..d3c6cbf54c 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -8722,7 +8722,7 @@ static bool setting_append_list( general_read_handler, SD_FLAG_ADVANCED); - if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone")) + if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone") || string_is_equal(settings->arrays.menu_driver, "rgui")) { CONFIG_UINT( list, list_info, @@ -8739,7 +8739,10 @@ static bool setting_append_list( (*list)[list_info->index - 1].get_string_representation = &setting_get_string_representation_uint_menu_thumbnails; menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); + } + if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone")) + { CONFIG_UINT( list, list_info, &settings->uints.menu_left_thumbnails, From c017271d8af03ec3b7c95f8f3696203bf045db18 Mon Sep 17 00:00:00 2001 From: Nano Date: Sun, 13 Jan 2019 19:12:10 +0100 Subject: [PATCH 016/234] Fix #6747 Black bug --- configuration.c | 2 +- gfx/drivers/d3d10.c | 2 +- gfx/drivers/d3d11.c | 2 +- gfx/drivers/d3d12.c | 2 +- gfx/drivers/d3d8.c | 2 +- gfx/drivers/d3d9.c | 2 +- gfx/drivers/gdi_gfx.c | 2 +- gfx/drivers/gl.c | 36 +++++++++++++++++++++++++++++------- gfx/drivers/vulkan.c | 2 +- gfx/video_driver.c | 6 +++++- gfx/video_driver.h | 2 +- gfx/video_thread_wrapper.c | 4 ++-- menu/menu_setting.c | 2 +- 13 files changed, 46 insertions(+), 20 deletions(-) diff --git a/configuration.c b/configuration.c index c0532f4c43..3471e71807 100644 --- a/configuration.c +++ b/configuration.c @@ -1377,7 +1377,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("video_scale_integer", &settings->bools.video_scale_integer, true, scale_integer, false); SETTING_BOOL("video_smooth", &settings->bools.video_smooth, true, video_smooth, false); SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, force_aspect, false); - SETTING_BOOL("video_threaded", video_driver_get_threaded(), true, video_threaded, false); + SETTING_BOOL("video_threaded", &settings->bools.video_threaded, true, video_threaded, false); SETTING_BOOL("video_shared_context", &settings->bools.video_shared_context, true, video_shared_context, false); SETTING_BOOL("auto_screenshot_filename", &settings->bools.auto_screenshot_filename, true, auto_screenshot_filename, false); SETTING_BOOL("video_force_srgb_disable", &settings->bools.video_force_srgb_disable, true, false, false); diff --git a/gfx/drivers/d3d10.c b/gfx/drivers/d3d10.c index b5dc33d0e3..a465b9a754 100644 --- a/gfx/drivers/d3d10.c +++ b/gfx/drivers/d3d10.c @@ -1580,7 +1580,7 @@ static uintptr_t d3d10_gfx_load_texture( return (uintptr_t)texture; } -static void d3d10_gfx_unload_texture(void* data, uintptr_t handle) +static void d3d10_gfx_unload_texture(void* data, uintptr_t handle, bool threaded) { d3d10_texture_t* texture = (d3d10_texture_t*)handle; diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 6e0850b712..f01a09eead 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -1640,7 +1640,7 @@ static uintptr_t d3d11_gfx_load_texture( return (uintptr_t)texture; } -static void d3d11_gfx_unload_texture(void* data, uintptr_t handle) +static void d3d11_gfx_unload_texture(void* data, uintptr_t handle, bool threaded) { d3d11_texture_t* texture = (d3d11_texture_t*)handle; diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 2251a428d4..658dcaaff9 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -1759,7 +1759,7 @@ static uintptr_t d3d12_gfx_load_texture( return (uintptr_t)texture; } -static void d3d12_gfx_unload_texture(void* data, uintptr_t handle) +static void d3d12_gfx_unload_texture(void* data, uintptr_t handle, bool threaded) { d3d12_texture_t* texture = (d3d12_texture_t*)handle; diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index 21830cd500..33c0bd8023 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -1818,7 +1818,7 @@ static uintptr_t d3d8_load_texture(void *video_data, void *data, return id; } -static void d3d8_unload_texture(void *data, uintptr_t id) +static void d3d8_unload_texture(void *data, uintptr_t id, bool threaded) { LPDIRECT3DTEXTURE8 texid; if (!id) diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9.c index 2d5af2a9d1..b19a0b1b19 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9.c @@ -1989,7 +1989,7 @@ static uintptr_t d3d9_load_texture(void *video_data, void *data, return id; } -static void d3d9_unload_texture(void *data, uintptr_t id) +static void d3d9_unload_texture(void *data, uintptr_t id, bool threaded) { LPDIRECT3DTEXTURE9 texid; if (!id) diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c index 034a6db400..70d4f8e31c 100644 --- a/gfx/drivers/gdi_gfx.c +++ b/gfx/drivers/gdi_gfx.c @@ -610,7 +610,7 @@ static uintptr_t gdi_load_texture(void *video_data, void *data, return (uintptr_t)texture; } -static void gdi_unload_texture(void *data, uintptr_t handle) +static void gdi_unload_texture(void *data, uintptr_t handle, bool threaded) { struct gdi_texture *texture = (struct gdi_texture*)handle; diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index b7d2f25da8..02ac726d98 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -2492,6 +2492,12 @@ static void video_texture_load_gl( ); } +static void video_texture_unload_gl( + uintptr_t *id) +{ + glDeleteTextures(1, (GLuint*)id); +} + #ifdef HAVE_THREADS static int video_texture_load_wrap_gl_mipmap(void *data) { @@ -2514,13 +2520,20 @@ static int video_texture_load_wrap_gl(void *data) TEXTURE_FILTER_LINEAR, &id); return (int)id; } + +static int video_texture_unload_wrap_gl(void *data) +{ + if (!data) + return 0; + video_texture_unload_gl((uintptr_t*)data); + return 0; +} #endif static uintptr_t gl_load_texture(void *video_data, void *data, bool threaded, enum texture_filter_type filter_type) { uintptr_t id = 0; - #ifdef HAVE_THREADS if (threaded) { @@ -2535,7 +2548,8 @@ static uintptr_t gl_load_texture(void *video_data, void *data, default: break; } - return video_thread_texture_load(data, func); + id=video_thread_texture_load(data, func); + return id; } #endif @@ -2543,14 +2557,22 @@ static uintptr_t gl_load_texture(void *video_data, void *data, return id; } -static void gl_unload_texture(void *data, uintptr_t id) +static void gl_unload_texture(void *video_data, uintptr_t data, bool threaded) { - GLuint glid; - if (!id) + if (!data) return; + GLuint glid = (GLuint)data; - glid = (GLuint)id; - glDeleteTextures(1, &glid); +#ifdef HAVE_THREADS + if (threaded) + { + custom_command_method_t func = video_texture_unload_wrap_gl; + video_thread_texture_load((void *)&data, func); + return; + } +#endif + + video_texture_unload_gl(&data); } static void gl_set_coords(void *handle_data, void *shader_data, diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 483ee8ae09..2408f2f9d1 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -2334,7 +2334,7 @@ static uintptr_t vulkan_load_texture(void *video_data, void *data, return (uintptr_t)texture; } -static void vulkan_unload_texture(void *data, uintptr_t handle) +static void vulkan_unload_texture(void *data, uintptr_t handle, bool threaded) { vk_t *vk = (vk_t*)data; struct vk_texture *texture = (struct vk_texture*)handle; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 3d29a3c182..f3d9cc119b 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -147,6 +147,7 @@ static bool video_driver_crt_switching_active = false; static struct retro_system_av_info video_driver_av_info; + static enum retro_pixel_format video_driver_pix_fmt = RETRO_PIXEL_FORMAT_0RGB1555; static const void *frame_cache_data = NULL; @@ -1050,6 +1051,9 @@ static bool video_driver_init_internal(bool *video_is_threaded) video_driver_find_driver(); #ifdef HAVE_THREADS + /* Set the driver to threaded based on the settings configuration */ + video_driver_threaded = settings->bools.video_threaded; + /* Check video_driver_threaded and video_driver_hw-context to determine if the video driver is threaded */ video.is_threaded = video_driver_is_threaded_internal(); *video_is_threaded = video.is_threaded; @@ -2725,7 +2729,7 @@ bool video_driver_texture_unload(uintptr_t *id) if (!video_driver_poke || !video_driver_poke->unload_texture) return false; - video_driver_poke->unload_texture(video_driver_data, *id); + video_driver_poke->unload_texture(video_driver_data, *id, video_driver_is_threaded_internal()); *id = 0; return true; } diff --git a/gfx/video_driver.h b/gfx/video_driver.h index eea9ef14e4..905fef9817 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -710,7 +710,7 @@ typedef struct video_poke_interface const void *mat_data); uintptr_t (*load_texture)(void *video_data, void *data, bool threaded, enum texture_filter_type filter_type); - void (*unload_texture)(void *data, uintptr_t id); + void (*unload_texture)(void *data, uintptr_t id, bool threaded); void (*set_video_mode)(void *data, unsigned width, unsigned height, bool fullscreen); float (*get_refresh_rate)(void *data); diff --git a/gfx/video_thread_wrapper.c b/gfx/video_thread_wrapper.c index 1093deae0a..f29099c80f 100644 --- a/gfx/video_thread_wrapper.c +++ b/gfx/video_thread_wrapper.c @@ -1198,7 +1198,7 @@ static uintptr_t thread_load_texture(void *video_data, void *data, return thr->poke->load_texture(thr->driver_data, data, threaded, filter_type); } -static void thread_unload_texture(void *video_data, uintptr_t id) +static void thread_unload_texture(void *video_data, uintptr_t id, bool threaded) { thread_video_t *thr = (thread_video_t*)video_data; @@ -1206,7 +1206,7 @@ static void thread_unload_texture(void *video_data, uintptr_t id) return; if (thr->poke && thr->poke->unload_texture) - thr->poke->unload_texture(thr->driver_data, id); + thr->poke->unload_texture(thr->driver_data, id, threaded); } static void thread_apply_state_changes(void *data) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 9fac37f45f..aa00b8ea26 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -5850,7 +5850,7 @@ static bool setting_append_list( #if defined(HAVE_THREADS) CONFIG_BOOL( list, list_info, - video_driver_get_threaded(), + &settings->bools.video_threaded, MENU_ENUM_LABEL_VIDEO_THREADED, MENU_ENUM_LABEL_VALUE_VIDEO_THREADED, video_threaded, From 20cb84189ee4adc7fe5cd62b5cb78ccc02157161 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sat, 19 Jan 2019 12:04:55 +0100 Subject: [PATCH 017/234] Fix problems with UWP filesystem in Release builds --- libretro-common/vfs/vfs_implementation_uwp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index 4a8b174c24..b65b83f2a9 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -65,9 +65,9 @@ namespace template T RunAsync(std::function()> func) { - bool finished = false; - Platform::Exception^ exception = nullptr; - T result; + volatile bool finished = false; + volatile Platform::Exception^ exception = nullptr; + volatile T result; func().then([&](concurrency::task t) { try { From e5a2221eacbd2064367823249a3e3d4c0db58493 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sat, 19 Jan 2019 12:13:16 +0100 Subject: [PATCH 018/234] Make lambdas safer for multithreading --- .../vfs/vfs_implementation_uwp.cpp | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index b65b83f2a9..6c0b8122b6 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -68,7 +68,7 @@ namespace volatile bool finished = false; volatile Platform::Exception^ exception = nullptr; volatile T result; - func().then([&](concurrency::task t) { + func().then([&finished, &exception, &result](concurrency::task t) { try { result = t.get(); @@ -240,7 +240,7 @@ namespace if (*(path->End() - 1) == '\\') { /* Ends with a slash, so it's definitely a directory */ - return RunAsyncAndCatchErrors([&]() { + return RunAsyncAndCatchErrors([=]() { return concurrency::create_task(LocateStorageItem(path)); }, nullptr); } @@ -248,12 +248,12 @@ namespace { /* No final slash - probably a file (since RetroArch usually slash-terminates dirs), but there is still a chance it's a directory */ IStorageItem^ item; - item = RunAsyncAndCatchErrors([&]() { + item = RunAsyncAndCatchErrors([=]() { return concurrency::create_task(LocateStorageItem(path)); }, nullptr); if (!item) { - item = RunAsyncAndCatchErrors([&]() { + item = RunAsyncAndCatchErrors([=]() { return concurrency::create_task(LocateStorageItem(path)); }, nullptr); } @@ -306,18 +306,18 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns retro_assert(!dirpath_str->IsEmpty() && !filename_str->IsEmpty()); - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(LocateStorageItem(dirpath_str)).then([&](StorageFolder^ dir) { + return RunAsyncAndCatchErrors([=]() { + return concurrency::create_task(LocateStorageItem(dirpath_str)).then([=](StorageFolder^ dir) { if (mode == RETRO_VFS_FILE_ACCESS_READ) return dir->GetFileAsync(filename_str); else return dir->CreateFileAsync(filename_str, (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ? CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting); - }).then([&](StorageFile^ file) { + }).then([=](StorageFile^ file) { FileAccessMode accessMode = mode == RETRO_VFS_FILE_ACCESS_READ ? FileAccessMode::Read : FileAccessMode::ReadWrite; return file->OpenAsync(accessMode); - }).then([&](IRandomAccessStream^ fpstream) { + }).then([=](IRandomAccessStream^ fpstream) { libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream)); if (!stream) return (libretro_vfs_implementation_file*)NULL; @@ -462,8 +462,8 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void return -1; IBuffer^ buffer = CreateNativeBuffer(s, len, 0); - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) { + return RunAsyncAndCatchErrors([=]() { + return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity, InputStreamOptions::None)).then([=](IBuffer^ buf) { retro_assert(buf == buffer); return (int64_t)buffer->Length; }); @@ -476,8 +476,8 @@ int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, cons return -1; IBuffer^ buffer = CreateNativeBuffer(const_cast(s), len, len); - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) { + return RunAsyncAndCatchErrors([=]() { + return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([=](unsigned int written) { return (int64_t)written; }); }, -1); @@ -488,8 +488,8 @@ int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream) if (!stream || !stream->fp) return -1; - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(stream->fp->FlushAsync()).then([&](bool this_value_is_not_even_documented_wtf) { + return RunAsyncAndCatchErrors([=]() { + return concurrency::create_task(stream->fp->FlushAsync()).then([=](bool this_value_is_not_even_documented_wtf) { /* The bool value may be reporting an error or something, but just leave it alone for now */ /* https://github.com/MicrosoftDocs/winrt-api/issues/841 */ return 0; @@ -507,10 +507,10 @@ int retro_vfs_file_remove_impl(const char *path) Platform::String^ path_str = ref new Platform::String(path_wide); free(path_wide); - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(LocateStorageItem(path_str)).then([&](StorageFile^ file) { + return RunAsyncAndCatchErrors([=]() { + return concurrency::create_task(LocateStorageItem(path_str)).then([=](StorageFile^ file) { return file->DeleteAsync(StorageDeleteOption::PermanentDelete); - }).then([&]() { + }).then([=]() { return 0; }); }, -1); @@ -543,19 +543,19 @@ int retro_vfs_file_rename_impl(const char *old_path, const char *new_path) retro_assert(!old_path_str->IsEmpty() && !new_dir_path_str->IsEmpty() && !new_file_name_str->IsEmpty()); - return RunAsyncAndCatchErrors([&]() { + return RunAsyncAndCatchErrors([=]() { concurrency::task old_file_task = concurrency::create_task(LocateStorageItem(old_path_str)); concurrency::task new_dir_task = concurrency::create_task(LocateStorageItem(new_dir_path_str)); - return concurrency::create_task([&] { + return concurrency::create_task([=] { /* Run these two tasks in parallel */ /* TODO: There may be some cleaner way to express this */ concurrency::task_group group; - group.run([&] { return old_file_task; }); - group.run([&] { return new_dir_task; }); + group.run([=] { return old_file_task; }); + group.run([=] { return new_dir_task; }); group.wait(); - }).then([&]() { + }).then([=]() { return old_file_task.get()->MoveAsync(new_dir_task.get(), new_file_name_str, NameCollisionOption::ReplaceExisting); - }).then([&]() { + }).then([=]() { return 0; }); }, -1); @@ -583,8 +583,8 @@ int retro_vfs_stat_impl(const char *path, int32_t *size) if (!item) return 0; - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(item->GetBasicPropertiesAsync()).then([&](BasicProperties^ properties) { + return RunAsyncAndCatchErrors([=]() { + return concurrency::create_task(item->GetBasicPropertiesAsync()).then([=](BasicProperties^ properties) { if (size) *size = properties->Size; return item->IsOfType(StorageItemTypes::Folder) ? RETRO_VFS_STAT_IS_VALID | RETRO_VFS_STAT_IS_DIRECTORY : RETRO_VFS_STAT_IS_VALID; @@ -622,10 +622,10 @@ int retro_vfs_mkdir_impl(const char *dir) free(dir_local); - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(LocateStorageItem(parent_path_str)).then([&](StorageFolder^ parent) { + return RunAsyncAndCatchErrors([=]() { + return concurrency::create_task(LocateStorageItem(parent_path_str)).then([=](StorageFolder^ parent) { return parent->CreateFolderAsync(dir_name_str); - }).then([&](concurrency::task new_dir) { + }).then([=](concurrency::task new_dir) { try { new_dir.get(); @@ -668,8 +668,8 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i Platform::String^ name_str = ref new Platform::String(name_wide); free(name_wide); - rdir->directory = RunAsyncAndCatchErrors^>([&]() { - return concurrency::create_task(LocateStorageItem(name_str)).then([&](StorageFolder^ folder) { + rdir->directory = RunAsyncAndCatchErrors^>([=]() { + return concurrency::create_task(LocateStorageItem(name_str)).then([=](StorageFolder^ folder) { return folder->GetItemsAsync(); }); }, nullptr); @@ -741,7 +741,7 @@ bool uwp_drive_exists(const char *path) Platform::String^ path_str = ref new Platform::String(path_wide); free(path_wide); - return RunAsyncAndCatchErrors([&]() { + return RunAsyncAndCatchErrors([=]() { return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path_str)).then([](StorageFolder^ properties) { return true; }); @@ -750,7 +750,7 @@ bool uwp_drive_exists(const char *path) char* uwp_trigger_picker(void) { - return RunAsyncAndCatchErrors([&]() { + return RunAsyncAndCatchErrors([=]() { return TriggerPickerAddDialog().then([](Platform::String^ path) { return utf16_to_utf8_string_alloc(path->Data()); }); From 159839e3534a5feb463f8621a2a776f6f74871f3 Mon Sep 17 00:00:00 2001 From: meleu Date: Sat, 19 Jan 2019 14:24:28 -0200 Subject: [PATCH 019/234] rcheevos leftover --- Makefile.ctr | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.ctr b/Makefile.ctr index c276e79b3e..63d072b6e4 100644 --- a/Makefile.ctr +++ b/Makefile.ctr @@ -137,7 +137,6 @@ CFLAGS += -I. \ -Ideps/libz \ -Ideps/7zip \ -Ideps/stb \ - -Ideps/rcheevos/include \ -Ilibretro-common/include CFLAGS += -DRARCH_INTERNAL -DRARCH_CONSOLE From f78f447b12d89a0c7b176bcc42023d6d00ada9fb Mon Sep 17 00:00:00 2001 From: meleu Date: Sat, 19 Jan 2019 15:14:24 -0200 Subject: [PATCH 020/234] better handling HAVE_NEW_CHEEVOS build --- Makefile.common | 112 +++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 44 deletions(-) diff --git a/Makefile.common b/Makefile.common index a6bf00da77..9a44cc7e01 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1665,54 +1665,78 @@ ifeq ($(HAVE_NETWORKING), 1) network/netplay/netplay_buf.o \ network/netplay/netplay_room_parse.o - # Retro Achievements + # RetroAchievements ifeq ($(HAVE_CHEEVOS), 1) DEFINES += -DHAVE_CHEEVOS - - OBJ += cheevos/cheevos.o \ - cheevos/badges.o \ - cheevos/var.o \ - cheevos/cond.o - ifeq ($(HAVE_LUA), 1) - DEFINES += -DHAVE_LUA \ - -DLUA_32BITS \ - -Ideps/lua/src - OBJ += deps/lua/src/lapi.o \ - deps/lua/src/lcode.o \ - deps/lua/src/lctype.o \ - deps/lua/src/ldebug.o \ - deps/lua/src/ldo.o \ - deps/lua/src/ldump.o \ - deps/lua/src/lfunc.o \ - deps/lua/src/lgc.o \ - deps/lua/src/llex.o \ - deps/lua/src/lmem.o \ - deps/lua/src/lobject.o \ - deps/lua/src/lopcodes.o \ - deps/lua/src/lparser.o \ - deps/lua/src/lstate.o \ - deps/lua/src/lstring.o \ - deps/lua/src/ltable.o \ - deps/lua/src/ltm.o \ - deps/lua/src/lundump.o \ - deps/lua/src/lvm.o \ - deps/lua/src/lzio.o \ - deps/lua/src/lauxlib.o \ - deps/lua/src/lbaselib.o \ - deps/lua/src/lbitlib.o \ - deps/lua/src/lcorolib.o \ - deps/lua/src/ldblib.o \ - deps/lua/src/liolib.o \ - deps/lua/src/lmathlib.o \ - deps/lua/src/loslib.o \ - deps/lua/src/lstrlib.o \ - deps/lua/src/ltablib.o \ - deps/lua/src/lutf8lib.o \ - deps/lua/src/loadlib.o \ - deps/lua/src/linit.o + ifeq ($(HAVE_NEW_CHEEVOS), 1) + DEFINES += -DHAVE_NEW_CHEEVOS \ + -Ideps/rcheevos/include \ + -Ideps/lua/src + OBJ += cheevos-new/cheevos.o \ + cheevos-new/badges.o \ + cheevos-new/fixup.o \ + cheevos-new/parser.o \ + cheevos-new/hash.o \ + deps/rcheevos/src/rcheevos/trigger.o \ + deps/rcheevos/src/rcheevos/condset.o \ + deps/rcheevos/src/rcheevos/condition.o \ + deps/rcheevos/src/rcheevos/operand.o \ + deps/rcheevos/src/rcheevos/term.o \ + deps/rcheevos/src/rcheevos/expression.o \ + deps/rcheevos/src/rcheevos/value.o \ + deps/rcheevos/src/rcheevos/lboard.o \ + deps/rcheevos/src/rcheevos/alloc.o \ + deps/rcheevos/src/rcheevos/format.o \ + deps/rcheevos/src/rurl/url.o + + ifeq ($(HAVE_LUA), 1) + DEFINES += -DHAVE_LUA \ + -DLUA_32BITS \ + -Ideps/lua/src + OBJ += deps/lua/src/lapi.o \ + deps/lua/src/lcode.o \ + deps/lua/src/lctype.o \ + deps/lua/src/ldebug.o \ + deps/lua/src/ldo.o \ + deps/lua/src/ldump.o \ + deps/lua/src/lfunc.o \ + deps/lua/src/lgc.o \ + deps/lua/src/llex.o \ + deps/lua/src/lmem.o \ + deps/lua/src/lobject.o \ + deps/lua/src/lopcodes.o \ + deps/lua/src/lparser.o \ + deps/lua/src/lstate.o \ + deps/lua/src/lstring.o \ + deps/lua/src/ltable.o \ + deps/lua/src/ltm.o \ + deps/lua/src/lundump.o \ + deps/lua/src/lvm.o \ + deps/lua/src/lzio.o \ + deps/lua/src/lauxlib.o \ + deps/lua/src/lbaselib.o \ + deps/lua/src/lbitlib.o \ + deps/lua/src/lcorolib.o \ + deps/lua/src/ldblib.o \ + deps/lua/src/liolib.o \ + deps/lua/src/lmathlib.o \ + deps/lua/src/loslib.o \ + deps/lua/src/lstrlib.o \ + deps/lua/src/ltablib.o \ + deps/lua/src/lutf8lib.o \ + deps/lua/src/loadlib.o \ + deps/lua/src/linit.o + else + DEFINES += -DRC_DISABLE_LUA + endif + + # if not HAVE_NEW_CHEEVOS else - DEFINES += -DRC_DISABLE_LUA + OBJ += cheevos/cheevos.o \ + cheevos/badges.o \ + cheevos/var.o \ + cheevos/cond.o endif endif From b7acc33bdaacf1f99518d3027a0628e95f18fef8 Mon Sep 17 00:00:00 2001 From: meleu Date: Sat, 19 Jan 2019 15:29:54 -0200 Subject: [PATCH 021/234] cheevos-new: update nes/snes/lynx hashing methods --- cheevos-new/cheevos.c | 139 ++++++++++-------------------------------- 1 file changed, 33 insertions(+), 106 deletions(-) diff --git a/cheevos-new/cheevos.c b/cheevos-new/cheevos.c index 78d7d0d6ab..7f065ee277 100644 --- a/cheevos-new/cheevos.c +++ b/cheevos-new/cheevos.c @@ -1118,6 +1118,8 @@ enum static int cheevos_iterate(coro_t* coro) { + const int snes_header_len = 0x200; + const int lynx_header_len = 0x40; ssize_t num_read = 0; size_t to_read = 4096; uint8_t *buffer = NULL; @@ -1159,10 +1161,10 @@ static int cheevos_iterate(coro_t* coro) static cheevos_finder_t finders[] = { - {SNES_MD5, "SNES (8Mb padding)", snes_exts}, + {SNES_MD5, "SNES (discards header)", snes_exts}, {GENESIS_MD5, "Genesis (6Mb padding)", genesis_exts}, - {LYNX_MD5, "Atari Lynx (only first 512 bytes)", lynx_exts}, - {NES_MD5, "NES (discards VROM)", NULL}, + {LYNX_MD5, "Atari Lynx (discards header)", lynx_exts}, + {NES_MD5, "NES (discards header)", NULL}, {GENERIC_MD5, "Generic (plain content)", NULL}, {FILENAME_MD5, "Generic (filename)", NULL} }; @@ -1403,33 +1405,22 @@ found: * Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found *************************************************************************/ CORO_SUB(SNES_MD5) - MD5_Init(&coro->md5); - coro->offset = 0; - coro->count = 0; - - CORO_GOSUB(EVAL_MD5); - - if (coro->count == 0) + /* Checks for the existence of a headered SNES file. + Unheadered files fall back to GENERIC_MD5. */ + if (coro->len < 0x2000 || coro->len % 0x2000 != snes_header_len) { - MD5_Final(coro->hash, &coro->md5); coro->gameid = 0; CORO_RET(); } - if (coro->count < CHEEVOS_MB(8)) - { - /* - * Inputs: CHEEVOS_VAR_MD5, CHEEVOS_VAR_OFFSET, CHEEVOS_VAR_COUNT - * Outputs: CHEEVOS_VAR_MD5 - */ - coro->offset = 0; - coro->count = CHEEVOS_MB(8) - coro->count; - CORO_GOSUB(FILL_MD5); - } + coro->offset = 512; + coro->count = 0; + CORO_GOSUB(EVAL_MD5); MD5_Final(coro->hash, &coro->md5); + CORO_GOTO(GET_GAMEID); /************************************************************************** @@ -1469,16 +1460,18 @@ found: *************************************************************************/ CORO_SUB(LYNX_MD5) - if (coro->len < 0x0240) + /* Checks for the existence of a headered Lynx file. + Unheadered files fall back to GENERIC_MD5. */ + if (coro->len <= lynx_header_len || + memcmp("LYNX", (void *)coro->data, 5) != 0) { coro->gameid = 0; CORO_RET(); } MD5_Init(&coro->md5); - - coro->offset = 0x0040; - coro->count = 0x0200; + coro->offset = lynx_header_len; + coro->count = coro->len - lynx_header_len; CORO_GOSUB(EVAL_MD5); MD5_Final(coro->hash, &coro->md5); @@ -1491,13 +1484,8 @@ found: *************************************************************************/ CORO_SUB(NES_MD5) - /* Note about the references to the FCEU emulator below. There is no - * core-specific code in this function, it's rather Retro Achievements - * specific code that must be followed to the letter so we compute - * the correct ROM hash. Retro Achievements does indeed use some - * FCEU related method to compute the hash, since its NES emulator - * is based on it. */ - + /* Checks for the existence of a headered NES file. + Unheadered files fall back to GENERIC_MD5. */ if (coro->len < sizeof(coro->header)) { coro->gameid = 0; @@ -1506,84 +1494,23 @@ found: memcpy((void*)&coro->header, coro->data, sizeof(coro->header)); - - if (coro->header.id[0] == 'N' - && coro->header.id[1] == 'E' - && coro->header.id[2] == 'S' - && coro->header.id[3] == 0x1a) + + if ( coro->header.id[0] != 'N' + || coro->header.id[1] != 'E' + || coro->header.id[2] != 'S' + || coro->header.id[3] != 0x1a) { - size_t romsize = 256; - /* from FCEU core - compute size using the cart mapper */ - int mapper = (coro->header.rom_type >> 4) | (coro->header.rom_type2 & 0xF0); - - if (coro->header.rom_size) - romsize = next_pow2(coro->header.rom_size); - - /* for games not to the power of 2, so we just read enough - * PRG rom from it, but we have to keep ROM_size to the power of 2 - * since PRGCartMapping wants ROM_size to be to the power of 2 - * so instead if not to power of 2, we just use head.ROM_size when - * we use FCEU_read. */ - coro->round = mapper != 53 && mapper != 198 && mapper != 228; - coro->bytes = coro->round ? romsize : coro->header.rom_size; - - coro->offset = sizeof(coro->header) + (coro->header.rom_type & 4 - ? sizeof(coro->header) : 0); - - /* from FCEU core - check if Trainer included in ROM data */ - MD5_Init(&coro->md5); - coro->count = 0x4000 * coro->bytes; - CORO_GOSUB(EVAL_MD5); - - if (coro->count < 0x4000 * coro->bytes) - { - coro->offset = 0xff; - coro->count = 0x4000 * coro->bytes - coro->count; - CORO_GOSUB(FILL_MD5); - } - - MD5_Final(coro->hash, &coro->md5); - CORO_GOTO(GET_GAMEID); + coro->gameid = 0; + CORO_RET(); } - else - { - unsigned i; - size_t chunks = coro->len >> 14; - size_t chunk_size = 0x4000; - /* Fall back to headerless hashing - * PRG ROM size is unknown, so test by 16KB chunks */ + MD5_Init(&coro->md5); + coro->offset = sizeof(coro->header); + coro->count = coro->len - coro->offset; + CORO_GOSUB(EVAL_MD5); - coro->round = 0; - coro->offset = 0; - - for (i = 0; i < chunks; i++) - { - MD5_Init(&coro->md5); - - coro->bytes = i + 1; - coro->count = coro->bytes * chunk_size; - - CORO_GOSUB(EVAL_MD5); - - if (coro->count < 0x4000 * coro->bytes) - { - coro->offset = 0xff; - coro->count = 0x4000 * coro->bytes - coro->count; - CORO_GOSUB(FILL_MD5); - } - - MD5_Final(coro->hash, &coro->md5); - CORO_GOSUB(GET_GAMEID); - - if (coro->gameid > 0) - { - break; - } - } - - CORO_RET(); - } + MD5_Final(coro->hash, &coro->md5); + CORO_GOTO(GET_GAMEID); /************************************************************************** * Info Tries to identify a "generic" game From 8e02ebd98785a223ca91297749ca38fafe7c2031 Mon Sep 17 00:00:00 2001 From: meleu Date: Sat, 19 Jan 2019 17:59:41 -0200 Subject: [PATCH 022/234] cheevos-new: no magic numbers --- cheevos-new/cheevos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheevos-new/cheevos.c b/cheevos-new/cheevos.c index 7f065ee277..851e2e82c1 100644 --- a/cheevos-new/cheevos.c +++ b/cheevos-new/cheevos.c @@ -1415,7 +1415,7 @@ found: CORO_RET(); } - coro->offset = 512; + coro->offset = snes_header_len; coro->count = 0; CORO_GOSUB(EVAL_MD5); From 46676289d4d3ea262ffa0b8275270ef31236bf03 Mon Sep 17 00:00:00 2001 From: orbea Date: Sat, 19 Jan 2019 12:12:43 -0800 Subject: [PATCH 023/234] Fix segfault with a null gl context. --- gfx/drivers/gl.c | 4 ++++ libretro-common/glsym/rglgen.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index b7d2f25da8..c37dfe8819 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -1727,6 +1727,7 @@ static void *gl_init(const video_info_t *video, char *error_string = NULL; gl_t *gl = (gl_t*)calloc(1, sizeof(gl_t)); const gfx_ctx_driver_t *ctx_driver = gl_get_context(gl); + if (!gl || !ctx_driver) goto error; @@ -1782,6 +1783,9 @@ static void *gl_init(const video_info_t *video, RARCH_LOG("[GL]: Vendor: %s, Renderer: %s.\n", vendor, renderer); RARCH_LOG("[GL]: Version: %s.\n", version); + if (string_is_equal(ctx_driver->ident, "null")) + goto error; + if (!string_is_empty(version)) sscanf(version, "%d.%d", &gl->version_major, &gl->version_minor); diff --git a/libretro-common/glsym/rglgen.c b/libretro-common/glsym/rglgen.c index c87d85bfd7..a05d5445d9 100644 --- a/libretro-common/glsym/rglgen.c +++ b/libretro-common/glsym/rglgen.c @@ -38,5 +38,8 @@ void rglgen_resolve_symbols_custom(rglgen_proc_address_t proc, void rglgen_resolve_symbols(rglgen_proc_address_t proc) { + if (!proc) + return; + rglgen_resolve_symbols_custom(proc, rglgen_symbol_map); } From 1a0d5030f9f0511112ebfa89b2cc161bc2ee7e4d Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 19 Jan 2019 23:02:48 +0100 Subject: [PATCH 024/234] shader_vulkan.cpp - doesn't need math.h --- gfx/drivers_shader/shader_vulkan.cpp | 196 +++++++++++++++------------ 1 file changed, 106 insertions(+), 90 deletions(-) diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index c674994534..97fca27faf 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -473,12 +472,12 @@ class Pass struct PushConstant { VkShaderStageFlags stages = 0; - vector buffer; // uint32_t to have correct alignment. + vector buffer; /* uint32_t to have correct alignment. */ }; PushConstant push; }; -// struct here since we're implementing the opaque typedef from C. +/* struct here since we're implementing the opaque typedef from C. */ struct vulkan_filter_chain { public: @@ -750,7 +749,8 @@ bool vulkan_filter_chain::init_history() return true; } - // We don't need to store array element #0, since it's aliased with the actual original. + /* We don't need to store array element #0, + * since it's aliased with the actual original. */ required_images--; original_history.reserve(required_images); common.original_history.resize(required_images); @@ -763,8 +763,10 @@ bool vulkan_filter_chain::init_history() RARCH_LOG("[Vulkan filter chain]: Using history of %u frames.\n", required_images); - // On first frame, we need to clear the textures to a known state, but we need - // a command buffer for that, so just defer to first frame. + /* On first frame, we need to clear the textures to + * a known state, but we need + * a command buffer for that, so just defer to first frame. + */ require_clear = true; return true; } @@ -775,7 +777,7 @@ bool vulkan_filter_chain::init_feedback() bool use_feedbacks = false; - // Final pass cannot have feedback. + /* Final pass cannot have feedback. */ for (unsigned i = 0; i < passes.size() - 1; i++) { bool use_feedback = false; @@ -879,7 +881,7 @@ bool vulkan_filter_chain::init_ubo() vkGetPhysicalDeviceProperties(gpu, &props); common.ubo_alignment = props.limits.minUniformBufferOffsetAlignment; - // Who knows. :) + /* Who knows. :) */ if (common.ubo_alignment == 0) common.ubo_alignment = 1; @@ -948,7 +950,7 @@ void vulkan_filter_chain::clear_history_and_feedback(VkCommandBuffer cmd) void vulkan_filter_chain::build_offscreen_passes(VkCommandBuffer cmd, const VkViewport &vp) { - // First frame, make sure our history and feedback textures are in a clean state. + /* First frame, make sure our history and feedback textures are in a clean state. */ if (require_clear) { clear_history_and_feedback(cmd); @@ -991,7 +993,7 @@ void vulkan_filter_chain::update_history(DeferredDisposer &disposer, VkCommandBu { VkImageLayout src_layout = input_texture.layout; - // Transition input texture to something appropriate. + /* Transition input texture to something appropriate. */ if (input_texture.layout != VK_IMAGE_LAYOUT_GENERAL) { vulkan_image_layout_transition_levels(cmd, @@ -1019,7 +1021,7 @@ void vulkan_filter_chain::update_history(DeferredDisposer &disposer, VkCommandBu tmp->copy(cmd, input_texture.image, src_layout); - // Transition input texture back. + /* Transition input texture back. */ if (input_texture.layout != VK_IMAGE_LAYOUT_GENERAL) { vulkan_image_layout_transition_levels(cmd, @@ -1032,16 +1034,17 @@ void vulkan_filter_chain::update_history(DeferredDisposer &disposer, VkCommandBu VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } - // Should ring buffer, but we don't have *that* many passes. + /* Should ring buffer, but we don't have *that* many passes. */ move_backward(begin(original_history), end(original_history) - 1, end(original_history)); swap(original_history.front(), tmp); } void vulkan_filter_chain::end_frame(VkCommandBuffer cmd) { - // If we need to keep old frames, copy it after fragment is complete. - // TODO: We can improve pipelining by figuring out which pass is the last that reads from - // the history and dispatch the copy earlier. + /* If we need to keep old frames, copy it after fragment is complete. + * TODO: We can improve pipelining by figuring out which + * pass is the last that reads from + * the history and dispatch the copy earlier. */ if (!original_history.empty()) { DeferredDisposer disposer(deferred_calls[current_sync_index]); @@ -1052,7 +1055,7 @@ void vulkan_filter_chain::end_frame(VkCommandBuffer cmd) void vulkan_filter_chain::build_viewport_pass( VkCommandBuffer cmd, const VkViewport &vp, const float *mvp) { - // First frame, make sure our history and feedback textures are in a clean state. + /* First frame, make sure our history and feedback textures are in a clean state. */ if (require_clear) { clear_history_and_feedback(cmd); @@ -1092,7 +1095,7 @@ void vulkan_filter_chain::build_viewport_pass( passes.back()->build_commands(disposer, cmd, original, source, vp, mvp); - // For feedback FBOs, swap current and previous. + /* For feedback FBOs, swap current and previous. */ for (auto &pass : passes) pass->end_frame(); } @@ -1308,7 +1311,7 @@ bool Pass::init_pipeline_layout() vector bindings; vector desc_counts; - // Main UBO. + /* Main UBO. */ VkShaderStageFlags ubo_mask = 0; if (reflection.ubo_stage_mask & SLANG_STAGE_VERTEX_MASK) ubo_mask |= VK_SHADER_STAGE_VERTEX_BIT; @@ -1323,7 +1326,7 @@ bool Pass::init_pipeline_layout() desc_counts.push_back({ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, num_sync_indices }); } - // Semantic textures. + /* Semantic textures. */ for (auto &semantic : reflection.semantic_textures) { for (auto &texture : semantic) @@ -1358,7 +1361,7 @@ bool Pass::init_pipeline_layout() layout_info.setLayoutCount = 1; layout_info.pSetLayouts = &set_layout; - // Push constants + /* Push constants */ VkPushConstantRange push_range = {}; if (reflection.push_constant_stage_mask && reflection.push_constant_size) { @@ -1408,12 +1411,12 @@ bool Pass::init_pipeline() if (!init_pipeline_layout()) return false; - // Input assembly + /* Input assembly */ VkPipelineInputAssemblyStateCreateInfo input_assembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - // VAO state + /* VAO state */ VkVertexInputAttributeDescription attributes[2] = {{0}}; VkVertexInputBindingDescription binding = {0}; @@ -1437,7 +1440,7 @@ bool Pass::init_pipeline() vertex_input.vertexAttributeDescriptionCount = 2; vertex_input.pVertexAttributeDescriptions = attributes; - // Raster state + /* Raster state */ VkPipelineRasterizationStateCreateInfo raster = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; raster.polygonMode = VK_POLYGON_MODE_FILL; @@ -1448,7 +1451,7 @@ bool Pass::init_pipeline() raster.depthBiasEnable = false; raster.lineWidth = 1.0f; - // Blend state + /* Blend state */ VkPipelineColorBlendAttachmentState blend_attachment = {0}; VkPipelineColorBlendStateCreateInfo blend = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; @@ -1457,13 +1460,13 @@ bool Pass::init_pipeline() blend.attachmentCount = 1; blend.pAttachments = &blend_attachment; - // Viewport state + /* Viewport state */ VkPipelineViewportStateCreateInfo viewport = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; viewport.viewportCount = 1; viewport.scissorCount = 1; - // Depth-stencil state + /* Depth-stencil state */ VkPipelineDepthStencilStateCreateInfo depth_stencil = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; depth_stencil.depthTestEnable = false; @@ -1473,12 +1476,12 @@ bool Pass::init_pipeline() depth_stencil.minDepthBounds = 0.0f; depth_stencil.maxDepthBounds = 1.0f; - // Multisample state + /* Multisample state */ VkPipelineMultisampleStateCreateInfo multisample = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - // Dynamic state + /* Dynamic state */ VkPipelineDynamicStateCreateInfo dynamic = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; static const VkDynamicState dynamics[] = { @@ -1486,7 +1489,7 @@ bool Pass::init_pipeline() dynamic.pDynamicStates = dynamics; dynamic.dynamicStateCount = sizeof(dynamics) / sizeof(dynamics[0]); - // Shaders + /* Shaders */ VkPipelineShaderStageCreateInfo shader_stages[2] = { { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }, { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }, @@ -1539,16 +1542,18 @@ CommonResources::CommonResources(VkDevice device, const VkPhysicalDeviceMemoryProperties &memory_properties) : device(device) { - // The final pass uses an MVP designed for [0, 1] range VBO. - // For in-between passes, we just go with identity matrices, so keep it simple. + /* The final pass uses an MVP designed for [0, 1] range VBO. + * For in-between passes, we just go with identity matrices, + * so keep it simple. + */ const float vbo_data[] = { - // Offscreen + /* Offscreen */ -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, +1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, +1.0f, 1.0f, 1.0f, - // Final + /* Final */ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, +1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, @@ -1657,12 +1662,12 @@ void Pass::allocate_buffers() { if (reflection.ubo_stage_mask) { - // Align + /* Align */ common->ubo_offset = (common->ubo_offset + common->ubo_alignment - 1) & ~(common->ubo_alignment - 1); ubo_offset = common->ubo_offset; - // Allocate + /* Allocate */ common->ubo_offset += reflection.ubo_size; } } @@ -1719,7 +1724,7 @@ bool Pass::build() if (!slang_reflect_spirv(vertex_shader, fragment_shader, &reflection)) return false; - // Filter out parameters which we will never use anyways. + /* Filter out parameters which we will never use anyways. */ filtered_parameters.clear(); for (i = 0; i < reflection.semantic_float_parameters.size(); i++) @@ -1837,7 +1842,7 @@ void Pass::build_semantic_parameter(uint8_t *data, unsigned index, float value) { auto &refl = reflection.semantic_float_parameters[index]; - // We will have filtered out stale parameters. + /* We will have filtered out stale parameters. */ if (data && refl.uniform) *reinterpret_cast(data + refl.ubo_offset) = value; @@ -1876,7 +1881,7 @@ void Pass::build_semantic_texture_array(VkDescriptorSet set, uint8_t *buffer, void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, const float *mvp, const Texture &original, const Texture &source) { - // MVP + /* MVP */ if (buffer && reflection.semantics[SLANG_SEMANTIC_MVP].uniform) { size_t offset = reflection.semantics[SLANG_SEMANTIC_MVP].ubo_offset; @@ -1895,7 +1900,7 @@ void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, build_identity_matrix(reinterpret_cast(push.buffer.data() + (offset >> 2))); } - // Output information + /* Output information */ build_semantic_vec4(buffer, SLANG_SEMANTIC_OUTPUT, current_framebuffer_size.width, current_framebuffer_size.height); build_semantic_vec4(buffer, SLANG_SEMANTIC_FINAL_VIEWPORT, @@ -1904,21 +1909,21 @@ void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, build_semantic_uint(buffer, SLANG_SEMANTIC_FRAME_COUNT, frame_count_period ? uint32_t(frame_count % frame_count_period) : uint32_t(frame_count)); - // Standard inputs + /* Standard inputs */ build_semantic_texture(set, buffer, SLANG_TEXTURE_SEMANTIC_ORIGINAL, original); build_semantic_texture(set, buffer, SLANG_TEXTURE_SEMANTIC_SOURCE, source); - // ORIGINAL_HISTORY[0] is an alias of ORIGINAL. + /* ORIGINAL_HISTORY[0] is an alias of ORIGINAL. */ build_semantic_texture_array(set, buffer, SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY, 0, original); - // Parameters. + /* Parameters. */ for (auto ¶m : filtered_parameters) { float value = common->shader_preset->parameters[param.index].current; build_semantic_parameter(buffer, param.semantic_index, value); } - // Previous inputs. + /* Previous inputs. */ unsigned i = 0; for (auto &texture : common->original_history) { @@ -1928,7 +1933,7 @@ void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, i++; } - // Previous passes. + /* Previous passes. */ i = 0; for (auto &texture : common->pass_outputs) { @@ -1938,7 +1943,7 @@ void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, i++; } - // Feedback FBOs. + /* Feedback FBOs. */ i = 0; for (auto &texture : common->framebuffer_feedback) { @@ -1948,7 +1953,7 @@ void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, i++; } - // LUTs. + /* LUTs. */ i = 0; for (auto &lut : common->luts) { @@ -1997,10 +2002,10 @@ void Pass::build_commands( reflection.ubo_size); } - // The final pass is always executed inside - // another render pass since the frontend will - // want to overlay various things on top for - // the passes that end up on-screen. + /* The final pass is always executed inside + * another render pass since the frontend will + * want to overlay various things on top for + * the passes that end up on-screen. */ if (!final_pass) { /* Render. */ @@ -2086,7 +2091,7 @@ void Pass::build_commands( framebuffer->generate_mips(cmd); else { - // Barrier to sync with next pass. + /* Barrier to sync with next pass. */ vulkan_image_layout_transition_levels( cmd, framebuffer->get_image(),VK_REMAINING_MIP_LEVELS, @@ -2148,19 +2153,20 @@ void Framebuffer::clear(VkCommandBuffer cmd) void Framebuffer::generate_mips(VkCommandBuffer cmd) { unsigned i; - // This is run every frame, so make sure - // we aren't opting into the "lazy" way of doing this. :) + /* This is run every frame, so make sure + * we aren't opting into the "lazy" way of doing this. :) */ VkImageMemoryBarrier barriers[2] = { { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }, { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }, }; - // First, transfer the input mip level to TRANSFER_SRC_OPTIMAL. - // This should allow the surface to stay compressed. - // All subsequent mip-layers are now transferred into DST_OPTIMAL from - // UNDEFINED at this point. + /* First, transfer the input mip level to TRANSFER_SRC_OPTIMAL. + * This should allow the surface to stay compressed. + * All subsequent mip-layers are now transferred into DST_OPTIMAL from + * UNDEFINED at this point. + */ - // Input + /* Input */ barriers[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barriers[0].oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; @@ -2173,7 +2179,7 @@ void Framebuffer::generate_mips(VkCommandBuffer cmd) barriers[0].subresourceRange.levelCount = 1; barriers[0].subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - // The rest of the mip chain + /* The rest of the mip chain */ barriers[1].srcAccessMask = 0; barriers[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barriers[1].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -2196,8 +2202,9 @@ void Framebuffer::generate_mips(VkCommandBuffer cmd) for (i = 1; i < levels; i++) { - // For subsequent passes, we have to transition from DST_OPTIMAL to SRC_OPTIMAL, - // but only do so one mip-level at a time. + /* For subsequent passes, we have to transition + * from DST_OPTIMAL to SRC_OPTIMAL, + * but only do so one mip-level at a time. */ if (i > 1) { barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -2241,10 +2248,15 @@ void Framebuffer::generate_mips(VkCommandBuffer cmd) 1, &blit_region, VK_FILTER_LINEAR); } - // We are now done, and we have all mip-levels except the last in TRANSFER_SRC_OPTIMAL, - // and the last one still on TRANSFER_DST_OPTIMAL, so do a final barrier which - // moves everything to SHADER_READ_ONLY_OPTIMAL in one go along with the execution barrier to next pass. - // Read-to-read memory barrier, so only need execution barrier for first transition. + /* We are now done, and we have all mip-levels except + * the last in TRANSFER_SRC_OPTIMAL, + * and the last one still on TRANSFER_DST_OPTIMAL, + * so do a final barrier which + * moves everything to SHADER_READ_ONLY_OPTIMAL in + * one go along with the execution barrier to next pass. + * Read-to-read memory barrier, so only need execution + * barrier for first transition. + */ barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barriers[0].subresourceRange.baseMipLevel = 0; @@ -2252,7 +2264,7 @@ void Framebuffer::generate_mips(VkCommandBuffer cmd) barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; barriers[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // This is read-after-write barrier. + /* This is read-after-write barrier. */ barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barriers[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barriers[1].subresourceRange.baseMipLevel = levels - 1; @@ -2268,8 +2280,10 @@ void Framebuffer::generate_mips(VkCommandBuffer cmd) 0, nullptr, 2, barriers); - // Next pass will wait for ALL_GRAPHICS_BIT, and since we have dstStage as FRAGMENT_SHADER, - // the dependency chain will ensure we don't start next pass until the mipchain is complete. + /* Next pass will wait for ALL_GRAPHICS_BIT, and since + * we have dstStage as FRAGMENT_SHADER, + * the dependency chain will ensure we don't start + * next pass until the mipchain is complete. */ } void Framebuffer::copy(VkCommandBuffer cmd, @@ -2336,11 +2350,12 @@ void Framebuffer::init(DeferredDisposer *disposer) memory_properties, mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - // Can reuse already allocated memory. + /* Can reuse already allocated memory. */ if (memory.size < mem_reqs.size || memory.type != alloc.memoryTypeIndex) { - // Memory might still be in use since we don't want to totally stall - // the world for framebuffer recreation. + /* Memory might still be in use since we don't want + * to totally stall + * the world for framebuffer recreation. */ if (memory.memory != VK_NULL_HANDLE && disposer) { auto d = device; @@ -2385,8 +2400,8 @@ void Framebuffer::init_render_pass() VkAttachmentReference color_ref = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - // We will always write to the entire framebuffer, - // so we don't really need to clear. + /* We will always write to the entire framebuffer, + * so we don't really need to clear. */ VkAttachmentDescription attachment = {0}; attachment.format = format; attachment.samples = VK_SAMPLE_COUNT_1_BIT; @@ -2435,13 +2450,13 @@ void Framebuffer::set_size(DeferredDisposer &disposer, const Size2D &size, VkFor size.width, size.height, (unsigned)this->format); { - // The current framebuffers, etc, might still be in use - // so defer deletion. - // We'll most likely be able to reuse the memory, - // so don't free it here. - // - // Fake lambda init captures for C++11. - // + /* The current framebuffers, etc, might still be in use + * so defer deletion. + * We'll most likely be able to reuse the memory, + * so don't free it here. + * + * Fake lambda init captures for C++11. + */ auto d = device; auto i = image; auto v = view; @@ -2479,7 +2494,7 @@ Framebuffer::~Framebuffer() vkFreeMemory(device, memory.memory, nullptr); } -// C glue +/* C glue */ vulkan_filter_chain_t *vulkan_filter_chain_new( const vulkan_filter_chain_create_info *info) { @@ -2871,7 +2886,8 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( if (itr != shader->parameters + shader->num_parameters) { - // Allow duplicate #pragma parameter, but only if they are exactly the same. + /* Allow duplicate #pragma parameter, but + * only if they are exactly the same. */ if (meta_param.desc != itr->desc || meta_param.initial != itr->initial || meta_param.minimum != itr->minimum || @@ -2914,7 +2930,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( if (!output.meta.name.empty()) chain->set_pass_name(i, output.meta.name.c_str()); - // Preset overrides. + /* Preset overrides. */ if (*pass->alias) chain->set_pass_name(i, pass->alias); @@ -2929,9 +2945,10 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( pass_info.address = wrap_to_address(pass->wrap); pass_info.max_levels = 1; - // TODO: Expose max_levels in slangp. - // CGP format is a bit awkward in that it uses mipmap_input, - // so we much check if next pass needs the mipmapping. + /* TODO: Expose max_levels in slangp. + * CGP format is a bit awkward in that it uses mipmap_input, + * so we much check if next pass needs the mipmapping. + */ if (next_pass && next_pass->mipmap) pass_info.max_levels = ~0u; @@ -2940,7 +2957,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( bool explicit_format = output.meta.rt_format != SLANG_FORMAT_UNKNOWN; - // Set a reasonable default. + /* Set a reasonable default. */ if (output.meta.rt_format == SLANG_FORMAT_UNKNOWN) output.meta.rt_format = SLANG_FORMAT_R8G8B8A8_UNORM; @@ -2972,13 +2989,12 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( } else { - // Preset overrides shader. - // Kinda ugly ... + /* Preset overrides shader. + * Kinda ugly ... */ if (pass->fbo.srgb_fbo) output.meta.rt_format = SLANG_FORMAT_R8G8B8A8_SRGB; else if (pass->fbo.fp_fbo) output.meta.rt_format = SLANG_FORMAT_R16G16B16A16_SFLOAT; - /// pass_info.rt_format = glslang_format_to_vk(output.meta.rt_format); RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n", From 0abe27190942eb443927a142201de4a699ebda4e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 19 Jan 2019 23:15:48 +0100 Subject: [PATCH 025/234] Take out some header includes --- discord/discord.c | 31 ++++++++++++++++++---------- discord/discord.h | 13 +++--------- gfx/drivers_shader/glslang_util.cpp | 10 +++++---- gfx/drivers_shader/slang_process.cpp | 16 +++++++++++++- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/discord/discord.c b/discord/discord.c index 80a74c96e7..ca3b9da9ee 100644 --- a/discord/discord.c +++ b/discord/discord.c @@ -14,16 +14,21 @@ */ #include +#include +#include #include "discord.h" #include "discord_register.h" +#include "../deps/discord-rpc/include/discord_rpc.h" + #include "../retroarch.h" #include "../configuration.h" #include "../core.h" #include "../core_info.h" #include "../paths.h" #include "../playlist.h" +#include "../verbosity.h" #include "../msg_hash.h" @@ -305,11 +310,13 @@ void discord_update(enum discord_presence presence) discord_presence.instance = 0; break; case DISCORD_PRESENCE_GAME_PAUSED: - discord_presence.smallImageKey = "paused"; - discord_presence.smallImageText = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PAUSED); - discord_presence.details = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME_PAUSED); - pause_time = time(0); - ellapsed_time = difftime(time(0), start_time); + discord_presence.smallImageKey = "paused"; + discord_presence.smallImageText = msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PAUSED); + discord_presence.details = msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME_PAUSED); + pause_time = time(0); + ellapsed_time = difftime(time(0), start_time); discord_presence.startTimestamp = pause_time; break; case DISCORD_PRESENCE_GAME: @@ -339,13 +346,15 @@ void discord_update(enum discord_presence presence) if (pause_time != 0) start_time = time(0) - ellapsed_time; - pause_time = 0; + pause_time = 0; ellapsed_time = 0; discord_presence.smallImageKey = "playing"; - discord_presence.smallImageText = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PLAYING); + discord_presence.smallImageText = msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PLAYING); discord_presence.startTimestamp = start_time; - discord_presence.details = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME); + discord_presence.details = msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME); discord_presence.state = label; discord_presence.instance = 0; @@ -366,9 +375,9 @@ void discord_update(enum discord_presence presence) snprintf(join_secret, sizeof(join_secret), "%d|%s", room->id, room->nickname); discord_presence.joinSecret = strdup(join_secret); /* discord_presence.spectateSecret = "SPECSPECSPEC"; */ - discord_presence.partyId = strdup(party_name); - discord_presence.partyMax = 0; - discord_presence.partySize = 0; + discord_presence.partyId = strdup(party_name); + discord_presence.partyMax = 0; + discord_presence.partySize = 0; RARCH_LOG("[Discord] join secret: %s\n", join_secret); RARCH_LOG("[Discord] party id: %s\n", party_name); diff --git a/discord/discord.h b/discord/discord.h index 34505dae59..3b0f8d693d 100644 --- a/discord/discord.h +++ b/discord/discord.h @@ -20,15 +20,8 @@ #include #include #include -#include #include -#include -#include -#include - -#include "../deps/discord-rpc/include/discord_rpc.h" -#include "verbosity.h" enum discord_presence { @@ -53,13 +46,13 @@ void discord_shutdown(void); void discord_update(enum discord_presence presence); -void discord_run_callbacks(); +void discord_run_callbacks(void); -bool discord_is_ready(); +bool discord_is_ready(void); void discord_avatar_set_ready(bool ready); -bool discord_avatar_is_ready(); +bool discord_avatar_is_ready(void); char* discord_get_own_username(void); diff --git a/gfx/drivers_shader/glslang_util.cpp b/gfx/drivers_shader/glslang_util.cpp index eb7dbfe41d..a817ac3ac3 100644 --- a/gfx/drivers_shader/glslang_util.cpp +++ b/gfx/drivers_shader/glslang_util.cpp @@ -293,6 +293,8 @@ bool glslang_parse_meta(const vector &lines, glslang_meta *meta) for (auto &line : lines) { + const char *line_c = line.c_str(); + if (line.find("#pragma name ") == 0) { const char *str = NULL; @@ -303,7 +305,7 @@ bool glslang_parse_meta(const vector &lines, glslang_meta *meta) return false; } - str = line.c_str() + strlen("#pragma name "); + str = line_c + strlen("#pragma name "); while (*str == ' ') str++; @@ -312,7 +314,7 @@ bool glslang_parse_meta(const vector &lines, glslang_meta *meta) else if (line.find("#pragma parameter ") == 0) { float initial, minimum, maximum, step; - int ret = sscanf(line.c_str(), "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", + int ret = sscanf(line_c, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", id, desc, &initial, &minimum, &maximum, &step); if (ret == 5) @@ -347,7 +349,7 @@ bool glslang_parse_meta(const vector &lines, glslang_meta *meta) } else { - RARCH_ERR("[slang]: Invalid #pragma parameter line: \"%s\".\n", line.c_str()); + RARCH_ERR("[slang]: Invalid #pragma parameter line: \"%s\".\n", line_c); return false; } } @@ -361,7 +363,7 @@ bool glslang_parse_meta(const vector &lines, glslang_meta *meta) return false; } - str = line.c_str() + strlen("#pragma format "); + str = line_c + strlen("#pragma format "); while (*str == ' ') str++; diff --git a/gfx/drivers_shader/slang_process.cpp b/gfx/drivers_shader/slang_process.cpp index 5d9d91b563..84a7c89c44 100644 --- a/gfx/drivers_shader/slang_process.cpp +++ b/gfx/drivers_shader/slang_process.cpp @@ -1,4 +1,18 @@ - +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2017 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + #include #include #include From 83241ed0b17d0236ddcb4b0610f4d0a180224821 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 19 Jan 2019 23:27:59 +0100 Subject: [PATCH 026/234] Some header cleanups --- discord/discord.c | 2 +- gfx/common/vulkan_common.c | 10 ++++------ ui/drivers/qt/ui_qt_window.cpp | 2 -- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/discord/discord.c b/discord/discord.c index ca3b9da9ee..e971825597 100644 --- a/discord/discord.c +++ b/discord/discord.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include "discord.h" #include "discord_register.h" diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 9958f7526b..2dff930de7 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -28,15 +28,13 @@ #endif #include "vulkan_common.h" -#include "../../libretro-common/include/retro_timers.h" +#include #include "../../configuration.h" #include "../include/vulkan/vulkan.h" -#include "../../libretro-common/include/retro_assert.h" +#include #include "vksym.h" -#include "../../libretro-common/include/dynamic/dylib.h" -#include "../../libretro-common/include/libretro_vulkan.h" -#include "../../libretro-common/include/retro_math.h" -#include "../../libretro-common/include/string/stdstring.h" +#include +#include #define VENDOR_ID_AMD 0x1002 #define VENDOR_ID_NV 0x10DE diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index b6618adec9..cdfd39b98a 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include "../ui_qt.h" #include "invader_png.h" @@ -74,7 +73,6 @@ extern "C" { #include #include #include -#include #ifdef HAVE_OPENSSL #include #include From 22e99568edaa0d5cfef3753ab2fcc37b1ed7a0b1 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 00:48:02 +0100 Subject: [PATCH 027/234] Small cleanups --- gfx/drivers/gl.c | 3 ++- menu/drivers/rgui.c | 50 +++++++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index 76ec8dc164..410dd8f5c3 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -2563,9 +2563,10 @@ static uintptr_t gl_load_texture(void *video_data, void *data, static void gl_unload_texture(void *video_data, uintptr_t data, bool threaded) { + GLuint glid; if (!data) return; - GLuint glid = (GLuint)data; + glid = (GLuint)data; #ifdef HAVE_THREADS if (threaded) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 580c8ee9d5..9dd3dceeba 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -648,9 +648,8 @@ static void load_thumbnail(const char *path) /* Do nothing if current thumbnail path hasn't changed */ if (!string_is_empty(thumbnail.path) && !string_is_empty(thumbnail.path)) { - if (string_is_equal(thumbnail.path, path)) { + if (string_is_equal(thumbnail.path, path)) return; - } } /* 'Reset' current thumbnail */ @@ -670,25 +669,33 @@ static void load_thumbnail(const char *path) if (rpng_load_image_argb(path, &png_data, &width, &height)) { /* Have to crop image if larger than max allowed size... */ - if (width > THUMB_MAX_WIDTH) { + if (width > THUMB_MAX_WIDTH) + { x_offset = (width - THUMB_MAX_WIDTH) >> 1; thumbnail.width = THUMB_MAX_WIDTH; - } else { + } + else + { x_offset = 0; thumbnail.width = width; } - if (height > THUMB_MAX_HEIGHT) { + if (height > THUMB_MAX_HEIGHT) + { y_offset = (height - THUMB_MAX_HEIGHT) >> 1; thumbnail.height = THUMB_MAX_HEIGHT; - } else { + } + else + { y_offset = 0; thumbnail.height = height; } /* Copy (cropped) image to thumbnail buffer, performing * pixel format conversion */ - for (x = 0; x < thumbnail.width; x++) { - for (y = 0; y < thumbnail.height; y++) { + for (x = 0; x < thumbnail.width; x++) + { + for (y = 0; y < thumbnail.height; y++) + { thumbnail.data[x + (y * thumbnail.width)] = argb32_to_pixel_platform_format(png_data[(x + x_offset) + ((y + y_offset) * width)]); } @@ -721,28 +728,36 @@ static void rgui_render_thumbnail(void) * cannot assume fb_width and fb_height are constant and * >= thumbnail.width and thumbnail.height (even though * they are...) */ - if (thumbnail.width <= fb_width) { + if (thumbnail.width <= fb_width) + { thumb_x_offset = 0; fb_x_offset = (fb_width - thumbnail.width) >> 1; width = thumbnail.width; - } else { + } + else + { thumb_x_offset = (thumbnail.width - fb_width) >> 1; fb_x_offset = 0; width = fb_width; } - if (thumbnail.height <= fb_height) { + if (thumbnail.height <= fb_height) + { thumb_y_offset = 0; fb_y_offset = (fb_height - thumbnail.height) >> 1; height = thumbnail.height; - } else { + } + else + { thumb_y_offset = (thumbnail.height - fb_height) >> 1; fb_y_offset = 0; height = fb_height; } /* Copy thumbnail to framebuffer */ - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { rgui_framebuf_data[(y + fb_y_offset) * (fb_pitch >> 1) + (x + fb_x_offset)] = thumbnail.data[(x + thumb_x_offset) + ((y + thumb_y_offset) * thumbnail.width)]; } @@ -829,6 +844,7 @@ static void prepare_rgui_colors(rgui_t *rgui, settings_t *settings) { rgui_theme_t theme_colors; rgui->color_theme = settings->uints.menu_rgui_color_theme; + if (rgui->color_theme == RGUI_THEME_CUSTOM) { theme_colors.hover_color = settings->uints.menu_entry_hover_color; @@ -1691,16 +1707,12 @@ static void rgui_update_thumbnail_path(void *userdata) tmp_new[0] = '\0'; while((scrub_char_pointer = strpbrk(tmp, "&*/:`\"<>?\\|"))) - { *scrub_char_pointer = '_'; - } fill_pathname_join(tmp_new, new_path, tmp, PATH_MAX_LENGTH * sizeof(char)); if (!string_is_empty(tmp_new)) - { strlcpy(new_path, tmp_new, sizeof(new_path)); - } free(tmp_new); tmp_new = NULL; @@ -1713,9 +1725,7 @@ static void rgui_update_thumbnail_path(void *userdata) strlcat(new_path, file_path_str(FILE_PATH_PNG_EXTENSION), sizeof(new_path)); if (!string_is_empty(new_path)) - { rgui->thumbnail_path = strdup(new_path); - } } } } From d3ae2cbd298ba9db057e5430d29bb1806481bff5 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 01:49:21 +0100 Subject: [PATCH 028/234] Cleanup some header includes --- gfx/common/gl_common.h | 2 +- gfx/common/vulkan_common.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gfx/common/gl_common.h b/gfx/common/gl_common.h index 893fdfb709..b3d44e011c 100644 --- a/gfx/common/gl_common.h +++ b/gfx/common/gl_common.h @@ -29,13 +29,13 @@ #include #include #include +#include #include #include "../../verbosity.h" #include "../font_driver.h" #include "../video_coord_array.h" #include "../video_driver.h" -#include RETRO_BEGIN_DECLS diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index a16104087c..f09a06ff83 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -48,10 +48,7 @@ #include "../font_driver.h" #include "../video_driver.h" #include "../drivers_shader/shader_vulkan.h" -#include "../../libretro-common/include/gfx/math/matrix_4x4.h" #include "../include/vulkan/vulkan.h" -#include "../../libretro-common/include/gfx/scaler/scaler.h" -#include "../../libretro-common/include/libretro_vulkan.h" RETRO_BEGIN_DECLS From 8349f9217cc0a12149d0147904bbd7f8c53bfac6 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 01:52:20 +0100 Subject: [PATCH 029/234] Warning cleanup --- gfx/drivers/gl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index 410dd8f5c3..a7abdfecca 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -2563,10 +2563,8 @@ static uintptr_t gl_load_texture(void *video_data, void *data, static void gl_unload_texture(void *video_data, uintptr_t data, bool threaded) { - GLuint glid; if (!data) return; - glid = (GLuint)data; #ifdef HAVE_THREADS if (threaded) From 9bb7132b97b6b585e2cba743d62143010dd3f76a Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 01:57:24 +0100 Subject: [PATCH 030/234] Move command_playlist_ functions to playlist.c (RGUI) Header buildfix --- command.c | 50 --------------------------------------------- command.h | 19 ----------------- menu/drivers/rgui.c | 2 ++ playlist.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ playlist.h | 17 +++++++++++++++ 5 files changed, 69 insertions(+), 69 deletions(-) diff --git a/command.c b/command.c index 7d97477708..a55eed7c12 100644 --- a/command.c +++ b/command.c @@ -1766,56 +1766,6 @@ static bool command_event_resize_windowed_scale(void) return true; } -void command_playlist_push_write( - playlist_t *playlist, - const char *path, - const char *label, - const char *core_path, - const char *core_name) -{ - if (!playlist) - return; - - if (playlist_push( - playlist, - path, - label, - core_path, - core_name, - NULL, - NULL - )) - playlist_write_file(playlist); -} - -void command_playlist_update_write( - playlist_t *plist, - size_t idx, - const char *path, - const char *label, - const char *core_path, - const char *core_display_name, - const char *crc32, - const char *db_name) -{ - playlist_t *playlist = plist ? plist : playlist_get_cached(); - - if (!playlist) - return; - - playlist_update( - playlist, - idx, - path, - label, - core_path, - core_display_name, - crc32, - db_name); - - playlist_write_file(playlist); -} - /** * command_event: * @cmd : Event command index. diff --git a/command.h b/command.h index 7659ea605a..f6cf023d1a 100644 --- a/command.h +++ b/command.h @@ -27,8 +27,6 @@ #include "config.h" #endif -#include "playlist.h" - RETRO_BEGIN_DECLS typedef struct command command_t; @@ -272,23 +270,6 @@ bool command_free(command_t *handle); **/ bool command_event(enum event_command action, void *data); -void command_playlist_push_write( - playlist_t *playlist, - const char *path, - const char *label, - const char *core_path, - const char *core_name); - -void command_playlist_update_write( - playlist_t *playlist, - size_t idx, - const char *path, - const char *label, - const char *core_path, - const char *core_display_name, - const char *crc32, - const char *db_name); - RETRO_END_DECLS #endif diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 9dd3dceeba..e7d125a7b4 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include "../../config.h" #endif +#include "../../playlist.h" #include "../../frontend/frontend_driver.h" #include "menu_generic.h" diff --git a/playlist.c b/playlist.c index 52510d0765..1149fbb1c8 100644 --- a/playlist.c +++ b/playlist.c @@ -1057,3 +1057,53 @@ void playlist_qsort(playlist_t *playlist) sizeof(struct playlist_entry), (int (*)(const void *, const void *))playlist_qsort_func); } + +void command_playlist_push_write( + playlist_t *playlist, + const char *path, + const char *label, + const char *core_path, + const char *core_name) +{ + if (!playlist) + return; + + if (playlist_push( + playlist, + path, + label, + core_path, + core_name, + NULL, + NULL + )) + playlist_write_file(playlist); +} + +void command_playlist_update_write( + playlist_t *plist, + size_t idx, + const char *path, + const char *label, + const char *core_path, + const char *core_display_name, + const char *crc32, + const char *db_name) +{ + playlist_t *playlist = plist ? plist : playlist_get_cached(); + + if (!playlist) + return; + + playlist_update( + playlist, + idx, + path, + label, + core_path, + core_display_name, + crc32, + db_name); + + playlist_write_file(playlist); +} diff --git a/playlist.h b/playlist.h index b6b2414070..308297142e 100644 --- a/playlist.h +++ b/playlist.h @@ -135,6 +135,23 @@ playlist_t *playlist_get_cached(void); bool playlist_init_cached(const char *path, size_t size); +void command_playlist_push_write( + playlist_t *playlist, + const char *path, + const char *label, + const char *core_path, + const char *core_name); + +void command_playlist_update_write( + playlist_t *playlist, + size_t idx, + const char *path, + const char *label, + const char *core_path, + const char *core_display_name, + const char *crc32, + const char *db_name); + RETRO_END_DECLS #endif From 0083e10926628a6322a4c9bca29ddc9383b8c7a2 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 02:17:43 +0100 Subject: [PATCH 031/234] Some header include changes - create task_file_transfer.h --- discord/discord.c | 1 + menu/cbs/menu_cbs_ok.c | 1 + menu/menu_networking.c | 1 + tasks/task_audio_mixer.c | 1 + tasks/task_file_transfer.c | 1 + tasks/task_file_transfer.h | 73 +++++++++++++++++++++++++++++++++++ tasks/task_http.c | 1 + tasks/task_image.c | 1 + tasks/task_netplay_lan_scan.c | 1 + tasks/task_wifi.c | 2 + tasks/tasks_internal.h | 44 --------------------- 11 files changed, 83 insertions(+), 44 deletions(-) create mode 100644 tasks/task_file_transfer.h diff --git a/discord/discord.c b/discord/discord.c index e971825597..401f7d167d 100644 --- a/discord/discord.c +++ b/discord/discord.c @@ -31,6 +31,7 @@ #include "../verbosity.h" #include "../msg_hash.h" +#include "../tasks/task_file_transfer.h" #ifdef HAVE_NETWORKING #include "../../network/netplay/netplay.h" diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index d95f527b28..c8f5dbe88e 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -57,6 +57,7 @@ #include "../../defaults.h" #include "../../managers/core_option_manager.h" #include "../../managers/cheat_manager.h" +#include "../../tasks/task_file_transfer.h" #include "../../tasks/tasks_internal.h" #include "../../input/input_remapping.h" #include "../../paths.h" diff --git a/menu/menu_networking.c b/menu/menu_networking.c index 4d2a2beec9..38dee85723 100644 --- a/menu/menu_networking.c +++ b/menu/menu_networking.c @@ -39,6 +39,7 @@ #include "../configuration.h" #include "../file_path_special.h" #include "../msg_hash.h" +#include "../tasks/task_file_transfer.h" #include "../tasks/tasks_internal.h" void print_buf_lines(file_list_t *list, char *buf, diff --git a/tasks/task_audio_mixer.c b/tasks/task_audio_mixer.c index 2887d0e86c..19a1758817 100644 --- a/tasks/task_audio_mixer.c +++ b/tasks/task_audio_mixer.c @@ -32,6 +32,7 @@ #include "../file_path_special.h" #include "../verbosity.h" +#include "task_file_transfer.h" #include "tasks_internal.h" typedef struct nbio_buf diff --git a/tasks/task_file_transfer.c b/tasks/task_file_transfer.c index 2249681508..df57c452a4 100644 --- a/tasks/task_file_transfer.c +++ b/tasks/task_file_transfer.c @@ -21,6 +21,7 @@ #include +#include "task_file_transfer.h" #include "tasks_internal.h" #include "../verbosity.h" diff --git a/tasks/task_file_transfer.h b/tasks/task_file_transfer.h new file mode 100644 index 0000000000..ef04c85065 --- /dev/null +++ b/tasks/task_file_transfer.h @@ -0,0 +1,73 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef TASKS_FILE_TRANSFER_H +#define TASKS_FILE_TRANSFER_H + +#include +#include +#include + +#include + +#include "../msg_hash.h" + +RETRO_BEGIN_DECLS + +enum nbio_type +{ + NBIO_TYPE_NONE = 0, + NBIO_TYPE_JPEG, + NBIO_TYPE_PNG, + NBIO_TYPE_TGA, + NBIO_TYPE_BMP, + NBIO_TYPE_OGG, + NBIO_TYPE_FLAC, + NBIO_TYPE_MP3, + NBIO_TYPE_MOD, + NBIO_TYPE_WAV +}; + +enum nbio_status_flags +{ + NBIO_FLAG_NONE = 0, + NBIO_FLAG_IMAGE_SUPPORTS_RGBA +}; + +typedef int (*transfer_cb_t)(void *data, size_t len); + +typedef struct nbio_handle +{ + enum nbio_type type; + bool is_finished; + unsigned status; + unsigned pos_increment; + uint32_t status_flags; + void *data; + char *path; + struct nbio_t *handle; + msg_queue_t *msg_queue; + transfer_cb_t cb; +} nbio_handle_t; + +typedef struct +{ + enum msg_hash_enums enum_idx; + char path[PATH_MAX_LENGTH]; +} file_transfer_t; + +RETRO_END_DECLS + +#endif diff --git a/tasks/task_http.c b/tasks/task_http.c index 4c595f18d8..6d9b0cf110 100644 --- a/tasks/task_http.c +++ b/tasks/task_http.c @@ -24,6 +24,7 @@ #include "../verbosity.h" #include "../gfx/video_display_server.h" +#include "task_file_transfer.h" #include "tasks_internal.h" enum http_status_enum diff --git a/tasks/task_image.c b/tasks/task_image.c index 1828cec7c0..5673242da9 100644 --- a/tasks/task_image.c +++ b/tasks/task_image.c @@ -28,6 +28,7 @@ #include "../file_path_special.h" #include "../verbosity.h" +#include "task_file_transfer.h" #include "tasks_internal.h" enum image_status_enum diff --git a/tasks/task_netplay_lan_scan.c b/tasks/task_netplay_lan_scan.c index b05348c63b..dba19116e6 100644 --- a/tasks/task_netplay_lan_scan.c +++ b/tasks/task_netplay_lan_scan.c @@ -18,6 +18,7 @@ #include #include "../paths.h" +#include "task_file_transfer.h" #include "tasks_internal.h" #ifdef HAVE_CONFIG_H diff --git a/tasks/task_wifi.c b/tasks/task_wifi.c index 7003b23163..bf945b3c36 100644 --- a/tasks/task_wifi.c +++ b/tasks/task_wifi.c @@ -21,6 +21,8 @@ #include #include "tasks_internal.h" + +#include "../msg_hash.h" #include "../verbosity.h" #include "../wifi/wifi_driver.h" diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 3eeaec5a0c..1b94e25f3b 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -22,7 +22,6 @@ #include #include -#include #include #ifdef HAVE_CONFIG_H @@ -33,12 +32,9 @@ #include "../content.h" #include "../core_type.h" -#include "../msg_hash.h" RETRO_BEGIN_DECLS -typedef int (*transfer_cb_t)(void *data, size_t len); - enum content_mode_load { CONTENT_MODE_LOAD_NONE = 0, @@ -55,46 +51,6 @@ enum nbio_status_enum NBIO_STATUS_TRANSFER_FINISHED }; -enum nbio_status_flags -{ - NBIO_FLAG_NONE = 0, - NBIO_FLAG_IMAGE_SUPPORTS_RGBA -}; - -enum nbio_type -{ - NBIO_TYPE_NONE = 0, - NBIO_TYPE_JPEG, - NBIO_TYPE_PNG, - NBIO_TYPE_TGA, - NBIO_TYPE_BMP, - NBIO_TYPE_OGG, - NBIO_TYPE_FLAC, - NBIO_TYPE_MP3, - NBIO_TYPE_MOD, - NBIO_TYPE_WAV -}; - -typedef struct nbio_handle -{ - enum nbio_type type; - bool is_finished; - unsigned status; - unsigned pos_increment; - uint32_t status_flags; - void *data; - char *path; - struct nbio_t *handle; - msg_queue_t *msg_queue; - transfer_cb_t cb; -} nbio_handle_t; - -typedef struct -{ - enum msg_hash_enums enum_idx; - char path[PATH_MAX_LENGTH]; -} file_transfer_t; - #ifdef HAVE_NETWORKING typedef struct { From 4f53e14f4ff24b8854fcdd15fc6d988fb9502490 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 02:26:33 +0100 Subject: [PATCH 032/234] Header include cleanups --- dynamic.c | 3 ++- dynamic.h | 3 +-- runahead/dirty_input.c | 3 +-- runahead/mylist.h | 1 + 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dynamic.c b/dynamic.c index a6d3074013..64d6a3890d 100644 --- a/dynamic.c +++ b/dynamic.c @@ -496,8 +496,9 @@ bool libretro_get_system_info(const char *path, * Setup libretro callback symbols. Returns true on success, * or false if symbols could not be loaded. **/ -bool init_libretro_sym_custom(enum rarch_core_type type, struct retro_core_t *current_core, const char *lib_path, dylib_t *lib_handle_p) +bool init_libretro_sym_custom(enum rarch_core_type type, struct retro_core_t *current_core, const char *lib_path, void *_lib_handle_p) { + dylib_t *lib_handle_p = (dylib_t*)_lib_handle_p; #ifdef HAVE_DYNAMIC /* the library handle for use with the SYMBOL macro */ dylib_t lib_handle_local; diff --git a/dynamic.h b/dynamic.h index 2138927f58..a879e38d71 100644 --- a/dynamic.h +++ b/dynamic.h @@ -20,7 +20,6 @@ #include #include #include -#include #include "core_type.h" @@ -133,7 +132,7 @@ bool libretro_get_shared_context(void); bool init_libretro_sym(enum rarch_core_type type, struct retro_core_t *core); -bool init_libretro_sym_custom(enum rarch_core_type type, struct retro_core_t *current_core, const char *lib_path, dylib_t *lib_handle_p); +bool init_libretro_sym_custom(enum rarch_core_type type, struct retro_core_t *current_core, const char *lib_path, void *lib_handle_p); /** * uninit_libretro_sym: diff --git a/runahead/dirty_input.c b/runahead/dirty_input.c index 7aa33f632c..f167692b43 100644 --- a/runahead/dirty_input.c +++ b/runahead/dirty_input.c @@ -1,6 +1,7 @@ #include #include +#include #include "../core.h" #include "../dynamic.h" @@ -98,9 +99,7 @@ static void input_state_set_last(unsigned port, unsigned device, ) { if (id >= element->state_size) - { InputListElementExpand(element, id); - } element->state[id] = value; return; } diff --git a/runahead/mylist.h b/runahead/mylist.h index be9a12d8dd..ec0238912d 100644 --- a/runahead/mylist.h +++ b/runahead/mylist.h @@ -4,6 +4,7 @@ #include #include #include +#include RETRO_BEGIN_DECLS From 2e5530b531614ef7558af8f8e0d3bdf08e7c127d Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 02:32:27 +0100 Subject: [PATCH 033/234] Take out unused variable --- menu/drivers/rgui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index e7d125a7b4..40e20ddf73 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -644,7 +644,7 @@ static void load_thumbnail(const char *path) { unsigned width, height; uint32_t *png_data = NULL; - unsigned x, y, index; + unsigned x, y; unsigned x_offset, y_offset; /* Do nothing if current thumbnail path hasn't changed */ From 7c4fcb4960e948bb822a349620934e58ab466c42 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Sun, 20 Jan 2019 02:37:05 +0100 Subject: [PATCH 034/234] Fix Xcode warnings --- dynamic.c | 12 +++++------- menu/drivers/null.c | 4 ---- menu/drivers/ozone/ozone.c | 1 - menu/drivers/xmb.c | 1 - runahead/secondary_core.c | 1 - 5 files changed, 5 insertions(+), 14 deletions(-) diff --git a/dynamic.c b/dynamic.c index 64d6a3890d..274169bf31 100644 --- a/dynamic.c +++ b/dynamic.c @@ -191,9 +191,7 @@ static bool environ_cb_get_system_info(unsigned cmd, void *data) break; case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO: { - unsigned i = 0; - unsigned j = 0; - unsigned size = i; + unsigned i, j, size; const struct retro_subsystem_info *info = (const struct retro_subsystem_info*)data; subsystem_current_count = 0; @@ -1516,7 +1514,7 @@ bool rarch_environment_cb(unsigned cmd, void *data) { memcpy(hwr, cb, offsetof(struct retro_hw_render_callback, stencil)); - memset((uint8_t*)hwr + offsetof(struct retro_hw_render_callback, stencil), + memset((uint8_t*)hwr + offsetof(struct retro_hw_render_callback, stencil), 0, sizeof(*cb) - offsetof(struct retro_hw_render_callback, stencil)); } else @@ -1930,7 +1928,7 @@ bool rarch_environment_cb(unsigned cmd, void *data) { const uint32_t supported_vfs_version = 3; static struct retro_vfs_interface vfs_iface = - { + { /* VFS API v1 */ retro_vfs_file_get_path_impl, retro_vfs_file_open_impl, @@ -1942,9 +1940,9 @@ bool rarch_environment_cb(unsigned cmd, void *data) retro_vfs_file_write_impl, retro_vfs_file_flush_impl, retro_vfs_file_remove_impl, - retro_vfs_file_rename_impl, + retro_vfs_file_rename_impl, /* VFS API v2 */ - retro_vfs_file_truncate_impl, + retro_vfs_file_truncate_impl, /* VFS API v3 */ retro_vfs_stat_impl, retro_vfs_mkdir_impl, diff --git a/menu/drivers/null.c b/menu/drivers/null.c index 9022267cb1..35708a5e81 100644 --- a/menu/drivers/null.c +++ b/menu/drivers/null.c @@ -36,10 +36,6 @@ static void* null_init(void **userdata, bool video_is_threaded) static void null_free(void *data) { - menu_handle_t *menu = (menu_handle_t*)data; - - /*if (menu) - free(menu);*/ } static void null_toggle(void *userdata, bool menu_on) diff --git a/menu/drivers/ozone/ozone.c b/menu/drivers/ozone/ozone.c index 957a30cfc8..dd133b282a 100644 --- a/menu/drivers/ozone/ozone.c +++ b/menu/drivers/ozone/ozone.c @@ -526,7 +526,6 @@ static int ozone_list_push(void *data, void *userdata, { menu_displaylist_ctx_parse_entry_t entry; int ret = -1; - unsigned i = 0; core_info_list_t *list = NULL; menu_handle_t *menu = (menu_handle_t*)data; const struct retro_subsystem_info* subsystem; diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index eb07a978f3..7c6ac6b526 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -5475,7 +5475,6 @@ static int xmb_list_push(void *data, void *userdata, { menu_displaylist_ctx_parse_entry_t entry; int ret = -1; - unsigned i = 0; core_info_list_t *list = NULL; menu_handle_t *menu = (menu_handle_t*)data; const struct retro_subsystem_info* subsystem; diff --git a/runahead/secondary_core.c b/runahead/secondary_core.c index b30dc30156..7ff00f8ed9 100644 --- a/runahead/secondary_core.c +++ b/runahead/secondary_core.c @@ -51,7 +51,6 @@ void clear_controller_port_map(void); static char *get_temp_directory_alloc(void) { - settings_t *settings = config_get_ptr(); char *path = NULL; #ifdef _WIN32 #ifdef LEGACY_WIN32 From cfd72284697977c93844e317fbee2021b1f06ccc Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 02:57:12 +0100 Subject: [PATCH 035/234] Cleanups --- tasks/task_file_transfer.h | 8 ++++++++ tasks/tasks_internal.h | 11 ++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tasks/task_file_transfer.h b/tasks/task_file_transfer.h index ef04c85065..f1dc43379a 100644 --- a/tasks/task_file_transfer.h +++ b/tasks/task_file_transfer.h @@ -26,6 +26,14 @@ RETRO_BEGIN_DECLS +enum nbio_status_enum +{ + NBIO_STATUS_INIT = 0, + NBIO_STATUS_TRANSFER, + NBIO_STATUS_TRANSFER_PARSE, + NBIO_STATUS_TRANSFER_FINISHED +}; + enum nbio_type { NBIO_TYPE_NONE = 0, diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 1b94e25f3b..06d4c98b19 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -43,14 +43,6 @@ enum content_mode_load CONTENT_MODE_LOAD_CONTENT_WITH_IMAGEVIEWER_CORE_FROM_MENU }; -enum nbio_status_enum -{ - NBIO_STATUS_INIT = 0, - NBIO_STATUS_TRANSFER, - NBIO_STATUS_TRANSFER_PARSE, - NBIO_STATUS_TRANSFER_FINISHED -}; - #ifdef HAVE_NETWORKING typedef struct { @@ -182,7 +174,8 @@ void task_file_load_handler(retro_task_t *task); bool task_audio_mixer_load_handler(retro_task_t *task); -bool take_screenshot(const char *path, bool silence, bool has_valid_framebuffer, bool fullpath, bool use_thread); +bool take_screenshot(const char *path, bool silence, + bool has_valid_framebuffer, bool fullpath, bool use_thread); bool event_load_save_files(void); From b13777e9fcc20fc119ede91ef0d87e1f54bb821e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 03:16:58 +0100 Subject: [PATCH 036/234] Header cleanups --- command.c | 1 + configuration.c | 1 + frontend/frontend.c | 3 +- gfx/common/win32_common.c | 2 +- menu/cbs/menu_cbs_ok.c | 1 + menu/drivers/ozone/ozone.c | 1 + menu/drivers/xmb.c | 1 + network/netplay/netplay_frontend.c | 2 + retroarch.c | 1 + tasks/task_content.c | 1 + tasks/task_content.h | 117 +++++++++++++++++++++++++++++ tasks/task_netplay_find_content.c | 1 + tasks/task_powerstate.h | 37 +++++++++ tasks/task_save.c | 1 + tasks/tasks_internal.h | 86 --------------------- ui/drivers/qt/ui_qt_window.cpp | 1 + 16 files changed, 169 insertions(+), 88 deletions(-) create mode 100644 tasks/task_content.h create mode 100644 tasks/task_powerstate.h diff --git a/command.c b/command.c index a55eed7c12..f3214b2622 100644 --- a/command.c +++ b/command.c @@ -89,6 +89,7 @@ #include "managers/cheat_manager.h" #include "managers/state_manager.h" #include "ui/ui_companion_driver.h" +#include "tasks/task_content.h" #include "tasks/tasks_internal.h" #include "list_special.h" diff --git a/configuration.c b/configuration.c index 3471e71807..9880f7cf44 100644 --- a/configuration.c +++ b/configuration.c @@ -50,6 +50,7 @@ #include "verbosity.h" #include "lakka.h" +#include "tasks/task_content.h" #include "tasks/tasks_internal.h" #include "../list_special.h" diff --git a/frontend/frontend.c b/frontend/frontend.c index c1e281228a..3c954f20f1 100644 --- a/frontend/frontend.c +++ b/frontend/frontend.c @@ -29,9 +29,10 @@ #endif #include "frontend.h" +#include "frontend_driver.h" #include "../configuration.h" #include "../ui/ui_companion_driver.h" -#include "../tasks/tasks_internal.h" +#include "../tasks/task_content.h" #include "../driver.h" #include "../paths.h" diff --git a/gfx/common/win32_common.c b/gfx/common/win32_common.c index 773cf408fb..7afdfdb845 100644 --- a/gfx/common/win32_common.c +++ b/gfx/common/win32_common.c @@ -44,6 +44,7 @@ #include "../../driver.h" #include "../../paths.h" #include "../../retroarch.h" +#include "../../tasks/task_content.h" #include "../../tasks/tasks_internal.h" #include "../../core_info.h" @@ -51,7 +52,6 @@ #include #include -#include "../../retroarch.h" #include "../../input/input_driver.h" #include "../../input/input_keymaps.h" #include "../video_thread_wrapper.h" diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index c8f5dbe88e..18019b2f7b 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -57,6 +57,7 @@ #include "../../defaults.h" #include "../../managers/core_option_manager.h" #include "../../managers/cheat_manager.h" +#include "../../tasks/task_content.h" #include "../../tasks/task_file_transfer.h" #include "../../tasks/tasks_internal.h" #include "../../input/input_remapping.h" diff --git a/menu/drivers/ozone/ozone.c b/menu/drivers/ozone/ozone.c index dd133b282a..bbb066f61a 100644 --- a/menu/drivers/ozone/ozone.c +++ b/menu/drivers/ozone/ozone.c @@ -48,6 +48,7 @@ #include "../../../core_info.h" #include "../../../core.h" #include "../../../verbosity.h" +#include "../../../tasks/task_powerstate.h" #include "../../../tasks/tasks_internal.h" #include "../../../dynamic.h" diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 7c6ac6b526..25e64e2bbe 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -60,6 +60,7 @@ #include "../../playlist.h" #include "../../retroarch.h" +#include "../../tasks/task_powerstate.h" #include "../../tasks/tasks_internal.h" #include "../../cheevos/badges.h" diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index ae0767a7cf..662c741bb3 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -36,7 +36,9 @@ #include "netplay_private.h" #include "../../configuration.h" +#include "../../frontend/frontend_driver.h" #include "../../input/input_driver.h" +#include "../../tasks/task_content.h" #include "../../tasks/tasks_internal.h" #include "../../file_path_special.h" #include "../../paths.h" diff --git a/retroarch.c b/retroarch.c index b523c6d747..6c509b6ccc 100644 --- a/retroarch.c +++ b/retroarch.c @@ -112,6 +112,7 @@ #include "managers/core_option_manager.h" #include "managers/cheat_manager.h" #include "managers/state_manager.h" +#include "tasks/task_content.h" #include "tasks/tasks_internal.h" #include "performance_counters.h" diff --git a/tasks/task_content.c b/tasks/task_content.c index 3445f69383..6aed80dd5f 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -69,6 +69,7 @@ #include "../cheevos/cheevos.h" #endif +#include "task_content.h" #include "tasks_internal.h" #include "../command.h" diff --git a/tasks/task_content.h b/tasks/task_content.h new file mode 100644 index 0000000000..7055307181 --- /dev/null +++ b/tasks/task_content.h @@ -0,0 +1,117 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - Higor Euripedes + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ +#ifndef TASKS_HANDLER_CONTENT_H +#define TASKS_HANDLER_CONTENT_H + +#include + +#include +#include +#include + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include "../content.h" +#include "../core_type.h" + +RETRO_BEGIN_DECLS + +enum content_mode_load +{ + CONTENT_MODE_LOAD_NONE = 0, + CONTENT_MODE_LOAD_CONTENT_WITH_CURRENT_CORE_FROM_MENU, + CONTENT_MODE_LOAD_CONTENT_WITH_FFMPEG_CORE_FROM_MENU, + CONTENT_MODE_LOAD_CONTENT_WITH_IMAGEVIEWER_CORE_FROM_MENU +}; + +bool task_push_load_content_with_current_core_from_companion_ui( + const char *fullpath, + content_ctx_info_t *content_info, + enum rarch_core_type type, + retro_task_callback_t cb, + void *user_data); + +bool task_push_load_content_from_cli( + const char *core_path, + const char *fullpath, + content_ctx_info_t *content_info, + enum rarch_core_type type, + retro_task_callback_t cb, + void *user_data); + +bool task_push_load_new_core( + const char *core_path, + const char *fullpath, + content_ctx_info_t *content_info, + enum rarch_core_type type, + retro_task_callback_t cb, + void *user_data); + +bool task_push_start_builtin_core(content_ctx_info_t *content_info, + enum rarch_core_type type, + retro_task_callback_t cb, + void *user_data); + +bool task_push_start_current_core(content_ctx_info_t *content_info); + +bool task_push_start_dummy_core(content_ctx_info_t *content_info); + +bool task_push_load_content_with_new_core_from_companion_ui( + const char *core_path, + const char *fullpath, + const char *label, + content_ctx_info_t *content_info, + retro_task_callback_t cb, + void *user_data); + +#ifdef HAVE_MENU +bool task_push_load_content_with_new_core_from_menu( + const char *core_path, + const char *fullpath, + content_ctx_info_t *content_info, + enum rarch_core_type type, + retro_task_callback_t cb, + void *user_data); + +bool task_push_load_content_from_playlist_from_menu( + const char *core_path, + const char *fullpath, + const char *label, + content_ctx_info_t *content_info, + retro_task_callback_t cb, + void *user_data); + +bool task_push_load_content_with_core_from_menu( + const char *fullpath, + content_ctx_info_t *content_info, + enum rarch_core_type type, + retro_task_callback_t cb, + void *user_data); +bool task_push_load_subsystem_with_core_from_menu( + const char *fullpath, + content_ctx_info_t *content_info, + enum rarch_core_type type, + retro_task_callback_t cb, + void *user_data); +#endif + +RETRO_END_DECLS + +#endif diff --git a/tasks/task_netplay_find_content.c b/tasks/task_netplay_find_content.c index 86667219b8..3236253590 100644 --- a/tasks/task_netplay_find_content.c +++ b/tasks/task_netplay_find_content.c @@ -27,6 +27,7 @@ #include #include +#include "task_content.h" #include "tasks_internal.h" #include "../file_path_special.h" #include "../verbosity.h" diff --git a/tasks/task_powerstate.h b/tasks/task_powerstate.h new file mode 100644 index 0000000000..a3f7270faf --- /dev/null +++ b/tasks/task_powerstate.h @@ -0,0 +1,37 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - Higor Euripedes + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ +#ifndef TASK_POWER_STATE_H +#define TASK_POWER_STATE_H + +#include + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +RETRO_BEGIN_DECLS + +void task_push_get_powerstate(void); + +enum frontend_powerstate get_last_powerstate(int *percent); + +RETRO_END_DECLS + +#endif diff --git a/tasks/task_save.c b/tasks/task_save.c index d79139ad88..155d31f2ab 100644 --- a/tasks/task_save.c +++ b/tasks/task_save.c @@ -44,6 +44,7 @@ #include "../network/netplay/netplay.h" #endif +#include "../content.h" #include "../core.h" #include "../file_path_special.h" #include "../configuration.h" diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 06d4c98b19..d4e02d5a1b 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -30,19 +30,8 @@ #include "../audio/audio_driver.h" -#include "../content.h" -#include "../core_type.h" - RETRO_BEGIN_DECLS -enum content_mode_load -{ - CONTENT_MODE_LOAD_NONE = 0, - CONTENT_MODE_LOAD_CONTENT_WITH_CURRENT_CORE_FROM_MENU, - CONTENT_MODE_LOAD_CONTENT_WITH_FFMPEG_CORE_FROM_MENU, - CONTENT_MODE_LOAD_CONTENT_WITH_IMAGEVIEWER_CORE_FROM_MENU -}; - #ifdef HAVE_NETWORKING typedef struct { @@ -99,77 +88,6 @@ bool task_push_decompress( retro_task_callback_t cb, void *user_data); -bool task_push_load_content_with_current_core_from_companion_ui( - const char *fullpath, - content_ctx_info_t *content_info, - enum rarch_core_type type, - retro_task_callback_t cb, - void *user_data); - -bool task_push_load_content_from_cli( - const char *core_path, - const char *fullpath, - content_ctx_info_t *content_info, - enum rarch_core_type type, - retro_task_callback_t cb, - void *user_data); - -bool task_push_load_new_core( - const char *core_path, - const char *fullpath, - content_ctx_info_t *content_info, - enum rarch_core_type type, - retro_task_callback_t cb, - void *user_data); - -bool task_push_start_builtin_core(content_ctx_info_t *content_info, - enum rarch_core_type type, - retro_task_callback_t cb, - void *user_data); - -bool task_push_start_current_core(content_ctx_info_t *content_info); - -bool task_push_start_dummy_core(content_ctx_info_t *content_info); - -bool task_push_load_content_with_new_core_from_companion_ui( - const char *core_path, - const char *fullpath, - const char *label, - content_ctx_info_t *content_info, - retro_task_callback_t cb, - void *user_data); - -#ifdef HAVE_MENU -bool task_push_load_content_with_new_core_from_menu( - const char *core_path, - const char *fullpath, - content_ctx_info_t *content_info, - enum rarch_core_type type, - retro_task_callback_t cb, - void *user_data); - -bool task_push_load_content_from_playlist_from_menu( - const char *core_path, - const char *fullpath, - const char *label, - content_ctx_info_t *content_info, - retro_task_callback_t cb, - void *user_data); - -bool task_push_load_content_with_core_from_menu( - const char *fullpath, - content_ctx_info_t *content_info, - enum rarch_core_type type, - retro_task_callback_t cb, - void *user_data); -bool task_push_load_subsystem_with_core_from_menu( - const char *fullpath, - content_ctx_info_t *content_info, - enum rarch_core_type type, - retro_task_callback_t cb, - void *user_data); -#endif - void task_file_load_handler(retro_task_t *task); bool task_audio_mixer_load_handler(retro_task_t *task); @@ -207,10 +125,6 @@ bool input_autoconfigure_get_swap_override(void); void input_autoconfigure_joypad_reindex_devices(void); -void task_push_get_powerstate(void); - -enum frontend_powerstate get_last_powerstate(int *percent); - bool task_push_audio_mixer_load_and_play( const char *fullpath, retro_task_callback_t cb, void *user_data, bool system, diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index cdfd39b98a..8d5026901e 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -67,6 +67,7 @@ extern "C" { #include "../../../menu/menu_driver.h" #endif #include "../../../config.def.h" +#include "../../../tasks/task_content.h" #include "../../../tasks/tasks_internal.h" #include #include From 5102911da641d2838e67276037dbd171896c6602 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Sun, 20 Jan 2019 03:26:35 +0100 Subject: [PATCH 037/234] (OSX) Buildfix --- ui/drivers/ui_cocoa.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index b93d748cf3..6a5caaf2fc 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -35,6 +35,7 @@ #include "../../paths.h" #include "../../core.h" #include "../../retroarch.h" +#include "../../tasks/task_content.h" #include "../../tasks/tasks_internal.h" #include ".././verbosity.h" From bd16d5c9dcf29e608ce4820b7dadcd92beb5dab9 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Sun, 20 Jan 2019 03:31:45 +0100 Subject: [PATCH 038/234] Fix function signature of metal_unload_texture --- gfx/drivers/metal.m | 4 +--- ui/drivers/ui_cocoa_metal.m | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gfx/drivers/metal.m b/gfx/drivers/metal.m index 29c792c9ab..0023135139 100644 --- a/gfx/drivers/metal.m +++ b/gfx/drivers/metal.m @@ -194,12 +194,10 @@ static uintptr_t metal_load_texture(void *video_data, void *data, return (uintptr_t)(__bridge_retained void *)(t); } -static void metal_unload_texture(void *data, uintptr_t handle) +static void metal_unload_texture(void *data, uintptr_t handle, bool threaded) { if (!handle) - { return; - } Texture *t = (__bridge_transfer Texture *)(void *)handle; t = nil; } diff --git a/ui/drivers/ui_cocoa_metal.m b/ui/drivers/ui_cocoa_metal.m index 6dd34e15e4..3df31b91f6 100644 --- a/ui/drivers/ui_cocoa_metal.m +++ b/ui/drivers/ui_cocoa_metal.m @@ -35,6 +35,7 @@ #include "../../paths.h" #include "../../core.h" #include "../../retroarch.h" +#include "../../tasks/task_content.h" #include "../../tasks/tasks_internal.h" #include ".././verbosity.h" From cf83332b4913634d97afbce379597df5e0df2fa4 Mon Sep 17 00:00:00 2001 From: orbea Date: Sun, 20 Jan 2019 08:08:02 -0800 Subject: [PATCH 039/234] qb: Replace remaining uses of echo with printf. --- qb/qb.comp.sh | 8 ++++---- qb/qb.params.sh | 7 +++---- qb/qb.system.sh | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/qb/qb.comp.sh b/qb/qb.comp.sh index 58740d4d80..c65d176f51 100644 --- a/qb/qb.comp.sh +++ b/qb/qb.comp.sh @@ -35,7 +35,7 @@ elif [ -z "$CC" ]; then cc_status='not found' fi -echo "Checking for suitable working C compiler ... $CC $cc_status" +printf %s\\n "Checking for suitable working C compiler ... $CC $cc_status" if [ "$cc_works" = '0' ] && [ "$USE_LANG_C" = 'yes' ]; then die 1 'Error: Cannot proceed without a working C compiler.' @@ -72,7 +72,7 @@ elif [ -z "$CXX" ]; then cxx_status='not found' fi -echo "Checking for suitable working C++ compiler ... $CXX $cxx_status" +printf %s\\n "Checking for suitable working C++ compiler ... $CXX $cxx_status" if [ "$cxx_works" = '0' ] && [ "$USE_LANG_CXX" = 'yes' ]; then die : 'Warning: A working C++ compiler was not found, C++ features will be disabled.' @@ -84,7 +84,7 @@ if [ "$OS" = "Win32" ]; then WINDRES="$(exists "${CROSS_COMPILE}windres")" || WINDRES="" [ -z "$WINDRES" ] && die 1 "$echobuf ... Not found. Exiting." fi - echo "$echobuf ... $WINDRES" + printf %s\\n "$echobuf ... $WINDRES" fi if [ -z "$PKG_CONF_PATH" ]; then @@ -98,7 +98,7 @@ if [ -z "$PKG_CONF_PATH" ]; then done fi -echo "Checking for pkg-config ... $PKG_CONF_PATH" +printf %s\\n "Checking for pkg-config ... $PKG_CONF_PATH" if [ "$PKG_CONF_PATH" = "none" ]; then die : 'Warning: pkg-config not found, package checks will fail.' diff --git a/qb/qb.params.sh b/qb/qb.params.sh index 2a68f0605e..40fdf63106 100644 --- a/qb/qb.params.sh +++ b/qb/qb.params.sh @@ -43,14 +43,13 @@ EOF print_help_option "--host=HOST" "Cross-compile with HOST-gcc instead of gcc" print_help_option "--help" "Show this help" - echo "" - echo "Custom options:" + printf %s\\n '' 'Custom options:' while read -r VAR COMMENT; do TMPVAR="${VAR%=*}" COMMENT="${COMMENT#*#}" VAL="${VAR#*=}" - VAR="$(echo "${TMPVAR#HAVE_}" | tr '[:upper:]' '[:lower:]')" + VAR="$(printf %s "${TMPVAR#HAVE_}" | tr '[:upper:]' '[:lower:]')" case "$VAR" in 'c89_'*) continue;; *) @@ -70,7 +69,7 @@ EOF } opt_exists() # $opt is returned if exists in OPTS -{ opt="$(echo "$1" | tr '[:lower:]' '[:upper:]')" +{ opt="$(printf %s "$1" | tr '[:lower:]' '[:upper:]')" err="$2" eval "set -- $OPTS" for OPT do [ "$opt" = "$OPT" ] && return; done diff --git a/qb/qb.system.sh b/qb/qb.system.sh index 22a2fb73a8..d8c8ae9db4 100644 --- a/qb/qb.system.sh +++ b/qb/qb.system.sh @@ -47,4 +47,4 @@ if [ -e /etc/lsb-release ]; then DISTRO="(${DISTRIB_DESCRIPTION} ${DISTRIB_RELEASE})" fi -echo "Checking operating system ... $OS ${DISTRO}" +printf %s\\n "Checking operating system ... $OS ${DISTRO}" From 1a7d69621f321b315394ffabe987a3306aa00c0b Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 17:33:07 +0100 Subject: [PATCH 040/234] Revert "Fix function signature of metal_unload_texture" This reverts commit bd16d5c9dcf29e608ce4820b7dadcd92beb5dab9. --- gfx/drivers/metal.m | 4 +++- ui/drivers/ui_cocoa_metal.m | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gfx/drivers/metal.m b/gfx/drivers/metal.m index 0023135139..29c792c9ab 100644 --- a/gfx/drivers/metal.m +++ b/gfx/drivers/metal.m @@ -194,10 +194,12 @@ static uintptr_t metal_load_texture(void *video_data, void *data, return (uintptr_t)(__bridge_retained void *)(t); } -static void metal_unload_texture(void *data, uintptr_t handle, bool threaded) +static void metal_unload_texture(void *data, uintptr_t handle) { if (!handle) + { return; + } Texture *t = (__bridge_transfer Texture *)(void *)handle; t = nil; } diff --git a/ui/drivers/ui_cocoa_metal.m b/ui/drivers/ui_cocoa_metal.m index 3df31b91f6..6dd34e15e4 100644 --- a/ui/drivers/ui_cocoa_metal.m +++ b/ui/drivers/ui_cocoa_metal.m @@ -35,7 +35,6 @@ #include "../../paths.h" #include "../../core.h" #include "../../retroarch.h" -#include "../../tasks/task_content.h" #include "../../tasks/tasks_internal.h" #include ".././verbosity.h" From 435007326579dd416935c4f82b69344445f28696 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 17:34:38 +0100 Subject: [PATCH 041/234] Revert "Revert "Fix function signature of metal_unload_texture"" This reverts commit 1a7d69621f321b315394ffabe987a3306aa00c0b. --- gfx/drivers/metal.m | 4 +--- ui/drivers/ui_cocoa_metal.m | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gfx/drivers/metal.m b/gfx/drivers/metal.m index 29c792c9ab..0023135139 100644 --- a/gfx/drivers/metal.m +++ b/gfx/drivers/metal.m @@ -194,12 +194,10 @@ static uintptr_t metal_load_texture(void *video_data, void *data, return (uintptr_t)(__bridge_retained void *)(t); } -static void metal_unload_texture(void *data, uintptr_t handle) +static void metal_unload_texture(void *data, uintptr_t handle, bool threaded) { if (!handle) - { return; - } Texture *t = (__bridge_transfer Texture *)(void *)handle; t = nil; } diff --git a/ui/drivers/ui_cocoa_metal.m b/ui/drivers/ui_cocoa_metal.m index 6dd34e15e4..3df31b91f6 100644 --- a/ui/drivers/ui_cocoa_metal.m +++ b/ui/drivers/ui_cocoa_metal.m @@ -35,6 +35,7 @@ #include "../../paths.h" #include "../../core.h" #include "../../retroarch.h" +#include "../../tasks/task_content.h" #include "../../tasks/tasks_internal.h" #include ".././verbosity.h" From 04ec598b97ae4d041f0612821f0d598588ac8dab Mon Sep 17 00:00:00 2001 From: meleu Date: Sun, 20 Jan 2019 16:08:31 -0200 Subject: [PATCH 042/234] add './configure --enable-new_cheevos' option --- qb/config.params.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/qb/config.params.sh b/qb/config.params.sh index d1b178569a..8dfa6716c4 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -117,6 +117,7 @@ HAVE_QT=auto # Qt companion support C89_QT=no HAVE_XSHM=no # XShm video driver support HAVE_CHEEVOS=yes # Retro Achievements +HAVE_NEW_CHEEVOS=no # use rcheevos to process RetroAchievements C89_CHEEVOS=no HAVE_LUA=no # Lua support (for Retro Achievements) HAVE_DISCORD=yes # Discord Integration From cd35fb94406cda8c88f2b1937eed17c1f29ae2c7 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Sun, 20 Jan 2019 22:12:05 +0400 Subject: [PATCH 043/234] Change prev_width and prev_height to unsigned int --- gfx/drivers_context/wayland_ctx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index a712c64895..32ae40f80c 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -94,8 +94,8 @@ typedef struct gfx_ctx_wayland_data bool resize; bool configured; bool activated; - int prev_width; - int prev_height; + unsigned prev_width; + unsigned prev_height; unsigned width; unsigned height; struct wl_registry *registry; From 7d186f7d2c7c63b137fd76159e78f414f1b3a8fb Mon Sep 17 00:00:00 2001 From: M4xw Date: Sun, 20 Jan 2019 20:06:14 +0100 Subject: [PATCH 044/234] Revert PR #8043 --- configuration.c | 2 +- gfx/drivers/d3d10.c | 2 +- gfx/drivers/d3d11.c | 2 +- gfx/drivers/d3d12.c | 2 +- gfx/drivers/d3d8.c | 2 +- gfx/drivers/d3d9.c | 2 +- gfx/drivers/gdi_gfx.c | 2 +- gfx/drivers/gl.c | 35 +++++++---------------------------- gfx/drivers/vulkan.c | 2 +- gfx/video_driver.c | 6 +----- gfx/video_driver.h | 2 +- gfx/video_thread_wrapper.c | 4 ++-- menu/menu_setting.c | 2 +- 13 files changed, 20 insertions(+), 45 deletions(-) diff --git a/configuration.c b/configuration.c index 9880f7cf44..3eff180dd7 100644 --- a/configuration.c +++ b/configuration.c @@ -1378,7 +1378,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("video_scale_integer", &settings->bools.video_scale_integer, true, scale_integer, false); SETTING_BOOL("video_smooth", &settings->bools.video_smooth, true, video_smooth, false); SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, force_aspect, false); - SETTING_BOOL("video_threaded", &settings->bools.video_threaded, true, video_threaded, false); + SETTING_BOOL("video_threaded", video_driver_get_threaded(), true, video_threaded, false); SETTING_BOOL("video_shared_context", &settings->bools.video_shared_context, true, video_shared_context, false); SETTING_BOOL("auto_screenshot_filename", &settings->bools.auto_screenshot_filename, true, auto_screenshot_filename, false); SETTING_BOOL("video_force_srgb_disable", &settings->bools.video_force_srgb_disable, true, false, false); diff --git a/gfx/drivers/d3d10.c b/gfx/drivers/d3d10.c index a465b9a754..b5dc33d0e3 100644 --- a/gfx/drivers/d3d10.c +++ b/gfx/drivers/d3d10.c @@ -1580,7 +1580,7 @@ static uintptr_t d3d10_gfx_load_texture( return (uintptr_t)texture; } -static void d3d10_gfx_unload_texture(void* data, uintptr_t handle, bool threaded) +static void d3d10_gfx_unload_texture(void* data, uintptr_t handle) { d3d10_texture_t* texture = (d3d10_texture_t*)handle; diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index f01a09eead..6e0850b712 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -1640,7 +1640,7 @@ static uintptr_t d3d11_gfx_load_texture( return (uintptr_t)texture; } -static void d3d11_gfx_unload_texture(void* data, uintptr_t handle, bool threaded) +static void d3d11_gfx_unload_texture(void* data, uintptr_t handle) { d3d11_texture_t* texture = (d3d11_texture_t*)handle; diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 658dcaaff9..2251a428d4 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -1759,7 +1759,7 @@ static uintptr_t d3d12_gfx_load_texture( return (uintptr_t)texture; } -static void d3d12_gfx_unload_texture(void* data, uintptr_t handle, bool threaded) +static void d3d12_gfx_unload_texture(void* data, uintptr_t handle) { d3d12_texture_t* texture = (d3d12_texture_t*)handle; diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index 33c0bd8023..21830cd500 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -1818,7 +1818,7 @@ static uintptr_t d3d8_load_texture(void *video_data, void *data, return id; } -static void d3d8_unload_texture(void *data, uintptr_t id, bool threaded) +static void d3d8_unload_texture(void *data, uintptr_t id) { LPDIRECT3DTEXTURE8 texid; if (!id) diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9.c index b19a0b1b19..2d5af2a9d1 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9.c @@ -1989,7 +1989,7 @@ static uintptr_t d3d9_load_texture(void *video_data, void *data, return id; } -static void d3d9_unload_texture(void *data, uintptr_t id, bool threaded) +static void d3d9_unload_texture(void *data, uintptr_t id) { LPDIRECT3DTEXTURE9 texid; if (!id) diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c index 70d4f8e31c..034a6db400 100644 --- a/gfx/drivers/gdi_gfx.c +++ b/gfx/drivers/gdi_gfx.c @@ -610,7 +610,7 @@ static uintptr_t gdi_load_texture(void *video_data, void *data, return (uintptr_t)texture; } -static void gdi_unload_texture(void *data, uintptr_t handle, bool threaded) +static void gdi_unload_texture(void *data, uintptr_t handle) { struct gdi_texture *texture = (struct gdi_texture*)handle; diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index a7abdfecca..c37dfe8819 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -2496,12 +2496,6 @@ static void video_texture_load_gl( ); } -static void video_texture_unload_gl( - uintptr_t *id) -{ - glDeleteTextures(1, (GLuint*)id); -} - #ifdef HAVE_THREADS static int video_texture_load_wrap_gl_mipmap(void *data) { @@ -2524,20 +2518,13 @@ static int video_texture_load_wrap_gl(void *data) TEXTURE_FILTER_LINEAR, &id); return (int)id; } - -static int video_texture_unload_wrap_gl(void *data) -{ - if (!data) - return 0; - video_texture_unload_gl((uintptr_t*)data); - return 0; -} #endif static uintptr_t gl_load_texture(void *video_data, void *data, bool threaded, enum texture_filter_type filter_type) { uintptr_t id = 0; + #ifdef HAVE_THREADS if (threaded) { @@ -2552,8 +2539,7 @@ static uintptr_t gl_load_texture(void *video_data, void *data, default: break; } - id=video_thread_texture_load(data, func); - return id; + return video_thread_texture_load(data, func); } #endif @@ -2561,21 +2547,14 @@ static uintptr_t gl_load_texture(void *video_data, void *data, return id; } -static void gl_unload_texture(void *video_data, uintptr_t data, bool threaded) +static void gl_unload_texture(void *data, uintptr_t id) { - if (!data) + GLuint glid; + if (!id) return; -#ifdef HAVE_THREADS - if (threaded) - { - custom_command_method_t func = video_texture_unload_wrap_gl; - video_thread_texture_load((void *)&data, func); - return; - } -#endif - - video_texture_unload_gl(&data); + glid = (GLuint)id; + glDeleteTextures(1, &glid); } static void gl_set_coords(void *handle_data, void *shader_data, diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 2408f2f9d1..483ee8ae09 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -2334,7 +2334,7 @@ static uintptr_t vulkan_load_texture(void *video_data, void *data, return (uintptr_t)texture; } -static void vulkan_unload_texture(void *data, uintptr_t handle, bool threaded) +static void vulkan_unload_texture(void *data, uintptr_t handle) { vk_t *vk = (vk_t*)data; struct vk_texture *texture = (struct vk_texture*)handle; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index f3d9cc119b..3d29a3c182 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -147,7 +147,6 @@ static bool video_driver_crt_switching_active = false; static struct retro_system_av_info video_driver_av_info; - static enum retro_pixel_format video_driver_pix_fmt = RETRO_PIXEL_FORMAT_0RGB1555; static const void *frame_cache_data = NULL; @@ -1051,9 +1050,6 @@ static bool video_driver_init_internal(bool *video_is_threaded) video_driver_find_driver(); #ifdef HAVE_THREADS - /* Set the driver to threaded based on the settings configuration */ - video_driver_threaded = settings->bools.video_threaded; - /* Check video_driver_threaded and video_driver_hw-context to determine if the video driver is threaded */ video.is_threaded = video_driver_is_threaded_internal(); *video_is_threaded = video.is_threaded; @@ -2729,7 +2725,7 @@ bool video_driver_texture_unload(uintptr_t *id) if (!video_driver_poke || !video_driver_poke->unload_texture) return false; - video_driver_poke->unload_texture(video_driver_data, *id, video_driver_is_threaded_internal()); + video_driver_poke->unload_texture(video_driver_data, *id); *id = 0; return true; } diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 905fef9817..eea9ef14e4 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -710,7 +710,7 @@ typedef struct video_poke_interface const void *mat_data); uintptr_t (*load_texture)(void *video_data, void *data, bool threaded, enum texture_filter_type filter_type); - void (*unload_texture)(void *data, uintptr_t id, bool threaded); + void (*unload_texture)(void *data, uintptr_t id); void (*set_video_mode)(void *data, unsigned width, unsigned height, bool fullscreen); float (*get_refresh_rate)(void *data); diff --git a/gfx/video_thread_wrapper.c b/gfx/video_thread_wrapper.c index f29099c80f..1093deae0a 100644 --- a/gfx/video_thread_wrapper.c +++ b/gfx/video_thread_wrapper.c @@ -1198,7 +1198,7 @@ static uintptr_t thread_load_texture(void *video_data, void *data, return thr->poke->load_texture(thr->driver_data, data, threaded, filter_type); } -static void thread_unload_texture(void *video_data, uintptr_t id, bool threaded) +static void thread_unload_texture(void *video_data, uintptr_t id) { thread_video_t *thr = (thread_video_t*)video_data; @@ -1206,7 +1206,7 @@ static void thread_unload_texture(void *video_data, uintptr_t id, bool threaded) return; if (thr->poke && thr->poke->unload_texture) - thr->poke->unload_texture(thr->driver_data, id, threaded); + thr->poke->unload_texture(thr->driver_data, id); } static void thread_apply_state_changes(void *data) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 622ffc6b96..d3c6cbf54c 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -5850,7 +5850,7 @@ static bool setting_append_list( #if defined(HAVE_THREADS) CONFIG_BOOL( list, list_info, - &settings->bools.video_threaded, + video_driver_get_threaded(), MENU_ENUM_LABEL_VIDEO_THREADED, MENU_ENUM_LABEL_VALUE_VIDEO_THREADED, video_threaded, From b6e9dbd92c7ff517c628f92198efb29f65170902 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 20 Jan 2019 20:35:04 +0100 Subject: [PATCH 045/234] (Android) Buildfix --- runahead/secondary_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runahead/secondary_core.c b/runahead/secondary_core.c index 7ff00f8ed9..254a249cc9 100644 --- a/runahead/secondary_core.c +++ b/runahead/secondary_core.c @@ -76,7 +76,10 @@ static char *get_temp_directory_alloc(void) free(wideStr); #endif #elif defined ANDROID - path = strcpy_alloc_force(settings->paths.directory_libretro); + { + settings_t *settings = config_get_ptr(); + path = strcpy_alloc_force(settings->paths.directory_libretro); + } #else path = "/tmp"; if (getenv("TMPDIR")) From cb602c190d832b5646e931a41d29e90880d293ea Mon Sep 17 00:00:00 2001 From: orbea Date: Sun, 20 Jan 2019 13:59:40 -0800 Subject: [PATCH 046/234] Some C89_BUILD fixes. --- input/drivers_joypad/linuxraw_joypad.c | 1 + libretro-common/vfs/vfs_implementation.c | 2 +- qb/config.params.sh | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/input/drivers_joypad/linuxraw_joypad.c b/input/drivers_joypad/linuxraw_joypad.c index 8a209aa5a7..09237b88ec 100644 --- a/input/drivers_joypad/linuxraw_joypad.c +++ b/input/drivers_joypad/linuxraw_joypad.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c index 4d5098c758..23f385dac4 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -1161,6 +1161,7 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir) return false; #else struct stat buf; + char path[PATH_MAX_LENGTH]; #if defined(DT_DIR) const struct dirent *entry = (const struct dirent*)rdir->entry; if (entry->d_type == DT_DIR) @@ -1170,7 +1171,6 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir) return false; #endif /* dirent struct doesn't have d_type, do it the slow way ... */ - char path[PATH_MAX_LENGTH]; path[0] = '\0'; fill_pathname_join(path, rdir->orig_path, retro_vfs_dirent_get_name_impl(rdir), sizeof(path)); if (stat(path, &buf) < 0) diff --git a/qb/config.params.sh b/qb/config.params.sh index 8dfa6716c4..524b012bec 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -117,8 +117,8 @@ HAVE_QT=auto # Qt companion support C89_QT=no HAVE_XSHM=no # XShm video driver support HAVE_CHEEVOS=yes # Retro Achievements -HAVE_NEW_CHEEVOS=no # use rcheevos to process RetroAchievements -C89_CHEEVOS=no +HAVE_NEW_CHEEVOS=no # Use rcheevos to process RetroAchievements +C89_NEW_CHEEVOS=no HAVE_LUA=no # Lua support (for Retro Achievements) HAVE_DISCORD=yes # Discord Integration C89_DISCORD=no From b0b39a161087eb3b4a30caa6983955817f4607fc Mon Sep 17 00:00:00 2001 From: radius Date: Sun, 20 Jan 2019 17:06:50 -0500 Subject: [PATCH 047/234] this should fix errors with --disable-menu --- tasks/task_content.c | 7 +++++-- tasks/task_content.h | 2 +- tasks/task_netplay_find_content.c | 12 ++++++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tasks/task_content.c b/tasks/task_content.c index 6aed80dd5f..f3dcb8f891 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -1698,7 +1698,6 @@ bool task_push_load_content_with_current_core_from_companion_ui( return true; } -#ifdef HAVE_MENU bool task_push_load_content_with_core_from_menu( const char *fullpath, content_ctx_info_t *content_info, @@ -1716,9 +1715,11 @@ bool task_push_load_content_with_core_from_menu( return false; } +#ifdef HAVE_MENU /* Push quick menu onto menu stack */ if (type != CORE_TYPE_DUMMY) menu_driver_ctl(RARCH_MENU_CTL_SET_PENDING_QUICK_MENU, NULL); +#endif return true; } @@ -1740,14 +1741,16 @@ bool task_push_load_subsystem_with_core_from_menu( return false; } +#ifdef HAVE_MENU /* Push quick menu onto menu stack */ if (type != CORE_TYPE_DUMMY) menu_driver_ctl(RARCH_MENU_CTL_SET_PENDING_QUICK_MENU, NULL); +#endif return true; } -#endif + void content_get_status( bool *contentless, diff --git a/tasks/task_content.h b/tasks/task_content.h index 7055307181..8e5d552d95 100644 --- a/tasks/task_content.h +++ b/tasks/task_content.h @@ -97,6 +97,7 @@ bool task_push_load_content_from_playlist_from_menu( content_ctx_info_t *content_info, retro_task_callback_t cb, void *user_data); +#endif bool task_push_load_content_with_core_from_menu( const char *fullpath, @@ -110,7 +111,6 @@ bool task_push_load_subsystem_with_core_from_menu( enum rarch_core_type type, retro_task_callback_t cb, void *user_data); -#endif RETRO_END_DECLS diff --git a/tasks/task_netplay_find_content.c b/tasks/task_netplay_find_content.c index 3236253590..77f786134a 100644 --- a/tasks/task_netplay_find_content.c +++ b/tasks/task_netplay_find_content.c @@ -86,7 +86,6 @@ static void netplay_crc_scan_callback(void *task_data, return; } -#ifdef HAVE_MENU /* regular core with content file */ if (!string_is_empty(state->core_path) && !string_is_empty(state->content_path) && !state->contentless && !state->current) @@ -103,12 +102,17 @@ static void netplay_crc_scan_callback(void *task_data, state->content_path, &content_info, CORE_TYPE_PLAIN, NULL, NULL); else - task_push_load_content_with_new_core_from_menu( - state->core_path, state->content_path, + { + task_push_load_new_core(state->core_path, NULL, &content_info, CORE_TYPE_PLAIN, NULL, NULL); + task_push_load_content_with_core_from_menu( + state->content_path, &content_info, + CORE_TYPE_PLAIN, NULL, NULL); + } + } else -#endif + /* contentless core */ if (!string_is_empty(state->core_path) && !string_is_empty(state->content_path) && state->contentless) From 40e9fe5cf1691e0c1289d1f77795e6876c763cf6 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Mon, 21 Jan 2019 11:07:32 +0000 Subject: [PATCH 048/234] (RGUI) Fix information display bug --- menu/drivers/rgui.c | 22 ++++++++++++++++++---- menu/menu_displaylist.c | 31 ++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 40e20ddf73..bb8669cc02 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -423,6 +423,7 @@ typedef struct char *thumbnail_system; char *thumbnail_content; char *thumbnail_path; + char *thumbnail_playlist; } rgui_t; #define THUMB_MAX_WIDTH 320 @@ -1591,6 +1592,8 @@ static void rgui_free(void *data) free(rgui->thumbnail_content); if (!string_is_empty(rgui->thumbnail_path)) free(rgui->thumbnail_path); + if (!string_is_empty(rgui->thumbnail_playlist)) + free(rgui->thumbnail_playlist); } fb_font_inited = menu_display_get_font_data_init(); @@ -1737,11 +1740,23 @@ static void rgui_update_thumbnail_path(void *userdata) static void rgui_set_thumbnail_system(void *userdata, char *s, size_t len) { rgui_t *rgui = (rgui_t*)userdata; + char tmp_path[PATH_MAX_LENGTH] = {0}; if (!rgui) return; if (!string_is_empty(rgui->thumbnail_system)) free(rgui->thumbnail_system); + if (!string_is_empty(rgui->thumbnail_playlist)) + free(rgui->thumbnail_playlist); rgui->thumbnail_system = strdup(s); + /* Get associated playlist file name + * (i.e. thumbnail_system>.lpl) */ + if (!string_is_empty(rgui->thumbnail_system)) + { + strlcpy(tmp_path, rgui->thumbnail_system, sizeof(tmp_path)); + strlcat(tmp_path, file_path_str(FILE_PATH_LPL_EXTENSION), sizeof(tmp_path)); + if (!string_is_empty(tmp_path)) + rgui->thumbnail_playlist = strdup(tmp_path); + } } static void rgui_update_thumbnail_content(void *userdata) @@ -1759,10 +1774,9 @@ static void rgui_update_thumbnail_content(void *userdata) rgui->is_playlist_entry = false; title[0] = '\0'; menu_entries_get_title(title, sizeof(title)); - if (!string_is_empty(rgui->thumbnail_system)) + if (!string_is_empty(rgui->thumbnail_playlist)) { - /* An ugly but effective test... */ - if (strstr(path_basename(title), rgui->thumbnail_system) != NULL) + if (string_is_equal(path_basename(title), rgui->thumbnail_playlist)) { /* Get label of currently selected playlist entry * > This is pretty nasty, but I can't see any other way of doing @@ -1800,7 +1814,7 @@ static void rgui_update_thumbnail_image(void *userdata) return; rgui->show_thumbnail = !rgui->show_thumbnail; - + if (rgui->show_thumbnail) { rgui_update_thumbnail_content(rgui); diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 60000e98e7..e809799bfb 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -1290,6 +1290,7 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info, unsigned i; size_t selection = menu_navigation_get_selection(); size_t list_size = playlist_size(playlist); + settings_t *settings = config_get_ptr(); if (list_size == 0) goto error; @@ -1330,7 +1331,11 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info, if (core_name) strlcpy(fill_buf, core_name, path_size); - if (!is_history && i == selection && !string_is_empty(label)) + /* Note: this function is never called when using RGUI, + * but if it ever were then we must ensure that thumbnail + * updates are omitted (since this functionality is + * handled elsewhere) */ + if (!is_history && i == selection && !string_is_empty(label) && !string_is_equal(settings->arrays.menu_driver, "rgui")) { char *content_basename = strdup(label); @@ -1659,16 +1664,24 @@ static int menu_displaylist_parse_database_entry(menu_handle_t *menu, snprintf(crc_str, sizeof(crc_str), "%08X", db_info_entry->crc32); - if (!string_is_empty(db_info_entry->name)) - strlcpy(thumbnail_content, db_info_entry->name, - sizeof(thumbnail_content)); + /* It is unclear why parsing a database should trigger a + * thumbnail update, but I guess this is here for a reason... + * Regardless, thumbnail updates must be disabled when using + * RGUI, since this functionality is handled elsewhere + * (and doing it here creates harmful conflicts) */ + if (!string_is_equal(settings->arrays.menu_driver, "rgui")) + { + if (!string_is_empty(db_info_entry->name)) + strlcpy(thumbnail_content, db_info_entry->name, + sizeof(thumbnail_content)); - if (!string_is_empty(thumbnail_content)) - menu_driver_set_thumbnail_content(thumbnail_content, - sizeof(thumbnail_content)); + if (!string_is_empty(thumbnail_content)) + menu_driver_set_thumbnail_content(thumbnail_content, + sizeof(thumbnail_content)); - menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); - menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); + } if (playlist) { From 56ddc76ebb934996252519ed9983f1439a537010 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Mon, 21 Jan 2019 16:13:45 +0000 Subject: [PATCH 049/234] (RGUI) Replace RPNG + direct file access with task_push_image_load() --- menu/drivers/rgui.c | 247 ++++++++++++++++++++------------------------ 1 file changed, 110 insertions(+), 137 deletions(-) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index bb8669cc02..984af4d5fa 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -52,10 +52,7 @@ /* Thumbnail additions */ #include -#if defined(HAVE_RPNG) -#include -#include -#endif +#include "../../tasks/tasks_internal.h" #define RGUI_TERM_START_X(width) (width / 21) #define RGUI_TERM_START_Y(height) (height / 9) @@ -424,6 +421,7 @@ typedef struct char *thumbnail_content; char *thumbnail_path; char *thumbnail_playlist; + uint32_t thumbnail_queue_size; } rgui_t; #define THUMB_MAX_WIDTH 320 @@ -559,97 +557,10 @@ static uint16_t argb32_to_rgba4444(uint32_t col) #endif -/* From rpng_test.c */ -static bool rpng_load_image_argb(const char *path, uint32_t **data, - unsigned *width, unsigned *height) +static void request_thumbnail(rgui_t *rgui, const char *path) { - /* Check for RPNG support... - * > This seems to be the cleanest place to do it - saves having - * to litter the code with '#if defined(HAVE_RPNG)' all over the - * place... */ -#if defined(HAVE_RPNG) - int retval; - size_t file_len; - bool ret = true; - rpng_t *rpng = NULL; - void *ptr = NULL; - struct nbio_t* handle = (struct nbio_t*)nbio_open(path, NBIO_READ); - - if (!handle) - goto end; - - nbio_begin_read(handle); - - while (!nbio_iterate(handle)); - - ptr = nbio_get_ptr(handle, &file_len); - - if (!ptr) - { - ret = false; - goto end; - } - - rpng = rpng_alloc(); - - if (!rpng) - { - ret = false; - goto end; - } - - if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) - { - ret = false; - goto end; - } - - if (!rpng_start(rpng)) - { - ret = false; - goto end; - } - - while (rpng_iterate_image(rpng)); - - if (!rpng_is_valid(rpng)) - { - ret = false; - goto end; - } - - do - { - retval = rpng_process_image(rpng, - (void**)data, file_len, width, height); - }while(retval == IMAGE_PROCESS_NEXT); - - if (retval == IMAGE_PROCESS_ERROR || retval == IMAGE_PROCESS_ERROR_END) - ret = false; - -end: - if (handle) - nbio_free(handle); - if (rpng) - rpng_free(rpng); - rpng = NULL; - if (!ret) - free(*data); - return ret; -#else - return false; -#endif -} - -static void load_thumbnail(const char *path) -{ - unsigned width, height; - uint32_t *png_data = NULL; - unsigned x, y; - unsigned x_offset, y_offset; - /* Do nothing if current thumbnail path hasn't changed */ - if (!string_is_empty(thumbnail.path) && !string_is_empty(thumbnail.path)) + if (!string_is_empty(path) && !string_is_empty(thumbnail.path)) { if (string_is_equal(thumbnail.path, path)) return; @@ -668,51 +579,105 @@ static void load_thumbnail(const char *path) thumbnail.path = strdup(path); if (filestream_exists(path)) { - /* Load image */ - if (rpng_load_image_argb(path, &png_data, &width, &height)) + /* Would like to cancel any existing image load tasks + * here, but can't see how to do it... */ + if(task_push_image_load(thumbnail.path, menu_display_handle_thumbnail_upload, NULL)) { - /* Have to crop image if larger than max allowed size... */ - if (width > THUMB_MAX_WIDTH) - { - x_offset = (width - THUMB_MAX_WIDTH) >> 1; - thumbnail.width = THUMB_MAX_WIDTH; - } - else - { - x_offset = 0; - thumbnail.width = width; - } - if (height > THUMB_MAX_HEIGHT) - { - y_offset = (height - THUMB_MAX_HEIGHT) >> 1; - thumbnail.height = THUMB_MAX_HEIGHT; - } - else - { - y_offset = 0; - thumbnail.height = height; - } - - /* Copy (cropped) image to thumbnail buffer, performing - * pixel format conversion */ - for (x = 0; x < thumbnail.width; x++) - { - for (y = 0; y < thumbnail.height; y++) - { - thumbnail.data[x + (y * thumbnail.width)] = - argb32_to_pixel_platform_format(png_data[(x + x_offset) + ((y + y_offset) * width)]); - } - } - - thumbnail.is_valid = true; - - free(png_data); - png_data = NULL; + rgui->thumbnail_queue_size++; } } } } +static void process_thumbnail(rgui_t *rgui, struct texture_image *image) +{ + unsigned width, height; + unsigned x, y; + unsigned x_offset, y_offset; + + /* Ensure that we only process the most recently loaded + * thumbnail image (i.e. don't waste CPU cycles processing + * old images if we have a backlog) + * > NB: After some testing, cannot seem to ever trigger a + * situation where rgui->thumbnail_queue_size is greater + * than 1, so perhaps image loading is synchronous after all. + * This probably makes the check redundant, but we'll leave + * it here for now... */ + if (rgui->thumbnail_queue_size > 0) + rgui->thumbnail_queue_size--; + if (rgui->thumbnail_queue_size > 0) + return; + + if (!image->pixels) + return; + + width = image->width; + height = image->height; + + /* Have to crop image if larger than max allowed size... */ + if (width > THUMB_MAX_WIDTH) + { + x_offset = (width - THUMB_MAX_WIDTH) >> 1; + thumbnail.width = THUMB_MAX_WIDTH; + } + else + { + x_offset = 0; + thumbnail.width = width; + } + if (height > THUMB_MAX_HEIGHT) + { + y_offset = (height - THUMB_MAX_HEIGHT) >> 1; + thumbnail.height = THUMB_MAX_HEIGHT; + } + else + { + y_offset = 0; + thumbnail.height = height; + } + + /* Copy (cropped) image to thumbnail buffer, performing + * pixel format conversion */ + for (x = 0; x < thumbnail.width; x++) + { + for (y = 0; y < thumbnail.height; y++) + { + thumbnail.data[x + (y * thumbnail.width)] = + argb32_to_pixel_platform_format(image->pixels[(x + x_offset) + ((y + y_offset) * width)]); + } + } + + thumbnail.is_valid = true; + + /* Tell menu that a display update is required */ + rgui->force_redraw = true; +} + +static bool rgui_load_image(void *userdata, void *data, enum menu_image_type type) +{ + rgui_t *rgui = (rgui_t*)userdata; + + if (!rgui || !data) + return false; + + switch (type) + { + case MENU_IMAGE_WALLPAPER: + /* Add this later... :) */ + break; + case MENU_IMAGE_THUMBNAIL: + { + struct texture_image *image = (struct texture_image*)data; + process_thumbnail(rgui, image); + } + break; + default: + break; + } + + return true; +} + static void rgui_render_thumbnail(void) { size_t fb_pitch; @@ -1048,7 +1013,7 @@ static void rgui_render_background(rgui_t *rgui) } /* Skip drawing border if we are currently showing a thumbnail */ - if (!rgui->show_thumbnail || !rgui->is_playlist_entry || !thumbnail.is_valid) + if (!(rgui->show_thumbnail && rgui->is_playlist_entry && (thumbnail.is_valid || (rgui->thumbnail_queue_size > 0)))) { if (rgui_framebuf_data) { @@ -1307,7 +1272,14 @@ static void rgui_render(void *data, bool is_idle) rgui_render_background(rgui); - if (rgui->show_thumbnail && rgui->is_playlist_entry && thumbnail.is_valid) + /* If thumbnails are enabled and we are viewing a playlist, + * switch to thumbnail view mode if either current thumbnail + * is valid or we are waiting for current thumbnail to load + * (if load is pending we'll get a blank screen + title, but + * this is better than switching back to the text playlist + * view, which causes ugly flickering when scrolling quickly + * through a list...) */ + if (rgui->show_thumbnail && rgui->is_playlist_entry && (thumbnail.is_valid || (rgui->thumbnail_queue_size > 0))) { menu_animation_ctx_ticker_t ticker; char thumbnail_title_buf[255]; @@ -1566,6 +1538,7 @@ static void *rgui_init(void **userdata, bool video_is_threaded) rgui->last_width = fb_width; rgui->last_height = fb_height; + rgui->thumbnail_queue_size = 0; /* Ensure that we start with thumbnails disabled */ rgui->show_thumbnail = false; @@ -1821,7 +1794,7 @@ static void rgui_update_thumbnail_image(void *userdata) if (rgui->is_playlist_entry) { rgui_update_thumbnail_path(rgui); - load_thumbnail(rgui->thumbnail_path); + request_thumbnail(rgui, rgui->thumbnail_path); } } } @@ -1844,7 +1817,7 @@ static void rgui_navigation_set(void *data, bool scroll) if (rgui->is_playlist_entry) { rgui_update_thumbnail_path(rgui); - load_thumbnail(rgui->thumbnail_path); + request_thumbnail(rgui, rgui->thumbnail_path); } } @@ -1981,7 +1954,7 @@ menu_ctx_driver_t menu_ctx_rgui = { NULL, NULL, NULL, - NULL, + rgui_load_image, "rgui", rgui_environ, rgui_pointer_tap, From d3f81e8db83100935a858acb8477fcd47dcbecd9 Mon Sep 17 00:00:00 2001 From: orbea Date: Mon, 21 Jan 2019 13:03:40 -0800 Subject: [PATCH 050/234] Fix the osx metal travis build. --- gfx/common/metal/Context.h | 1 + pkg/apple/BaseConfig.xcconfig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/common/metal/Context.h b/gfx/common/metal/Context.h index 2897367664..e180ac5917 100644 --- a/gfx/common/metal/Context.h +++ b/gfx/common/metal/Context.h @@ -8,6 +8,7 @@ #import #import +#import #import "RendererCommon.h" @interface Texture : NSObject diff --git a/pkg/apple/BaseConfig.xcconfig b/pkg/apple/BaseConfig.xcconfig index 9085e1a869..dad83bc730 100644 --- a/pkg/apple/BaseConfig.xcconfig +++ b/pkg/apple/BaseConfig.xcconfig @@ -4,7 +4,7 @@ // // Created by Stuart Carnie on 5/10/18. // -OTHER_CFLAGS = $(inherited) -DHAVE_RUNAHEAD -DHAVE_GRIFFIN -DHAVE_FLAC -DHAVE_DR_FLAC -DHAVE_DR_MP3 -DHAVE_LROUND -DFLAC__HAS_OGG=0 -DHAVE_CHD -DHAVE_STB_VORBIS -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DHAVE_UPDATE_ASSETS -DHAVE_LANGEXTRA -DRC_DISABLE_LUA -DHAVE_CHEEVOS -DHAVE_IMAGEVIEWER -DHAVE_IOHIDMANAGER -DHAVE_CORETEXT -DHAVE_RGUI -DHAVE_MENU -DOSX -DHAVE_CC_RESAMPLER -DHAVE_GLSL -DINLINE=inline -D__LIBRETRO__ -DHAVE_COREAUDIO -DHAVE_DYNAMIC -DHAVE_OVERLAY -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DHAVE_NETPLAYDISCOVERY -DRARCH_INTERNAL -DHAVE_THREADS -DHAVE_DYLIB -DHAVE_7ZIP -DHAVE_MATERIALUI -DHAVE_HID -DHAVE_XMB -DHAVE_SEGA -DHAVE_SHADERPIPELINE -DHAVE_MMAP -DHAVE_LIBRETRODB -DHAVE_GETOPT_LONG -DHAVE_METAL -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_SPIRV_CROSS -DWANT_GLSLANG -DENABLE_HLSL -DGLSLANG_OSINCLUDE_UNIX -DMETAL_DEBUG -DHAVE_OPENGL -DHAVE_OZONE +OTHER_CFLAGS = $(inherited) -DHAVE_RUNAHEAD -DHAVE_GRIFFIN -DHAVE_FLAC -DHAVE_DR_FLAC -DHAVE_DR_MP3 -DHAVE_LROUND -DFLAC__HAS_OGG=0 -DHAVE_CHD -DHAVE_STB_VORBIS -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DHAVE_UPDATE_ASSETS -DHAVE_LANGEXTRA -DRC_DISABLE_LUA -DHAVE_CHEEVOS -DHAVE_IMAGEVIEWER -DHAVE_IOHIDMANAGER -DHAVE_CORETEXT -DHAVE_RGUI -DHAVE_MENU -DOSX -DHAVE_CC_RESAMPLER -DHAVE_GLSL -DINLINE=inline -D__LIBRETRO__ -DHAVE_COREAUDIO -DHAVE_DYNAMIC -DHAVE_OVERLAY -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DHAVE_NETPLAYDISCOVERY -DRARCH_INTERNAL -DHAVE_THREADS -DHAVE_DYLIB -DHAVE_7ZIP -DHAVE_MATERIALUI -DHAVE_HID -DHAVE_XMB -DHAVE_SEGA -DHAVE_SHADERPIPELINE -DHAVE_MMAP -DHAVE_LIBRETRODB -DHAVE_GETOPT_LONG -DHAVE_METAL -DHAVE_COCOA_METAL -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_SPIRV_CROSS -DWANT_GLSLANG -DENABLE_HLSL -DGLSLANG_OSINCLUDE_UNIX -DMETAL_DEBUG -DHAVE_OPENGL -DHAVE_OZONE SRCBASE = $(SRCROOT)/../.. DEPS_DIR = $(SRCBASE)/deps From 838ac651840a5222d57000a58d1e039daeb040a9 Mon Sep 17 00:00:00 2001 From: meleu Date: Tue, 22 Jan 2019 04:05:58 -0200 Subject: [PATCH 051/234] CHANGES.md: Update NES/SNES/Lynx hashing methods - CHEEVOS: Update the hashing methods to identify NES, SNES and Lynx games (more accurate and accepting headerless ROMs). --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 782daae2ed..a6a961e56b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ # 1.7.6 (future) - ANDROID: Fix Xperia Play input binding - CHEEVOS: Reset when hardcore mode is toggled +- CHEEVOS: Update the hashing methods to identify NES, SNES and Lynx games (more accurate and accepting headerless ROMs). - COMMON: Add new JSON playlist format - CORE UPDATER: Allow sideloading cores from the menu - CPU FILTERS: Add Normal2x filter. From 32fa63a593ff8c5e2bb8268061cead11755a6580 Mon Sep 17 00:00:00 2001 From: orbea Date: Mon, 21 Jan 2019 23:07:39 -0800 Subject: [PATCH 052/234] travis: Update to xcode10.1. This should save a few minutes during the build. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6fea0eee65..7be5f133d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,9 +39,8 @@ matrix: script: - xcodebuild -target RetroArch -configuration Release -project pkg/apple/RetroArch.xcodeproj - os: osx - osx_image: xcode9.3 + osx_image: xcode10.1 script: - - brew update - brew install --force-bottle qt5 - xcodebuild -target RetroArchQt -configuration Release -project pkg/apple/RetroArch_Metal.xcodeproj deploy: From 9d0e9632c1b885d2e279431de5fc466e68a846b4 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Tue, 22 Jan 2019 15:00:45 +0000 Subject: [PATCH 053/234] (RGUI) Add automatic downscaling of large thumbnails --- menu/drivers/rgui.c | 101 ++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 26 deletions(-) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 984af4d5fa..49a05eef45 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -589,11 +589,64 @@ static void request_thumbnail(rgui_t *rgui, const char *path) } } -static void process_thumbnail(rgui_t *rgui, struct texture_image *image) +static bool downscale_thumbnail(struct texture_image *image_src, struct texture_image *image_dst) +{ + uint32_t x_ratio, y_ratio; + unsigned x_src, y_src; + unsigned x_dst, y_dst; + static const float display_aspect_ratio = (float)THUMB_MAX_WIDTH / (float)THUMB_MAX_HEIGHT; + + /* Determine output dimensions */ + float aspect_ratio = (float)image_src->width / (float)image_src->height; + if (aspect_ratio > display_aspect_ratio) + { + image_dst->width = THUMB_MAX_WIDTH; + image_dst->height = image_src->height * THUMB_MAX_WIDTH / image_src->width; + /* Account for any possible rounding errors... */ + image_dst->height = (image_dst->height < 1) ? 1 : image_dst->height; + image_dst->height = (image_dst->height > THUMB_MAX_HEIGHT) ? THUMB_MAX_HEIGHT : image_dst->height; + } + else + { + image_dst->height = THUMB_MAX_HEIGHT; + image_dst->width = image_src->width * THUMB_MAX_HEIGHT / image_src->height; + /* Account for any possible rounding errors... */ + image_dst->width = (image_dst->width < 1) ? 1 : image_dst->width; + image_dst->width = (image_dst->width > THUMB_MAX_WIDTH) ? THUMB_MAX_WIDTH : image_dst->width; + } + + /* Allocate pixel buffer */ + image_dst->pixels = (uint32_t*)calloc(image_dst->width * image_dst->height, sizeof(uint32_t)); + if (!image_dst->pixels) + return false; + + /* Perform nearest neighbour resampling */ + x_ratio = ((image_src->width << 16) / image_dst->width); + y_ratio = ((image_src->height << 16) / image_dst->height); + + for (y_dst = 0; y_dst < image_dst->height; y_dst++) + { + y_src = (y_dst * y_ratio) >> 16; + for (x_dst = 0; x_dst < image_dst->width; x_dst++) + { + x_src = (x_dst * x_ratio) >> 16; + image_dst->pixels[(y_dst * image_dst->width) + x_dst] = image_src->pixels[(y_src * image_src->width) + x_src]; + } + } + + return true; +} + +static void process_thumbnail(rgui_t *rgui, struct texture_image *image_src) { - unsigned width, height; unsigned x, y; - unsigned x_offset, y_offset; + struct texture_image *image = NULL; + struct texture_image image_resampled = { + 0, + 0, + NULL, + false + }; /* Ensure that we only process the most recently loaded * thumbnail image (i.e. don't waste CPU cycles processing @@ -608,42 +661,32 @@ static void process_thumbnail(rgui_t *rgui, struct texture_image *image) if (rgui->thumbnail_queue_size > 0) return; - if (!image->pixels) + /* Sanity check */ + if (!image_src->pixels || (image_src->width < 1) || (image_src->height < 1)) return; - width = image->width; - height = image->height; - - /* Have to crop image if larger than max allowed size... */ - if (width > THUMB_MAX_WIDTH) + /* Downscale thumbnail if it exceeds maximum size limits */ + if ((image_src->width > THUMB_MAX_WIDTH) || (image_src->height > THUMB_MAX_HEIGHT)) { - x_offset = (width - THUMB_MAX_WIDTH) >> 1; - thumbnail.width = THUMB_MAX_WIDTH; + if (!downscale_thumbnail(image_src, &image_resampled)) + return; + image = &image_resampled; } else { - x_offset = 0; - thumbnail.width = width; - } - if (height > THUMB_MAX_HEIGHT) - { - y_offset = (height - THUMB_MAX_HEIGHT) >> 1; - thumbnail.height = THUMB_MAX_HEIGHT; - } - else - { - y_offset = 0; - thumbnail.height = height; + image = image_src; } - /* Copy (cropped) image to thumbnail buffer, performing - * pixel format conversion */ + thumbnail.width = image->width; + thumbnail.height = image->height; + + /* Copy image to thumbnail buffer, performing pixel format conversion */ for (x = 0; x < thumbnail.width; x++) { for (y = 0; y < thumbnail.height; y++) { thumbnail.data[x + (y * thumbnail.width)] = - argb32_to_pixel_platform_format(image->pixels[(x + x_offset) + ((y + y_offset) * width)]); + argb32_to_pixel_platform_format(image->pixels[x + (y * thumbnail.width)]); } } @@ -651,6 +694,12 @@ static void process_thumbnail(rgui_t *rgui, struct texture_image *image) /* Tell menu that a display update is required */ rgui->force_redraw = true; + + /* Clean up */ + image = NULL; + if (image_resampled.pixels) + free(image_resampled.pixels); + image_resampled.pixels = NULL; } static bool rgui_load_image(void *userdata, void *data, enum menu_image_type type) From db46d4322480fc273ae5df98cb2d25ac7437ebba Mon Sep 17 00:00:00 2001 From: orbea Date: Tue, 22 Jan 2019 09:02:48 -0800 Subject: [PATCH 054/234] qb: Add --enable-debug. --- qb/config.libs.sh | 12 ++++++++++++ qb/config.params.sh | 1 + 2 files changed, 13 insertions(+) diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 4b2dbb4954..67424b03c9 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -588,6 +588,18 @@ check_macro NEON __ARM_NEON__ add_define MAKEFILE OS "$OS" +if [ "$HAVE_DEBUG" = 'yes' ]; then + add_define MAKEFILE DEBUG 1 + if [ "$HAVE_OPENGL" = 'yes' ] || + [ "$HAVE_OPENGLES" = 'yes' ] || + [ "$HAVE_OPENGLES3" = 'yes' ]; then + add_define MAKEFILE GL_DEBUG 1 + fi + if [ "$HAVE_VULKAN" = 'yes' ]; then + add_define MAKEFILE VULKAN_DEBUG 1 + fi +fi + if [ "$HAVE_ZLIB" = 'no' ] && [ "$HAVE_RPNG" != 'no' ]; then HAVE_RPNG=no die : 'Notice: zlib is not available, RPNG will also be disabled.' diff --git a/qb/config.params.sh b/qb/config.params.sh index 524b012bec..029eb822ef 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -6,6 +6,7 @@ HAVE_OPENGLES_LIBS= # Link flags for custom GLES library HAVE_OPENGLES_CFLAGS= # C-flags for custom GLES library HAVE_CACA=no # Libcaca support HAVE_SIXEL=no # Libsixel support +HAVE_DEBUG=no # Enable a debug build HAVE_LIBRETRODB=yes # Libretrodb support HAVE_MENU=yes # Enable menu drivers HAVE_RGUI=auto # RGUI menu From 4bf4d281119ea5532cdfb14506121fe5bee1836f Mon Sep 17 00:00:00 2001 From: CozmoP <25121396+CozmoP@users.noreply.github.com> Date: Tue, 22 Jan 2019 19:50:19 +0100 Subject: [PATCH 055/234] Qt: workaround for 5.12.0 drag n drop regression --- ui/drivers/qt/filedropwidget.cpp | 5 +++++ ui/drivers/qt/filedropwidget.h | 1 + 2 files changed, 6 insertions(+) diff --git a/ui/drivers/qt/filedropwidget.cpp b/ui/drivers/qt/filedropwidget.cpp index 2261cfd70a..d8e4b8f3a3 100644 --- a/ui/drivers/qt/filedropwidget.cpp +++ b/ui/drivers/qt/filedropwidget.cpp @@ -69,6 +69,11 @@ void FileDropWidget::dragEnterEvent(QDragEnterEvent *event) event->acceptProposedAction(); } +void FileDropWidget::dragMoveEvent(QDragMoveEvent *event) +{ + event->acceptProposedAction(); +} + void FileDropWidget::dropEvent(QDropEvent *event) { const QMimeData *data = event->mimeData(); diff --git a/ui/drivers/qt/filedropwidget.h b/ui/drivers/qt/filedropwidget.h index 83199295ca..0c2d01a9bf 100644 --- a/ui/drivers/qt/filedropwidget.h +++ b/ui/drivers/qt/filedropwidget.h @@ -19,6 +19,7 @@ signals: void deletePressed(); protected: void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); void keyPressEvent(QKeyEvent *event); void paintEvent(QPaintEvent *event); From bd84bb1c8e8d0b37c0d6828af6be195d4f042363 Mon Sep 17 00:00:00 2001 From: bparker06 Date: Tue, 22 Jan 2019 23:14:11 -0500 Subject: [PATCH 056/234] Update CHANGES.md --- CHANGES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a6a961e56b..cf6e862aed 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,11 @@ - CHEEVOS: Reset when hardcore mode is toggled - CHEEVOS: Update the hashing methods to identify NES, SNES and Lynx games (more accurate and accepting headerless ROMs). - COMMON: Add new JSON playlist format +- COMMON: Fix playlist corruption when deleting items +- COMMON: Fix archive progress display calculation +- COMMON: Fix playlist entries appearing with previously used names +- COMMON: Fix screenshot filename with no core or content +- COMMON: Allow compiling without menu support - CORE UPDATER: Allow sideloading cores from the menu - CPU FILTERS: Add Normal2x filter. - DATE: Add Date / Time style options. @@ -10,6 +15,7 @@ - DISCORD: Register the application name properly. - DISK CONTROL: Remember the last used folder / current active folder to make disk-swapping faster. - INPUT: Add new menu toggle (hold start button for 2 seconds) +- INPUT: Fix arrow keys being incorrectly bound as numpad keys - INPUT/SDL: Flush the joypad events. Decreases cpu usage over time with the SDL joypad driver. - LOCALIZATION: Add Greek translation. - LOCALIZATION: Update German translation. @@ -19,6 +25,9 @@ - LOCALIZATION: Update Spanish translation. - MENU: Only show CRT SwitchRes if video display server is implemented (Windows/Linux for now) - MENU: User Interface -> Appearance -> 'Menu Font Green/Blue Color' settings now work properly. +- MENU/QT/WIMP: Allow building with MSVC2017 +- MENU/QT/WIMP: Add detailed file browser table +- MENU/QT/WIMP: New grid view implementation that is faster and loads thumbnails on-demand - MIDI: Add a Linux ALSA driver for MIDI. - NETPLAY: Force fast-save-states when netlay is enabled - NETPLAY: Allow quick joining subsystem lobbies @@ -35,12 +44,14 @@ - VULKAN: Fix RGUI crashing at startup. - VULKAN: Fix secondary screens in overlays not working. - WAYLAND: Implement idle-inhibit support (needed for screensaver suspend). +- WAYLAND: Fix fullscreen toggle - WIIU: Initial netplay peer-to-peer support. Network information working. - WINDOWS/WSA: Network Information info is blank until first network operation. - WINDOWS: Fix an ancient bug that caused wrong mappings for keyboard arrows - WINDOWS: Remember window size and position if so desired - WINDOWS: SSL/TLS connections now work properly. - UWP: Initial UWP port. +- VFS: Update to version 3 - XBONE: Initial Xbox One port. - XMB/OZONE: Add more icons - ???: Easter Egg From f6481d7f5e4f5dacc093b2765167f1fa79c503a9 Mon Sep 17 00:00:00 2001 From: Hisman Yosika Date: Wed, 23 Jan 2019 20:13:17 +0900 Subject: [PATCH 057/234] Update msg_hash_ko.h Korean translation --- intl/msg_hash_ko.h | 504 ++++++++++++++++++++++----------------------- 1 file changed, 252 insertions(+), 252 deletions(-) diff --git a/intl/msg_hash_ko.h b/intl/msg_hash_ko.h index 4d6d3cc5f6..536b7c2cd6 100644 --- a/intl/msg_hash_ko.h +++ b/intl/msg_hash_ko.h @@ -8,7 +8,7 @@ MSG_HASH( ) MSG_HASH( MSG_NATIVE, - "Native" + "기본" ) MSG_HASH( MSG_DEVICE_DISCONNECTED_FROM_PORT, @@ -108,7 +108,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_HORIZONTAL_ANIMATION, - "Enable horizontal animation for the menu. This will have a performance hit." + "ë©”ë‰´ì˜ ì¢Œìš° 애니메ì´ì…˜ì„ 활성화 했습니다. ì„±ëŠ¥ì— ì˜í–¥ì´ ê°ˆ 수 있습니다." ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_SETTINGS, @@ -670,27 +670,27 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_MINUS, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_PLUS, "ìš° 아날로그 Y+ (하)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, - "Gun Trigger") + "무기 방아쇠") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_RELOAD, - "Gun Reload") + "무기 재장전") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_A, - "Gun Aux A") + "무기 ë³´ì¡°(Aux) A") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_B, - "Gun Aux B") + "무기 ë³´ì¡° B") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_C, - "Gun Aux C") + "무기 ë³´ì¡° C") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_START, - "Gun Start") + "무기 시작버튼") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_SELECT, - "Gun Select") + "무기 ì„ íƒë²„튼") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_UP, - "Gun D-pad Up") + "무기 D-패드 위") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_DOWN, - "Gun D-pad Down") + "무기 D-패드 아래") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_LEFT, - "Gun D-pad Left") + "무기 D-패드 왼쪽") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_RIGHT, - "Gun D-pad Right") + "무기 D-패드 오른쪽") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_AUTODETECT_ENABLE, "ìžë™ì„¤ì • 사용") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_AXIS_THRESHOLD, @@ -754,23 +754,23 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_Y, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_KEY, "(키: %s)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_LEFT, - "Mouse 1") + "마우스 1") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_RIGHT, - "Mouse 2") + "마우스 2") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_MIDDLE, - "Mouse 3") + "마우스 3") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_BUTTON4, - "Mouse 4") + "마우스 4") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_BUTTON5, - "Mouse 5") + "마우스 5") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_WHEEL_UP, - "Wheel Up") + "마우스 휠 스í¬ë¡¤ ì—…") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_WHEEL_DOWN, - "Wheel Down") + "마우스 휠 스í¬ë¡¤ 다운") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_HORIZ_WHEEL_UP, - "Wheel Left") + "마우스 휠 스í¬ë¡¤ 왼쪽") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_HORIZ_WHEEL_DOWN, - "Wheel Right") + "마우스 휠 스í¬ë¡¤ 오른쪽") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_KEYBOARD_GAMEPAD_MAPPING_TYPE, "키보드 게임패드 설정 형ì‹") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MAX_USERS, @@ -856,7 +856,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_LATE, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_NORMAL, "보통") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_PREFER_FRONT_TOUCH, - "Prefer Front Touch") + "ì „ë©´ 터치 선호") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_REMAPPING_DIRECTORY, "입력설정 파ì¼") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_REMAP_BINDS_ENABLE, @@ -916,7 +916,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_SPANISH, MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_VIETNAMESE, "베트남어") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ARABIC, - "Arabic") + "ì•„ëžì–´") MSG_HASH(MENU_ENUM_LABEL_VALUE_LEFT_ANALOG, "좌 아날로그") MSG_HASH(MENU_ENUM_LABEL_VALUE_LIBRETRO_DIR_PATH, @@ -976,7 +976,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FILE_BROWSER_SETTINGS, MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_LINEAR_FILTER, "메뉴 선형 í•„í„°") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_HORIZONTAL_ANIMATION, - "Horizontal Animation") + "좌우 애니메ì´ì…˜") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SETTINGS, "메뉴") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_WALLPAPER, @@ -1333,9 +1333,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_RIBBON, MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_RIBBON_SIMPLIFIED, "리본 (단순화)") MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_SIMPLE_SNOW, - "Simple Snow") + "눈 (단순화)") MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_SNOW, - "Snow") + "눈") MSG_HASH(MENU_ENUM_LABEL_VALUE_SHOW_ADVANCED_SETTINGS, "고급 설정 ë³´ìž„") MSG_HASH(MENU_ENUM_LABEL_VALUE_SHOW_HIDDEN_FILES, @@ -1705,55 +1705,55 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS, MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ALPHA_FACTOR, "메뉴 알파 요소") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FONT_COLOR_RED, - "Menu Font Red Color") + "메뉴 í°íЏ 빨강") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FONT_COLOR_GREEN, - "Menu Font Green Color") + "메뉴 í°íЏ ì´ˆë¡") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FONT_COLOR_BLUE, - "Menu Font Blue Color") + "메뉴 í°íЏ 파랑") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_FONT, "메뉴 í°íЏ") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_CUSTOM, - "사용ìž") + "ì‚¬ìš©ìž ì§€ì •") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_FLATUI, - "FlatUI") + "í‰ë©´UI") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_MONOCHROME, - "Monochrome") + "í‘ë°±") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_MONOCHROME_INVERTED, - "Monochrome Inverted") + "í‘ë°± 색 반전") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_SYSTEMATIC, - "Systematic") + "체계ì ") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_NEOACTIVE, - "NeoActive") + "미래") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_PIXEL, - "Pixel") + "픽셀") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_RETROACTIVE, - "RetroActive") + "레트로í’") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_RETROSYSTEM, - "Retrosystem") + "레트로시스템") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_DOTART, - "Dot-Art") + "ì ë¬˜ë²•") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME, "메뉴 ìƒ‰ìƒ í…Œë§ˆ") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_APPLE_GREEN, - "Apple Green") + "애플 그린") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_DARK, - "Dark") + "다í¬") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_DARK_PURPLE, - "Dark Purple") + "ì–´ë‘ìš´ ë³´ë¼") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_ELECTRIC_BLUE, - "Electric Blue") + "ì¼ë ‰íŠ¸ë¦­ 블루") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_GOLDEN, - "Golden") + "금색") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_LEGACY_RED, - "Legacy Red") + "레거시 레드") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_MIDNIGHT_BLUE, - "Midnight Blue") + "미드나잇 블루") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_PLAIN, - "Plain") + "산뜻한") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_UNDERSEA, - "Undersea") + "심해") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_VOLCANIC_RED, - "Volcanic Red") + "ë³¼ìºë‹‰ 레드") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_RIBBON_ENABLE, "메뉴 ì‰ì´ë” 파ì´í”„ë¼ì¸") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SCALE_FACTOR, @@ -1775,7 +1775,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "ë„·í”Œë ˆì´ íƒ­ ë³´ì´ê¸°") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, - "Menu Layout") + "매뉴 형태") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "메뉴 ì•„ì´ì½˜ 테마") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1783,7 +1783,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, MSG_HASH(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_TWO, "ì‰ì´ë” 프리셋") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, - "ë„전과제 사용 설정. ìžì„¸í•œ 정보는 http://retroachievements.org 방문.") + "ë„전과제 ì‚¬ìš©ì„ ì„¤ì •í–ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ 정보는 http://retroachievements.org 방문해주세요.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, "ë¹„ê³µì‹ ë„전과제 ë˜ëŠ” 테스트 목ì ì˜ 베타기능 사용 설정/í•´ì œ.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, @@ -1877,7 +1877,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "í™”ë©´ì˜ ì •í™•í•œ 리프레시 비율(Hz) 측정치.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, - "The refresh rate as reported by the display driver.") + "ë””ìŠ¤í”Œë ˆì´ ë“œë¼ì´ë²„ê°€ 보고한 화면 주사율입니다.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "비디오 출력 설정 변경.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2097,7 +2097,7 @@ MSG_HASH(MSG_INPUT_CHEAT_FILENAME, MSG_HASH(MSG_INPUT_PRESET_FILENAME, "프리셋 파ì¼ëª…") MSG_HASH(MSG_INPUT_RENAME_ENTRY, - "Rename Title") + "제목 수정") MSG_HASH(MSG_INTERFACE, "ì¸í„°íŽ˜ì´ìФ") MSG_HASH(MSG_INTERNAL_STORAGE, @@ -3036,414 +3036,414 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_Y, "ë·°í¬íŠ¸ì˜ Yì¶• 위치를 ì •ì˜í•˜ëŠ” ë° ì‚¬ìš©ë˜ëŠ” ì‚¬ìš©ìž ë·°í¬íЏ 오프셋. '정수 단위 화면 í¬ê¸°'ê°€ 활성화 ëœ ê²½ìš° 무시ë˜ê³  ìžë™ìœ¼ë¡œ ì¤‘ì•™ì´ ë©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_USE_MITM_SERVER, - "Use Relay Server") + "중계 서버 사용") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_USE_MITM_SERVER, - "Forward netplay connections through a man-in-the-middle server. Useful if the host is behind a firewall or has NAT/UPnP problems.") + "ë„·í”Œë ˆì´ ì ‘ì†ì‹œ 중계 서버를 사용합니다. ë°©ìž¥ì´ ë°©í™”ë²½ì„ ì‚¬ìš©í•˜ê³  있거나 NAT/UPnP 문제가 ìƒê²¼ì„경우 유용합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER, - "Add to mixer") + "ë¯¹ì„œì— ì¶”ê°€") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_PLAY, - "Add to mixer and play") + "ë¯¹ì„œì— ì¶”ê°€ 후 재ìƒ") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION, - "Add to mixer") + "ë¯¹ì„œì— ì¶”ê°€") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION_AND_PLAY, - "Add to mixer and play") + "ë¯¹ì„œì— ì¶”ê°€ 후 재ìƒ") MSG_HASH(MENU_ENUM_LABEL_VALUE_FILTER_BY_CURRENT_CORE, - "Filter by current core") + "현재 ì½”ì–´ì— ë”°ë¼ í•„í„°") MSG_HASH( MSG_AUDIO_MIXER_VOLUME, - "Global audio mixer volume" + "ì „ì—­ 오디오 믹서 볼륨" ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_MIXER_VOLUME, - "Global audio mixer volume (in dB). 0 dB is normal volume, and no gain is applied." + "ì „ì—­ 오디오 믹서 볼륨 (dB 단위). 0 dBì´ ê¸°ë³¸ 볼륨, ì¦í­ì€ ì ìš©ë˜ì§€ 않습니다." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_VOLUME, - "Audio Mixer Volume Level (dB)" + "오디오 믹서 볼륨 í¬ê¸° (dB)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_MUTE, - "Audio Mixer Mute" + "오디오 믹서 ìŒì†Œê±°" ) MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MIXER_MUTE, - "Mute/unmute mixer audio.") + "믹서 ë³¼ë¥¨ì„ ìŒì†Œê±°/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_MENU_SHOW_ONLINE_UPDATER, - "Show Online Updater") + "온ë¼ì¸ ì—…ë°ì´íЏ 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_ONLINE_UPDATER, - "Show/hide the 'Online Updater' option.") + "온ë¼ì¸ ì—…ë°ì´íЏ ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CORE_UPDATER, - "Show Core Updater") + "코어 ì—…ë°ì´íЏ 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CORE_UPDATER, - "Show/hide the ability to update cores (and core info files).") + "ì—…ë°ì´íЏ 가능한 코어와 코어 ì •ë³´ 파ì¼ì„ 표시/í•´ì œ 합니다.") MSG_HASH(MSG_PREPARING_FOR_CONTENT_SCAN, - "Preparing for content scan...") + "컨í…츠 스캔 준비중...") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_DELETE, - "Delete core") + "코어 ì‚­ì œ") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_DELETE, - "Remove this core from disk.") + "ì´ ì½”ì–´ë¥¼ 삭제합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY, - "Rename the title of the entry.") + "ì—”íŠ¸ë¦¬ì˜ ì œëª©ì„ ìˆ˜ì •í•©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_RENAME_ENTRY, - "Rename") + "수정") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FRAMEBUFFER_OPACITY, - "Framebuffer Opacity") + "프레임 ë²„í¼ ë¶ˆíˆ¬ëª…ë„") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_FRAMEBUFFER_OPACITY, - "Modify the opacity of the framebuffer.") + "프레임 버í¼ì˜ 불투명ë„를 수정합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES, - "Favorites") + "ì¦ê²¨ì°¾ê¸°") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_FAVORITES, - "Content which you have added to 'Favorites' will appear here.") + "ì¦ê²¨ì°¾ê¸°ë¡œ 등ë¡í•œ 컨í…츠가 ì´ê³³ì— 표시ë©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_MUSIC, - "Music") + "ìŒì•…") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_MUSIC, - "Music which has been previously played will appear here.") + "ì´ì „ì— ìž¬ìƒë˜ì—ˆë˜ 노래가 ì´ê³³ì— 표시ë©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_IMAGES, - "Image") + "사진") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_IMAGES, - "Images which have been previously viewed will appear here.") + "ì´ì „ì— ì—´ëžŒí–ˆë˜ ì‚¬ì§„ì´ ì´ê³³ì— 표시ë©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_VIDEO, - "Video") + "ì˜ìƒ") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_VIDEO, - "Videos which have been previously played will appear here.") + "ì´ì „ì— ìž¬ìƒë˜ì—ˆë˜ ì˜ìƒë“¤ì´ ì´ê³³ì— 표시ë©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_ICONS_ENABLE, - "Menu Icons") + "메뉴 ì•„ì´ì½˜") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_ICONS_ENABLE, - "Enable/disable the menu icons shown at the lefthand side of the menu entries.") + "메뉴 ì—”íŠ¸ë¦¬ì— ì™¼ìª½ì— í‘œì‹œë˜ëŠ” 메뉴 ì•„ì´ì½˜ë“¤ì„ 표시/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MAIN_MENU_ENABLE_SETTINGS, - "Enable Settings Tab") + "설정 탭 표시") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS_PASSWORD, - "Set Password For Enabling Settings Tab") + "'설정 탭 표시'ëž€ì— ë¹„ë°€ë²ˆí˜¸ 설정") MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD, - "Enter Password") + "비밀번호 ìž…ë ¥") MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_OK, - "Password correct.") + "비밀번호가 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤.") MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_NOK, - "Password incorrect.") + "비밀번호가 틀렸습니다.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_MAIN_MENU_ENABLE_SETTINGS, - "Enables the Settings tab. A restart is required for the tab to appear.") + "설정 íƒ­ì„ í‘œì‹œ/í•´ì œ 합니다. 다시 표시하기 위해 ìž¬ì‹œìž‘ì´ í•„ìš”í•©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_SETTINGS_PASSWORD, - "Supplying a password when hiding the settings tab makes it possible to later restore it from the menu, by going to the Main Menu tab, selecting Enable Settings Tab and entering the password.") + "설정 íƒ­ì„ ìˆ¨ê¸¸ë•Œ 비밀번호를 설정해 ë‚˜ì¤‘ì— ë˜ëŒë¦´ìˆ˜ 있게 ë” í•©ë‹ˆë‹¤. ë©”ì¸ ë©”ë‰´ì—서 '설정 탭 표시'를 ì„ íƒ í›„ 비밀번호를 입력해 ë˜ëŒë¦´ìˆ˜ 있습니다.") MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_ENTRY_RENAME, - "Allow the user to rename entries in collections.") + "ì½œë ‰ì…˜ì— ìžˆëŠ” ì—”íŠ¸ë¦¬ë“¤ì„ íŽ¸ì§‘í•  수 있게 허용합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_ENTRY_RENAME, - "Allow to rename entries") + "엔트리 편집 허용") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CORE, - "Show Load Core") + "코어 불러오기 설정 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CORE, - "Show/hide the 'Load Core' option.") + "코어 ë¶ˆëŸ¬ì˜¤ê¸°ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CONTENT, - "Show Load Content") + "컨í…츠 불러오기 설정 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CONTENT, - "Show/hide the 'Load Content' option.") + "컨í…츠 ë¶ˆëŸ¬ì˜¤ê¸°ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_INFORMATION, - "Show Information") + "ì •ë³´ 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_INFORMATION, - "Show/hide the 'Information' option.") + "ì •ë³´ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CONFIGURATIONS, - "Show Configurations") + "설정(Config) 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CONFIGURATIONS, - "Show/hide the 'Configurations' option.") + "설정(Config)ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_HELP, - "Show Help") + "ë„ì›€ë§ í‘œì‹œ") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_HELP, - "Show/hide the 'Help' option.") + "ë„움ë§ì„ 표시/í•´ì œ 합니다.") #ifdef HAVE_LAKKA MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_QUIT_RETROARCH, - "Show Restart RetroArch") + "RetroArch 재시작 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_QUIT_RETROARCH, - "Show/hide the 'Restart RetroArch' option.") + "RetroArch 재시작 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") #else MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_QUIT_RETROARCH, - "Show Quit RetroArch") + "RetroArch 나가기 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_QUIT_RETROARCH, - "Show/hide the 'Quit RetroArch' option.") + "RetroArch 나가기 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") #endif MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_REBOOT, - "Show Reboot") + "재시작 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_REBOOT, - "Show/hide the 'Reboot' option.") + "재시작 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_SHUTDOWN, - "Show Shutdown") + "ì „ì› ë„기 표시") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_SHUTDOWN, - "Show/hide the 'Shutdown' option.") + "ì „ì› ë„기 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_VIEWS_SETTINGS, - "Quick Menu") + "빠른 메뉴") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_VIEWS_SETTINGS, - "Show or hide elements on the Quick Menu screen.") + "빠른 ë©”ë‰´ì˜ ì»¨í…츠를 표시/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_TAKE_SCREENSHOT, - "Show Take Screenshot") + "스í¬ë¦°ìƒ· ì°ê¸° 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_TAKE_SCREENSHOT, - "Show/hide the 'Take Screenshot' option.") + "스í¬ë¦°ìƒ· ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_LOAD_STATE, - "Show Save/Load State") + "저장/불러오기 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_LOAD_STATE, - "Show/hide the options for saving/loading state.") + "저장/불러오기 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, - "Show Undo Save/Load State") + "저장/불러오기 ìƒíƒœ ë˜ëŒë¦¬ê¸° 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, - "Show/hide the options for undoing save/load state.") + "저장/불러오기 ìƒíƒœ ë˜ëŒë¦¬ê¸° ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_ADD_TO_FAVORITES, - "Show Add to Favorites") + "ì¦ê²¨ì°¾ê¸°ì— 추가 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_ADD_TO_FAVORITES, - "Show/hide the 'Add to Favorites' option.") + "ì¦ê²¨ì°¾ê¸°ì— 추가 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_START_RECORDING, - "Show Start Recording") + "녹화 시작 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_START_RECORDING, - "Show/hide the 'Start Recording' option.") + "녹화 시작 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_START_STREAMING, - "Show Start Streaming") + "방송 시작 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_START_STREAMING, - "Show/hide the 'Start Streaming' option.") + "방송 시작 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_RESET_CORE_ASSOCIATION, - "Show Reset Core Association") + "코어 리스트 초기화 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_RESET_CORE_ASSOCIATION, - "Show/hide the 'Reset Core Association' option.") + "코어 리스트 초기화 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_OPTIONS, - "Show Options") + "설정 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_OPTIONS, - "Show/hide the 'Options' option.") + "'설정' ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CONTROLS, - "Show Controls") + "ì¡°ìž‘ 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CONTROLS, - "Show/hide the 'Controls' option.") + "ì¡°ìž‘ ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CHEATS, - "Show Cheats") + "치트 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CHEATS, - "Show/hide the 'Cheats' option.") + "치트 ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SHADERS, - "Show Shaders") + "ì‰ì´ë” 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SHADERS, - "Show/hide the 'Shaders' option.") + "ì‰ì´ë” ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, - "Show Save Core Overrides") + "코어 ë®ì–´ì“°ê¸° 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, - "Show/hide the 'Save Core Overrides' option.") + "코어 ë®ì–´ì“°ê¸° ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, - "Show Save Game Overrides") + "게임 저장 ë®ì–´ì“°ê¸° 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, - "Show/hide the 'Save Game Overrides' option.") + "게임 저장 ë®ì–´ì“°ê¸° ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_INFORMATION, - "Show Information") + "ì •ë³´ 표시") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_INFORMATION, - "Show/hide the 'Information' option.") + "ì •ë³´ ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_DISABLE_KIOSK_MODE, - "Disable Kiosk Mode") + "í‚¤ì˜¤ìŠ¤í¬ ëª¨ë“œ 비활성화") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_DISABLE_KIOSK_MODE, - "Disables kiosk mode. A restart is required for the change to take full effect.") + "í‚¤ì˜¤ìŠ¤í¬ ëª¨ë“œë¥¼ 비활성화 합니다. 완전한 비활성화를 위해 ìž¬ì‹œìž‘ì´ í•„ìš”í•©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_ENABLE_KIOSK_MODE, - "Enable Kiosk Mode") + "공중전화 모드 활성화") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENABLE_KIOSK_MODE, - "Protects the setup by hiding all configuration related settings.") + "모든 ì„¤ì •ì„ ìˆ¨ê²¨ 편집할수 없게 합니다. ê°œë°©ëœ ê³³ì—서 ì„¤ì •ì´ íŽ¸ì§‘ë˜ëŠ” ì¼ì„ 막ì„때 유용합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_KIOSK_MODE_PASSWORD, - "Set Password For Disabling Kiosk Mode") + "í‚¤ì˜¤ìŠ¤í¬ ëª¨ë“œ 비활성화 비밀번호 설정") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_KIOSK_MODE_PASSWORD, - "Supplying a password when enabling kiosk mode makes it possible to later disable it from the menu, by going to the Main Menu, selecting Disable Kiosk Mode and entering the password.") + "í‚¤ì˜¤ìŠ¤í¬ ëª¨ë“œë¥¼ 비활성화할때 비밀번호를 설정해 ë‚˜ì¤‘ì— ì„¤ì •í•  수 있게 ë” í•©ë‹ˆë‹¤. ë©”ì¸ ë©”ë‰´ì—서 'í‚¤ì˜¤ìŠ¤í¬ ëª¨ë“œ 비활성화'를 ì„ íƒ í›„ 비밀번호를 입력해 설정할 수 있습니다.") MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD, - "Enter Password") + "비밀번호 ìž…ë ¥") MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_OK, - "Password correct.") + "비밀번호가 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤.") MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_NOK, - "Password incorrect.") + "비밀번호가 틀렸습니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, - "Automatically add content to playlist") + "ìž¬ìƒ ëª©ë¡ì— 컨í…츠 검색 후 ìžë™ 추가") MSG_HASH(MENU_ENUM_SUBLABEL_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, - "Automatically scans loaded content so they appear inside playlists.") + "컨í…츠를 ìžë™ìœ¼ë¡œ 검색해 ìž¬ìƒ ëª©ë¡ì— 표시합니다.") MSG_HASH(MSG_SCANNING_OF_FILE_FINISHED, - "Scanning of file finished") + "íŒŒì¼ ìŠ¤ìº” 완료") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, - "Audio Resampler Quality") + "오디오 리샘플러 품질") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, - "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") + "ì´ ê°’ì„ ë‚´ë ¤ì„œ ì˜¤ë””ì˜¤ì˜ ë°˜ì‘ ì†ë„를 늘리거나 올려서 ì˜¤ë””ì˜¤ì˜ í’ˆì§ˆì„ ê°œì„ í•©ë‹ˆë‹¤. 둘중 하나는 í¬ê¸°í•´ì•¼ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, - "Display Statistics") + "통계 표시") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, - "Show onscreen technical statistics.") + "í™”ë©´ì— í‘œì‹œë˜ëŠ” 고급 사용ìžìš© 통계를 표시합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, - "Enable border filler") + "ì°½ í…Œë‘리 채우기 설정") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, - "Enable border filler thickness") + "ì°½ í…Œë‘리 굵기 설정") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, - "Enable background filler thickness") -MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For CRT displays only. Attempts to use exact core/game resolution and refresh rate.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") + "바탕화면 í•„í„° 굵기 설정") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "ê° ì½”ì–´/ê²Œìž„ì— ì í•©í•œ í•´ìƒë„와 ì£¼ì‚¬ìœ¨ì„ ì‚¬ìš©í•©ë‹ˆë‹¤. CRT ë””ìŠ¤í”Œë ˆì´ ì „ìš© 설정입니다.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT 리소스 전환") MSG_HASH( MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, - "Switch among native and ultrawide super resolutions." + "기본/고화질 í•´ìƒë„중 하나를 ì„ íƒí•©ë‹ˆë‹¤." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, - "Show Rewind Settings") + "ë˜ê°ê¸° 설정 표시") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, - "Show/hide the Rewind options.") + "ë˜ê°ê¸° ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, - "Show/hide the Latency options.") + "ë ˆì´í„´ì‹œ ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, - "Show Latency Settings") + "ë ˆì´í„´ì‹œ 설정 표시") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, - "Show/hide the Overlay options.") + "ì˜¤ë²„ë ˆì´ ì„¤ì •ëž€ì„ í‘œì‹œ/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, - "Show Overlay Settings") + "ì˜¤ë²„ë ˆì´ ì„¤ì • 표시") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU, - "Enable menu audio") + "메뉴 íš¨ê³¼ìŒ í™œì„±í™”") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_ENABLE_MENU, - "Enable or disable menu sound.") + "메뉴 효과ìŒì„ 활성화/í•´ì œ 합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_SETTINGS, - "Mixer Settings") + "믹서 설정") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MIXER_SETTINGS, - "View and/or modify audio mixer settings.") + "오디오 ì„¤ì •ì„ í™•ì¸í•˜ê±°ë‚˜ 편집합니다.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_OVERRIDE_OPTIONS, - "Overrides") + "기존 설정 ë®ì–´ì“°ê¸°") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_OVERRIDE_OPTIONS, - "Options for overriding the global configuration.") + "ê¸°ì¡´ì˜ ì „ì—­ ì„¤ì •ì„ ë®ì–´ ì”니다.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY, - "Will start playback of the audio stream. Once finished, it will remove the current audio stream from memory.") + "오디오 ìŠ¤íŠ¸ë¦¼ì„ ìž¬ìƒí•©ë‹ˆë‹¤. ìž¬ìƒ í›„ì— ì˜¤ë””ì˜¤ ìŠ¤íŠ¸ë¦¼ì„ ë©”ëª¨ë¦¬ì—서 제거합니다.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY_LOOPED, - "Will start playback of the audio stream. Once finished, it will loop and play the track again from the beginning.") + "오디오 ìŠ¤íŠ¸ë¦¼ì„ ìž¬ìƒí•©ë‹ˆë‹¤. ìž¬ìƒ í›„ì— ë‹¤ì‹œ 반복합니다.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY_SEQUENTIAL, - "Will start playback of the audio stream. Once finished, it will jump to the next audio stream in sequential order and repeat this behavior. Useful as an album playback mode.") + "오디오 ìŠ¤íŠ¸ë¦¼ì„ ìž¬ìƒí•©ë‹ˆë‹¤. ìž¬ìƒ í›„ì— ë‹¤ìŒ ì˜¤ë””ì˜¤ 스트림으로 넘어갑니다. 앨범 ìž¬ìƒ ëª¨ë“œì— ìœ ìš©í•©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_STOP, - "This will stop playback of the audio stream, but not remove it from memory. You can start playing it again by selecting 'Play'.") + "재ìƒë˜ë˜ 오디오 ìŠ¤íŠ¸ë¦¼ì„ ë©ˆì¶”ê³  메모리는 유지합니다. ìž¬ìƒ ë²„íŠ¼ì„ ëˆŒëŸ¬ 다시 재ìƒí•  수 있습니다.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_REMOVE, - "This will stop playback of the audio stream and remove it entirely from memory.") + "재ìƒë˜ë˜ 오디오 ìŠ¤íŠ¸ë¦¼ì„ ë©ˆì¶”ê³  메모리ì—서 완전히 제거합니다.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_VOLUME, - "Adjust the volume of the audio stream.") + "오디오 ìŠ¤íŠ¸ë¦¼ì˜ ë³¼ë¥¨ì„ ì„¤ì •í•©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_SUBLABEL_ADD_TO_MIXER, - "Add this audio track to an available audio stream slot. If no slots are currently available, it will be ignored.") + "ì´ ì˜¤ë””ì˜¤ íŠ¸ëž™ì„ ê°€ëŠ¥í•œ 오디오 스트림 ìŠ¬ë¡¯ì— ì¶”ê°€í•©ë‹ˆë‹¤. ìž¬ìƒ ê°€ëŠ¥í•œ ìŠ¬ë¡¯ì´ ì—†ìœ¼ë©´ 무시ë©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_SUBLABEL_ADD_TO_MIXER_AND_PLAY, - "Add this audio track to an available audio stream slot and play it. If no slots are currently available, it will be ignored.") + "ì´ ì˜¤ë””ì˜¤ íŠ¸ëž™ì„ ê°€ëŠ¥í•œ 오디오 스트림 ìŠ¬ë¡¯ì— ì¶”ê°€í•œ ë’¤ 재ìƒí•©ë‹ˆë‹¤. ìž¬ìƒ ê°€ëŠ¥í•œ ìŠ¬ë¡¯ì´ ì—†ìœ¼ë©´ 무시ë©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY, - "Play") + "재ìƒ") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY_LOOPED, - "Play (Looped)") + "ìž¬ìƒ (반복)") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY_SEQUENTIAL, - "Play (Sequential)") + "ìž¬ìƒ (ì—°ì† ìž¬ìƒ)") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_STOP, - "Stop") + "중지") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_REMOVE, - "Remove") + "ì‚­ì œ") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_VOLUME, - "Volume") + "볼륨") MSG_HASH(MENU_ENUM_LABEL_VALUE_DETECT_CORE_LIST_OK_CURRENT_CORE, - "Current core") + "현재 코어") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_SEARCH_CLEAR, - "Clear") + "초기화") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_IN_MENU, - "In-Menu") + "메뉴 ì„ íƒì¤‘") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME, - "In-Game") + "게임 중") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME_PAUSED, - "In-Game (Paused)") + "게임 중 (ì¼ì‹œ ì •ì§€ë¨)") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PLAYING, - "Playing") + "실행 중") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PAUSED, - "Paused") + "ì¼ì‹œ ì •ì§€") MSG_HASH( MENU_ENUM_LABEL_VALUE_DISCORD_ALLOW, - "Enable Discord" + "Discord 활성화" ) MSG_HASH( MENU_ENUM_SUBLABEL_DISCORD_ALLOW, - "Enable or disable Discord support. Will not work with the browser version, only native desktop client." + "Discord ì§€ì›ì„ 활성화/í•´ì œ 합니다. í´ë¼ì´ì–¸íЏ 버전 ì´ì™¸ì— 브ë¼ìš°ì € 버전 Discordì—는 ì ìš©ì´ ë˜ì§€ ì•Šì„ ìˆ˜ 있습니다." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_POWER_MANAGEMENT_SETTINGS, - "Power Management") + "ì „ë ¥ 관리") MSG_HASH(MENU_ENUM_SUBLABEL_POWER_MANAGEMENT_SETTINGS, - "Change power management settings.") + "ì „ë ¥ 관리 ì„¤ì •ë“¤ì„ ìˆ˜ì •í•©ë‹ˆë‹¤.") MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, - "Sustained Performance Mode") + "ì§€ì†ëœ 성능 모드") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, - "mpv support") + "mpv ì§€ì›") MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, - "Adaptive Vsync" + "ì ì‘형 ìˆ˜ì§ ë™ê¸°" ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, - "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + "ì„¤ì •ëœ ì£¼ì‚¬ìœ¨ë³´ë‹¤ ë‚®ì€ ì„±ëŠ¥ì´ ê°ì§€ë  경우 ìˆ˜ì§ ë™ê¸°í™”ê°€ ìžë™ìœ¼ë¡œ 활성화ë©ë‹ˆë‹¤. ë²„ë²…ìž„ì„ ë°©ì§€í•  수 있고 ì—너지 ì ˆì•½ì— ë„ì›€ì´ ë©ë‹ˆë‹¤." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CRT_SWITCHRES_SETTINGS, - "CRT SwitchRes" + "CRT 리소스 변경" ) MSG_HASH( MENU_ENUM_SUBLABEL_CRT_SWITCHRES_SETTINGS, - "Output native, low-resolution signals for use with CRT displays." + "기본 출력, CRT 디스플레ì´ì™€ 함께 사용하기위한 저해ìƒë„ 신호를 사용합니다." ) MSG_HASH( MENU_ENUM_SUBLABEL_CRT_SWITCH_X_AXIS_CENTERING, - "Cycle through these options if the image is not centered properly on the display." + "ì´ë¯¸ì§€ê°€ ë””ìŠ¤í”Œë ˆì´ ì¤‘ì•™ì— í‘œì‹œë ë•Œê¹Œì§€ 해당 ì„¤ì •ë“¤ì„ ë²ˆê°ˆì•„ 가면서 ì ìš©í•´ì£¼ì„¸ìš”." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CRT_SWITCH_X_AXIS_CENTERING, - "X-Axis Centering" + "X-ì¶• 센터ë§" ) MSG_HASH( MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_USE_CUSTOM_REFRESH_RATE, - "Use a custom refresh rate specified in the config file if needed.") + "설정 파ì¼ì— 쓰여진 ì‚¬ìš©ìž ì§€ì • ì£¼ì‚¬ìœ¨ì„ ì‚¬ìš©í•©ë‹ˆë‹¤.") MSG_HASH( MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_USE_CUSTOM_REFRESH_RATE, - "Use Custom Refresh Rate") + "주사율 ì‚¬ìš©ìž ì„¤ì •") MSG_HASH( MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_OUTPUT_DISPLAY_ID, - "Select the output port connected to the CRT display.") + "CRT 디스플레ì´ì™€ ì—°ê²°ëœ í¬íŠ¸ë¥¼ ì„ íƒí•´ì£¼ì„¸ìš”.") MSG_HASH( MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_OUTPUT_DISPLAY_ID, - "Output Display ID") + "출력ë˜ëŠ” ë””ìŠ¤í”Œë ˆì´ ID") MSG_HASH( MENU_ENUM_LABEL_VALUE_QUICK_MENU_START_RECORDING, - "Start Recording" + "녹화 시작" ) MSG_HASH( MENU_ENUM_SUBLABEL_QUICK_MENU_START_RECORDING, - "Starts recording." + "녹화를 시작합니다." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_QUICK_MENU_STOP_RECORDING, - "Stop Recording" + "녹화 중지" ) MSG_HASH( MENU_ENUM_SUBLABEL_QUICK_MENU_STOP_RECORDING, - "Stops recording." + "녹화를 중지합니다." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_QUICK_MENU_START_STREAMING, - "Start Streaming" + "방송 시작" ) MSG_HASH( MENU_ENUM_SUBLABEL_QUICK_MENU_START_STREAMING, - "Starts streaming." + "ë°©ì†¡ì„ ì‹œìž‘í•©ë‹ˆë‹¤." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_QUICK_MENU_STOP_STREAMING, - "Stop Streaming" + "방송 중지" ) MSG_HASH( MENU_ENUM_SUBLABEL_QUICK_MENU_STOP_STREAMING, - "Stops streaming." + "ë°©ì†¡ì„ ì¤‘ì§€í•©ë‹ˆë‹¤." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_RECORDING_TOGGLE, - "Recording toggle" + "토글 녹화" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_STREAMING_TOGGLE, - "Streaming toggle" + "토글 스트리ë°" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_RECORD_QUALITY, - "Record Quality" + "녹화 품질" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_STREAM_QUALITY, - "Stream Quality" + "방송 품질" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_STREAMING_URL, - "Streaming URL" + "ìŠ¤íŠ¸ë¦¬ë° URL" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_UDP_STREAM_PORT, - "UDP Stream Port" + "UDP 스트림 í¬íЏ" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ACCOUNTS_TWITCH, @@ -3454,72 +3454,72 @@ MSG_HASH( "YouTube" ) MSG_HASH(MENU_ENUM_LABEL_VALUE_TWITCH_STREAM_KEY, - "Twitch Stream Key") + "Twitch 스트림 키") MSG_HASH(MENU_ENUM_LABEL_VALUE_YOUTUBE_STREAM_KEY, - "YouTube Stream Key") + "YouTube 스트림 키") MSG_HASH(MENU_ENUM_LABEL_VALUE_STREAMING_MODE, - "Streaming Mode") + "방송 모드") MSG_HASH(MENU_ENUM_LABEL_VALUE_STREAMING_TITLE, - "Title of Stream") + "방송 제목") MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_SPLIT_JOYCON, - "Split Joy-Con" + "Joy-Con 분할하기" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_RESET_TO_DEFAULT_CONFIG, - "Reset To Defaults" + "기본 설정으로 ë˜ëŒë¦¬ê¸°" ) MSG_HASH( MENU_ENUM_SUBLABEL_RESET_TO_DEFAULT_CONFIG, - "Reset the current configuration to default values." + "현재 ì„¤ì •ì„ ê¸°ë³¸ 설정으로 ë˜ëŒë¦½ë‹ˆë‹¤." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_OK, - "OK" + "네" ) MSG_HASH(MENU_ENUM_LABEL_VALUE_OZONE_MENU_COLOR_THEME, "메뉴 테마 색ìƒ") MSG_HASH( MENU_ENUM_LABEL_VALUE_OZONE_COLOR_THEME_BASIC_WHITE, - "Basic White" + "기본 하양색" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_OZONE_COLOR_THEME_BASIC_BLACK, - "Basic Black" + "기본 검정색" ) MSG_HASH( MENU_ENUM_SUBLABEL_OZONE_MENU_COLOR_THEME, - "Select a different color theme." + "다른 색깔 테마를 설정해주세요." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_USE_PREFERRED_SYSTEM_COLOR_THEME, - "Use preferred system color theme") + "ì„ í˜¸ëœ ì‹œìŠ¤í…œ ìƒ‰ìƒ í…Œë§ˆ 사용") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_USE_PREFERRED_SYSTEM_COLOR_THEME, - "Use your operating system's color theme (if any) - overrides theme settings.") + "(존재할경우)시스템 색ìƒì— ë”°ë¼ ìƒ‰ìƒ í…Œë§ˆë¥¼ ì ìš©í•©ë‹ˆë‹¤. - ê¸°ì¡´ì˜ í…Œë§ˆ ì„¤ì •ì€ ë¬´ì‹œë©ë‹ˆë‹¤.") MSG_HASH(MSG_RESAMPLER_QUALITY_LOWEST, - "Lowest") + "매우 ë‚®ìŒ") MSG_HASH(MSG_RESAMPLER_QUALITY_LOWER, - "Lower") + "ë‚®ìŒ") MSG_HASH(MSG_RESAMPLER_QUALITY_NORMAL, - "Normal") + "보통") MSG_HASH(MSG_RESAMPLER_QUALITY_HIGHER, - "Higher") + "높ìŒ") MSG_HASH(MSG_RESAMPLER_QUALITY_HIGHEST, - "Highest") + "매우 높ìŒ") MSG_HASH( MENU_ENUM_LABEL_VALUE_NO_MUSIC_AVAILABLE, - "No music available." + "ìŒì•…ì´ ë¹„ì—ˆìŠµë‹ˆë‹¤." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NO_VIDEOS_AVAILABLE, - "No videos available." + "ì˜ìƒì´ 비었습니다." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NO_IMAGES_AVAILABLE, - "No images available." + "ì‚¬ì§„ì´ ë¹„ì—ˆìŠµë‹ˆë‹¤." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NO_FAVORITES_AVAILABLE, - "No favorites available." + "ì¦ê²¨ì°¾ê¸°ê°€ 비었습니다." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_SAVE_POSITION, - "Remember Window Position and Size") + "ì°½ 위치와 사ì´ì¦ˆë¥¼ 기억합니다.") From 3b24d34545ea38b5d0c5930c75b228cdc31f360a Mon Sep 17 00:00:00 2001 From: Hisman Yosika Date: Wed, 23 Jan 2019 20:34:15 +0900 Subject: [PATCH 058/234] Minor translation errors in korean --- intl/msg_hash_ko.c | 78 ++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/intl/msg_hash_ko.c b/intl/msg_hash_ko.c index fcf0c1601d..ea3aa929e0 100644 --- a/intl/msg_hash_ko.c +++ b/intl/msg_hash_ko.c @@ -42,50 +42,55 @@ int menu_hash_get_help_ko_enum(enum msg_hash_enums msg, char *s, size_t len) switch (idx) { case RARCH_FAST_FORWARD_KEY: snprintf(s, len, - "빨리ê°ê¸°ì™€ 보통ì†ë„ 전환." + "빨리ê°ê¸°ì™€ 보통ì†ë„ê°„ 전환합니다." ); break; case RARCH_FAST_FORWARD_HOLD_KEY: snprintf(s, len, - "빨리ê°ê¸° ì¼ì‹œì •ì§€. \n" - " \n" - "ë²„íŠ¼ì„ ë†“ìœ¼ë©´ 빨기ê°ê¸° 중지." + "빨리ê°ê¸°ë¥¼ 실행합니다. \n" + " \n" + "ë²„íŠ¼ì„ ë†“ìœ¼ë©´ 빨리ê°ê¸°ë¥¼ 중지합니다." ); break; + case RARCH_SLOWMOTION_KEY: + snprintf(s, len, + "ìŠ¬ë¡œìš°ëª¨ì…˜ì„ ì „í™˜í•©ë‹ˆë‹¤."); + break; case RARCH_SLOWMOTION_HOLD_KEY: snprintf(s, len, - "슬로우모션 대기."); + "ìŠ¬ë¡œìš°ëª¨ì…˜ì„ ì‹¤í–‰í•©ë‹ˆë‹¤."); break; case RARCH_PAUSE_TOGGLE: snprintf(s, len, - "ì¼ì‹œì •ì§€ ìƒíƒœì™€ í•´ì œ ìƒíƒœì˜ 전환."); + "ì¼ì‹œì •ì§€/í•´ì œ ìƒíƒœë¥¼ 전환합니다."); break; + case RARCH_FRAMEADVANCE: snprintf(s, len, - "컨í…츠가 ì¼ì‹œì •지시 프레임 ì§„í–‰."); + "컨í…츠 ì¼ì‹œì •지시 í”„ë ˆìž„ì„ ì§„í–‰í•©ë‹ˆë‹¤."); break; case RARCH_SHADER_NEXT: snprintf(s, len, - "디렉토리 ì•ˆì˜ ë‹¤ìŒ ì‰ì´ë” ì ìš©."); + "디렉토리 ì•ˆì˜ ë‹¤ìŒ ì‰ì´ë”를 ì ìš©í•©ë‹ˆë‹¤."); break; case RARCH_SHADER_PREV: snprintf(s, len, - "디렉토리 ì•ˆì˜ ì´ì „ ì‰ì´ë” ì ìš©."); + "디렉토리 ì•ˆì˜ ì´ì „ ì‰ì´ë”를 ì ìš©í•©ë‹ˆë‹¤."); break; case RARCH_CHEAT_INDEX_PLUS: case RARCH_CHEAT_INDEX_MINUS: case RARCH_CHEAT_TOGGLE: snprintf(s, len, - "치트."); + "치트"); break; case RARCH_RESET: snprintf(s, len, - "컨í…츠 초기화."); + "컨í…츠를 초기화합니다."); break; case RARCH_SCREENSHOT: snprintf(s, len, - "스í¬ë¦°ìƒ· ì´¬ì˜."); + "스í¬ë¦°ìƒ·ì„ ì´¬ì˜í•©ë‹ˆë‹¤."); break; case RARCH_MUTE: snprintf(s, len, @@ -93,57 +98,62 @@ int menu_hash_get_help_ko_enum(enum msg_hash_enums msg, char *s, size_t len) break; case RARCH_OSK: snprintf(s, len, - "온스í¬ë¦° 키보드 전환."); + "온스í¬ë¦° 키보드를 전환합니다."); break; + case RARCH_FPS_TOGGLE: + snprintf(s, len, + "FPS 표시를 전환합니다."); + break; case RARCH_NETPLAY_GAME_WATCH: snprintf(s, len, - "ë„·í”Œë ˆì´ í”Œë ˆì´/관전 모드 전환."); + "ë„·í”Œë ˆì´ í”Œë ˆì´/관전 모드를 전환합니다."); break; case RARCH_ENABLE_HOTKEY: snprintf(s, len, - "추가 핫키 사용. \n" + "추가 핫키를 사용합니다. \n" " \n" "ì´ í•«í‚¤ê°€ 설정ë˜ë©´ 키보드, ì¡°ì´ìŠ¤í‹± 버튼,\n" - "ì¡°ì´ìŠ¤í‹± 축등 모든 핫키가 ì„¤ì •ëœ í‚¤ì™€ \n" + "ì¡°ì´ìŠ¤í‹± 축등 모든 핫키가 ì´ í‚¤ì™€ \n" "함께 ëˆŒë ¸ì„ ë•Œì—ë§Œ 사용가능하게 ë©ë‹ˆë‹¤. \n" " \n" " \n" - "다시 ë§í•˜ë©´ 키보드ìƒì˜ 모듯 핫키를 \n" - "사용ìžê°€ 차단할 수 있게ë©ë‹ˆë‹¤."); + "ë˜ëŠ” 키보드ìƒì˜ 모든 핫키가 \n" + "사용ìžì— ì˜í•´ 차단ë ìˆ˜ 있습니다."); break; case RARCH_VOLUME_UP: snprintf(s, len, - "오디오 볼륨 ì¦ê°€."); + "오디오 ë³¼ë¥¨ì„ ì¦ê°€í•©ë‹ˆë‹¤."); break; case RARCH_VOLUME_DOWN: snprintf(s, len, - "오디오 볼륨 ê°ì†Œ."); + "오디오 ë³¼ë¥¨ì„ ê°ì†Œí•©ë‹ˆë‹¤."); break; case RARCH_OVERLAY_NEXT: snprintf(s, len, - "ë‹¤ìŒ ì˜¤ë²„ë ˆì´ë¡œ 전환. 화면 ì ìš©."); + "ë‹¤ìŒ ì˜¤ë²„ë ˆì´ë¡œ 전환합니다. í™”ë©´ì„ \n" + "ë®ì–´ 씌ì›ë‹ˆë‹¤."); break; case RARCH_DISK_EJECT_TOGGLE: snprintf(s, len, - "ë””ìŠ¤í¬ êº¼ë„¤ê¸° 전환. \n" + "ë””ìŠ¤í¬ êº¼ë‚´ê¸°ë¥¼ 전환합니다. \n" " \n" - "다중-ë””ìŠ¤í¬ ì»¨í…ì¸ ì— ì‚¬ìš©. "); + "다중 ë””ìŠ¤í¬ ì»¨í…ì¸ ì— ì‚¬ìš©ë©ë‹ˆë‹¤. "); break; case RARCH_DISK_NEXT: case RARCH_DISK_PREV: snprintf(s, len, - "Cycles through disk images. Use after ejecting. \n" - " \n" - "Complete by toggling eject again."); + "ë””ìŠ¤í¬ ì´ë¯¸ì§€ê°„ íƒìƒ‰í•©ë‹ˆë‹¤. \n" + "ë””ìŠ¤í¬ ì´ë¯¸ì§€ë¥¼ 꺼낸 í›„ì— ì‚¬ìš©í•˜ì„¸ìš”. \n" + " \n" + "꺼내기 ì „í™˜ì„ ë‹¤ì‹œ 눌러 완료합니다."); break; case RARCH_GRAB_MOUSE_TOGGLE: snprintf(s, len, - "Toggles mouse grab. \n" + "마우스 ê³ ì •ì„ ì „í™˜í•©ë‹ˆë‹¤. \n" " \n" - "When mouse is grabbed, RetroArch hides the \n" - "mouse, and keeps the mouse pointer inside \n" - "the window to allow relative mouse input to \n" - "work better."); + "마우스 ê³ ì •ì´ í™œì„±í™” ë˜ë©´, RetroArchê°€ 마우스를 \n" + "숨기고 ì°½ ì•ˆì— ê³ ì •ì‹œì¼œ 마우스 ìž…ë ¥ì„ ì›í™œí•˜ê²Œ \n" + "ë” í•©ë‹ˆë‹¤."); break; case RARCH_GAME_FOCUS_TOGGLE: snprintf(s, len, @@ -153,15 +163,15 @@ int menu_hash_get_help_ko_enum(enum msg_hash_enums msg, char *s, size_t len) "hotkeys and keep/warp the mouse pointer inside the window."); break; case RARCH_MENU_TOGGLE: - snprintf(s, len, "Toggles menu."); + snprintf(s, len, "메뉴를 전환합니다."); break; case RARCH_LOAD_STATE_KEY: snprintf(s, len, - "Loads state."); + "ìƒíƒœ 불러오기"); break; case RARCH_FULLSCREEN_TOGGLE_KEY: snprintf(s, len, - "Toggles fullscreen."); + "ì „ì²´í™”ë©´ì„ ì „í™˜í•©ë‹ˆë‹¤."); break; case RARCH_QUIT_KEY: snprintf(s, len, From 11af72286bec75c2c71868720918e99b6f3db3d2 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Wed, 23 Jan 2019 11:55:17 +0000 Subject: [PATCH 059/234] (Vulkan) Enable RGUI 'Menu Linear Filter' option --- gfx/drivers/vulkan.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 483ee8ae09..e5395e1d07 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -1867,6 +1867,8 @@ static bool vulkan_frame(void *data, const void *frame, #if defined(HAVE_MENU) if (vk->menu.enable) { + settings_t *settings = config_get_ptr(); + menu_driver_frame(video_info); if (vk->menu.textures[vk->menu.last_index].image != VK_NULL_HANDLE || @@ -1882,8 +1884,16 @@ static bool vulkan_frame(void *data, const void *frame, if (optimal->memory != VK_NULL_HANDLE) quad.texture = optimal; - quad.sampler = optimal->mipmap ? - vk->samplers.mipmap_linear : vk->samplers.linear; + if (settings->bools.menu_linear_filter) + { + quad.sampler = optimal->mipmap ? + vk->samplers.mipmap_linear : vk->samplers.linear; + } + else + { + quad.sampler = optimal->mipmap ? + vk->samplers.mipmap_nearest : vk->samplers.nearest; + } quad.mvp = &vk->mvp_no_rot; quad.color.r = 1.0f; @@ -2371,6 +2381,7 @@ static uint32_t vulkan_get_flags(void *data) BIT32_SET(flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES); BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); return flags; } From 7ba6ffdfbef827b432d676db5dfd2d273b8f1ad4 Mon Sep 17 00:00:00 2001 From: bparker06 Date: Wed, 23 Jan 2019 08:40:00 -0500 Subject: [PATCH 060/234] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index cf6e862aed..40801c5014 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,7 @@ - LOCALIZATION: Update Japanese translation. - LOCALIZATION: Update Simplified Chinese translation. - LOCALIZATION: Update Spanish translation. +- MENU: New "ozone" menu driver. - MENU: Only show CRT SwitchRes if video display server is implemented (Windows/Linux for now) - MENU: User Interface -> Appearance -> 'Menu Font Green/Blue Color' settings now work properly. - MENU/QT/WIMP: Allow building with MSVC2017 From 5102361e2ce40391954af0ee08e594b39ba4e34d Mon Sep 17 00:00:00 2001 From: natinusala Date: Wed, 23 Jan 2019 12:05:53 +0100 Subject: [PATCH 061/234] menu_animation: add delayed animations --- menu/menu_animation.c | 23 +++++++++++++++++++++++ menu/menu_animation.h | 8 ++++++++ 2 files changed, 31 insertions(+) diff --git a/menu/menu_animation.c b/menu/menu_animation.c index fbdb8451ae..17fe8013d8 100644 --- a/menu/menu_animation.c +++ b/menu/menu_animation.c @@ -333,6 +333,29 @@ void menu_animation_free(void) da_free(anim.pending); } +static void menu_delayed_animation_cb(void *userdata) +{ + menu_delayed_animation_t *delayed_animation = (menu_delayed_animation_t*) userdata; + + menu_animation_push(&delayed_animation->entry); + + free(delayed_animation); +} + +void menu_animation_push_delayed(unsigned delay, menu_animation_ctx_entry_t *entry) +{ + menu_timer_ctx_entry_t timer_entry; + menu_delayed_animation_t *delayed_animation = (menu_delayed_animation_t*) malloc(sizeof(menu_delayed_animation_t)); + + memcpy(&delayed_animation->entry, entry, sizeof(menu_animation_ctx_entry_t)); + + timer_entry.cb = menu_delayed_animation_cb; + timer_entry.duration = delay; + timer_entry.userdata = delayed_animation; + + menu_timer_start(&delayed_animation->timer, &timer_entry); +} + bool menu_animation_push(menu_animation_ctx_entry_t *entry) { struct tween t; diff --git a/menu/menu_animation.h b/menu/menu_animation.h index d5a50acedd..64ca8a454e 100644 --- a/menu/menu_animation.h +++ b/menu/menu_animation.h @@ -127,6 +127,12 @@ typedef struct menu_timer_ctx_entry void *userdata; } menu_timer_ctx_entry_t; +typedef struct menu_delayed_animation +{ + menu_timer_t timer; + menu_animation_ctx_entry_t entry; +} menu_delayed_animation_t; + void menu_timer_start(menu_timer_t *timer, menu_timer_ctx_entry_t *timer_entry); void menu_timer_kill(menu_timer_t *timer); @@ -151,6 +157,8 @@ void menu_animation_kill_by_subject(menu_animation_ctx_subject_t *subject); bool menu_animation_push(menu_animation_ctx_entry_t *entry); +void menu_animation_push_delayed(unsigned delay, menu_animation_ctx_entry_t *entry); + float menu_animation_get_delta_time(void); bool menu_animation_ctl(enum menu_animation_ctl_state state, void *data); From bd56e1e29c9de65a23cb00b03e72a17eadb53441 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Wed, 23 Jan 2019 16:44:20 +0000 Subject: [PATCH 062/234] (RGUI) Allow selection of thumbnail downscaling method --- config.def.h | 2 ++ configuration.c | 1 + configuration.h | 1 + intl/msg_hash_lbl.h | 2 ++ intl/msg_hash_us.h | 16 +++++++++ menu/drivers/rgui.c | 76 +++++++++++++++++++++++++++++++++-------- menu/menu_displaylist.c | 4 +++ menu/menu_driver.h | 8 +++++ menu/menu_setting.c | 49 ++++++++++++++++++++++++++ msg_hash.h | 5 +++ 10 files changed, 149 insertions(+), 15 deletions(-) diff --git a/config.def.h b/config.def.h index 98c1c33740..2ed6bfb5ab 100644 --- a/config.def.h +++ b/config.def.h @@ -752,6 +752,8 @@ static const unsigned menu_timedate_style = 5; static const bool xmb_vertical_thumbnails = false; +static unsigned rgui_thumbnail_downscaler = RGUI_THUMB_SCALE_POINT; + #ifdef IOS static const bool ui_companion_start_on_boot = false; #else diff --git a/configuration.c b/configuration.c index 3eff180dd7..45e69835f2 100644 --- a/configuration.c +++ b/configuration.c @@ -1654,6 +1654,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings, SETTING_UINT("menu_thumbnails", &settings->uints.menu_thumbnails, true, menu_thumbnails_default, false); SETTING_UINT("menu_timedate_style", &settings->uints.menu_timedate_style, true, menu_timedate_style, false); SETTING_UINT("rgui_menu_color_theme", &settings->uints.menu_rgui_color_theme, true, rgui_color_theme, false); + SETTING_UINT("rgui_thumbnail_downscaler", &settings->uints.menu_rgui_thumbnail_downscaler, true, rgui_thumbnail_downscaler, false); #ifdef HAVE_LIBNX SETTING_UINT("split_joycon_p1", &settings->uints.input_split_joycon[0], true, 0, false); SETTING_UINT("split_joycon_p2", &settings->uints.input_split_joycon[1], true, 0, false); diff --git a/configuration.h b/configuration.h index 464885a58f..cbe6f7888f 100644 --- a/configuration.h +++ b/configuration.h @@ -403,6 +403,7 @@ typedef struct settings unsigned menu_timedate_style; unsigned menu_thumbnails; unsigned menu_left_thumbnails; + unsigned menu_rgui_thumbnail_downscaler; unsigned menu_dpi_override_value; unsigned menu_entry_normal_color; unsigned menu_entry_hover_color; diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index aef8983686..0dcb5bb540 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1117,6 +1117,8 @@ MSG_HASH(MENU_ENUM_LABEL_LEFT_THUMBNAILS, "left thumbnails") MSG_HASH(MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, "xmb_vertical_thumbnails") +MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER, + "rgui_thumbnail_downscaler") MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_DIRECTORY, "thumbnails_directory") MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 0615dca690..04877b9445 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2934,6 +2934,22 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_XMB_VERTICAL_THUMBNAILS, "Thumbnails Vertical Disposition" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_RGUI_THUMBNAIL_DOWNSCALER, + "Thumbnail Downscaling Method" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_POINT, + "Nearest Neighbour (Fast)" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_BILINEAR, + "Bilinear" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC, + "Sinc/Lanczos3 (Slow)" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY, "Thumbnails" diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 49a05eef45..b6147583d1 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -53,6 +53,7 @@ /* Thumbnail additions */ #include #include "../../tasks/tasks_internal.h" +#include #define RGUI_TERM_START_X(width) (width / 21) #define RGUI_TERM_START_Y(height) (height / 9) @@ -422,6 +423,7 @@ typedef struct char *thumbnail_path; char *thumbnail_playlist; uint32_t thumbnail_queue_size; + struct scaler_ctx image_scaler; } rgui_t; #define THUMB_MAX_WIDTH 320 @@ -589,14 +591,12 @@ static void request_thumbnail(rgui_t *rgui, const char *path) } } -static bool downscale_thumbnail(struct texture_image *image_src, struct texture_image *image_dst) +static bool downscale_thumbnail(rgui_t *rgui, struct texture_image *image_src, struct texture_image *image_dst) { - uint32_t x_ratio, y_ratio; - unsigned x_src, y_src; - unsigned x_dst, y_dst; - static const float display_aspect_ratio = (float)THUMB_MAX_WIDTH / (float)THUMB_MAX_HEIGHT; + settings_t *settings = config_get_ptr(); /* Determine output dimensions */ + static const float display_aspect_ratio = (float)THUMB_MAX_WIDTH / (float)THUMB_MAX_HEIGHT; float aspect_ratio = (float)image_src->width / (float)image_src->height; if (aspect_ratio > display_aspect_ratio) { @@ -620,19 +620,65 @@ static bool downscale_thumbnail(struct texture_image *image_src, struct texture_ if (!image_dst->pixels) return false; - /* Perform nearest neighbour resampling */ - x_ratio = ((image_src->width << 16) / image_dst->width); - y_ratio = ((image_src->height << 16) / image_dst->height); - - for (y_dst = 0; y_dst < image_dst->height; y_dst++) + /* Determine scaling method */ + if (settings->uints.menu_rgui_thumbnail_downscaler == RGUI_THUMB_SCALE_POINT) { - y_src = (y_dst * y_ratio) >> 16; - for (x_dst = 0; x_dst < image_dst->width; x_dst++) + uint32_t x_ratio, y_ratio; + unsigned x_src, y_src; + unsigned x_dst, y_dst; + + /* Perform nearest neighbour resampling + * > Fastest method, minimal performance impact */ + x_ratio = ((image_src->width << 16) / image_dst->width); + y_ratio = ((image_src->height << 16) / image_dst->height); + + for (y_dst = 0; y_dst < image_dst->height; y_dst++) { - x_src = (x_dst * x_ratio) >> 16; - image_dst->pixels[(y_dst * image_dst->width) + x_dst] = image_src->pixels[(y_src * image_src->width) + x_src]; + y_src = (y_dst * y_ratio) >> 16; + for (x_dst = 0; x_dst < image_dst->width; x_dst++) + { + x_src = (x_dst * x_ratio) >> 16; + image_dst->pixels[(y_dst * image_dst->width) + x_dst] = image_src->pixels[(y_src * image_src->width) + x_src]; + } } } + else + { + /* Perform either bilinear or sinc (Lanczos3) resampling + * using libretro-common scaler + * > Better quality, but substantially higher performance + * impact - although not an issue on desktop-class + * hardware */ + rgui->image_scaler.in_width = image_src->width; + rgui->image_scaler.in_height = image_src->height; + rgui->image_scaler.in_stride = image_src->width * sizeof(uint32_t); + rgui->image_scaler.in_fmt = SCALER_FMT_ARGB8888; + + rgui->image_scaler.out_width = image_dst->width; + rgui->image_scaler.out_height = image_dst->height; + rgui->image_scaler.out_stride = image_dst->width * sizeof(uint32_t); + rgui->image_scaler.out_fmt = SCALER_FMT_ARGB8888; + + rgui->image_scaler.scaler_type = (settings->uints.menu_rgui_thumbnail_downscaler == RGUI_THUMB_SCALE_SINC) ? + SCALER_TYPE_SINC : SCALER_TYPE_BILINEAR; + + /* This reset is redundant, since scaler_ctx_gen_filter() + * calls it - but do it anyway in case the + * scaler_ctx_gen_filter() internals ever change... */ + scaler_ctx_gen_reset(&rgui->image_scaler); + if(!scaler_ctx_gen_filter(&rgui->image_scaler)) + { + /* Could be leftovers if scaler_ctx_gen_filter() + * fails, so reset just in case... */ + scaler_ctx_gen_reset(&rgui->image_scaler); + return false; + } + + scaler_ctx_scale(&rgui->image_scaler, image_dst->pixels, image_src->pixels); + /* Reset again - don't want to leave anything hanging around + * if the user switches back to nearest neighbour scaling */ + scaler_ctx_gen_reset(&rgui->image_scaler); + } return true; } @@ -668,7 +714,7 @@ static void process_thumbnail(rgui_t *rgui, struct texture_image *image_src) /* Downscale thumbnail if it exceeds maximum size limits */ if ((image_src->width > THUMB_MAX_WIDTH) || (image_src->height > THUMB_MAX_HEIGHT)) { - if (!downscale_thumbnail(image_src, &image_resampled)) + if (!downscale_thumbnail(rgui, image_src, &image_resampled)) return; image = &image_resampled; } diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index e809799bfb..118e8cbde5 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -6119,6 +6119,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, PARSE_ONLY_BOOL, false) == 0) count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER, + PARSE_ONLY_UINT, false) == 0) + count++; if (count == 0) menu_entries_append_enum(info->list, diff --git a/menu/menu_driver.h b/menu/menu_driver.h index 681ac785a3..81282c1d4d 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -383,6 +383,14 @@ enum menu_toggle_reason MENU_TOGGLE_REASON_MESSAGE }; +enum rgui_thumbnail_scaler +{ + RGUI_THUMB_SCALE_POINT = 0, + RGUI_THUMB_SCALE_BILINEAR, + RGUI_THUMB_SCALE_SINC, + RGUI_THUMB_SCALE_LAST +}; + typedef uintptr_t menu_texture_item; typedef struct menu_display_ctx_clearcolor diff --git a/menu/menu_setting.c b/menu/menu_setting.c index d3c6cbf54c..048a09d360 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -786,6 +786,36 @@ static void setting_get_string_representation_uint_rgui_menu_color_theme( } } +static void setting_get_string_representation_uint_rgui_thumbnail_scaler( + rarch_setting_t *setting, + char *s, size_t len) +{ + if (!setting) + return; + + switch (*setting->value.target.unsigned_integer) + { + case RGUI_THUMB_SCALE_POINT: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_POINT), + len); + break; + case RGUI_THUMB_SCALE_BILINEAR: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_BILINEAR), + len); + break; + case RGUI_THUMB_SCALE_SINC: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC), + len); + break; + } +} + static void setting_get_string_representation_uint_xmb_icon_theme( rarch_setting_t *setting, char *s, size_t len) @@ -8741,6 +8771,25 @@ static bool setting_append_list( menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); } + if (string_is_equal(settings->arrays.menu_driver, "rgui")) + { + CONFIG_UINT( + list, list_info, + &settings->uints.menu_rgui_thumbnail_downscaler, + MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER, + MENU_ENUM_LABEL_VALUE_MENU_RGUI_THUMBNAIL_DOWNSCALER, + rgui_thumbnail_downscaler, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_uint_rgui_thumbnail_scaler; + menu_settings_list_current_add_range(list, list_info, 0, RGUI_THUMB_SCALE_LAST-1, 1, true, true); + } + if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone")) { CONFIG_UINT( diff --git a/msg_hash.h b/msg_hash.h index a1226afcd2..d72ee9c761 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -883,6 +883,7 @@ enum msg_hash_enums MENU_LABEL(THUMBNAILS), MENU_LABEL(LEFT_THUMBNAILS), MENU_LABEL(XMB_VERTICAL_THUMBNAILS), + MENU_LABEL(MENU_RGUI_THUMBNAIL_DOWNSCALER), MENU_LABEL(TIMEDATE_ENABLE), MENU_LABEL(TIMEDATE_STYLE), MENU_LABEL(BATTERY_LEVEL_ENABLE), @@ -1943,6 +1944,10 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_SCREENSHOTS, MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_TITLE_SCREENS, + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_POINT, + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_BILINEAR, + MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC, + /* Callback strings */ MENU_ENUM_LABEL_CB_CORE_CONTENT_DIRS_LIST, MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD, From 0d84e0a9492672a8e4fb9b4774abfc57eeddfd4d Mon Sep 17 00:00:00 2001 From: CozmoP <25121396+CozmoP@users.noreply.github.com> Date: Wed, 23 Jan 2019 19:06:37 +0100 Subject: [PATCH 063/234] Qt: add comment for QTBUG-72844 workaround --- ui/drivers/qt/filedropwidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/drivers/qt/filedropwidget.cpp b/ui/drivers/qt/filedropwidget.cpp index d8e4b8f3a3..e5f25fb7a4 100644 --- a/ui/drivers/qt/filedropwidget.cpp +++ b/ui/drivers/qt/filedropwidget.cpp @@ -69,6 +69,7 @@ void FileDropWidget::dragEnterEvent(QDragEnterEvent *event) event->acceptProposedAction(); } +/* Workaround for QTBUG-72844. Without it, you can't drop on this if you first drag over another widget that doesn't accept drops. */ void FileDropWidget::dragMoveEvent(QDragMoveEvent *event) { event->acceptProposedAction(); From d34e10985ed131d074c7b772a6532d1430a44e78 Mon Sep 17 00:00:00 2001 From: CozmoP <25121396+CozmoP@users.noreply.github.com> Date: Wed, 23 Jan 2019 19:28:59 +0100 Subject: [PATCH 064/234] Qt: allow changing thumbnails by drag and drop. --- ui/drivers/qt/ui_qt_window.cpp | 129 +++++++++++++++++++++++++++++++++ ui/drivers/ui_qt.cpp | 52 ++++++++++++- ui/drivers/ui_qt.h | 10 ++- 3 files changed, 186 insertions(+), 5 deletions(-) diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index b6618adec9..bf64fd5614 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -1266,6 +1266,109 @@ void MainWindow::changeThumbnailType(ThumbnailType type) m_gridView->viewport()->update(); } +QString MainWindow::changeThumbnail(const QImage &image, QString type) +{ + QHash hash = getCurrentContentHash(); + QString label = hash["label_noext"]; + QString dirString = QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + hash["db_name"] + "/" + type; + QString thumbPath = dirString + "/" + label.replace(m_fileSanitizerRegex, "_") + ".png"; + QByteArray dirArray = QDir::toNativeSeparators(dirString).toUtf8(); + const char *dirData = dirArray.constData(); + QByteArray thumbArray = QDir::toNativeSeparators(thumbPath).toUtf8(); + const char *thumbData = thumbArray.constData(); + QDir dir(dirString); + int quality = -1; + QImage scaledImage(image); + + if (!dir.exists()) + { + if (dir.mkpath(".")) + RARCH_LOG("[Qt]: Created directory: %s\n", dirData); + else + { + RARCH_ERR("[Qt]: Could not create directory: %s\n", dirData); + return QString(); + } + } + + if (m_settings->contains("thumbnail_max_size")) + { + int size = m_settings->value("thumbnail_max_size", 512).toInt(); + + if (size != 0) + scaledImage = image.scaled(size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + + if (m_settings->contains("thumbnail_quality")) + quality = m_settings->value("thumbnail_quality", -1).toInt(); + + if (scaledImage.save(thumbPath, "png", quality)) + { + RARCH_LOG("[Qt]: Saved image: %s\n", thumbData); + m_playlistModel->reloadThumbnailPath(thumbPath); + updateVisibleItems(); + + return thumbPath; + } + + RARCH_ERR("[Qt]: Could not save image: %s\n", thumbData); + return QString(); +} + +void MainWindow::onThumbnailDropped(const QImage &image, ThumbnailType thumbnailType) +{ + switch (thumbnailType) + { + case THUMBNAIL_TYPE_BOXART: + { + QString path = changeThumbnail(image, THUMBNAIL_BOXART); + + if (path.isNull()) + return; + + if (m_thumbnailPixmap) + delete m_thumbnailPixmap; + + m_thumbnailPixmap = new QPixmap(path); + + onResizeThumbnailOne(); + break; + } + + case THUMBNAIL_TYPE_TITLE_SCREEN: + { + QString path = changeThumbnail(image, THUMBNAIL_TITLE); + + if (path.isNull()) + return; + + if (m_thumbnailPixmap2) + delete m_thumbnailPixmap2; + + m_thumbnailPixmap2 = new QPixmap(path); + + onResizeThumbnailTwo(); + break; + } + + case THUMBNAIL_TYPE_SCREENSHOT: + { + QString path = changeThumbnail(image, THUMBNAIL_SCREENSHOT); + + if (path.isNull()) + return; + + if (m_thumbnailPixmap3) + delete m_thumbnailPixmap3; + + m_thumbnailPixmap3 = new QPixmap(path); + + onResizeThumbnailThree(); + break; + } + } +} + QVector > MainWindow::getCoreInfo() { QVector > infoList; @@ -2108,6 +2211,22 @@ void MainWindow::setCoreActions() } } +void MainWindow::setThumbnailsAcceptDrops(bool accept) +{ + ThumbnailWidget *thumbnail = findChild("thumbnail1Widget"); + ThumbnailWidget *thumbnail2 = findChild("thumbnail2Widget"); + ThumbnailWidget *thumbnail3 = findChild("thumbnail3Widget"); + + if (thumbnail) + thumbnail->setAcceptDrops(accept); + + if (thumbnail2) + thumbnail2->setAcceptDrops(accept); + + if (thumbnail3) + thumbnail3->setAcceptDrops(accept); +} + void MainWindow::onTabWidgetIndexChanged(int index) { if (m_browserAndPlaylistTabWidget->tabText(index) == msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_TAB_FILE_BROWSER)) @@ -2432,12 +2551,22 @@ void MainWindow::onCurrentItemChanged(const QHash &hash) m_thumbnailPixmap = new QPixmap(hash["path"]); m_thumbnailPixmap2 = new QPixmap(*m_thumbnailPixmap); m_thumbnailPixmap3 = new QPixmap(*m_thumbnailPixmap); + + setThumbnailsAcceptDrops(false); } else { m_thumbnailPixmap = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_BOXART + "/" + label + ".png"); m_thumbnailPixmap2 = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_TITLE + "/" + label + ".png"); m_thumbnailPixmap3 = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_SCREENSHOT + "/" + label + ".png"); + + if (m_currentBrowser == BROWSER_TYPE_PLAYLISTS) + { + if (currentPlaylistIsSpecial()) + setThumbnailsAcceptDrops(false); + else + setThumbnailsAcceptDrops(true); + } } resizeThumbnails(true, true, true); diff --git a/ui/drivers/ui_qt.cpp b/ui/drivers/ui_qt.cpp index 9cf8e0ed45..e499a43ddb 100644 --- a/ui/drivers/ui_qt.cpp +++ b/ui/drivers/ui_qt.cpp @@ -63,9 +63,10 @@ typedef struct ui_companion_qt ui_window_qt_t *window; } ui_companion_qt_t; -ThumbnailWidget::ThumbnailWidget(QWidget *parent) : +ThumbnailWidget::ThumbnailWidget(ThumbnailType type, QWidget *parent) : QFrame(parent) ,m_sizeHint(QSize(256, 256)) + ,m_thumbnailType(type) { } @@ -111,6 +112,40 @@ void ThumbnailWidget::setSizeHint(QSize size) m_sizeHint = size; } +void ThumbnailWidget::dragEnterEvent(QDragEnterEvent *event) +{ + const QMimeData *data = event->mimeData(); + + if (data->hasUrls()) + event->acceptProposedAction(); +} + +/* Workaround for QTBUG-72844. Without it, you can't drop on this if you first drag over another widget that doesn't accept drops. */ +void ThumbnailWidget::dragMoveEvent(QDragMoveEvent *event) +{ + event->acceptProposedAction(); +} + +void ThumbnailWidget::dropEvent(QDropEvent *event) +{ + const QMimeData *data = event->mimeData(); + + if (data->hasUrls()) + { + const QString imageString = data->urls().at(0).toLocalFile(); + const QImage image(imageString); + + if (!image.isNull()) + emit(filesDropped(image, m_thumbnailType)); + else + { + QByteArray stringArray = QDir::toNativeSeparators(imageString).toUtf8(); + const char *stringData = stringArray.constData(); + RARCH_ERR("[Qt]: Could not read image: %s\n", stringData); + } + } +} + ThumbnailLabel::ThumbnailLabel(QWidget *parent) : QWidget(parent) ,m_pixmap(NULL) @@ -403,9 +438,14 @@ static void* ui_companion_qt_init(void) browserButtonsHBoxLayout->addItem(new QSpacerItem(browserAndPlaylistTabWidget->tabBar()->width(), 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); - thumbnailWidget = new ThumbnailWidget(); - thumbnail2Widget = new ThumbnailWidget(); - thumbnail3Widget = new ThumbnailWidget(); + thumbnailWidget = new ThumbnailWidget(THUMBNAIL_TYPE_BOXART); + thumbnailWidget->setObjectName("thumbnail1Widget"); + + thumbnail2Widget = new ThumbnailWidget(THUMBNAIL_TYPE_TITLE_SCREEN); + thumbnail2Widget->setObjectName("thumbnail2Widget"); + + thumbnail3Widget = new ThumbnailWidget(THUMBNAIL_TYPE_SCREENSHOT); + thumbnail3Widget->setObjectName("thumbnail3Widget"); thumbnailWidget->setLayout(new QVBoxLayout()); thumbnail2Widget->setLayout(new QVBoxLayout()); @@ -415,6 +455,10 @@ static void* ui_companion_qt_init(void) thumbnail2Widget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); thumbnail3Widget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + QObject::connect(thumbnailWidget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType))); + QObject::connect(thumbnail2Widget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType))); + QObject::connect(thumbnail3Widget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType))); + thumbnail = new ThumbnailLabel(); thumbnail->setObjectName("thumbnail"); diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index cad3009d9e..36ab03b338 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -42,7 +42,6 @@ #include #include #include -#include #include "qt/filedropwidget.h" @@ -168,6 +167,7 @@ class ThumbnailWidget : public QFrame Q_OBJECT public: ThumbnailWidget(QWidget *parent = 0); + ThumbnailWidget(ThumbnailType type, QWidget *parent = 0); ThumbnailWidget(const ThumbnailWidget& other) { retro_assert(false && "DONT EVER USE THIS"); } QSize sizeHint() const; @@ -175,13 +175,18 @@ public: signals: void mouseDoubleClicked(); void mousePressed(); + void filesDropped(const QImage& image, ThumbnailType type); private: QSize m_sizeHint; + ThumbnailType m_thumbnailType; protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); }; class ThumbnailLabel : public QWidget @@ -457,6 +462,7 @@ public slots: void downloadPlaylistThumbnails(QString playlistPath); void downloadNextPlaylistThumbnail(QString system, QString title, QString type, QUrl url = QUrl()); void changeThumbnailType(ThumbnailType type); + void onThumbnailDropped(const QImage &image, ThumbnailType type); private slots: void onLoadCoreClicked(const QStringList &extensionFilters = QStringList()); @@ -540,6 +546,8 @@ private: bool currentPlaylistIsAll(); void applySearch(); void updateItemsCount(); + void setThumbnailsAcceptDrops(bool accept); + QString changeThumbnail(const QImage &image, QString type); PlaylistModel *m_playlistModel; QSortFilterProxyModel *m_proxyModel; From 4d927528dfdea7db514db5f323c05ec6734a65e9 Mon Sep 17 00:00:00 2001 From: CozmoP <25121396+CozmoP@users.noreply.github.com> Date: Wed, 23 Jan 2019 21:21:30 +0100 Subject: [PATCH 065/234] Qt: refactor thumbnail path creation. --- ui/drivers/qt/qt_playlist.cpp | 36 +++++++++++++++++++++------- ui/drivers/qt/ui_qt_window.cpp | 43 +++++++++------------------------- ui/drivers/ui_qt.h | 5 +++- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/ui/drivers/qt/qt_playlist.cpp b/ui/drivers/qt/qt_playlist.cpp index 62f87b62ce..2bd62e14d3 100644 --- a/ui/drivers/qt/qt_playlist.cpp +++ b/ui/drivers/qt/qt_playlist.cpp @@ -130,18 +130,25 @@ void PlaylistModel::setThumbnailCacheLimit(int limit) QString PlaylistModel::getThumbnailPath(const QModelIndex &index, QString type) const { + return getThumbnailPath(m_contents.at(index.row()), type); +} + +QString PlaylistModel::getPlaylistThumbnailsDir(const QString playlistName) const +{ + return QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + playlistName; +} + +bool PlaylistModel::isSupportedImage(const QString path) const +{ + int lastIndex = -1; QByteArray extension; QString extensionStr; - QString thumbnailFileNameNoExt; - int lastIndex = -1; - - const QHash &hash = m_contents.at(index.row()); - lastIndex = hash["path"].lastIndexOf('.'); + lastIndex = path.lastIndexOf('.'); if (lastIndex >= 0) { - extensionStr = hash["path"].mid(lastIndex + 1); + extensionStr = path.mid(lastIndex + 1); if (!extensionStr.isEmpty()) { @@ -150,15 +157,26 @@ QString PlaylistModel::getThumbnailPath(const QModelIndex &index, QString type) } if (!extension.isEmpty() && m_imageFormats.contains(extension)) + return true; + + return false; +} + +QString PlaylistModel::getSanitizedThumbnailName(QString label) const +{ + return label.replace(m_fileSanitizerRegex, "_") + ".png"; +} + +QString PlaylistModel::getThumbnailPath(const QHash &hash, QString type) const +{ + if (isSupportedImage(hash["path"])) { /* use thumbnail widgets to show regular image files */ return hash["path"]; } else { - thumbnailFileNameNoExt = hash["label_noext"]; - thumbnailFileNameNoExt.replace(m_fileSanitizerRegex, "_"); - return QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + hash.value("db_name") + "/" + type + "/" + thumbnailFileNameNoExt + ".png"; + return getPlaylistThumbnailsDir(hash.value("db_name")) + "/" + type + "/" + getSanitizedThumbnailName(hash["label_noext"]); } } diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index bf64fd5614..952a35c08a 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -303,7 +303,6 @@ MainWindow::MainWindow(QWidget *parent) : ,m_thumbnailPixmap(NULL) ,m_thumbnailPixmap2(NULL) ,m_thumbnailPixmap3(NULL) - ,m_fileSanitizerRegex("[&*/:`<>?\\|]") ,m_settings(NULL) ,m_viewOptionsDialog(NULL) ,m_coreInfoDialog(new CoreInfoDialog(this, NULL)) @@ -1269,9 +1268,8 @@ void MainWindow::changeThumbnailType(ThumbnailType type) QString MainWindow::changeThumbnail(const QImage &image, QString type) { QHash hash = getCurrentContentHash(); - QString label = hash["label_noext"]; - QString dirString = QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + hash["db_name"] + "/" + type; - QString thumbPath = dirString + "/" + label.replace(m_fileSanitizerRegex, "_") + ".png"; + QString dirString = m_playlistModel->getPlaylistThumbnailsDir(hash["db_name"]) + "/" + type; + QString thumbPath = dirString + "/" + m_playlistModel->getSanitizedThumbnailName(hash["label_noext"]); QByteArray dirArray = QDir::toNativeSeparators(dirString).toUtf8(); const char *dirData = dirArray.constData(); QByteArray thumbArray = QDir::toNativeSeparators(thumbPath).toUtf8(); @@ -2514,29 +2512,7 @@ void MainWindow::onCurrentFileChanged(const QModelIndex &index) void MainWindow::onCurrentItemChanged(const QHash &hash) { - settings_t *settings = config_get_ptr(); - QString label; - QString playlist_name; - QByteArray extension; - QString extensionStr; - int lastIndex = -1; - - label = hash["label_noext"]; - label.replace(m_fileSanitizerRegex, "_"); - - lastIndex = hash["path"].lastIndexOf('.'); - - if (lastIndex >= 0) - { - extensionStr = hash["path"].mid(lastIndex + 1); - - if (!extensionStr.isEmpty()) - { - extension = extensionStr.toLower().toUtf8(); - } - } - - playlist_name = hash["db_name"]; + QString path = hash["path"]; if (m_thumbnailPixmap) delete m_thumbnailPixmap; @@ -2545,10 +2521,10 @@ void MainWindow::onCurrentItemChanged(const QHash &hash) if (m_thumbnailPixmap3) delete m_thumbnailPixmap3; - if (!extension.isEmpty() && m_imageFormats.contains(extension)) + if (m_playlistModel->isSupportedImage(path)) { /* use thumbnail widgets to show regular image files */ - m_thumbnailPixmap = new QPixmap(hash["path"]); + m_thumbnailPixmap = new QPixmap(path); m_thumbnailPixmap2 = new QPixmap(*m_thumbnailPixmap); m_thumbnailPixmap3 = new QPixmap(*m_thumbnailPixmap); @@ -2556,9 +2532,12 @@ void MainWindow::onCurrentItemChanged(const QHash &hash) } else { - m_thumbnailPixmap = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_BOXART + "/" + label + ".png"); - m_thumbnailPixmap2 = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_TITLE + "/" + label + ".png"); - m_thumbnailPixmap3 = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_SCREENSHOT + "/" + label + ".png"); + QString thumbnailsDir = m_playlistModel->getPlaylistThumbnailsDir(hash["db_name"]); + QString thumbnailName = m_playlistModel->getSanitizedThumbnailName(hash["label_noext"]); + + m_thumbnailPixmap = new QPixmap(thumbnailsDir + "/" + THUMBNAIL_BOXART + "/" + thumbnailName); + m_thumbnailPixmap2 = new QPixmap(thumbnailsDir + "/" + THUMBNAIL_TITLE + "/" + thumbnailName); + m_thumbnailPixmap3 = new QPixmap(thumbnailsDir + "/" + THUMBNAIL_SCREENSHOT + "/" + thumbnailName); if (m_currentBrowser == BROWSER_TYPE_PLAYLISTS) { diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index 36ab03b338..0684a833cd 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -142,6 +142,9 @@ public: void reloadThumbnailPath(const QString path); void reloadSystemThumbnails(const QString system); void setThumbnailCacheLimit(int limit); + bool isSupportedImage(const QString path) const; + QString getPlaylistThumbnailsDir(const QString playlistName) const; + QString getSanitizedThumbnailName(QString label) const; signals: void imageLoaded(const QImage image, const QModelIndex &index, const QString &path); @@ -157,6 +160,7 @@ private: QRegularExpression m_fileSanitizerRegex; ThumbnailType m_thumbnailType = THUMBNAIL_TYPE_BOXART; QString getThumbnailPath(const QModelIndex &index, QString type) const; + QString getThumbnailPath(const QHash &hash, QString type) const; QString getCurrentTypeThumbnailPath(const QModelIndex &index) const; void getPlaylistItems(QString path); void loadImage(const QModelIndex &index, const QString &path); @@ -579,7 +583,6 @@ private: QPixmap *m_thumbnailPixmap; QPixmap *m_thumbnailPixmap2; QPixmap *m_thumbnailPixmap3; - QRegularExpression m_fileSanitizerRegex; QSettings *m_settings; ViewOptionsDialog *m_viewOptionsDialog; CoreInfoDialog *m_coreInfoDialog; From 6b328ec9037690f9a957551af263505026e56c00 Mon Sep 17 00:00:00 2001 From: DEX357 Date: Thu, 24 Jan 2019 01:49:31 +0100 Subject: [PATCH 066/234] Update msg_hash_pl.h --- intl/msg_hash_pl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intl/msg_hash_pl.h b/intl/msg_hash_pl.h index 59853c16d0..a6dd7c13d4 100644 --- a/intl/msg_hash_pl.h +++ b/intl/msg_hash_pl.h @@ -8,7 +8,7 @@ MSG_HASH( ) MSG_HASH( MSG_NATIVE, - "Native" + "Natywny" ) MSG_HASH( MSG_DEVICE_DISCONNECTED_FROM_PORT, @@ -3557,7 +3557,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "Tylko dla wyÅ›wietlaczy CRT. MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT Przełącz rozdzielczość") MSG_HASH( MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, - "Switch among native and ultrawide super resolutions." + "Przełącz miÄ™dzy natywnymi i superszybkimi superrozdzielczoÅ›ciami." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super rozdzielczość") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, From 5fcedc86195c9b1b8a79c7b5f9e59f9c5c46012b Mon Sep 17 00:00:00 2001 From: orbea Date: Wed, 23 Jan 2019 17:54:54 -0800 Subject: [PATCH 067/234] Fix disk control and subsystems when navigating to the root directory. Fixes https://github.com/libretro/RetroArch/issues/5642 Fixes https://github.com/libretro/RetroArch/issues/8071 --- menu/menu_displaylist.c | 1 + 1 file changed, 1 insertion(+) diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 118e8cbde5..867aa5695b 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -8140,6 +8140,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist break; case DISPLAYLIST_DEFAULT: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); + load_content = false; use_filebrowser = true; break; case DISPLAYLIST_CORES_DETECTED: From 4722d41b0b3aba975e22b4c275a891553fbcecb9 Mon Sep 17 00:00:00 2001 From: orbea Date: Thu, 24 Jan 2019 08:08:00 -0800 Subject: [PATCH 068/234] xmb: Fix segfault when appending disk images. --- menu/drivers/xmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 25e64e2bbe..8308ac8829 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -975,7 +975,7 @@ static void xmb_update_thumbnail_path(void *data, unsigned i, char pos) xmb_node_t *node = (xmb_node_t*) file_list_get_userdata_at_offset(selection_buf, i); - if (!string_is_empty(node->fullpath) && + if (node && !string_is_empty(node->fullpath) && (pos == 'R' || (pos == 'L' && string_is_equal(xmb_thumbnails_ident('R'), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))))) { From 088860e49942c20419dbd27e37a5be6444e3a64d Mon Sep 17 00:00:00 2001 From: orbea Date: Thu, 24 Jan 2019 10:58:59 -0800 Subject: [PATCH 069/234] Silence -Wformat-truncation warnings with DEBUG=1. --- gfx/video_shader_parse.c | 2 +- input/input_remapping.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 7572b298b1..0b9e45089b 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -1062,7 +1062,7 @@ void video_shader_write_conf_cgp(config_file_t *conf, for (i = 0; i < shader->luts; i++) { - char key[64]; + char key[128]; key[0] = '\0'; diff --git a/input/input_remapping.c b/input/input_remapping.c index d435d1088a..b187756954 100644 --- a/input/input_remapping.c +++ b/input/input_remapping.c @@ -56,7 +56,7 @@ bool input_remapping_load_file(void *data, const char *path) char s1[64], s2[64], s3[64]; char btn_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; char key_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; - char stk_ident[8][128] = {{0}}; + char stk_ident[8][192] = {{0}}; char key_strings[RARCH_FIRST_CUSTOM_BIND + 8][128] = { "b", "y", "select", "start", From aa2fd6cfedcc20b4d5a549db4b67127d31bfd5aa Mon Sep 17 00:00:00 2001 From: orbea Date: Thu, 24 Jan 2019 13:48:46 -0800 Subject: [PATCH 070/234] Makefile.common: Fix building discord-rpc with --disable-threads. --- Makefile.common | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile.common b/Makefile.common index 9a44cc7e01..074ff48601 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1744,6 +1744,11 @@ ifeq ($(HAVE_NETWORKING), 1) NEED_CXX_LINKER = 1 DEFINES += -DHAVE_DISCORD DEFINES += -Ideps/discord-rpc/include/ -Ideps/discord-rpc/thirdparty/rapidjson-1.1.0/include/ + + ifneq ($(HAVE_THREADS), 1) + DEFINES += -DDISCORD_DISABLE_IO_THREAD + endif + OBJ += deps/discord-rpc/src/discord_rpc.o \ deps/discord-rpc/src/rpc_connection.o \ deps/discord-rpc/src/serialization.o \ From fc6b7d5ddb5160cc8e136c40d2b9dbbaa3c5e274 Mon Sep 17 00:00:00 2001 From: orbea Date: Thu, 24 Jan 2019 14:27:24 -0800 Subject: [PATCH 071/234] Makefile.common: Remove duplicate -DHAVE_GLSL. --- Makefile.common | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.common b/Makefile.common index 9a44cc7e01..139d0565f9 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1160,7 +1160,6 @@ ifeq ($(HAVE_GL_CONTEXT), 1) endif OBJ += gfx/drivers_shader/shader_glsl.o - DEFINES += -DHAVE_GLSL endif ifeq ($(HAVE_EGL), 1) From 0dc40a2d66506924730850c3cc503633fe11d444 Mon Sep 17 00:00:00 2001 From: orbea Date: Thu, 24 Jan 2019 15:38:37 -0800 Subject: [PATCH 072/234] qb: Cleanup config.libs.sh. --- qb/config.libs.sh | 125 ++++++++++++++++---------------------------- qb/config.params.sh | 2 +- qb/qb.libs.sh | 66 +++++++++++++++++++---- 3 files changed, 101 insertions(+), 92 deletions(-) diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 67424b03c9..ab7ace414a 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -87,7 +87,6 @@ fi if [ "$HAVE_PRESERVE_DYLIB" = "yes" ]; then die : 'Notice: Disabling dlclose() of shared objects for Valgrind support.' - add_define MAKEFILE HAVE_PRESERVE_DYLIB "1" fi if [ "$HAVE_FLOATHARD" = "yes" ]; then @@ -126,9 +125,7 @@ if [ "$HAVE_SSE" = "yes" ]; then fi if [ "$HAVE_EGL" != "no" ] && [ "$OS" != 'Win32' ]; then - check_pkgconf EGL "$VC_PREFIX"egl - # some systems have EGL libs, but no pkgconfig - check_val '' EGL "-l${VC_PREFIX}EGL $EXTRA_GL_LIBS" + check_val '' EGL "-l${VC_PREFIX}EGL $EXTRA_GL_LIBS" '' "${VC_PREFIX}egl" '' '' if [ "$HAVE_EGL" = "yes" ]; then EGL_LIBS="$EGL_LIBS $EXTRA_GL_LIBS" fi @@ -184,12 +181,6 @@ else check_lib '' DYLIB "$DYLIB" dlopen fi -if [ "$HAVE_CXX" != 'yes' ]; then - HAVE_DISCORD='no' - HAVE_QT='no' - HAVE_VULKAN='no' -fi - check_lib '' NETWORKING "$SOCKETLIB" socket "" "$SOCKETHEADER" if [ "$HAVE_NETWORKING" = 'yes' ]; then @@ -237,8 +228,7 @@ if [ "$HAVE_DYLIB" = 'no' ] && [ "$HAVE_DYNAMIC" = 'yes' ]; then die 1 'Error: Dynamic loading of libretro is enabled, but your platform does not appear to have dlopen(), use --disable-dynamic or --with-libretro="-lretro".' fi -check_pkgconf ALSA alsa -check_val '' ALSA -lasound alsa +check_val '' ALSA -lasound alsa alsa '' '' check_lib '' CACA -lcaca check_lib '' SIXEL -lsixel @@ -271,15 +261,22 @@ fi check_pkgconf RSOUND rsound 1.1 check_pkgconf ROAR libroar -check_pkgconf JACK jack 0.120.1 -check_pkgconf PULSE libpulse -check_pkgconf SDL sdl 1.2.10 -check_pkgconf SDL2 sdl2 2.0.0 +check_val '' JACK -ljack '' jack 0.120.1 '' +check_val '' PULSE -lpulse '' libpulse '' '' +check_val '' SDL -lSDL SDL sdl 1.2.10 '' +check_val '' SDL2 -lSDL2 SDL2 sdl2 2.0.0 '' -check_val '' JACK -ljack -check_val '' PULSE -lpulse -check_val '' SDL -lSDL SDL -check_val '' SDL2 -lSDL2 SDL2 +if [ "$HAVE_SDL2" = 'yes' ] && [ "$HAVE_SDL" = 'yes' ]; then + die : 'Notice: SDL drivers will be replaced by SDL2 ones.' + HAVE_SDL=no +fi + +check_enabled DISCORD discord + +if [ "$HAVE_DISCORD" != 'no' ]; then + # Enable discord by default if it hasn't been disabled by check_enabled. + HAVE_DISCORD=yes +fi check_enabled QT 'Qt companion' @@ -307,17 +304,11 @@ if [ "$HAVE_QT" != 'no' ]; then #fi fi -if [ "$HAVE_SDL2" = 'yes' ] && [ "$HAVE_SDL" = 'yes' ]; then - die : 'Notice: SDL drivers will be replaced by SDL2 ones.' - HAVE_SDL=no -fi - if [ "$HAVE_FLAC" = 'no' ]; then HAVE_BUILTINFLAC=no fi -check_pkgconf FLAC flac -check_val '' FLAC '-lFLAC' +check_val '' FLAC '-lFLAC' '' flac '' '' if [ "$HAVE_SSL" = 'no' ]; then HAVE_BUILTINMBEDTLS=no @@ -350,8 +341,7 @@ if [ "$HAVE_SSL" != 'no' ]; then fi fi -check_pkgconf LIBUSB libusb-1.0 1.0.13 -check_val '' LIBUSB -lusb-1.0 libusb-1.0 +check_val '' LIBUSB -lusb-1.0 libusb-1.0 libusb-1.0 1.0.13 '' if [ "$OS" = 'Win32' ]; then check_lib '' DINPUT -ldinput8 @@ -406,12 +396,10 @@ if [ "$HAVE_ZLIB" = 'no' ]; then elif [ "$HAVE_BUILTINZLIB" = 'yes' ]; then HAVE_ZLIB=yes else - check_pkgconf ZLIB zlib - check_val '' ZLIB '-lz' + check_val '' ZLIB '-lz' '' zlib '' '' fi -check_pkgconf MPV mpv -check_val '' MPV -lmpv +check_val '' MPV -lmpv '' mpv '' '' if [ "$HAVE_THREADS" = 'no' ] && [ "$HAVE_FFMPEG" != 'no' ]; then HAVE_FFMPEG='no' @@ -422,21 +410,13 @@ check_header DRMINGW exchndl.h check_lib '' DRMINGW -lexchndl if [ "$HAVE_FFMPEG" != 'no' ]; then - check_pkgconf AVCODEC libavcodec 54 - check_pkgconf AVFORMAT libavformat 54 - check_pkgconf AVDEVICE libavdevice - check_pkgconf SWRESAMPLE libswresample - check_pkgconf AVRESAMPLE libavresample - check_pkgconf AVUTIL libavutil 51 - check_pkgconf SWSCALE libswscale 2.1 - - check_val '' AVCODEC -lavcodec - check_val '' AVFORMAT -lavformat - check_val '' AVDEVICE -lavdevice - check_val '' SWRESAMPLE -lswresample - check_val '' AVRESAMPLE -lavresample - check_val '' AVUTIL -lavutil - check_val '' SWSCALE -lswscale + check_val '' AVCODEC -lavcodec '' libavcodec 54 '' + check_val '' AVFORMAT -lavformat '' libavformat 54 '' + check_val '' AVDEVICE -lavdevice '' libavdevice '' '' + check_val '' SWRESAMPLE -lswresample '' libswresample '' '' + check_val '' AVRESAMPLE -lavresample '' libavresample '' '' + check_val '' AVUTIL -lavutil '' libavutil 51 '' + check_val '' SWSCALE -lswscale '' libswscale 2.1 '' check_header AV_CHANNEL_LAYOUT libavutil/channel_layout.h @@ -454,10 +434,8 @@ if [ "$OS" != 'Win32' ]; then fi if [ "$HAVE_KMS" != "no" ]; then - check_pkgconf GBM gbm 9.0 - check_pkgconf DRM libdrm - check_val '' GBM -lgbm - check_val '' DRM -ldrm libdrm + check_val '' GBM -lgbm '' gbm 9.0 '' + check_val '' DRM -ldrm libdrm libdrm '' '' if [ "$HAVE_GBM" = "yes" ] && [ "$HAVE_DRM" = "yes" ] && [ "$HAVE_EGL" = "yes" ]; then HAVE_KMS=yes @@ -468,8 +446,7 @@ if [ "$HAVE_KMS" != "no" ]; then fi fi -check_pkgconf LIBXML2 libxml-2.0 -check_val '' LIBXML2 -lxml2 libxml2 +check_val '' LIBXML2 -lxml2 libxml2 libxml-2.0 '' '' if [ "$HAVE_EGL" = "yes" ]; then if [ "$HAVE_OPENGLES" != "no" ]; then @@ -485,34 +462,23 @@ if [ "$HAVE_EGL" = "yes" ]; then fi fi fi - check_pkgconf VG "$VC_PREFIX"vg - check_val '' VG "-l${VC_PREFIX}OpenVG $EXTRA_GL_LIBS" + check_val '' VG "-l${VC_PREFIX}OpenVG $EXTRA_GL_LIBS" '' "${VC_PREFIX}vg" '' '' else HAVE_VG=no HAVE_OPENGLES=no fi -check_pkgconf V4L2 libv4l2 -check_pkgconf FREETYPE freetype2 -check_pkgconf X11 x11 -check_pkgconf XCB xcb -check_pkgconf WAYLAND wayland-egl 1.15 -check_pkgconf WAYLAND_CURSOR wayland-cursor 1.15 +check_val '' V4L2 -lv4l2 '' libv4l2 '' '' +check_val '' FREETYPE -lfreetype freetype2 freetype2 '' '' +check_val '' X11 -lX11 '' x11 '' '' +check_val '' XCB -lxcb '' xcb '' '' +check_val '' WAYLAND '-lwayland-egl -lwayland-client' '' wayland-egl 1.15 '' +check_val '' WAYLAND_CURSOR -lwayland-cursor '' wayland-cursor 1.15 '' check_pkgconf WAYLAND_PROTOS wayland-protocols 1.15 -check_pkgconf XKBCOMMON xkbcommon 0.3.2 +check_val '' XKBCOMMON -lxkbcommon '' xkbcommon 0.3.2 '' check_pkgconf DBUS dbus-1 -check_pkgconf XEXT xext -check_pkgconf XF86VM xxf86vm - -check_val '' V4L2 -lv4l2 -check_val '' FREETYPE -lfreetype freetype2 -check_val '' X11 -lX11 -check_val '' XCB -lxcb -check_val '' WAYLAND '-lwayland-egl -lwayland-client' -check_val '' WAYLAND_CURSOR -lwayland-cursor -check_val '' XKBCOMMON -lxkbcommon -check_val '' XEXT -lXext -check_val '' XF86VM -lXxf86vm +check_val '' XEXT -lXext '' xext '' '' +check_val '' XF86VM -lXxf86vm '' xxf86vm '' '' if [ "$HAVE_WAYLAND_PROTOS" = yes ] && [ "$HAVE_WAYLAND" = yes ]; then check_pkgconf WAYLAND_SCANNER wayland-scanner 1.15 @@ -527,20 +493,17 @@ if [ "$HAVE_X11" = 'no' ]; then fi check_lib '' XRANDR -lXrandr -check_pkgconf XINERAMA xinerama -check_val '' XINERAMA -lXinerama +check_val '' XINERAMA -lXinerama '' xinerama '' '' if [ "$HAVE_X11" = 'yes' ] && [ "$HAVE_XEXT" = 'yes' ] && [ "$HAVE_XF86VM" = 'yes' ]; then - check_pkgconf XVIDEO xv - check_val '' XVIDEO -lXv + check_val '' XVIDEO -lXv '' xv '' '' else die : 'Notice: X11, Xext or xf86vm not present. Skipping X11 code paths.' HAVE_X11='no' HAVE_XVIDEO='no' fi -check_pkgconf UDEV libudev -check_val '' UDEV "-ludev" +check_val '' UDEV "-ludev" '' libudev '' '' check_header XSHM X11/Xlib.h X11/extensions/XShm.h check_header PARPORT linux/parport.h diff --git a/qb/config.params.sh b/qb/config.params.sh index 029eb822ef..ed9a6b94ae 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -121,7 +121,7 @@ HAVE_CHEEVOS=yes # Retro Achievements HAVE_NEW_CHEEVOS=no # Use rcheevos to process RetroAchievements C89_NEW_CHEEVOS=no HAVE_LUA=no # Lua support (for Retro Achievements) -HAVE_DISCORD=yes # Discord Integration +HAVE_DISCORD=auto # Discord Integration C89_DISCORD=no HAVE_SHADERPIPELINE=yes # Additional shader-based pipelines C89_SHADERPIPELINE=no diff --git a/qb/qb.libs.sh b/qb/qb.libs.sh index 0ecc808080..e3101511ce 100644 --- a/qb/qb.libs.sh +++ b/qb/qb.libs.sh @@ -7,7 +7,10 @@ SHARE_DIR="${SHARE_DIR:-${PREFIX}/share}" add_define() # $1 = MAKEFILE or CONFIG $2 = define $3 = value { eval "${1}_DEFINES=\"\${${1}_DEFINES} $2=$3\""; } -add_dirs() # $1 = INCLUDE or LIBRARY $@ = include or library paths +# add_dirs: +# $1 = INCLUDE or LIBRARY +# $@ = include or library paths +add_dirs() { ADD="$1"; LINK="${1%"${1#?}"}"; shift while [ "$1" ]; do eval "${ADD}_DIRS=\"\${${ADD}_DIRS} -${LINK}${1}\"" @@ -16,7 +19,10 @@ add_dirs() # $1 = INCLUDE or LIBRARY $@ = include or library paths eval "${ADD}_DIRS=\"\${${ADD}_DIRS# }\"" } -check_compiler() # $1 = language $2 = function in lib +# check_compiler: +# $1 = language +# $2 = function in lib +check_compiler() { if [ "$1" = cxx ]; then COMPILER="$CXX" TEMP_CODE="$TEMP_CXX" @@ -28,7 +34,10 @@ check_compiler() # $1 = language $2 = function in lib fi } -check_enabled() # $1 = HAVE_$1 $2 = lib +# check_enabled: +# $1 = HAVE_$1 +# $2 = lib +check_enabled() { [ "$HAVE_CXX" != 'no' ] && return 0 tmpval="$(eval "printf %s \"\$HAVE_$1\"")" @@ -40,7 +49,16 @@ check_enabled() # $1 = HAVE_$1 $2 = lib die 1 "Forced to build with $2 support and the C++ compiler is disabled. Exiting ..." } -check_lib() # $1 = language $2 = HAVE_$2 $3 = lib $4 = function in lib $5 = extralibs $6 = headers $7 = critical error message [checked only if non-empty] +# check_lib: +# Compiles a simple test program to check if a library is available. +# $1 = language +# $2 = HAVE_$2 +# $3 = lib +# $4 = function in lib +# $5 = extralibs +# $6 = headers +# $7 = critical error message [checked only if non-empty] +check_lib() { tmpval="$(eval "printf %s \"\$HAVE_$2\"")" [ "$tmpval" = 'no' ] && return 0 @@ -81,7 +99,13 @@ check_lib() # $1 = language $2 = HAVE_$2 $3 = lib $4 = function in lib $5 = return 0 } -check_pkgconf() # $1 = HAVE_$1 $2 = package $3 = version $4 = critical error message [checked only if non-empty] +# check_pkgconf: +# If available uses $PKG_CONF_PATH to find a library. +# $1 = HAVE_$1 +# $2 = package +# $3 = version [checked only if non-empty] +# $4 = critical error message [checked only if non-empty] +check_pkgconf() { tmpval="$(eval "printf %s \"\$HAVE_$1\"")" eval "TMP_$1=\$tmpval" [ "$tmpval" = 'no' ] && return 0 @@ -115,7 +139,10 @@ check_pkgconf() # $1 = HAVE_$1 $2 = package $3 = version $4 = critical error fi } -check_header() #$1 = HAVE_$1 $2, $3, ... = header files +# check_header: +# $1 = HAVE_$1 +# $@ = header files +check_header() { tmpval="$(eval "printf %s \"\$HAVE_$1\"")" [ "$tmpval" = 'no' ] && return 0 rm -f -- "$TEMP_C" @@ -137,7 +164,11 @@ check_header() #$1 = HAVE_$1 $2, $3, ... = header files die 1 "Build assumed that $header exists, but cannot locate. Exiting ..." } -check_macro() #$1 = HAVE_$1 $2 = macro name $3 = header name [included only if non-empty] +# check_macro: +# $1 = HAVE_$1 +# $2 = macro name +# $3 = header name [included only if non-empty] +check_macro() { tmpval="$(eval "printf %s \"\$HAVE_$1\"")" [ "$tmpval" = 'no' ] && return 0 if [ "${3}" ]; then @@ -166,7 +197,12 @@ EOF die 1 "Build assumed that $macro is defined, but it's not. Exiting ..." } -check_switch() # $1 = language $2 = HAVE_$2 $3 = switch $4 = critical error message [checked only if non-empty] +# check_switch: +# $1 = language +# $2 = HAVE_$2 +# $3 = switch +# $4 = critical error message [checked only if non-empty] +check_switch() { check_compiler "$1" '' ECHOBUF="Checking for availability of switch $3 in $COMPILER" @@ -181,8 +217,18 @@ check_switch() # $1 = language $2 = HAVE_$2 $3 = switch $4 = critical error m } } -check_val() # $1 = language $2 = HAVE_$2 $3 = lib $4 = include directory [checked only if non-empty] -{ tmpval="$(eval "printf %s \"\$HAVE_$2\"")" +# check_val: +# Uses check_pkgconf to find a library and falls back to check_lib if false. +# $1 = language +# $2 = HAVE_$2 +# $3 = lib +# $4 = include directory [checked only if non-empty] +# $5 = package +# $6 = version [checked only if non-empty] +# $7 = critical error message [checked only if non-empty] +check_val() +{ check_pkgconf "$2" "$5" "$6" "${7:-}" + tmpval="$(eval "printf %s \"\$HAVE_$2\"")" oldval="$(eval "printf %s \"\$TMP_$2\"")" if [ "$tmpval" = 'no' ] && [ "$oldval" != 'no' ]; then eval "HAVE_$2=auto" From 352fbc7cc74a4fa545203a12e0d2e9812c0c2a7f Mon Sep 17 00:00:00 2001 From: orbea Date: Thu, 24 Jan 2019 22:29:10 -0800 Subject: [PATCH 073/234] qb: Remove duplicate code in config.libs.sh. --- qb/config.libs.sh | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/qb/config.libs.sh b/qb/config.libs.sh index ab7ace414a..fba2da9f54 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -75,12 +75,6 @@ if [ "$HAVE_VIDEOCORE" = 'yes' ]; then fi fi -if [ "$HAVE_NEON" = "yes" ]; then - CFLAGS="$CFLAGS -mfpu=neon -marm" - CXXFLAGS="$CXXFLAGS -mfpu=neon -marm" - ASFLAGS="$ASFLAGS -mfpu=neon" -fi - if [ "$HAVE_7ZIP" = "yes" ]; then add_dirs INCLUDE ./deps/7zip fi @@ -89,18 +83,6 @@ if [ "$HAVE_PRESERVE_DYLIB" = "yes" ]; then die : 'Notice: Disabling dlclose() of shared objects for Valgrind support.' fi -if [ "$HAVE_FLOATHARD" = "yes" ]; then - CFLAGS="$CFLAGS -mfloat-abi=hard" - CXXFLAGS="$CXXFLAGS -mfloat-abi=hard" - ASFLAGS="$ASFLAGS -mfloat-abi=hard" -fi - -if [ "$HAVE_FLOATSOFTFP" = "yes" ]; then - CFLAGS="$CFLAGS -mfloat-abi=softfp" - CXXFLAGS="$CXXFLAGS -mfloat-abi=softfp" - ASFLAGS="$ASFLAGS -mfloat-abi=softfp" -fi - if [ "$HAVE_NEON" = "yes" ]; then CFLAGS="$CFLAGS -mfpu=neon -marm" CXXFLAGS="$CXXFLAGS -mfpu=neon -marm" From 2cc6505997e8ed7e49d8bf6e7214d07ca6fc61b6 Mon Sep 17 00:00:00 2001 From: orbea Date: Thu, 24 Jan 2019 23:07:43 -0800 Subject: [PATCH 074/234] qb: Fix HAVE_RETRO check. --- qb/config.libs.sh | 6 +++--- qb/qb.libs.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qb/config.libs.sh b/qb/config.libs.sh index fba2da9f54..bb09b97670 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -128,12 +128,12 @@ fi if [ "$LIBRETRO" ]; then die : 'Notice: Explicit libretro used, disabling dynamic libretro loading ...' HAVE_DYNAMIC='no' -else LIBRETRO="-lretro" +else + LIBRETRO="-lretro" fi [ "$HAVE_DYNAMIC" = 'yes' ] || { - #check_lib '' RETRO "$LIBRETRO" retro_init "$DYLIB" "Cannot find libretro, did you forget --with-libretro=\"-lretro\"?" - check_lib '' RETRO "$LIBRETRO" "$DYLIB" "Cannot find libretro, did you forget --with-libretro=\"-lretro\"?" + check_lib '' RETRO "$LIBRETRO" retro_init "$DYLIB" '' 'Cannot find libretro, did you forget --with-libretro="-lretro"?' add_define MAKEFILE libretro "$LIBRETRO" } diff --git a/qb/qb.libs.sh b/qb/qb.libs.sh index e3101511ce..09006990b0 100644 --- a/qb/qb.libs.sh +++ b/qb/qb.libs.sh @@ -56,7 +56,7 @@ check_enabled() # $3 = lib # $4 = function in lib # $5 = extralibs -# $6 = headers +# $6 = headers [checked only if non-empty] # $7 = critical error message [checked only if non-empty] check_lib() { tmpval="$(eval "printf %s \"\$HAVE_$2\"")" From 677395f05e71f3090c7de9f7bd8c05cbc5ec4229 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Fri, 25 Jan 2019 21:41:13 +0400 Subject: [PATCH 075/234] [Wayland] Set minimum wayland version to 1.12 --- gfx/common/wayland/generate_wayland_protos.sh | 16 ++++++++++++---- qb/config.libs.sh | 8 ++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/gfx/common/wayland/generate_wayland_protos.sh b/gfx/common/wayland/generate_wayland_protos.sh index 0c50161ed3..77f505ed47 100755 --- a/gfx/common/wayland/generate_wayland_protos.sh +++ b/gfx/common/wayland/generate_wayland_protos.sh @@ -1,5 +1,6 @@ #!/bin/sh WAYSCAN=/usr/bin/wayland-scanner +WAYSCAN_VER=$($WAYSCAN --version 2>&1 | awk '{print $2}') WAYLAND_PROTOS=/usr/share/wayland-protocols OUTPUT=gfx/common/wayland @@ -12,18 +13,25 @@ if [ ! -d $OUTPUT ]; then mkdir $OUTPUT fi +#Since Wayland 1.15 option "code" is deprecated. Recommended to use "private-code" option instead. +if [ "$WAYSCAN_VER -ge 1.15" ]; then + CODEGEN=private-code +else + CODEGEN=code +fi + #Generate xdg-shell_v6 header and .c files $WAYSCAN client-header $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.h -$WAYSCAN private-code $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.c +$WAYSCAN $CODEGEN $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.c #Generate xdg-shell header and .c files $WAYSCAN client-header $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.h -$WAYSCAN private-code $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.c +$WAYSCAN $CODEGEN $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.c #Generate idle-inhibit header and .c files $WAYSCAN client-header $WAYLAND_PROTOS/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml $OUTPUT/idle-inhibit-unstable-v1.h -$WAYSCAN private-code $WAYLAND_PROTOS/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml $OUTPUT/idle-inhibit-unstable-v1.c +$WAYSCAN $CODEGEN $WAYLAND_PROTOS/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml $OUTPUT/idle-inhibit-unstable-v1.c #Generate xdg-decoration header and .c files $WAYSCAN client-header $WAYLAND_PROTOS/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml $OUTPUT/xdg-decoration-unstable-v1.h -$WAYSCAN private-code $WAYLAND_PROTOS/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml $OUTPUT/xdg-decoration-unstable-v1.c +$WAYSCAN $CODEGEN $WAYLAND_PROTOS/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml $OUTPUT/xdg-decoration-unstable-v1.c diff --git a/qb/config.libs.sh b/qb/config.libs.sh index bb09b97670..c569ed8bb9 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -454,8 +454,8 @@ check_val '' V4L2 -lv4l2 '' libv4l2 '' '' check_val '' FREETYPE -lfreetype freetype2 freetype2 '' '' check_val '' X11 -lX11 '' x11 '' '' check_val '' XCB -lxcb '' xcb '' '' -check_val '' WAYLAND '-lwayland-egl -lwayland-client' '' wayland-egl 1.15 '' -check_val '' WAYLAND_CURSOR -lwayland-cursor '' wayland-cursor 1.15 '' +check_val '' WAYLAND '-lwayland-egl -lwayland-client' '' wayland-egl 1.12 '' +check_val '' WAYLAND_CURSOR -lwayland-cursor '' wayland-cursor 1.12 '' check_pkgconf WAYLAND_PROTOS wayland-protocols 1.15 check_val '' XKBCOMMON -lxkbcommon '' xkbcommon 0.3.2 '' check_pkgconf DBUS dbus-1 @@ -463,10 +463,10 @@ check_val '' XEXT -lXext '' xext '' '' check_val '' XF86VM -lXxf86vm '' xxf86vm '' '' if [ "$HAVE_WAYLAND_PROTOS" = yes ] && [ "$HAVE_WAYLAND" = yes ]; then - check_pkgconf WAYLAND_SCANNER wayland-scanner 1.15 + check_pkgconf WAYLAND_SCANNER wayland-scanner 1.12 ./gfx/common/wayland/generate_wayland_protos.sh else - die : 'Notice: wayland-egl or wayland-protocols not found, disabling wayland support.' + die : 'Notice: wayland (>=1.12) or wayland-protocols (>=1.15) not found. Disabling Wayland support.' HAVE_WAYLAND='no' fi From 63c7abef067704d8ece0a8b6563c48880a156134 Mon Sep 17 00:00:00 2001 From: orbea Date: Fri, 25 Jan 2019 14:10:14 -0800 Subject: [PATCH 076/234] qb: Allow testing more than one version in check_pkgconf. --- gfx/common/wayland/generate_wayland_protos.sh | 6 +++ qb/config.libs.sh | 10 +++-- qb/qb.libs.sh | 40 +++++++++++++------ 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/gfx/common/wayland/generate_wayland_protos.sh b/gfx/common/wayland/generate_wayland_protos.sh index 0c50161ed3..7db18419f8 100755 --- a/gfx/common/wayland/generate_wayland_protos.sh +++ b/gfx/common/wayland/generate_wayland_protos.sh @@ -12,6 +12,12 @@ if [ ! -d $OUTPUT ]; then mkdir $OUTPUT fi +if [ "${1:-}" = '1.12' ]; then + CODEGEN=code +else + CODEGEN=private-code +fi + #Generate xdg-shell_v6 header and .c files $WAYSCAN client-header $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.h $WAYSCAN private-code $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.c diff --git a/qb/config.libs.sh b/qb/config.libs.sh index bb09b97670..a9a8e16bc2 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -457,16 +457,18 @@ check_val '' XCB -lxcb '' xcb '' '' check_val '' WAYLAND '-lwayland-egl -lwayland-client' '' wayland-egl 1.15 '' check_val '' WAYLAND_CURSOR -lwayland-cursor '' wayland-cursor 1.15 '' check_pkgconf WAYLAND_PROTOS wayland-protocols 1.15 +check_pkgconf WAYLAND_SCANNER wayland-scanner '1.15 1.12' check_val '' XKBCOMMON -lxkbcommon '' xkbcommon 0.3.2 '' check_pkgconf DBUS dbus-1 check_val '' XEXT -lXext '' xext '' '' check_val '' XF86VM -lXxf86vm '' xxf86vm '' '' -if [ "$HAVE_WAYLAND_PROTOS" = yes ] && [ "$HAVE_WAYLAND" = yes ]; then - check_pkgconf WAYLAND_SCANNER wayland-scanner 1.15 - ./gfx/common/wayland/generate_wayland_protos.sh +if [ "$HAVE_WAYLAND_PROTOS" = yes ] && + [ "$HAVE_WAYLAND_SCANNER" = yes ] && + [ "$HAVE_WAYLAND" = yes ]; then + ./gfx/common/wayland/generate_wayland_protos.sh "$WAYLAND_SCANNER_VERSION" else - die : 'Notice: wayland-egl or wayland-protocols not found, disabling wayland support.' + die : 'Notice: wayland libraries not found, disabling wayland support.' HAVE_WAYLAND='no' fi diff --git a/qb/qb.libs.sh b/qb/qb.libs.sh index 09006990b0..d68f84b0e7 100644 --- a/qb/qb.libs.sh +++ b/qb/qb.libs.sh @@ -4,7 +4,10 @@ CONFIG_DEFINES='' PREFIX="${PREFIX:-/usr/local}" SHARE_DIR="${SHARE_DIR:-${PREFIX}/share}" -add_define() # $1 = MAKEFILE or CONFIG $2 = define $3 = value +# add_define: +# $1 = MAKEFILE or CONFIG +# $2 = define $3 = value +add_define() { eval "${1}_DEFINES=\"\${${1}_DEFINES} $2=$3\""; } # add_dirs: @@ -111,31 +114,41 @@ check_pkgconf() [ "$tmpval" = 'no' ] && return 0 ECHOBUF="Checking presence of package $2" - [ "$3" ] && ECHOBUF="$ECHOBUF >= $3" + [ "$3" ] && ECHOBUF="$ECHOBUF >= ${3##* }" [ "$PKG_CONF_PATH" = "none" ] && { eval "HAVE_$1=no" + eval "${1#HAVE_}_VERSION=0.0" printf %s\\n "$ECHOBUF ... no" return 0 } + val="$1" + pkg="$2" + err="$4" answer='no' version='no' - $PKG_CONF_PATH --atleast-version="${3:-0.0}" "$2" && { - answer='yes' - version="$("$PKG_CONF_PATH" --modversion "$2")" - eval "$1_CFLAGS=\"$("$PKG_CONF_PATH" "$2" --cflags)\"" - eval "$1_LIBS=\"$("$PKG_CONF_PATH" "$2" --libs)\"" - } + + eval "set -- ${3:-0.0}" + for ver do + if $PKG_CONF_PATH --atleast-version="$ver" "$pkg"; then + answer='yes' + version="$("$PKG_CONF_PATH" --modversion "$pkg")" + eval "${val}_CFLAGS=\"$("$PKG_CONF_PATH" "$pkg" --cflags)\"" + eval "${val}_LIBS=\"$("$PKG_CONF_PATH" "$pkg" --libs)\"" + eval "${val#HAVE_}_VERSION=\"$ver\"" + break + fi + done - eval "HAVE_$1=\"$answer\"" + eval "HAVE_$val=\"$answer\"" printf %s\\n "$ECHOBUF ... $version" if [ "$answer" = 'no' ]; then - [ "$4" ] && die 1 "$4" - [ "$tmpval" = 'yes' ] && \ - die 1 "Forced to build with package $2, but cannot locate. Exiting ..." + [ "$err" ] && die 1 "$err" + [ "$tmpval" = 'yes' ] && + die 1 "Forced to build with package $pkg, but cannot locate. Exiting ..." else - PKG_CONF_USED="$PKG_CONF_USED $1" + PKG_CONF_USED="$PKG_CONF_USED $val" fi } @@ -228,6 +241,7 @@ check_switch() # $7 = critical error message [checked only if non-empty] check_val() { check_pkgconf "$2" "$5" "$6" "${7:-}" + [ "$PKG_CONF_PATH" = "none" ] || return 0 tmpval="$(eval "printf %s \"\$HAVE_$2\"")" oldval="$(eval "printf %s \"\$TMP_$2\"")" if [ "$tmpval" = 'no' ] && [ "$oldval" != 'no' ]; then From 1ee66d520469d5fc7465e298b60923c93bee284e Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Fri, 25 Jan 2019 23:28:07 -0500 Subject: [PATCH 077/234] d3d: fix cross-compilation on Linux --- libretro-common/include/libretro_d3d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretro-common/include/libretro_d3d.h b/libretro-common/include/libretro_d3d.h index a0ba716fdb..51165a3717 100644 --- a/libretro-common/include/libretro_d3d.h +++ b/libretro-common/include/libretro_d3d.h @@ -32,7 +32,7 @@ #ifdef HAVE_D3D11 #include -#include +#include #define RETRO_HW_RENDER_INTERFACE_D3D11_VERSION 1 From 10d2d130041871049cee56aec447795da74323bf Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Sat, 26 Jan 2019 01:15:18 +0400 Subject: [PATCH 078/234] Fix version's comparison --- gfx/common/wayland/generate_wayland_protos.sh | 8 -------- qb/config.libs.sh | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/gfx/common/wayland/generate_wayland_protos.sh b/gfx/common/wayland/generate_wayland_protos.sh index 77f505ed47..899f8fb431 100755 --- a/gfx/common/wayland/generate_wayland_protos.sh +++ b/gfx/common/wayland/generate_wayland_protos.sh @@ -1,6 +1,5 @@ #!/bin/sh WAYSCAN=/usr/bin/wayland-scanner -WAYSCAN_VER=$($WAYSCAN --version 2>&1 | awk '{print $2}') WAYLAND_PROTOS=/usr/share/wayland-protocols OUTPUT=gfx/common/wayland @@ -13,13 +12,6 @@ if [ ! -d $OUTPUT ]; then mkdir $OUTPUT fi -#Since Wayland 1.15 option "code" is deprecated. Recommended to use "private-code" option instead. -if [ "$WAYSCAN_VER -ge 1.15" ]; then - CODEGEN=private-code -else - CODEGEN=code -fi - #Generate xdg-shell_v6 header and .c files $WAYSCAN client-header $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.h $WAYSCAN $CODEGEN $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.c diff --git a/qb/config.libs.sh b/qb/config.libs.sh index c569ed8bb9..bb92299841 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -463,10 +463,10 @@ check_val '' XEXT -lXext '' xext '' '' check_val '' XF86VM -lXxf86vm '' xxf86vm '' '' if [ "$HAVE_WAYLAND_PROTOS" = yes ] && [ "$HAVE_WAYLAND" = yes ]; then - check_pkgconf WAYLAND_SCANNER wayland-scanner 1.12 + check_pkgconf WAYLAND_SCANNER wayland-scanner 1.15 ./gfx/common/wayland/generate_wayland_protos.sh else - die : 'Notice: wayland (>=1.12) or wayland-protocols (>=1.15) not found. Disabling Wayland support.' + die : 'Notice: wayland-egl or wayland-protocols not found, disabling wayland support.' HAVE_WAYLAND='no' fi From 5ee7921b6516a67bff3f64572d0be07a231f79b1 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sat, 26 Jan 2019 14:16:40 +0100 Subject: [PATCH 079/234] Add CDFS support --- frontend/drivers/platform_ps2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/drivers/platform_ps2.c b/frontend/drivers/platform_ps2.c index 0d69d7615c..c937c1c928 100644 --- a/frontend/drivers/platform_ps2.c +++ b/frontend/drivers/platform_ps2.c @@ -510,6 +510,11 @@ static int frontend_ps2_parse_drive_list(void *data, bool load_content) msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), enum_idx, FILE_TYPE_DIRECTORY, 0, 0); + menu_entries_append_enum(list, + "cdfs:/", + msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), + enum_idx, + FILE_TYPE_DIRECTORY, 0, 0); menu_entries_append_enum(list, "hdd0:/", msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), From 4dbd15381a2211c488fcea09f3753643dbb36f01 Mon Sep 17 00:00:00 2001 From: Zlika Date: Sat, 26 Jan 2019 15:05:50 +0100 Subject: [PATCH 080/234] Add missing files in libretro-db Makefile --- libretro-db/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libretro-db/Makefile b/libretro-db/Makefile index 6960cf1478..ec3c055a8b 100644 --- a/libretro-db/Makefile +++ b/libretro-db/Makefile @@ -13,6 +13,8 @@ endif LIBRETRO_COMMON_C = \ $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \ + $(LIBRETRO_COMM_DIR)/file/file_path.c \ $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \ $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ From 8e26b13578f58af2a9779bc0a33956af7d53a947 Mon Sep 17 00:00:00 2001 From: benutzer193 Date: Sat, 26 Jan 2019 17:49:20 +0100 Subject: [PATCH 081/234] If window is not present, create window --- gfx/drivers_context/wayland_ctx.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 32ae40f80c..c513613e3a 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -657,8 +657,11 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, wl->width = width; wl->height = height; } - - wl_egl_window_resize(wl->win, width, height, 0, 0); + + if (wl->win) + wl_egl_window_resize(wl->win, width, height, 0, 0); + else + wl->win = wl_egl_window_create(wl->surface, wl->width * wl->buffer_scale, wl->height * wl->buffer_scale); wl->configured = false; } @@ -724,7 +727,10 @@ static void handle_zxdg_toplevel_config(void *data, struct zxdg_toplevel_v6 *top wl->height = height; } - wl_egl_window_resize(wl->win, width, height, 0, 0); + if (wl->win) + wl_egl_window_resize(wl->win, width, height, 0, 0); + else + wl->win = wl_egl_window_create(wl->surface, wl->width * wl->buffer_scale, wl->height * wl->buffer_scale); wl->configured = false; } From d7d5bc58b2462fcf9430e07ca6dcf8fec9c0c262 Mon Sep 17 00:00:00 2001 From: orbea Date: Fri, 25 Jan 2019 07:00:28 -0800 Subject: [PATCH 082/234] qb: Create qb.init.sh. --- configure | 2 ++ qb/qb.init.sh | 43 +++++++++++++++++++++++++++++++++++++++++++ qb/qb.libs.sh | 3 ++- qb/qb.params.sh | 11 ----------- qb/qb.system.sh | 22 ---------------------- 5 files changed, 47 insertions(+), 34 deletions(-) create mode 100644 qb/qb.init.sh diff --git a/configure b/configure index 5d7a948491..5c680b4064 100755 --- a/configure +++ b/configure @@ -4,6 +4,8 @@ PACKAGE_NAME=retroarch cat /dev/null > config.log +. qb/qb.init.sh + . qb/qb.system.sh . qb/qb.params.sh diff --git a/qb/qb.init.sh b/qb/qb.init.sh new file mode 100644 index 0000000000..405340e25c --- /dev/null +++ b/qb/qb.init.sh @@ -0,0 +1,43 @@ +# Only add standalone functions to this file which are easy to source anywhere. + +# die: +# Prints a warning or an exit error. +# $1 = exit code, use : to not exit when printing warnings +# $@ = exit or warning messages +die() +{ ret="$1" + shift 1 + printf %s\\n "$@" >&2 + case "$ret" in + : ) return 0 ;; + * ) exit "$ret" ;; + esac +} + +# exists: +# Finds executable files in the $PATH +# $@ = files +exists() +{ v=1 + while [ $# -gt 0 ]; do + arg="$1" + shift 1 + case "$arg" in ''|*/) continue ;; esac + x="${arg##*/}" + z="${arg%/*}" + [ ! -f "$z/$x" ] || [ ! -x "$z/$x" ] && [ "$z/$x" = "$arg" ] && + continue + [ "$x" = "$z" ] && [ -x "$z/$x" ] && [ ! -f "$arg" ] && z= + p=":$z:$PATH" + while [ "$p" != "${p#*:}" ]; do + p="${p#*:}" + d="${p%%:*}" + if [ -f "$d/$x" ] && [ -x "$d/$x" ]; then + printf %s\\n "$d/$x" + v=0 + break + fi + done + done + return $v +} diff --git a/qb/qb.libs.sh b/qb/qb.libs.sh index d68f84b0e7..1dfaeb7f99 100644 --- a/qb/qb.libs.sh +++ b/qb/qb.libs.sh @@ -6,7 +6,8 @@ SHARE_DIR="${SHARE_DIR:-${PREFIX}/share}" # add_define: # $1 = MAKEFILE or CONFIG -# $2 = define $3 = value +# $2 = define +# $3 = value add_define() { eval "${1}_DEFINES=\"\${${1}_DEFINES} $2=$3\""; } diff --git a/qb/qb.params.sh b/qb/qb.params.sh index 40fdf63106..937f168530 100644 --- a/qb/qb.params.sh +++ b/qb/qb.params.sh @@ -1,14 +1,3 @@ -die() # $1 = exit code, use : to not exit when printing warnings $@ = exit or warning messages -{ - ret="$1" - shift 1 - printf %s\\n "$@" >&2 - case "$ret" in - : ) return 0 ;; - * ) exit "$ret" ;; - esac -} - print_help_option() # $1 = option $@ = description { _opt="$1" diff --git a/qb/qb.system.sh b/qb/qb.system.sh index d8c8ae9db4..68c258e35a 100644 --- a/qb/qb.system.sh +++ b/qb/qb.system.sh @@ -1,25 +1,3 @@ -exists() # checks executables listed in $@ against the $PATH -{ - v=1 - while [ "$#" -gt 0 ]; do - arg="$1" - shift 1 - case "$arg" in ''|*/) continue ;; esac - x="${arg##*/}" - z="${arg%/*}" - [ ! -f "$z/$x" ] || [ ! -x "$z/$x" ] && [ "$z/$x" = "$arg" ] && continue - [ "$x" = "$z" ] && [ -x "$z/$x" ] && [ ! -f "$arg" ] && z= - p=":$z:$PATH" - while [ "$p" != "${p#*:}" ]; do - p="${p#*:}" - d="${p%%:*}" - { [ -f "$d/$x" ] && [ -x "$d/$x" ] && \ - { printf %s\\n "$d/$x"; v=0; break; }; } || : - done - done - return "$v" -} - if [ -n "$CROSS_COMPILE" ]; then case "$CROSS_COMPILE" in *'-mingw32'*) OS='Win32';; From 29a07895b9fe06ef53213d9c1ba5f683a3a8f865 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Sat, 26 Jan 2019 18:52:49 -0500 Subject: [PATCH 083/234] implement scissor test for D3D10/11, fixes #7897 --- gfx/drivers/d3d10.c | 17 ++++++++++ gfx/drivers/d3d11.c | 15 +++++++++ menu/drivers_display/menu_display_d3d10.c | 38 +++++++++++++++++++++-- menu/drivers_display/menu_display_d3d11.c | 38 +++++++++++++++++++++-- 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/gfx/drivers/d3d10.c b/gfx/drivers/d3d10.c index b5dc33d0e3..ad389744e1 100644 --- a/gfx/drivers/d3d10.c +++ b/gfx/drivers/d3d10.c @@ -68,6 +68,18 @@ d3d10_overlay_vertex_geom(void* data, unsigned index, float x, float y, float w, D3D10UnmapBuffer(d3d10->overlays.vbo); } +static void d3d10_clear_scissor(d3d10_video_t *d3d10) +{ + D3D10_RECT scissor_rect = {0}; + + scissor_rect.left = d3d10->vp.x; + scissor_rect.top = d3d10->vp.y; + scissor_rect.right = d3d10->vp.width; + scissor_rect.bottom = d3d10->vp.height; + + D3D10SetScissorRects(d3d10->device, 1, &scissor_rect); +} + static void d3d10_overlay_tex_geom(void* data, unsigned index, float u, float v, float w, float h) { d3d10_sprite_t* sprites = NULL; @@ -257,6 +269,8 @@ static void d3d10_update_viewport(void* data, bool force_full) d3d10->frame.output_size.w = 1.0f / d3d10->vp.height; d3d10->resize_viewport = false; + + d3d10_clear_scissor(d3d10); } static void d3d10_free_shader_preset(d3d10_video_t* d3d10) @@ -921,6 +935,7 @@ d3d10_gfx_init(const video_info_t* video, desc.FillMode = D3D10_FILL_SOLID; desc.CullMode = D3D10_CULL_NONE; + desc.ScissorEnable = TRUE; D3D10CreateRasterizerState(d3d10->device, &desc, &d3d10->state); } @@ -1318,6 +1333,8 @@ static bool d3d10_gfx_frame( D3D10ClearRenderTargetView(context, d3d10->renderTargetView, d3d10->clearcolor); D3D10SetViewports(context, 1, &d3d10->frame.viewport); + d3d10_clear_scissor(d3d10); + D3D10Draw(context, 4, 0); D3D10SetBlendState(context, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 6e0850b712..188eb784c4 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -81,6 +81,18 @@ d3d11_overlay_vertex_geom(void* data, unsigned index, float x, float y, float w, D3D11UnmapBuffer(d3d11->context, d3d11->overlays.vbo, 0); } +static void d3d11_clear_scissor(d3d11_video_t *d3d11) +{ + D3D11_RECT scissor_rect = {0}; + + scissor_rect.left = d3d11->vp.x; + scissor_rect.top = d3d11->vp.y; + scissor_rect.right = d3d11->vp.width; + scissor_rect.bottom = d3d11->vp.height; + + D3D11SetScissorRects(d3d11->context, 1, &scissor_rect); +} + static void d3d11_overlay_tex_geom(void* data, unsigned index, float u, float v, float w, float h) { D3D11_MAPPED_SUBRESOURCE mapped_vbo; @@ -272,6 +284,8 @@ static void d3d11_update_viewport(void* data, bool force_full) d3d11->frame.output_size.w = 1.0f / d3d11->vp.height; d3d11->resize_viewport = false; + + d3d11_clear_scissor(d3d11); } static void d3d11_free_shader_preset(d3d11_video_t* d3d11) @@ -993,6 +1007,7 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i desc.FillMode = D3D11_FILL_SOLID; desc.CullMode = D3D11_CULL_NONE; + desc.ScissorEnable = TRUE; D3D11CreateRasterizerState(d3d11->device, &desc, &d3d11->state); } diff --git a/menu/drivers_display/menu_display_d3d10.c b/menu/drivers_display/menu_display_d3d10.c index 026bfc70d7..c8e5792cf0 100644 --- a/menu/drivers_display/menu_display_d3d10.c +++ b/menu/drivers_display/menu_display_d3d10.c @@ -275,6 +275,40 @@ static bool menu_display_d3d10_font_init_first( return true; } +void menu_display_d3d10_scissor_begin(video_frame_info_t *video_info, int x, int y, unsigned width, unsigned height) +{ + D3D10_RECT rect = {0}; + d3d10_video_t *d3d10 = video_info ? + (d3d10_video_t*)video_info->userdata : NULL; + + rect.left = x; + rect.top = y; + rect.right = width + x; + rect.bottom = height + y; + + if (!d3d10 || !width || !height) + return; + + D3D10SetScissorRects(d3d10->device, 1, &rect); +} + +void menu_display_d3d10_scissor_end(video_frame_info_t *video_info) +{ + D3D10_RECT rect = {0}; + d3d10_video_t *d3d10 = video_info ? + (d3d10_video_t*)video_info->userdata : NULL; + + if (!d3d10) + return; + + rect.left = d3d10->vp.x; + rect.top = d3d10->vp.y; + rect.right = d3d10->vp.width; + rect.bottom = d3d10->vp.height; + + D3D10SetScissorRects(d3d10->device, 1, &rect); +} + menu_display_ctx_driver_t menu_display_ctx_d3d10 = { menu_display_d3d10_draw, menu_display_d3d10_draw_pipeline, @@ -290,6 +324,6 @@ menu_display_ctx_driver_t menu_display_ctx_d3d10 = { MENU_VIDEO_DRIVER_DIRECT3D10, "d3d10", true, - NULL, - NULL + menu_display_d3d10_scissor_begin, + menu_display_d3d10_scissor_end }; diff --git a/menu/drivers_display/menu_display_d3d11.c b/menu/drivers_display/menu_display_d3d11.c index 33d62f5a10..dd7ace57c8 100644 --- a/menu/drivers_display/menu_display_d3d11.c +++ b/menu/drivers_display/menu_display_d3d11.c @@ -274,6 +274,40 @@ static bool menu_display_d3d11_font_init_first( return true; } +void menu_display_d3d11_scissor_begin(video_frame_info_t *video_info, int x, int y, unsigned width, unsigned height) +{ + D3D11_RECT rect = {0}; + d3d11_video_t *d3d11 = video_info ? + (d3d11_video_t*)video_info->userdata : NULL; + + rect.left = x; + rect.top = y; + rect.right = width + x; + rect.bottom = height + y; + + if (!d3d11 || !width || !height) + return; + + D3D11SetScissorRects(d3d11->context, 1, &rect); +} + +void menu_display_d3d11_scissor_end(video_frame_info_t *video_info) +{ + D3D11_RECT rect = {0}; + d3d11_video_t *d3d11 = video_info ? + (d3d11_video_t*)video_info->userdata : NULL; + + if (!d3d11) + return; + + rect.left = d3d11->vp.x; + rect.top = d3d11->vp.y; + rect.right = d3d11->vp.width; + rect.bottom = d3d11->vp.height; + + D3D11SetScissorRects(d3d11->context, 1, &rect); +} + menu_display_ctx_driver_t menu_display_ctx_d3d11 = { menu_display_d3d11_draw, menu_display_d3d11_draw_pipeline, @@ -289,6 +323,6 @@ menu_display_ctx_driver_t menu_display_ctx_d3d11 = { MENU_VIDEO_DRIVER_DIRECT3D11, "d3d11", true, - NULL, - NULL + menu_display_d3d11_scissor_begin, + menu_display_d3d11_scissor_end }; From ae7b09afae75e02324bf29575c9a0b1863023e8a Mon Sep 17 00:00:00 2001 From: orbea Date: Fri, 25 Jan 2019 07:13:54 -0800 Subject: [PATCH 084/234] gfx: Update generate_wayland_protos.sh. --- gfx/common/wayland/generate_wayland_protos.sh | 68 +++++++++++++------ qb/config.libs.sh | 3 +- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/gfx/common/wayland/generate_wayland_protos.sh b/gfx/common/wayland/generate_wayland_protos.sh index 2732bb47b1..1921f1086f 100755 --- a/gfx/common/wayland/generate_wayland_protos.sh +++ b/gfx/common/wayland/generate_wayland_protos.sh @@ -1,35 +1,65 @@ #!/bin/sh -WAYSCAN=/usr/bin/wayland-scanner -WAYLAND_PROTOS=/usr/share/wayland-protocols -OUTPUT=gfx/common/wayland -if [ ! -d $WAYLAND_PROTOS ]; then - WAYSCAN=/usr/local/bin/wayland-scanner - WAYLAND_PROTOS=/usr/local/share/wayland-protocols -fi +set -eu -if [ ! -d $OUTPUT ]; then - mkdir $OUTPUT -fi +cd -- "$(cd -- "${0%/*}/" && pwd -P)" -if [ "${1:-}" = '1.12' ]; then +. ../../../qb/qb.init.sh + +SCANNER_VERSION='' +SHARE_DIR='' + +usage="generate_wayland_protos.sh - Generates wayland protocols. + + Usage: generate_wayland_protos.sh [OPTIONS] + -c, --codegen version Sets the wayland scanner compatibility version. + -h, --help Shows this message. + -s, --share path Sets the path of the wayland protocols directory." + +while [ $# -gt 0 ]; do + option="$1" + shift + case "$option" in + -- ) break ;; + -c|--codegen ) SCANNER_VERSION="$1"; shift ;; + -h|--help ) die 0 "$usage" ;; + -s|--share ) SHARE_DIR="$1/wayland-protocols"; shift ;; + * ) die 1 "Unrecognized option '$option', use -h for help." ;; + esac +done + +WAYSCAN="$(exists wayland-scanner || :)" + +[ "${WAYSCAN}" ] || die 1 "Error: No wayscan in ($PATH)" + +WAYLAND_PROTOS='' + +for protos in "$SHARE_DIR" /usr/local/share/wayland-protocols /usr/share/wayland-protocols; do + [ -d "$protos" ] || continue + WAYLAND_PROTOS="$protos" + break +done + +[ "${WAYLAND_PROTOS}" ] || die 1 'Error: No wayland-protocols directory found.' + +if [ "$SCANNER_VERSION" = '1.12' ]; then CODEGEN=code else CODEGEN=private-code fi #Generate xdg-shell_v6 header and .c files -$WAYSCAN client-header $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.h -$WAYSCAN $CODEGEN $WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml $OUTPUT/xdg-shell-unstable-v6.c +"$WAYSCAN" client-header "$WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml" ./xdg-shell-unstable-v6.h +"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/unstable/xdg-shell/xdg-shell-unstable-v6.xml" ./xdg-shell-unstable-v6.c #Generate xdg-shell header and .c files -$WAYSCAN client-header $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.h -$WAYSCAN $CODEGEN $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.c +"$WAYSCAN" client-header "$WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml" ./xdg-shell.h +"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml" ./xdg-shell.c #Generate idle-inhibit header and .c files -$WAYSCAN client-header $WAYLAND_PROTOS/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml $OUTPUT/idle-inhibit-unstable-v1.h -$WAYSCAN $CODEGEN $WAYLAND_PROTOS/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml $OUTPUT/idle-inhibit-unstable-v1.c +"$WAYSCAN" client-header "$WAYLAND_PROTOS/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml" ./idle-inhibit-unstable-v1.h +"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml" ./idle-inhibit-unstable-v1.c #Generate xdg-decoration header and .c files -$WAYSCAN client-header $WAYLAND_PROTOS/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml $OUTPUT/xdg-decoration-unstable-v1.h -$WAYSCAN $CODEGEN $WAYLAND_PROTOS/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml $OUTPUT/xdg-decoration-unstable-v1.c +"$WAYSCAN" client-header "$WAYLAND_PROTOS/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" ./xdg-decoration-unstable-v1.h +"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" ./xdg-decoration-unstable-v1.c diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 501b52daae..7454e2d3da 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -466,7 +466,8 @@ check_val '' XF86VM -lXxf86vm '' xxf86vm '' '' if [ "$HAVE_WAYLAND_PROTOS" = yes ] && [ "$HAVE_WAYLAND_SCANNER" = yes ] && [ "$HAVE_WAYLAND" = yes ]; then - ./gfx/common/wayland/generate_wayland_protos.sh "$WAYLAND_SCANNER_VERSION" + ./gfx/common/wayland/generate_wayland_protos.sh -c "$WAYLAND_SCANNER_VERSION" -s "$SHARE_DIR" || + die 1 'Error: Failed generating wayland protocols.' else die : 'Notice: wayland libraries not found, disabling wayland support.' HAVE_WAYLAND='no' From 8b6676e17fb70e14465571da484489aafb4c4129 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Sat, 26 Jan 2019 20:12:49 -0500 Subject: [PATCH 085/234] d3d9: implement scissor test --- gfx/common/d3d9_common.h | 6 ++++ gfx/drivers/d3d9.c | 1 + menu/drivers_display/menu_display_d3d9.c | 38 ++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/gfx/common/d3d9_common.h b/gfx/common/d3d9_common.h index 0707e688a3..d99201132e 100644 --- a/gfx/common/d3d9_common.h +++ b/gfx/common/d3d9_common.h @@ -457,6 +457,12 @@ static INLINE void d3d9_set_viewports(LPDIRECT3DDEVICE9 dev, IDirect3DDevice9_SetViewport(dev, (D3DVIEWPORT9*)vp); } +static INLINE void d3d9_set_scissor_rect( + LPDIRECT3DDEVICE9 dev, RECT *rect) +{ + IDirect3DDevice9_SetScissorRect(dev, rect); +} + static INLINE void d3d9_set_render_state( LPDIRECT3DDEVICE9 dev, D3DRENDERSTATETYPE state, DWORD value) { diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9.c index 2d5af2a9d1..891937c482 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9.c @@ -1033,6 +1033,7 @@ static bool d3d9_initialize(d3d9_video_t *d3d, const video_info_t *info) d3d_matrix_transpose(&d3d->mvp, &d3d->mvp_transposed); d3d9_set_render_state(d3d->dev, D3DRS_CULLMODE, D3DCULL_NONE); + d3d9_set_render_state(d3d->dev, D3DRS_SCISSORTESTENABLE, TRUE); return true; } diff --git a/menu/drivers_display/menu_display_d3d9.c b/menu/drivers_display/menu_display_d3d9.c index 37faaa120a..fa7b2a2a01 100644 --- a/menu/drivers_display/menu_display_d3d9.c +++ b/menu/drivers_display/menu_display_d3d9.c @@ -309,6 +309,40 @@ static bool menu_display_d3d9_font_init_first( return true; } +void menu_display_d3d9_scissor_begin(video_frame_info_t *video_info, int x, int y, unsigned width, unsigned height) +{ + RECT rect = {0}; + d3d9_video_t *d3d9 = video_info ? + (d3d9_video_t*)video_info->userdata : NULL; + + rect.left = x; + rect.top = y; + rect.right = width + x; + rect.bottom = height + y; + + if (!d3d9 || !width || !height) + return; + + d3d9_set_scissor_rect(d3d9->dev, &rect); +} + +void menu_display_d3d9_scissor_end(video_frame_info_t *video_info) +{ + RECT rect = {0}; + d3d9_video_t *d3d9 = video_info ? + (d3d9_video_t*)video_info->userdata : NULL; + + if (!d3d9) + return; + + rect.left = d3d9->vp.x; + rect.top = d3d9->vp.y; + rect.right = d3d9->vp.width; + rect.bottom = d3d9->vp.height; + + d3d9_set_scissor_rect(d3d9->dev, &rect); +} + menu_display_ctx_driver_t menu_display_ctx_d3d9 = { menu_display_d3d9_draw, menu_display_d3d9_draw_pipeline, @@ -324,6 +358,6 @@ menu_display_ctx_driver_t menu_display_ctx_d3d9 = { MENU_VIDEO_DRIVER_DIRECT3D9, "d3d9", false, - NULL, - NULL + menu_display_d3d9_scissor_begin, + menu_display_d3d9_scissor_end }; From 90db5e7e27b4b907d7bdf844e8f9ff4aa213439d Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Sun, 27 Jan 2019 11:22:16 -0500 Subject: [PATCH 086/234] Implement in-menu sound effects --- CHANGES.md | 1 + audio/audio_driver.c | 247 +++++++++++++++++- audio/audio_driver.h | 17 +- config.def.h | 7 + configuration.c | 6 +- configuration.h | 4 + file_path_special.c | 68 +++++ file_path_special.h | 2 + frontend/frontend.c | 2 + gfx/video_driver.c | 4 + intl/msg_hash_lbl.h | 12 + intl/msg_hash_us.h | 20 ++ libretro-common/audio/audio_mixer.c | 53 ++-- .../audio/resampler/audio_resampler.c | 43 +++ .../include/audio/audio_resampler.h | 8 + menu/cbs/menu_cbs_cancel.c | 5 + menu/cbs/menu_cbs_deferred_push.c | 8 +- menu/cbs/menu_cbs_info.c | 6 + menu/cbs/menu_cbs_ok.c | 19 ++ menu/cbs/menu_cbs_title.c | 8 +- menu/menu_cbs.h | 1 + menu/menu_displaylist.c | 46 +++- menu/menu_displaylist.h | 1 + menu/menu_driver.c | 6 + menu/menu_setting.c | 132 ++++++++-- msg_hash.h | 6 + record/record_driver.c | 41 +++ record/record_driver.h | 10 + retroarch.c | 41 ++- retroarch.cfg | 7 + tasks/task_audio_mixer.c | 5 + 31 files changed, 775 insertions(+), 61 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 40801c5014..550c51d995 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ - MENU: New "ozone" menu driver. - MENU: Only show CRT SwitchRes if video display server is implemented (Windows/Linux for now) - MENU: User Interface -> Appearance -> 'Menu Font Green/Blue Color' settings now work properly. +- MENU: Add option to enable in-menu sound effects - MENU/QT/WIMP: Allow building with MSVC2017 - MENU/QT/WIMP: Add detailed file browser table - MENU/QT/WIMP: New grid view implementation that is faster and loads thumbnails on-demand diff --git a/audio/audio_driver.c b/audio/audio_driver.c index 9290dc41b1..6814a8adbc 100644 --- a/audio/audio_driver.c +++ b/audio/audio_driver.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include "../config.h" @@ -35,6 +36,7 @@ #include "../gfx/video_driver.h" #include "../record/record_driver.h" #include "../frontend/frontend_driver.h" +#include "../tasks/tasks_internal.h" #include "../command.h" #include "../driver.h" @@ -42,9 +44,17 @@ #include "../retroarch.h" #include "../verbosity.h" #include "../list_special.h" +#include "../file_path_special.h" +#include "../content.h" + +#ifdef HAVE_THREADS +#include +#endif #define AUDIO_BUFFER_FREE_SAMPLES_COUNT (8 * 1024) +#define MENU_SOUND_FORMATS "ogg|mod|xm|s3m|mp3|flac" + /** * db_to_gain: * @db : Decibels. @@ -185,11 +195,34 @@ static const audio_driver_t *current_audio = NULL; static void *audio_driver_context_audio_data = NULL; static bool audio_suspended = false; +static bool audio_is_threaded = false; + +#ifdef HAVE_THREADS +static slock_t* s_audio_driver_lock = NULL; +#endif static void audio_mixer_play_stop_sequential_cb( audio_mixer_sound_t *sound, unsigned reason); static void audio_mixer_play_stop_cb( audio_mixer_sound_t *sound, unsigned reason); +static void audio_mixer_menu_stop_cb( + audio_mixer_sound_t *sound, unsigned reason); + +static void audio_driver_lock(void) +{ +#ifdef HAVE_THREADS + if (s_audio_driver_lock) + slock_lock(s_audio_driver_lock); +#endif +} + +static void audio_driver_unlock(void) +{ +#ifdef HAVE_THREADS + if (s_audio_driver_lock) + slock_unlock(s_audio_driver_lock); +#endif +} enum resampler_quality audio_driver_get_resampler_quality(void) { @@ -447,6 +480,7 @@ static bool audio_driver_init_internal(bool audio_cb_inited) #ifdef HAVE_THREADS if (audio_cb_inited) { + audio_is_threaded = true; RARCH_LOG("[Audio]: Starting threaded audio driver ...\n"); if (!audio_init_thread( ¤t_audio, @@ -465,6 +499,7 @@ static bool audio_driver_init_internal(bool audio_cb_inited) else #endif { + audio_is_threaded = false; audio_driver_context_audio_data = current_audio->init(*settings->arrays.audio_device ? settings->arrays.audio_device : NULL, @@ -507,6 +542,15 @@ static bool audio_driver_init_internal(bool audio_cb_inited) audio_source_ratio_original = audio_source_ratio_current = (double)settings->uints.audio_out_rate / audio_driver_input; +#ifdef HAVE_THREADS + if (s_audio_driver_lock) + slock_free(s_audio_driver_lock); + s_audio_driver_lock = slock_new(); +#endif + + audio_resampler_lock_init(); + audio_resampler_lock(); + if (!retro_resampler_realloc( &audio_driver_resampler_data, &audio_driver_resampler, @@ -519,6 +563,8 @@ static bool audio_driver_init_internal(bool audio_cb_inited) audio_driver_active = false; } + audio_resampler_unlock(); + aud_inp_data = (float*)malloc(max_bufsamples * sizeof(float)); retro_assert(aud_inp_data != NULL); @@ -589,9 +635,13 @@ void audio_driver_set_nonblocking_state(bool enable) audio_driver_context_audio_data, settings->bools.audio_sync ? enable : true); + audio_driver_lock(); + audio_driver_chunk_size = enable ? audio_driver_chunk_nonblock_size : audio_driver_chunk_block_size; + + audio_driver_unlock(); } /** @@ -609,6 +659,7 @@ static void audio_driver_flush(const int16_t *data, size_t samples) bool is_paused = false; bool is_idle = false; bool is_slowmotion = false; + bool is_active = false; const void *output_data = NULL; unsigned output_frames = 0; float audio_volume_gain = !audio_driver_mute_enable ? @@ -617,9 +668,13 @@ static void audio_driver_flush(const int16_t *data, size_t samples) src_data.data_out = NULL; src_data.output_frames = 0; + recording_driver_lock(); + if (recording_data) recording_push_audio(data, samples); + recording_driver_unlock(); + runloop_get_status(&is_paused, &is_idle, &is_slowmotion, &is_perfcnt_enable); @@ -629,9 +684,13 @@ static void audio_driver_flush(const int16_t *data, size_t samples) !audio_driver_output_samples_buf) return; + audio_driver_lock(); + convert_s16_to_float(audio_driver_input_data, data, samples, audio_volume_gain); + audio_driver_unlock(); + src_data.data_in = audio_driver_input_data; src_data.input_frames = samples >> 1; @@ -695,9 +754,15 @@ static void audio_driver_flush(const int16_t *data, size_t samples) src_data.ratio *= settings->floats.slowmotion_ratio; } - audio_driver_resampler->process(audio_driver_resampler_data, &src_data); + audio_driver_lock(); - if (audio_mixer_active) + audio_resampler_lock(); + audio_driver_resampler->process(audio_driver_resampler_data, &src_data); + audio_resampler_unlock(); + + is_active = audio_mixer_active; + + if (is_active) { bool override = audio_driver_mixer_mute_enable ? true : (audio_driver_mixer_volume_gain != 1.0f) ? true : false; @@ -707,6 +772,8 @@ static void audio_driver_flush(const int16_t *data, size_t samples) src_data.output_frames, mixer_gain, override); } + audio_driver_unlock(); + output_data = audio_driver_output_samples_buf; output_frames = (unsigned)src_data.output_frames; @@ -721,9 +788,13 @@ static void audio_driver_flush(const int16_t *data, size_t samples) output_frames *= sizeof(int16_t); } + audio_driver_lock(); + if (current_audio->write(audio_driver_context_audio_data, output_data, output_frames * 2) < 0) audio_driver_active = false; + + audio_driver_unlock(); } /** @@ -735,14 +806,24 @@ static void audio_driver_flush(const int16_t *data, size_t samples) **/ void audio_driver_sample(int16_t left, int16_t right) { + audio_driver_lock(); + if (audio_suspended) + { + audio_driver_unlock(); return; + } audio_driver_output_samples_conv_buf[audio_driver_data_ptr++] = left; audio_driver_output_samples_conv_buf[audio_driver_data_ptr++] = right; if (audio_driver_data_ptr < audio_driver_chunk_size) + { + audio_driver_unlock(); return; + } + + audio_driver_unlock(); audio_driver_flush(audio_driver_output_samples_conv_buf, audio_driver_data_ptr); @@ -753,9 +834,8 @@ void audio_driver_sample(int16_t left, int16_t right) void audio_driver_menu_sample(void) { static int16_t samples_buf[1024] = {0}; - struct retro_system_av_info - *av_info = video_viewport_get_system_av_info(); - const struct retro_system_timing *info = + struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); + const struct retro_system_timing *info = (const struct retro_system_timing*)&av_info->timing; unsigned sample_count = (info->sample_rate / info->fps) * 2; while (sample_count > 1024) @@ -966,10 +1046,13 @@ bool audio_driver_find_driver(void) void audio_driver_deinit_resampler(void) { + audio_resampler_lock(); if (audio_driver_resampler && audio_driver_resampler_data) audio_driver_resampler->free(audio_driver_resampler_data); audio_driver_resampler = NULL; audio_driver_resampler_data = NULL; + audio_resampler_unlock(); + audio_resampler_lock_free(); } bool audio_driver_free_devices_list(void) @@ -1095,6 +1178,28 @@ static void audio_mixer_play_stop_cb( } } +static void audio_mixer_menu_stop_cb( + audio_mixer_sound_t *sound, unsigned reason) +{ + int idx = audio_mixer_find_index(sound); + + switch (reason) + { + case AUDIO_MIXER_SOUND_FINISHED: + if (idx >= 0) + { + unsigned i = (unsigned)idx; + audio_mixer_streams[i].state = AUDIO_STREAM_STATE_STOPPED; + audio_mixer_streams[i].volume = 0.0f; + } + break; + case AUDIO_MIXER_SOUND_STOPPED: + break; + case AUDIO_MIXER_SOUND_REPEATED: + break; + } +} + static void audio_mixer_play_stop_sequential_cb( audio_mixer_sound_t *sound, unsigned reason) { @@ -1113,9 +1218,9 @@ static void audio_mixer_play_stop_sequential_cb( free(audio_mixer_streams[i].name); if (i < AUDIO_MIXER_MAX_STREAMS) - audio_mixer_streams[i].type = AUDIO_STREAM_TYPE_USER; + audio_mixer_streams[i].stream_type = AUDIO_STREAM_TYPE_USER; else - audio_mixer_streams[i].type = AUDIO_STREAM_TYPE_SYSTEM; + audio_mixer_streams[i].stream_type = AUDIO_STREAM_TYPE_SYSTEM; audio_mixer_streams[i].name = NULL; audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE; @@ -1243,17 +1348,22 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params) break; } + audio_driver_lock(); + audio_mixer_active = true; - audio_mixer_streams[free_slot].name = !string_is_empty(params->basename) ? strdup(params->basename) : NULL; + audio_mixer_streams[free_slot].name = !string_is_empty(params->basename) ? strdup(params->basename) : NULL; audio_mixer_streams[free_slot].buf = buf; audio_mixer_streams[free_slot].handle = handle; audio_mixer_streams[free_slot].voice = voice; - audio_mixer_streams[free_slot].type = params->stream_type; + audio_mixer_streams[free_slot].stream_type = params->stream_type; + audio_mixer_streams[free_slot].type = params->type; audio_mixer_streams[free_slot].state = params->state; audio_mixer_streams[free_slot].volume = params->volume; audio_mixer_streams[free_slot].stop_cb = stop_cb; + audio_driver_unlock(); + return true; } @@ -1291,12 +1401,128 @@ static void audio_driver_mixer_play_stream_internal(unsigned i, unsigned type) audio_mixer_streams[i].state = (enum audio_mixer_state)type; } +static void audio_driver_load_menu_bgm_callback(void *task_data, void *user_data, const char *error) +{ + bool contentless = false; + bool is_inited = false; + + content_get_status(&contentless, &is_inited); + + if (!is_inited) + audio_driver_mixer_play_menu_sound_looped(AUDIO_MIXER_SYSTEM_SLOT_BGM); +} + +void audio_driver_load_menu_sounds(void) +{ + settings_t *settings = config_get_ptr(); + char *sounds_path = NULL; + char *sounds_fallback_path = NULL; + const char *path_ok = NULL; + const char *path_cancel = NULL; + const char *path_notice = NULL; + const char *path_bgm = NULL; + struct string_list *list = NULL; + struct string_list *list_fallback = NULL; + int i = 0; + + sounds_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + sounds_fallback_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + sounds_path[0] = sounds_fallback_path[0] = '\0'; + + fill_pathname_join( + sounds_fallback_path, + settings->paths.directory_assets, + "sounds", + PATH_MAX_LENGTH * sizeof(char) + ); + + fill_pathname_application_special(sounds_path, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_SOUNDS); + + list = dir_list_new(sounds_path, MENU_SOUND_FORMATS, false, false, false, false); + list_fallback = dir_list_new(sounds_fallback_path, MENU_SOUND_FORMATS, false, false, false, false); + + if (!list) + { + list = list_fallback; + list_fallback = NULL; + } + + if (!list || list->size == 0) + goto end; + + if (list_fallback && list_fallback->size > 0) + { + for (i = 0; i < list_fallback->size; i++) + { + if (list->size == 0 || !string_list_find_elem(list, list_fallback->elems[i].data)) + { + union string_list_elem_attr attr = {0}; + string_list_append(list, list_fallback->elems[i].data, attr); + } + } + } + + for (i = 0; i < list->size; i++) + { + const char *path = list->elems[i].data; + const char *ext = path_get_extension(path); + char basename_noext[PATH_MAX_LENGTH]; + + basename_noext[0] = '\0'; + + fill_pathname_base_noext(basename_noext, path, sizeof(basename_noext)); + + if (audio_driver_mixer_extension_supported(ext)) + { + if (string_is_equal_noncase(basename_noext, "ok")) + path_ok = path; + if (string_is_equal_noncase(basename_noext, "cancel")) + path_cancel = path; + if (string_is_equal_noncase(basename_noext, "notice")) + path_notice = path; + if (string_is_equal_noncase(basename_noext, "bgm")) + path_bgm = path; + } + } + + if (path_ok && settings->bools.audio_enable_menu_ok) + task_push_audio_mixer_load(path_ok, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_OK); + if (path_cancel && settings->bools.audio_enable_menu_cancel) + task_push_audio_mixer_load(path_cancel, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_CANCEL); + if (path_notice && settings->bools.audio_enable_menu_notice) + task_push_audio_mixer_load(path_notice, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_NOTICE); + if (path_bgm && settings->bools.audio_enable_menu_bgm) + task_push_audio_mixer_load(path_bgm, audio_driver_load_menu_bgm_callback, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_BGM); + +end: + if (list) + string_list_free(list); + if (list_fallback) + string_list_free(list_fallback); + if (sounds_path) + free(sounds_path); + if (sounds_fallback_path) + free(sounds_fallback_path); +} + void audio_driver_mixer_play_stream(unsigned i) { audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_cb; audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING); } +void audio_driver_mixer_play_menu_sound_looped(unsigned i) +{ + audio_mixer_streams[i].stop_cb = audio_mixer_menu_stop_cb; + audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING_LOOPED); +} + +void audio_driver_mixer_play_menu_sound(unsigned i) +{ + audio_mixer_streams[i].stop_cb = audio_mixer_menu_stop_cb; + audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING); +} + void audio_driver_mixer_play_stream_looped(unsigned i) { audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_cb; @@ -1421,6 +1647,9 @@ bool audio_driver_deinit(void) { audio_driver_mixer_deinit(); audio_driver_free_devices_list(); + slock_free(s_audio_driver_lock); + s_audio_driver_lock = NULL; + if (!audio_driver_deinit_internal()) return false; return true; diff --git a/audio/audio_driver.h b/audio/audio_driver.h index 2e1f59e344..d6649e6c4b 100644 --- a/audio/audio_driver.h +++ b/audio/audio_driver.h @@ -37,7 +37,16 @@ RETRO_BEGIN_DECLS #define AUDIO_MIXER_MAX_STREAMS 16 -#define AUDIO_MIXER_MAX_SYSTEM_STREAMS (AUDIO_MIXER_MAX_STREAMS+4) +#define AUDIO_MIXER_MAX_SYSTEM_STREAMS (AUDIO_MIXER_MAX_STREAMS + 4) + +/* do not define more than (MAX_SYSTEM_STREAMS - MAX_STREAMS) */ +enum audio_mixer_system_slot +{ + AUDIO_MIXER_SYSTEM_SLOT_OK = AUDIO_MIXER_MAX_STREAMS, + AUDIO_MIXER_SYSTEM_SLOT_CANCEL, + AUDIO_MIXER_SYSTEM_SLOT_NOTICE, + AUDIO_MIXER_SYSTEM_SLOT_BGM +}; enum audio_action { @@ -315,6 +324,10 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params); void audio_driver_mixer_play_stream(unsigned i); +void audio_driver_mixer_play_menu_sound(unsigned i); + +void audio_driver_mixer_play_menu_sound_looped(unsigned i); + void audio_driver_mixer_play_stream_sequential(unsigned i); void audio_driver_mixer_play_stream_looped(unsigned i); @@ -335,6 +348,8 @@ const char *audio_driver_mixer_get_stream_name(unsigned i); bool compute_audio_buffer_statistics(audio_statistics_t *stats); +void audio_driver_load_menu_sounds(void); + extern audio_driver_t audio_rsound; extern audio_driver_t audio_audioio; extern audio_driver_t audio_oss; diff --git a/config.def.h b/config.def.h index 2ed6bfb5ab..167c78cf16 100644 --- a/config.def.h +++ b/config.def.h @@ -508,6 +508,13 @@ static const bool video_3ds_lcd_bottom = true; /* Will enable audio or not. */ static const bool audio_enable = true; +/* Enable menu audio sounds. */ +static const bool audio_enable_menu = false; +static const bool audio_enable_menu_ok = false; +static const bool audio_enable_menu_cancel = false; +static const bool audio_enable_menu_notice = false; +static const bool audio_enable_menu_bgm = false; + /* Output samplerate. */ #ifdef GEKKO static const unsigned out_rate = 32000; diff --git a/configuration.c b/configuration.c index 45e69835f2..ef846ff1e8 100644 --- a/configuration.c +++ b/configuration.c @@ -1395,7 +1395,11 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("keyboard_gamepad_enable", &settings->bools.input_keyboard_gamepad_enable, true, true, false); SETTING_BOOL("core_set_supports_no_game_enable", &settings->bools.set_supports_no_game_enable, true, true, false); SETTING_BOOL("audio_enable", &settings->bools.audio_enable, true, audio_enable, false); - SETTING_BOOL("audio_enable_menu", &settings->bools.audio_enable_menu, true, false, false); + SETTING_BOOL("audio_enable_menu", &settings->bools.audio_enable_menu, true, audio_enable_menu, false); + SETTING_BOOL("audio_enable_menu_ok", &settings->bools.audio_enable_menu_ok, true, audio_enable_menu_ok, false); + SETTING_BOOL("audio_enable_menu_cancel", &settings->bools.audio_enable_menu_cancel, true, audio_enable_menu_cancel, false); + SETTING_BOOL("audio_enable_menu_notice", &settings->bools.audio_enable_menu_notice, true, audio_enable_menu_notice, false); + SETTING_BOOL("audio_enable_menu_bgm", &settings->bools.audio_enable_menu_bgm, true, audio_enable_menu_bgm, false); SETTING_BOOL("audio_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE), true, false, false); SETTING_BOOL("audio_mixer_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MIXER_MUTE_ENABLE), true, false, false); SETTING_BOOL("location_allow", &settings->bools.location_allow, true, false, false); diff --git a/configuration.h b/configuration.h index cbe6f7888f..2763078bd4 100644 --- a/configuration.h +++ b/configuration.h @@ -110,6 +110,10 @@ typedef struct settings /* Audio */ bool audio_enable; bool audio_enable_menu; + bool audio_enable_menu_ok; + bool audio_enable_menu_cancel; + bool audio_enable_menu_notice; + bool audio_enable_menu_bgm; bool audio_sync; bool audio_rate_control; bool audio_wasapi_exclusive_mode; diff --git a/file_path_special.c b/file_path_special.c index 70769b97da..ca106bf89a 100644 --- a/file_path_special.c +++ b/file_path_special.c @@ -51,6 +51,10 @@ #include #include +#ifdef HAVE_MENU +#include +#endif + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -238,6 +242,70 @@ void fill_pathname_application_special(char *s, free(s1); } } +#endif + break; + case APPLICATION_SPECIAL_DIRECTORY_ASSETS_SOUNDS: + { +#ifdef HAVE_MENU + settings_t *settings = config_get_ptr(); + const char *menu_ident = settings->arrays.menu_driver; + char *s1 = (char*)calloc(1, PATH_MAX_LENGTH * sizeof(char)); + + if (string_is_equal(menu_ident, "xmb")) + { + fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB); + + if (!string_is_empty(s1)) + strlcat(s1, "/sounds", PATH_MAX_LENGTH * sizeof(char)); + } + else if (string_is_equal(menu_ident, "glui")) + { + fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI); + + if (!string_is_empty(s1)) + strlcat(s1, "/sounds", PATH_MAX_LENGTH * sizeof(char)); + } + else if (string_is_equal(menu_ident, "ozone")) + { + fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_OZONE); + + if (!string_is_empty(s1)) + strlcat(s1, "/sounds", PATH_MAX_LENGTH * sizeof(char)); + } + + if (string_is_empty(s1)) + { + fill_pathname_join( + s1, + settings->paths.directory_assets, + "sounds", + PATH_MAX_LENGTH * sizeof(char) + ); + } + + strlcpy(s, s1, len); + free(s1); +#endif + } + + break; + case APPLICATION_SPECIAL_DIRECTORY_ASSETS_OZONE: +#ifdef HAVE_OZONE + { + char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + settings_t *settings = config_get_ptr(); + + s1[0] = '\0'; + + fill_pathname_join( + s1, + settings->paths.directory_assets, + "ozone", + PATH_MAX_LENGTH * sizeof(char) + ); + strlcpy(s, s1, len); + free(s1); + } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB: diff --git a/file_path_special.h b/file_path_special.h index d98a6b3971..ec9c5c27ee 100644 --- a/file_path_special.h +++ b/file_path_special.h @@ -111,6 +111,8 @@ enum application_special_type APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH, APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_FONT, APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_ICONS, + APPLICATION_SPECIAL_DIRECTORY_ASSETS_OZONE, + APPLICATION_SPECIAL_DIRECTORY_ASSETS_SOUNDS, APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES, APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS }; diff --git a/frontend/frontend.c b/frontend/frontend.c index 3c954f20f1..effe00f8b4 100644 --- a/frontend/frontend.c +++ b/frontend/frontend.c @@ -38,6 +38,7 @@ #include "../paths.h" #include "../retroarch.h" #include "../verbosity.h" +#include "../record/record_driver.h" #if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) #include @@ -91,6 +92,7 @@ void main_exit(void *args) driver_ctl(RARCH_DRIVER_CTL_DEINIT, NULL); ui_companion_driver_free(); frontend_driver_free(); + recording_driver_lock_free(); #if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) CoUninitialize(); diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 3d29a3c182..3e05c64d70 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -1422,6 +1422,8 @@ bool video_driver_cached_frame(void) { void *recording = recording_driver_get_data_ptr(); + recording_driver_lock(); + /* Cannot allow recording when pushing duped frames. */ recording_data = NULL; @@ -1433,6 +1435,8 @@ bool video_driver_cached_frame(void) recording_data = recording; + recording_driver_unlock(); + return true; } diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 0dcb5bb540..7343eeded8 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -305,6 +305,8 @@ MSG_HASH(MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST, "deferred_audio_settings_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_AUDIO_MIXER_SETTINGS_LIST, "deferred_audio_mixer_settings_list") +MSG_HASH(MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST, + "deferred_menu_sounds_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST, "deferred_configuration_settings_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_LIST, @@ -1609,6 +1611,8 @@ MSG_HASH(MENU_ENUM_LABEL_AUDIO_ENABLE_MENU, "audio_enable_menu") MSG_HASH(MENU_ENUM_LABEL_AUDIO_MIXER_SETTINGS, "audio_mixer_settings") +MSG_HASH(MENU_ENUM_LABEL_MENU_SOUNDS, + "menu_sounds") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST, "deferred_mixer_stream_settings_list") MSG_HASH(MENU_ENUM_LABEL_QUICK_MENU_OVERRIDE_OPTIONS, @@ -1769,3 +1773,11 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_3DS_LCD_BOTTOM, "video_3ds_lcd_bottom") MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT, "playlist_use_old_format") +MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_OK, + "menu_sound_ok") +MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_CANCEL, + "menu_sound_cancel") +MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_NOTICE, + "menu_sound_notice") +MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_BGM, + "menu_sound_bgm") diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 1632690f8a..073cdefb27 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -8112,3 +8112,23 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_PLAYLIST_USE_OLD_FORMAT, "Save playlists using old format" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_SOUNDS, + "Menu Sounds" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_SOUND_OK, + "Enable OK sound" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_SOUND_CANCEL, + "Enable cancel sound" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_SOUND_NOTICE, + "Enable notice sound" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_SOUND_BGM, + "Enable BGM sound" + ) diff --git a/libretro-common/audio/audio_mixer.c b/libretro-common/audio/audio_mixer.c index f0022f957a..03e1a4eabf 100644 --- a/libretro-common/audio/audio_mixer.c +++ b/libretro-common/audio/audio_mixer.c @@ -188,7 +188,7 @@ struct audio_mixer_voice } types; }; -static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {0}; +static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {{0}}; static unsigned s_rate = 0; #ifdef HAVE_THREADS @@ -318,6 +318,8 @@ void audio_mixer_init(unsigned rate) s_voices[i].type = AUDIO_MIXER_TYPE_NONE; #ifdef HAVE_THREADS + if (s_locker) + slock_free(s_locker); s_locker = slock_new(); #endif } @@ -551,17 +553,18 @@ static bool audio_mixer_play_ogg( if (!ogg_buffer) { - resamp->free(resampler_data); + if (resamp && resampler_data) + resamp->free(resampler_data); goto error; } /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */ - if (voice->types.ogg.buffer) - memalign_free(voice->types.ogg.buffer); if (voice->types.ogg.stream) stb_vorbis_close(voice->types.ogg.stream); if (voice->types.ogg.resampler && voice->types.ogg.resampler_data) voice->types.ogg.resampler->free(voice->types.ogg.resampler_data); + if (voice->types.ogg.buffer) + memalign_free(voice->types.ogg.buffer); voice->types.ogg.resampler = resamp; voice->types.ogg.resampler_data = resampler_data; @@ -635,10 +638,11 @@ static bool audio_mixer_play_mod( goto error; } - if (voice->types.mod.buffer) - memalign_free(voice->types.mod.buffer); + /* FIXME: stopping and then starting a mod stream will crash here in dispose_replay (ASAN says struct replay is misaligned?) */ if (voice->types.mod.stream) dispose_replay(voice->types.mod.stream); + if (voice->types.mod.buffer) + memalign_free(voice->types.mod.buffer); voice->types.mod.buffer = (int*)mod_buffer; voice->types.mod.buf_samples = buf_samples; @@ -696,12 +700,12 @@ static bool audio_mixer_play_flac( goto error; } - if (voice->types.flac.buffer) - memalign_free(voice->types.flac.buffer); if (voice->types.flac.stream) drflac_close(voice->types.flac.stream); if (voice->types.flac.resampler && voice->types.flac.resampler_data) voice->types.flac.resampler->free(voice->types.flac.resampler_data); + if (voice->types.flac.buffer) + memalign_free(voice->types.flac.buffer); voice->types.flac.resampler = resamp; voice->types.flac.resampler_data = resampler_data; @@ -761,15 +765,16 @@ static bool audio_mixer_play_mp3( if (!mp3_buffer) { - resamp->free(resampler_data); + if (resamp && resampler_data) + resamp->free(resampler_data); goto error; } /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */ - if (voice->types.mp3.buffer) - memalign_free(voice->types.mp3.buffer); if (voice->types.mp3.resampler && voice->types.mp3.resampler_data) voice->types.mp3.resampler->free(voice->types.mp3.resampler_data); + if (voice->types.mp3.buffer) + memalign_free(voice->types.mp3.buffer); voice->types.mp3.resampler = resamp; voice->types.mp3.resampler_data = resampler_data; @@ -801,6 +806,8 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat, slock_lock(s_locker); #endif + audio_resampler_lock(); + for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++) { if (voice->type != AUDIO_MIXER_TYPE_NONE) @@ -849,6 +856,8 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat, else voice = NULL; + audio_resampler_unlock(); + #ifdef HAVE_THREADS slock_unlock(s_locker); #endif @@ -863,13 +872,13 @@ void audio_mixer_stop(audio_mixer_voice_t* voice) if (voice) { - stop_cb = voice->stop_cb; - sound = voice->sound; - #ifdef HAVE_THREADS slock_lock(s_locker); #endif + stop_cb = voice->stop_cb; + sound = voice->sound; + voice->type = AUDIO_MIXER_TYPE_NONE; #ifdef HAVE_THREADS @@ -971,7 +980,9 @@ again: info.ratio = voice->types.ogg.ratio; if (voice->types.ogg.resampler) + { voice->types.ogg.resampler->process(voice->types.ogg.resampler_data, &info); + } else memcpy(voice->types.ogg.buffer, temp_buffer, temp_samples * sizeof(float)); voice->types.ogg.position = 0; @@ -1118,7 +1129,9 @@ again: info.ratio = voice->types.flac.ratio; if (voice->types.flac.resampler) + { voice->types.flac.resampler->process(voice->types.flac.resampler_data, &info); + } else memcpy(voice->types.flac.buffer, temp_buffer, temp_samples * sizeof(float)); voice->types.flac.position = 0; @@ -1231,6 +1244,8 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo slock_lock(s_locker); #endif + audio_resampler_lock(); + for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++) { float volume = (override) ? volume_override : voice->volume; @@ -1265,10 +1280,6 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo } } -#ifdef HAVE_THREADS - slock_unlock(s_locker); -#endif - for (j = 0, sample = buffer; j < num_frames; j++, sample++) { if (*sample < -1.0f) @@ -1276,6 +1287,12 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo else if (*sample > 1.0f) *sample = 1.0f; } + + audio_resampler_unlock(); + +#ifdef HAVE_THREADS + slock_unlock(s_locker); +#endif } float audio_mixer_voice_get_volume(audio_mixer_voice_t *voice) diff --git a/libretro-common/audio/resampler/audio_resampler.c b/libretro-common/audio/resampler/audio_resampler.c index 8d27f06932..dc3df93d3a 100644 --- a/libretro-common/audio/resampler/audio_resampler.c +++ b/libretro-common/audio/resampler/audio_resampler.c @@ -28,6 +28,14 @@ #include