diff --git a/.gitignore b/.gitignore
index 89426b7bff..bc65d666b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,10 @@ menu/driverspzarch.c
.pc
/media/shaders_glsl/
/obj-w32/
+.cproject
+.settings
+libretro-super
+run.sh
# Wii U
*.depend
diff --git a/.project b/.project
index 871dee54b0..b5f91e201f 100644
--- a/.project
+++ b/.project
@@ -5,7 +5,23 @@
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
diff --git a/.travis.yml b/.travis.yml
index e950b2c19b..5fa1900042 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,7 +10,7 @@ matrix:
- g++-mingw-w64-i686
- mingw-w64-i686-dev
script:
- - CROSS_COMPILE=i686-w64-mingw32- ./configure --disable-d3d8 --disable-d3d9 --disable-d3d10 --disable-d3d11 --disable-d3d12 && make HAVE_ZLIB=1 HAVE_BUILTINZLIB=1 HAVE_RPNG=1
+ - CROSS_COMPILE=i686-w64-mingw32- CFLAGS="-D_WIN32_WINNT=0x0501" ./configure --disable-d3d8 --disable-d3d9 --disable-d3d10 --disable-d3d11 --disable-d3d12 && make HAVE_ZLIB=1 HAVE_BUILTINZLIB=1 HAVE_RPNG=1
- compiler: mingw-x64
addons:
apt:
@@ -18,7 +18,7 @@ matrix:
- g++-mingw-w64-x86-64
- mingw-w64-x86-64-dev
script:
- - CROSS_COMPILE=x86_64-w64-mingw32- ./configure --disable-d3d8 --disable-d3d9 --disable-d3d10 --disable-d3d11 --disable-d3d12 && make HAVE_ZLIB=1 HAVE_BUILTINZLIB=1 HAVE_RPNG=1
+ - CROSS_COMPILE=x86_64-w64-mingw32- CFLAGS="-D_WIN32_WINNT=0x0501" ./configure --disable-d3d8 --disable-d3d9 --disable-d3d10 --disable-d3d11 --disable-d3d12 && make HAVE_ZLIB=1 HAVE_BUILTINZLIB=1 HAVE_RPNG=1
- compiler: gcc
- compiler: clang
addons:
@@ -64,3 +64,5 @@ addons:
build_command_prepend: "./configure; make clean"
build_command: "make"
branch_pattern: coverity_scan
+notifications:
+ email: false
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 561af49173..2e6b11d97a 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -22,10 +22,7 @@
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
- ],
- "compilerPath": "/usr/bin/clang",
- "cStandard": "c11",
- "cppStandard": "c++17"
+ ]
},
{
"name": "Linux",
@@ -70,7 +67,9 @@
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
- }
+ },
+ "cStandard": "c11",
+ "cppStandard": "c++17"
},
{
"name": "msys2-mingw32",
@@ -125,5 +124,5 @@
}
}
],
- "version": 3
+ "version": 4
}
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6e1f69631a..e7552247cc 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -5,44 +5,41 @@
"version": "0.2.0",
"configurations": [
{
- "name": "msys2-mingw64 debug",
+ "name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/retroarch.exe",
- "args": [],
+ "args": ["-v"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
- "externalConsole": true,
+ "externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe",
"setupCommands": [
- {
- "description": "Enable pretty-printing for gdb",
- "text": "-enable-pretty-printing",
- "ignoreFailures": true
- }
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ }
]
},
- {
- "name": "msys2-mingw32 debug",
+ {
+ "name": "(gdb) Attach",
"type": "cppdbg",
- "request": "launch",
+ "request": "attach",
"program": "${workspaceFolder}/retroarch.exe",
- "args": [],
- "stopAtEntry": false,
- "cwd": "${workspaceFolder}",
- "environment": [],
- "externalConsole": true,
+ "processId": "${command:pickProcess}",
"MIMode": "gdb",
- "miDebuggerPath": "c:\\msys64\\mingw32\\bin\\gdb.exe",
+ "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe",
"setupCommands": [
- {
- "description": "Enable pretty-printing for gdb",
- "text": "-enable-pretty-printing",
- "ignoreFailures": true
- }
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ }
]
- }
+ },
+
]
}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index e90ca77e4a..345f8a0f8e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -12,6 +12,8 @@
"files.associations": {
"frontend_driver.h": "c",
"*.in": "c",
- "*.rh": "c"
+ "*.rh": "c",
+ "array": "c",
},
+ "C_Cpp.dimInactiveRegions": false,
}
\ No newline at end of file
diff --git a/CHANGES.md b/CHANGES.md
index 400723e915..c9ed1b06de 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,28 +1,114 @@
-# 1.7.2 (future)
+# 1.7.4 (future)
+- ANDROID: Add sustained performance mode, can be turned on/off in Power Management settings menu.
+- ANDROID: Powerstate/battery level support.
+- CHEEVOS: Fix crash when scrolling Achievement List while Unofficial Achievements enabled (#6732).
+- CHEEVOS: Added hitcounts support for PauseIf/ResetIf (#6817).
+- COMMON: Automatically hide "Configuration Override options" in Quick Menu.
+- COMMON: Small Bugfix to not trigger savestate code when pressing Reset.
+- COMMON: Added libsixel video driver.
+- EMSCRIPTEN: Fix Game Focus Toggle.
+- HID/OSX: Fix to set hid device registration deterministic (#6497), to address issue #6640 re-adding dynamic device registration.
+- LOCALIZATION: Update Italian translation.
+- LOCALIZATION: Update Japanese translation.
+- LOCALIZATION: Update Polish translation.
+- LOCALIZATION: Update Portuguese / Brazilian translation.
+- LOCALIZATION: Update Russian translation.
+- LOCALIZATION: Update Spanish translation.
+- MIDI: Add MIDI support to the libretro API. Dosbox is the first proof of concept core implementing libretro MIDI.
+- MIDI: Add a Windows driver for MIDI, based on winmm.
+- MENU/QT/WIMP: QT QSlider styling for Dark Theme.
+- MENU/QT/WIMP: Remove button ghostly inside highlighting.
+- METAL: Initial work-in-progress video driver for Metal. macOS-only right now, and currently requires macOS 10.13.
+- METAL: Supports XMB/MaterialUI, has a menu display driver. Has a font rendering driver.
+- METAL/SLANG: Slang shaders should be compatible with Metal video driver.
+- QNX: Fix Game Focus Toggle.
+- PS3: Add audio mixer support for FLAC and MP3.
+- PSP: Use proper button labels, fix inverted R-Stick Y axis.
+- REMAPS: Fix the way offsets are calculated for keyboard remapping.
+- RUNAHEAD: Fix full-screen mode change breaking Secondary Core's environment variables.
+- VITA: Use proper button labels, fix inverted R-Stick Y axis.
+- VULKAN: Fix two validation errors.
+- VULKAN: Try to avoid creating swapchains redundantly. Should fix black screen and having to alt tab out of window again to get display working on Nvidia GPUs (Windows).
+- VULKAN/OSX: Initial MoltenVK support. Not enabled yet, several MoltenVK bugs should be fixed first before we can have it fully working.
+- WINDOWS/DINPUT: Add rumble support.
+- WINDOWS/DINPUT: Fix Game Focus Toggle.
+- WINDOWS/RAWINPUT: Fix Game Focus Toggle.
+- X11: Fix Game Focus Toggle.
+- WII: Change deflicker setting to work in 480p or higher, and always enables vfilter so that the user can easily change brightness.
+- WIIU: Fix out-of-bounds rendering bug
+- WIIU: Implement UDP broadcast network logging on Wii U.
+- WIIU: Audio should no longer clip.
+
+# 1.7.3
+- AUDIO: Audio mixer supports FLAC/MP3 file types now!
+- COMMON: Fixed bug 'crashing in cores that don't range check retro_set_controller_type'. Some people were having crashes when device is set to RETRO_DEVICE_NONE and the cores don't check the number of ports, in VBAM's case it was overflowing and crashing. QuickNES was crashing too.
+- COMMON: Fixed buffer overflow in url encoding (affecting MSVC2010/2013).
+- COMMON: (QuickMenu) Added Configuration Override submenu.
+- HID: Merge new HID subsystem.
+- HID: Fix WaveBird support for the Wii U GCA.
+- HID/OSX: Fix regression with IODHIDManager - gamepads which are connected later would not be autoconfigured.
+- LOCALIZATION: Update Italian translation.
+- LOCALIZATION: Update Japanese translation.
+- LOCALIZATION: Update Portuguese translation.
+- MENU: New WIMP Qt GUI!
+- MENU: Audio mixer now works in the menu without any cores loaded. You have to enable the setting 'Enable menu audio' for this to work.
+- REMAPPING/OVERLAYS: Fix regression - overlays could no longer be remapped.
+- SCANNER: Add Wii Backup File WBFS support.
+- X11: CRT SwitchRes support for X11/Linux.
+
+# 1.7.2
- ANDROID/OPENSL: Prevent crashes when setting audio latency too low (buffer count can never be lower than 2 now).
+- CRT: Added CRT SwitchRes.
+- COMMON: Hide the 'Core delete' option if the 'Core updater' is also hidden.
- COMMON: Add way to reset core association for playlist entry.
- COMMON: Fix invalid long command line options causing infinite loop on Windows
- COMMON: Add OSD statistics for video/audio/core.
- COMMON: Added runahead system; allows you to drive down latency even further.
+- COMMON: Fix buggy behavior that could happen with ZIP file reading on some platforms as a result of not initializing struct.
- CHEEVOS: Support Atari 2600, Virtual Boy, and Arcade (only Neo Geo, CPS-1, CPS-2 and CPS-3 and only with fbalpha core).
- CHEEVOS: Add option to automatically take a screenshot when an achievement is triggered.
-- D3D11: Experimental hardware renderer. Allows for libretro cores to use D3D11 for hardware rendering.
-- D3D11/D3D12: Fix crashes with completely black or white thumbnail textures in XMB.
+- CHEEVOS: Fixed incompatibilities with Neo Geo Pocket achievement sets.
+- CHEEVOS: Store only login token, not password.
+- D3D10: Added D3D10 driver to release build. Has working shaders (Slang), overlay, and menu display driver support. Should be on par capabilities wise
+with D3D11 driver except for there being no hardware rendering right now.
+- D3D11: Experimental hardware renderer. Allows for libretro cores to use D3D11 for hardware rendering. First core to use this is PPSSPP.
+- D3D11: Increase backwards compatibility, shaders compile with Shader Model 4.0 now, added support for more feature levels.
+- D3D10/D3D11/D3D12: Fix crashes with completely black or white thumbnail textures in XMB.
+- GUI: Support disabling window decorations on Windows and Linux.
- LIBRETRO: Addition - Functions to enable and disable audio and video, and an environment function to query status of audio and video enables.
- LOCALIZATION: Update Italian translation.
- LOCALIZATION: Update Polish translation.
-- MENU: Disable XMB shadow icons by default for PowerPC and ARM for performance reasons.
+- MENU: Add Rewind/Latency/Overlay settings to Quick Menu, add options to show/hide them (User Interface -> Views -> Quick Menu)
+- MENU/RGUI: Only show Menu Linear Filter for RGUI and only show it for
+video drivers that implement it (D3D8/9/10/11/12/GL)
+- MENU/RGUI: Add User Interface -> Appearance options.
+- MENU/RGUI: D3D8/D3D9: Hookup Menu Linear Filter
+- MENU/XMB: Disable XMB shadow icons by default for PowerPC and ARM for performance reasons.
- MENU/XMB: Left/right thumbnails are now automatically scaled according to layout.
- MENU/XMB: Add Left Thumbnails (additional to the right).
- MENU/XMB: Fixed left/right tab regression.
- MENU/XMB: Fix scaling of tall images that were cut on bottom previously.
- MENU/XMB: Menu scale factor setting now changes texts length, image scaling and margins.
- MENU/XMB: Mouse cursor scales correctly now.
+- MENU/XMB: Add toggle to show/hide Playlist tabs.
+- MENU/XMB: Add menu layout - can switch between Desktop, Handheld and Auto.
+- MENU/XMB: Don't load menu pipeline shaders unless XMB is selected (D3D10/D3D11/D3D12/GL/Vulkan)
+- MENU/VIDEO: Only show black frame insertion for the video drivers/context drivers
+that support it (so far this includes - D3D8/D3D9, OpenGL, Vulkan)
+- MENU/VIDEO: Only show max swapchain images if supported by video driver and/or context driver (so far this includes - DRM EGL context driver, VideoCore EGL context driver, Vulkan)
- MENU/MaterialUI: Automatic DPI Scaling should be much improved now, now scales as expected at 1440p and 4K resolutions.
- MENU/MaterialUI: Fix wrong calculation of an entry height causing long playlists to end up outside of screen range. This also could cause crashes on low DPI screens.
- IOS: Fixed crash when opening downloaded roms from Safari or using the "Open in.." functionality. Added the compiler flag to support keyboard remapping to controls.
- IOS: Fixed buffer overlap that caused a crash while trying to download GLSL shaders from the buildbot.
- PS3: fix URLS
+- REMAPS: Mapping keyboard keys from more than one gamepad (works with dosbox)
+- REMAPS: Mapping more than one button to the same action
+- REMAPS: Unmapping buttons
+- REMAPS: Unmapping analogs
+- REMAPS: Mapping a button to trigger an analog response (tested with mupen, can run on SM64 with the d-pad now, triggers a full analog tilt)
+- REMAPS: Mapping an analog to another analog (having more than one analog mapped to the same output causes issues)
+- REMAPS: Mapping an analog to produce a button response
+- SCANNER: Should be able to scan dual-layer Wii disc images now, filestream code now supports files larger than 4GB.
- SHADERS/SLANG: Slang shaders should work again on Android version and MSVC versions (basically all the Griffin-based versions).
- SHADERS: If GL context is GLES2/3/Core context, Cg shaders are unavailable. Applies to shader list too.
- SHADERS: Hide cg/glsl shaders from being able to be selected if D3D8/9/10/11/Vulkan video drivers are selected.
@@ -36,7 +122,7 @@
- WINDOWS/MSVC 2003/2005/2010/2013/2015/2017: Add Cheevos support.
- VITA: Bugfix for 'PS Vita takes many time to start to accept input' issue.
- X11: Allow compositor disabling on X11 fullscreen through _NET_WM_BYPASS_COMPOSITOR
-- X11: Prioritize _NET_WM_STATE_FULLSCREEN in true fullscreen mode
+- X11: Prioritize _NET_WM_STATE_FULLSCREEN_ in true fullscreen mode
- WIIU: Fix OOB read/write in keyboard driver.
# 1.7.1
diff --git a/Makefile b/Makefile
index a9e72cb4b7..7e66bdb181 100644
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ endif
include Makefile.common
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang"),1)
- DEFINES += -Wno-invalid-source-encoding
+ DEFINES += -Wno-invalid-source-encoding -Wno-incompatible-ms-struct
endif
ifeq ($(shell $(CC) -v 2>&1 | grep -c "tcc"),1)
@@ -92,21 +92,22 @@ APPEND_CFLAGS := $(CFLAGS)
CXXFLAGS += $(APPEND_CFLAGS) -std=c++11 -D__STDC_CONSTANT_MACROS
OBJCFLAGS := $(CFLAGS) -D__STDC_CONSTANT_MACROS
-ifeq ($(CXX_BUILD), 1)
- LINK = $(CXX)
- CFLAGS := $(CXXFLAGS) -xc++
- CFLAGS += -DCXX_BUILD
- CXXFLAGS += -DCXX_BUILD
-else
- ifeq ($(NEED_CXX_LINKER),1)
+ifeq ($(HAVE_CXX), 1)
+ ifeq ($(CXX_BUILD), 1)
+ LINK = $(CXX)
+ CFLAGS := $(CXXFLAGS) -xc++
+ CFLAGS += -DCXX_BUILD
+ CXXFLAGS += -DCXX_BUILD
+ else ifeq ($(NEED_CXX_LINKER),1)
LINK = $(CXX)
- else ifeq ($(findstring Win32,$(OS)),)
- LINK = $(CC)
else
- # directx-related code is c++
- LINK = $(CXX)
+ LINK = $(CC)
endif
+else
+ LINK = $(CC)
+endif
+ifneq ($(CXX_BUILD), 1)
ifneq ($(GNU90_BUILD), 1)
ifneq ($(findstring icc,$(CC)),)
CFLAGS += -std=c99 -D_GNU_SOURCE
@@ -133,7 +134,7 @@ RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
ifneq ($(X86),)
CFLAGS += -m32
- CXXLAGS += -m32
+ CXXFLAGS += -m32
LDFLAGS += -m32
endif
@@ -150,8 +151,29 @@ ifneq ($(findstring $(GPERFTOOLS),tcmalloc),)
LIBS += -ltcmalloc
endif
+# Qt MOC generation, required for QObject-derived classes
+ifneq ($(MOC_HEADERS),)
+ # prefix moc_ to base filename of paths and change extension from h to cpp, so a/b/foo.h becomes a/b/moc_foo.cpp
+ MOC_SRC := $(join $(addsuffix moc_,$(addprefix $(OBJDIR)/,$(dir $(MOC_HEADERS)))), $(notdir $(MOC_HEADERS:.h=.cpp)))
+ MOC_OBJ := $(patsubst %.cpp,%.o,$(MOC_SRC))
+ RARCH_OBJ += $(MOC_OBJ)
+endif
+
all: $(TARGET) config.mk
+$(MOC_SRC):
+ @$(if $(Q), $(shell echo echo MOC $<),)
+ $(eval MOC_TMP := $(patsubst %.h,%_moc.cpp,$@))
+ $(Q)$(MOC) -o $(MOC_TMP) $<
+
+$(foreach x,$(join $(addsuffix :,$(MOC_SRC)),$(MOC_HEADERS)),$(eval $x))
+
+$(MOC_OBJ):
+ @$(if $(Q), $(shell echo echo CXX $<),)
+ $(Q)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) -MMD -c -o $@ $<
+
+$(foreach x,$(join $(addsuffix :,$(MOC_OBJ)),$(MOC_SRC)),$(eval $x))
+
ifeq ($(MAKECMDGOALS),clean)
config.mk:
else
@@ -250,3 +272,6 @@ clean:
rm -f *.d
.PHONY: all install uninstall clean
+
+print-%:
+ @echo '$*=$($*)'
diff --git a/Makefile.common b/Makefile.common
index 7163289e68..5710d4012f 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -147,6 +147,8 @@ ifneq ($(GIT_VERSION),)
endif
# General object files
+DEFINES += -DHAVE_DR_MP3
+CFLAGS += -DHAVE_DR_MP3
OBJ += frontend/frontend.o \
frontend/frontend_driver.o \
@@ -198,12 +200,15 @@ OBJ += frontend/frontend.o \
$(LIBRETRO_COMM_DIR)/hash/rhash.o \
audio/audio_driver.o \
$(LIBRETRO_COMM_DIR)/audio/audio_mixer.o \
+ input/common/input_common.o \
input/input_driver.o \
+ input/input_mapper.o \
led/led_driver.o \
led/drivers/led_null.o \
gfx/video_coord_array.o \
gfx/video_display_server.o \
gfx/video_driver.o \
+ gfx/video_crt_switch.o \
camera/camera_driver.o \
wifi/wifi_driver.o \
location/location_driver.o \
@@ -259,6 +264,8 @@ OBJ += frontend/frontend.o \
$(LIBRETRO_COMM_DIR)/features/features_cpu.o \
performance_counters.o \
verbosity.o \
+ midi/midi_driver.o \
+ midi/drivers/null_midi.o
ifeq ($(HAVE_RUNAHEAD), 1)
DEFINES += -DHAVE_RUNAHEAD
@@ -319,23 +326,27 @@ DEFINES += -DHAVE_IMAGEVIEWER
OBJ += cores/libretro-imageviewer/image_core.o
endif
-# Qt
-
-ifeq ($(HAVE_QT_WRAPPER), 1)
-OBJ += ui/drivers/ui_qt.o
-LIBS += -lQt5Quick -lQt5Widgets -lQt5Gui -lQt5Qml -lQt5Network -lQt5Core -L./ui/drivers/qt/build/release/
-LIBS += -lwrapper
-endif
+# Qt WIMP GUI
ifeq ($(HAVE_QT), 1)
OBJ += ui/drivers/ui_qt.o \
ui/drivers/qt/ui_qt_application.o \
ui/drivers/qt/ui_qt_window.o \
ui/drivers/qt/ui_qt_browser_window.o \
+ ui/drivers/qt/ui_qt_load_core_window.o \
ui/drivers/qt/ui_qt_msg_window.o
+MOC_HEADERS += ui/drivers/ui_qt.h \
+ ui/drivers/qt/ui_qt_load_core_window.h
+
+DEFINES += $(QT5CORE_CFLAGS) $(QT5GUI_CFLAGS) $(QT5WIDGETS_CFLAGS) -DHAVE_MAIN
+#DEFINES += $(QT5WEBENGINE_CFLAGS)
+LIBS += $(QT5CORE_LIBS) $(QT5GUI_LIBS) $(QT5WIDGETS_LIBS)
+#LIBS += $(QT5WEBENGINE_LIBS)
+NEED_CXX_LINKER = 1
+
ifneq ($(findstring Linux,$(OS)),)
-DEFINES += -I/usr/include/qt -fPIC
+DEFINES += -fPIC
endif
endif
@@ -677,6 +688,12 @@ ifeq ($(HAVE_XAUDIO), 1)
LIBS += -lole32
endif
+ifeq ($(HAVE_WINMM), 1)
+ OBJ += midi/drivers/winmm_midi.o
+ DEFINES += -DHAVE_WINMM
+ LIBS += -lwinmm
+endif
+
# Audio Resamplers
ifeq ($(HAVE_NEON),1)
@@ -1038,15 +1055,24 @@ ifeq ($(HAVE_CACA), 1)
endif
endif
+ifeq ($(HAVE_SIXEL), 1)
+ DEFINES += -DHAVE_SIXEL
+ CFLAGS += -I/usr/include/sixel
+ OBJ += gfx/drivers/sixel_gfx.o gfx/drivers_font/sixel_font.o \
+ gfx/drivers_context/sixel_ctx.o
+ LIBS += -lsixel
+
+ ifeq ($(HAVE_MENU_COMMON), 1)
+ OBJ += menu/drivers_display/menu_display_sixel.o
+ endif
+endif
+
ifeq ($(HAVE_PLAIN_DRM), 1)
OBJ += gfx/drivers/drm_gfx.o
CFLAGS += -I/usr/include/libdrm
LIBS += -ldrm
endif
-OBJ += \
- gfx/drivers_renderchain/null_renderchain.o
-
ifeq ($(HAVE_GL_CONTEXT), 1)
DEFINES += -DHAVE_OPENGL -DHAVE_GLSL
OBJ += gfx/drivers/gl.o \
@@ -1098,11 +1124,30 @@ ifneq ($(C89_BUILD), 1)
ifneq ($(HAVE_OPENGLES), 1)
OBJ += cores/libretro-ffmpeg/ffmpeg_fft.o
DEFINES += -I$(DEPS_DIR) -DHAVE_GL_FFT
- NEED_CXX_LINKER=1
endif
endif
endif
+ifeq ($(HAVE_METAL), 1)
+ DEFINES += -DHAVE_METAL
+ OBJ += gfx/common/metal/Context.o \
+ gfx/common/metal/Filter.o \
+ gfx/common/metal/RendererCommon.o \
+ gfx/common/metal/View.o \
+ gfx/common/metal/TexturedView.o \
+ gfx/common/metal/MenuDisplay.o \
+ gfx/common/metal_common.o \
+ gfx/drivers/metal.o \
+ menu/drivers_display/menu_display_metal.o \
+ gfx/drivers_font/metal_raster_font.o
+endif
+
+ifeq ($(HAVE_MPV), 1)
+ OBJ += cores/libretro-mpv/mpv-libretro.o
+ DEFINES += -I$(DEPS_DIR) -DHAVE_MPV
+ LIBS += -lmpv
+endif
+
ifeq ($(HAVE_OPENGLES), 1)
LIBS += $(OPENGLES_LIBS)
DEFINES += $(OPENGLES_CFLAGS) -DHAVE_OPENGLES
@@ -1194,7 +1239,7 @@ ifeq ($(HAVE_VULKAN), 1)
ifeq ($(HAVE_MENU_COMMON), 1)
OBJ += menu/drivers_display/menu_display_vulkan.o
endif
- LIBS += -lstdc++
+ NEED_CXX_LINKER = 1
DEFINES += -DHAVE_VULKAN
INCLUDE_DIRS += -Igfx/include
@@ -1269,14 +1314,15 @@ endif
endif
ifeq ($(HAVE_HLSL), 1)
- OBJ += gfx/drivers_renderchain/d3d9_hlsl_renderchain.o \
- gfx/drivers_shader/shader_hlsl.o
+ OBJ += gfx/drivers_renderchain/d3d9_hlsl_renderchain.o
endif
endif
ifeq ($(HAVE_D3D10), 1)
OBJ += gfx/drivers/d3d10.o \
- gfx/common/d3d10_common.o
+ gfx/common/d3d10_common.o \
+ gfx/drivers_font/d3d10_font.o \
+ menu/drivers_display/menu_display_d3d10.o
DEFINES += -DHAVE_D3D10
endif
@@ -1383,9 +1429,14 @@ ifeq ($(HAVE_GLSLANG), 1)
$(wildcard $(DEPS_DIR)/glslang/glslang/OGLCompilersDLL/*.cpp) \
$(wildcard $(DEPS_DIR)/glslang/glslang/glslang/MachineIndependent/*.cpp) \
$(wildcard $(DEPS_DIR)/glslang/glslang/glslang/MachineIndependent/preprocessor/*.cpp) \
- $(wildcard $(DEPS_DIR)/glslang/glslang/hlsl/*.cpp) \
$(wildcard $(DEPS_DIR)/glslang/glslang/glslang/OSDependent/$(GLSLANG_PLATFORM)/*.cpp)
+ifneq ($(findstring Win32,$(OS)),)
+DEFINES += -DENABLE_HLSL
+GLSLANG_SOURCES += $(wildcard $(DEPS_DIR)/glslang/glslang/hlsl/*.cpp)
+endif
+
+
OBJ += $(GLSLANG_SOURCES:.cpp=.o)
endif
@@ -1446,6 +1497,8 @@ endif
ifeq ($(HAVE_BUILTINFLAC),1)
HAVE_FLAC = 1
+ DEFINES += -DHAVE_DR_FLAC -I$(DEPS_DIR)
+ CFLAGS += -DHAVE_DR_FLAC
CFLAGS += -DHAVE_FLAC -I$(DEPS_DIR)/libFLAC/include
DEFINES += -DHAVE_STDINT_H -DHAVE_LROUND -DFLAC__HAS_OGG=0 \
-DFLAC_PACKAGE_VERSION="\"retroarch\""
@@ -1472,7 +1525,8 @@ ifeq ($(HAVE_BUILTINFLAC),1)
endif
OBJ += $(FLACOBJ)
else ifeq ($(HAVE_FLAC),1)
- LIBS += $(FLAC_LIBS)
+ DEFINES += -DHAVE_FLAC
+ LIBS += $(FLAC_LIBS)
endif
ifeq ($(HAVE_ZLIB), 1)
@@ -1483,7 +1537,7 @@ ifeq ($(HAVE_ZLIB), 1)
ifeq ($(HAVE_BUILTINZLIB), 1)
OBJ += $(DEPS_DIR)/libz/adler32.o \
$(DEPS_DIR)/libz/compress.o \
- $(DEPS_DIR)/libz/crc32.o \
+ $(DEPS_DIR)/libz/libz-crc32.o \
$(DEPS_DIR)/libz/deflate.o \
$(DEPS_DIR)/libz/gzclose.o \
$(DEPS_DIR)/libz/gzlib.o \
@@ -1502,19 +1556,27 @@ ifeq ($(HAVE_ZLIB), 1)
endif
endif
-ifeq ($(HAVE_FLAC), 1)
-ifeq ($(HAVE_7ZIP), 1)
-ifeq ($(HAVE_ZLIB), 1)
- DEFINES += -DHAVE_CHD -DWANT_SUBCODE -DWANT_RAW_DATA_SECTOR
+ifeq ($(HAVE_CHD), 1)
CFLAGS += -I$(LIBRETRO_COMM_DIR)/formats/libchdr
- OBJ += $(LIBRETRO_COMM_DIR)/formats/libchdr/bitstream.o \
- $(LIBRETRO_COMM_DIR)/formats/libchdr/cdrom.o \
- $(LIBRETRO_COMM_DIR)/formats/libchdr/chd.o \
- $(LIBRETRO_COMM_DIR)/formats/libchdr/flac.o \
- $(LIBRETRO_COMM_DIR)/formats/libchdr/huffman.o \
+ DEFINES += -DHAVE_CHD -DWANT_SUBCODE -DWANT_RAW_DATA_SECTOR
+ OBJ += $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_bitstream.o \
+ $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_cdrom.o \
+ $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_chd.o \
+ $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_huffman.o \
$(LIBRETRO_COMM_DIR)/streams/chd_stream.o
-endif
-endif
+
+ ifeq ($(HAVE_FLAC), 1)
+ OBJ += $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_flac.o \
+ $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_flac_codec.o
+ endif
+
+ ifeq ($(HAVE_7ZIP), 1)
+ OBJ += $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_lzma.o
+ endif
+
+ ifeq ($(HAVE_ZLIB), 1)
+ OBJ += $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_zlib.o
+ endif
endif
ifeq ($(HAVE_RTGA), 1)
@@ -1616,8 +1678,27 @@ ifeq ($(HAVE_NETWORKING), 1)
$(LIBRETRO_COMM_DIR)/utils/md5.o
endif
- ifeq ($(HAVE_KEYMAPPER), 1)
- OBJ += input/input_mapper.o
+ ifeq ($(HAVE_DISCORD), 1)
+ DEFINES += -DHAVE_DISCORD
+ DEFINES += -Ideps/discord-rpc/include/ -Ideps/discord-rpc/thirdparty/rapidjson-1.1.0/include/
+ OBJ += deps/discord-rpc/src/discord_rpc.o \
+ deps/discord-rpc/src/rpc_connection.o \
+ deps/discord-rpc/src/serialization.o \
+ discord/discord.o
+ifneq ($(findstring Win32,$(OS)),)
+ OBJ += deps/discord-rpc/src/discord_register_win.o \
+ deps/discord-rpc/src/connection_win.o
+ LIBS += -lpsapi -ladvapi32
+endif
+ifneq ($(findstring Linux,$(OS)),)
+ OBJ += deps/discord-rpc/src/discord_register_linux.o \
+ deps/discord-rpc/src/connection_unix.o
+endif
+ifneq ($(findstring Darwin,$(OS)),)
+ OBJ += deps/discord-rpc/src/discord_register_osx.o \
+ deps/discord-rpc/src/connection_unix.o
+endif
+
endif
ifeq ($(HAVE_NETWORKGAMEPAD), 1)
diff --git a/Makefile.ctr b/Makefile.ctr
index d47cc66c25..5e5f210307 100644
--- a/Makefile.ctr
+++ b/Makefile.ctr
@@ -5,7 +5,7 @@ DEBUG = 0
GRIFFIN_BUILD = 1
WHOLE_ARCHIVE_LINK = 0
BUILD_3DSX = 1
-BUILD_3DS = 1
+BUILD_3DS = 0
BUILD_CIA = 1
LIBCTRU_NO_DEPRECATION = 1
@@ -31,6 +31,12 @@ OBJ += ctr/ctr_system.o
OBJ += ctr/ctr_memory.o
OBJ += ctr/ctr_linear.o
OBJ += ctr/gpu_old.o
+OBJ += ctr/exec-3dsx/exec_cia.o \
+ ctr/exec-3dsx/exec_3dsx.o \
+ ctr/exec-3dsx/mini-hb-menu/launch.o \
+ ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.o \
+ ctr/exec-3dsx/mini-hb-menu/loaders/hax2.o \
+ ctr/exec-3dsx/mini-hb-menu/loaders/ninjhax1.o
ifeq ($(APP_BIG_TEXT_SECTION), 1)
APP_USE_SVCHAX = 1
@@ -162,7 +168,7 @@ endif
all: $(TARGET)
-$(TARGET): $(TARGET_3DSX) $(TARGET_3DS) $(TARGET_CIA) $(TARGET).core
+$(TARGET): $(TARGET_3DSX) $(TARGET_3DS) $(TARGET_CIA)
$(TARGET).3dsx: $(TARGET).elf
$(TARGET).elf: $(OBJ) libretro_ctr.a
@@ -255,9 +261,6 @@ $(TARGET).3ds: $(TARGET).elf $(TARGET).bnr $(TARGET).icn $(APP_RSF)
$(TARGET).cia: $(TARGET).elf $(TARGET).bnr $(TARGET).icn $(APP_RSF)
$(MAKEROM) -f cia -o $@ $(MAKEROM_ARGS_COMMON) -DAPP_ENCRYPTED=false
-$(TARGET).core: $(TARGET).elf
- echo $(APP_UNIQUE_ID) > $(TARGET).core
-
clean:
rm -f $(OBJ)
@@ -265,7 +268,6 @@ clean:
rm -f $(TARGET).elf
rm -f $(TARGET).3ds
rm -f $(TARGET).cia
- rm -f $(TARGET).core
rm -f $(TARGET).smdh
rm -f $(TARGET).bnr
rm -f $(TARGET).icn
diff --git a/Makefile.ctr.salamander b/Makefile.ctr.salamander
index f356cd9e78..2c45a1bfe2 100644
--- a/Makefile.ctr.salamander
+++ b/Makefile.ctr.salamander
@@ -2,12 +2,12 @@ TARGET := retroarch_3ds_salamander
LIBRETRO =
DEBUG = 0
-BUILD_3DSX = 0
+BUILD_3DSX = 1
BUILD_3DS = 0
BUILD_CIA = 1
-APP_TITLE = Retroarch 3DS
-APP_DESCRIPTION = Retroarch 3DS
+APP_TITLE = RetroArch 3DS
+APP_DESCRIPTION = RetroArch 3DS
APP_AUTHOR = Team Libretro
APP_PRODUCT_CODE = RETROARCH-3DS
APP_UNIQUE_ID = 0xBAC00
@@ -39,6 +39,13 @@ OBJ := ctr/ctr_system.o \
libretro-common/hash/rhash.o \
file_path_str.o \
verbosity.o
+
+OBJ += ctr/exec-3dsx/exec_cia.o \
+ ctr/exec-3dsx/exec_3dsx.o \
+ ctr/exec-3dsx/mini-hb-menu/launch.o \
+ ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.o \
+ ctr/exec-3dsx/mini-hb-menu/loaders/hax2.o \
+ ctr/exec-3dsx/mini-hb-menu/loaders/ninjhax1.o
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitpro")
@@ -182,7 +189,7 @@ ifeq ($(APP_BIG_TEXT_SECTION), 1)
else
rm -f $(TARGET).xml
endif
- -3dsxtool $< $@ $(_3DSXFLAGS)
+ $(DEVKITARM)/bin/3dsxtool $< $@ $(_3DSXFLAGS)
$(TARGET).elf: ctr/3dsx_custom_crt0.o
$(LD) $(LDFLAGS) $(OBJ) $(LIBDIRS) $(LIBS) -o $@
diff --git a/Makefile.msvc b/Makefile.msvc
index 77d02fc9fa..3ece3af7a4 100644
--- a/Makefile.msvc
+++ b/Makefile.msvc
@@ -25,6 +25,7 @@ HAVE_XAUDIO := 1
HAVE_XINPUT := 1
HAVE_WASAPI := 0
HAVE_THREAD_STORAGE := 1
+HAVE_WINMM := 1
HAVE_RPNG := 1
HAVE_ZLIB := 1
@@ -53,7 +54,6 @@ HAVE_NETWORK_CMD := 1
HAVE_OVERLAY := 1
HAVE_LANGEXTRA := 1
HAVE_CHEEVOS := 1
-HAVE_KEYMAPPER := 1
HAVE_SHADERPIPELINE := 1
HAVE_IMAGEVIEWER := 1
diff --git a/Makefile.ps3 b/Makefile.ps3
index f3f29d18de..16f731e05f 100644
--- a/Makefile.ps3
+++ b/Makefile.ps3
@@ -4,7 +4,7 @@ include version.all
#set to GCC for debug builds for use with debugger
CELL_BUILD_TOOLS = SNC
CELL_GPU_TYPE = RSX
-CELL_PSGL_VERSION = ultra-opt
+CELL_PSGL_VERSION = opt
ASSETS_DIR := media/assets
@@ -63,7 +63,7 @@ endif
PPU_SRCS = griffin/griffin.c
-DEFINES += -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_LIBRETRODB -DHAVE_MATERIALUI -DHAVE_SHADERPIPELINE -DRARCH_INTERNAL -DMSB_FIRST -DHAVE_OVERLAY -DHAVE_CC_RESAMPLER -DHAVE_STB_VORBIS -DHAVE_STB_FONT -DHAVE_RUNAHEAD
+DEFINES += -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_LIBRETRODB -DHAVE_MATERIALUI -DHAVE_SHADERPIPELINE -DRARCH_INTERNAL -DMSB_FIRST -DHAVE_OVERLAY -DHAVE_CC_RESAMPLER -DHAVE_STB_VORBIS -DHAVE_STB_FONT -DHAVE_RUNAHEAD -DHAVE_DR_MP3 -DHAVE_DR_FLAC
ifeq ($(DEX_BUILD), 1)
DEFINES += -DDEX_BUILD
@@ -96,7 +96,7 @@ ifeq ($(CELL_BUILD_TOOLS), SNC)
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
PPU_CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
-else ifneq($(system_platform), win)
+else ifneq ($(system_platform), win)
PPU_CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe
PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
PPU_CXXLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe
@@ -119,7 +119,7 @@ DEFINES += -DHAVE_THREADS -DRARCH_CONSOLE -DHAVE_OPENGL -DHAVE_HEADSET -DHAVE_LA
ifeq ($(DEBUG), 1)
PPU_OPTIMIZE_LV := -O0 -g
else
- PPU_OPTIMIZE_LV := -O3 -g
+ PPU_OPTIMIZE_LV := -O2 -g
endif
ifeq ($(HAVE_LOGGER), 1)
diff --git a/Makefile.ps3.cobra b/Makefile.ps3.cobra
index ce6f755c0a..3a270b2dd6 100644
--- a/Makefile.ps3.cobra
+++ b/Makefile.ps3.cobra
@@ -2,7 +2,7 @@ include version.all
#which compiler to build with - GCC or SNC
#set to GCC for debug builds for use with debugger
-CELL_BUILD_TOOLS = SNC
+CELL_BUILD_TOOLS = GCC
CELL_GPU_TYPE = RSX
CELL_PSGL_VERSION = ultra-opt
diff --git a/Makefile.ps3.salamander b/Makefile.ps3.salamander
index 49c8c9a719..c769ff105c 100644
--- a/Makefile.ps3.salamander
+++ b/Makefile.ps3.salamander
@@ -1,4 +1,4 @@
-CELL_BUILD_TOOLS = SNC
+CELL_BUILD_TOOLS = GCC
CELL_SDK ?= /usr/local/cell
HAVE_LOGGER = 0
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
diff --git a/Makefile.switch b/Makefile.switch
index a477749409..db887842c5 100644
--- a/Makefile.switch
+++ b/Makefile.switch
@@ -6,12 +6,13 @@ WHOLE_ARCHIVE_LINK = 0
OBJ :=
-DEFINES := -DSWITCH=1 -U__linux__ -U__linux
+DEFINES := -DSWITCH=1 -U__linux__ -U__linux -DRARCH_INTERNAL -DHAVE_DYNAMIC
ifeq ($(GRIFFIN_BUILD), 1)
OBJ += griffin/griffin.o
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_NEON -DHAVE_MATERIALUI -DHAVE_LIBRETRODB -DHAVE_CC_RESAMPLER
DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DWANT_ZLIB
+ DEFINES += -DHAVE_RUNAHEAD -DHAVE_DYNAMIC
else
HAVE_CC_RESAMPLER = 1
HAVE_MENU_COMMON = 1
@@ -29,6 +30,8 @@ else
HAVE_STATIC_VIDEO_FILTERS = 1
HAVE_STATIC_AUDIO_FILTERS = 1
HAVE_MENU = 1
+ HAVE_RUNAHEAD = 1
+ HAVE_DYNAMIC = 1
include Makefile.common
BLACKLIST :=
@@ -44,7 +47,7 @@ endif
include $(LIBTRANSISTOR_HOME)/libtransistor.mk
-INCDIRS := -I. -Ideps/libz -Ilibretro-common/include -Ideps/stb -I$(LIBTRANSISTOR_HOME)/build/sdl2_install/include/SDL2/
+INCDIRS := -I. -Ideps -Ideps/libz -Ilibretro-common/include -Ideps/stb -I$(LIBTRANSISTOR_HOME)/build/sdl2_install/include/SDL2/
LIBDIRS := -L.
TARGETS := $(TARGET).nro
diff --git a/Makefile.vita b/Makefile.vita
index 25d79a673e..5645c9cabd 100644
--- a/Makefile.vita
+++ b/Makefile.vita
@@ -16,7 +16,7 @@ DEFINES :=
ifeq ($(GRIFFIN_BUILD), 1)
OBJ += griffin/griffin.o
DEFINES += -DHAVE_GRIFFIN=1
- DEFINES += -DHAVE_NEON -DHAVE_MENU -DHAVE_XMB -DHAVE_MATERIALUI -DHAVE_LIBRETRODB
+ DEFINES += -DHAVE_NEON -DHAVE_MENU -DHAVE_XMB -DHAVE_MATERIALUI -DHAVE_LIBRETRODB DEFINES -DHAVE_KEYMAPPER
DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DWANT_ZLIB -DHAVE_CC_RESAMPLER
ifeq ($(DEBUG), 1)
DEFINES += -DHAVE_NETLOGGER
diff --git a/Makefile.wiiu b/Makefile.wiiu
index 0f512f5638..83c890e2a8 100644
--- a/Makefile.wiiu
+++ b/Makefile.wiiu
@@ -6,10 +6,10 @@ DEBUG = 0
GRIFFIN_BUILD = 0
SALAMANDER_BUILD = 0
WHOLE_ARCHIVE_LINK = 0
-WIIU_HID = 0
+WIIU_HID = 1
+HAVE_RUNAHEAD = 1
WIIU_LOG_RPX = 0
BUILD_DIR = objs/wiiu
-PC_DEVELOPMENT_IP_ADDRESS ?=
PC_DEVELOPMENT_TCP_PORT ?=
ifeq ($(SALAMANDER_BUILD),1)
@@ -28,11 +28,11 @@ ifneq ($(V), 1)
endif
OBJ :=
-OBJ += wiiu/input/wpad_driver.o
-OBJ += wiiu/input/kpad_driver.o
-OBJ += wiiu/input/pad_functions.o
+OBJ += wiiu/main.o
OBJ += wiiu/system/memory.o
+OBJ += wiiu/system/atomic.o
OBJ += wiiu/system/exception_handler.o
+OBJ += wiiu/system/missing_libc_functions.o
OBJ += wiiu/fs/sd_fat_devoptab.o
OBJ += wiiu/fs/fs_utils.o
OBJ += wiiu/hbl.o
@@ -45,18 +45,14 @@ endif
ifeq ($(WIIU_HID),1)
DEFINES += -DWIIU_HID
- OBJ += wiiu/input/hidpad_driver.o
- OBJ += wiiu/input/wiiu_hid.o
+ OBJ += input/drivers_joypad/wiiu/hidpad_driver.o
+ OBJ += input/drivers_hid/wiiu_hid.o
OBJ += input/connect/joypad_connection.o \
- input/connect/connect_ps2adapter.o \
- input/connect/connect_psxadapter.o \
- input/connect/connect_ps3.o \
- input/connect/connect_ps4.o \
- input/connect/connect_wii.o \
- input/connect/connect_nesusb.o \
- input/connect/connect_snesusb.o \
- input/connect/connect_wiiupro.o \
- input/connect/connect_wiiugca.o
+ input/common/hid/hid_device_driver.o \
+ input/common/hid/device_wiiu_gca.o \
+ input/common/hid/device_ds3.o \
+ input/common/hid/device_ds4.o \
+ input/common/hid/device_null.o
endif
ifeq ($(SALAMANDER_BUILD),1)
@@ -83,13 +79,15 @@ ifeq ($(SALAMANDER_BUILD),1)
else
DEFINES += -DRARCH_INTERNAL
DEFINES += -DHAVE_KEYMAPPER
- DEFINES += -DHAVE_RUNAHEAD
DEFINES += -DHAVE_UPDATE_ASSETS
DEFINES += -DHAVE_FILTERS_BUILTIN
DEFINES += -DHAVE_SLANG
DEFINES += -DHAVE_SHADERPIPELINE
- OBJ += wiiu/system/missing_libc_functions.o
+ifeq ($(HAVE_RUNAHEAD),1)
+ DEFINES += -DHAVE_RUNAHEAD
+endif
+
OBJ += wiiu/shader_utils.o
OBJ += gfx/drivers/gx2_shaders/tex.o
OBJ += gfx/drivers/gx2_shaders/sprite.o
@@ -120,8 +118,7 @@ else
HAVE_RGUI = 1
HAVE_ZLIB = 1
HAVE_7ZIP = 1
- HAVE_BUILTINZLIB = 1
- HAVE_KEYMAPPER = 1
+ HAVE_BUILTINZLIB = 0
HAVE_LIBRETRODB = 1
HAVE_ZARCH = 0
HAVE_MATERIALUI = 1
@@ -148,6 +145,10 @@ else
OBJ += menu/drivers_display/menu_display_wiiu.o
OBJ += input/drivers/wiiu_input.o
OBJ += input/drivers_joypad/wiiu_joypad.o
+ OBJ += input/drivers_joypad/wiiu/wpad_driver.o
+ OBJ += input/drivers_joypad/wiiu/kpad_driver.o
+ OBJ += input/drivers_joypad/wiiu/pad_functions.o
+
OBJ += audio/drivers/wiiu_audio.o
OBJ += frontend/drivers/platform_wiiu.o
endif
@@ -161,10 +162,6 @@ DEFINES += -DWIIU -DMSB_FIRST -D__WUT__
DEFINES += -DHAVE_MAIN
DEFINES += -DRARCH_CONSOLE
-ifneq ($(PC_DEVELOPMENT_IP_ADDRESS),)
- DEFINES += -DPC_DEVELOPMENT_IP_ADDRESS='"$(PC_DEVELOPMENT_IP_ADDRESS)"'
-endif
-
ifneq ($(PC_DEVELOPMENT_TCP_PORT),)
DEFINES += -DPC_DEVELOPMENT_TCP_PORT=$(PC_DEVELOPMENT_TCP_PORT)
endif
@@ -197,7 +194,16 @@ else
ELF2RPL := $(ELF2RPL).exe
endif
-INCDIRS := -I. -Ideps -Ideps/stb -Ideps/libz -Ideps/7zip -Ilibretro-common/include -Iwiiu -Iwiiu/include -I$(DEVKITPRO)/portlibs/ppc/include
+INCDIRS := -I.
+INCDIRS += -Ideps
+INCDIRS += -Ideps/stb
+INCDIRS += -Ideps/libz
+INCDIRS += -Ideps/7zip
+INCDIRS += -Ilibretro-common/include
+INCDIRS += -Iinput/include
+INCDIRS += -Iwiiu
+INCDIRS += -Iwiiu/include
+INCDIRS += -I$(DEVKITPRO)/portlibs/ppc/include
LIBDIRS := -L. -L$(DEVKITPRO)/portlibs/ppc/lib
CFLAGS := -mwup -mcpu=750 -meabi -mhard-float
@@ -226,7 +232,7 @@ CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions
LDFLAGS += -Wl,--gc-sections
-LIBS := $(WHOLE_START) -lretro_wiiu $(WHOLE_END) -lm
+LIBS := $(WHOLE_START) -lretro_wiiu $(WHOLE_END) -lm -lpng -lz
ifneq ($(WANT_LIBFAT), 1)
LIBS += -lfat
diff --git a/Makefile.win b/Makefile.win
index 26c3f7aa37..932d0f896f 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -18,6 +18,7 @@ HAVE_PYTHON = 0
DYNAMIC = 1
HAVE_XINPUT = 1
+HAVE_WINMM = 1
HAVE_SDL := 0
HAVE_SDL2 := 0
diff --git a/README.md b/README.md
index ccf7c912ec..1e4105cc53 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
# RetroArch
RetroArch is the reference frontend for the libretro API.
-Popular examples of implementations for this API includes videogame system emulators and game engines as well as
+Popular examples of implementations for this API includes video game system emulators and game engines as well as
more generalized 3D programs.
These programs are instantiated as dynamic libraries. We refer to these as "libretro cores".
@@ -27,12 +27,11 @@ interface to include support for emulators and/or game engines. libretro is comp
## Binaries
-Latest Windows binaries are currently hosted on the [buildbot](http://buildbot.libretro.com/).
+Latest binaries are currently hosted on the [buildbot](http://buildbot.libretro.com/).
## Support
-To reach developers, either make an issue here on GitHub, make a thread on the [forum](http://www.libretro.com/forums/),
-or visit our IRC channel: #retroarch @ irc.freenode.org.
+To reach developers, either make an issue here on GitHub, make a thread on the [forum](http://www.libretro.com/forums/), chat on [Discord](https://discord.gg/C4amCeV), or visit our IRC channel: #retroarch @ irc.freenode.org.
## Documentation
@@ -51,13 +50,13 @@ More developer-centric stuff is found [here](https://github.com/libretro/libretr
RetroArch attempts to be small and lean
while still having all the useful core features expected from an emulator.
-It is designed to be very portable and features a gamepad-centric UI.
+It is designed to be very portable and features a gamepad-centric and touchscreen UI.
It also has a full-featured command-line interface.
In some areas, RetroArch goes beyond and emphasizes on not-so-common technical features such as multi-pass shader support,
-real-time rewind (Braid-style), video recording (using FFmpeg), etc.
+real-time rewind (Braid-style), video recording (using FFmpeg), run-ahead input latency removal, etc.
-RetroArch also emphasizes on being easy to integrate into various launcher frontends.
+RetroArch also emphasizes being easy to integrate into various launcher frontends.
## Platforms
@@ -66,22 +65,24 @@ RetroArch has been ported to the following platforms:
- DOS
- Windows
- Linux
- - Emscripten
+ - Emscripten (WebAssembly and JavaScript)
- FreeBSD
- NetBSD
- OpenBSD
- Haiku
- Solaris
- - MacOS X
+ - macOS (PPC, x86-32 and x86-64)
- PlayStation 3
- PlayStation Portable
- PlayStation Vita
- Original Microsoft Xbox
- Microsoft Xbox 360 (Libxenon/XeXDK)
- - Nintendo Wii, GameCube (Libogc)
- - Nintendo WiiU
+ - Nintendo GameCube
+ - Nintendo Wii
+ - Nintendo Wii U
- Nintendo 3DS
- Nintendo Switch
+ - Nintendo NES/SNES Classic Edition
- Raspberry Pi
- Android
- iOS
@@ -144,3 +145,115 @@ To configure joypads, use the built-in menu or the `retroarch-joyconfig` command
## Compiling and installing
Instructions for compiling and installing RetroArch can be found in the [Libretro/RetroArch Documentation Center](https://docs.libretro.com/).
+
+## CRT 15Khz Resolution Switching
+
+CRT SwitchRes will turn on, on the fly. However, you will need to restart RetroArch to disable it. With CRT SwitchRes enable RetroArch will start in 2560 x 480 @ 60.
+
+If you are running Windows, before enabling the CRT SwitchRes options please make sure you have installed CRTEmudriver and installed some modelines. The minimum modelines for all games to switch correctly are:
+
+- 2560 x 192 @ 60.000000
+- 2560 x 200 @ 60.000000
+- 2560 x 240 @ 60.000000
+- 2560 x 224 @ 60.000000
+- 2560 x 237 @ 60.000000
+- 2560 x 256 @ 50.000000
+- 2560 x 254 @ 55.000000
+- 2560 x 448 @ 60.000000
+- 2560 x 480 @ 60.000000
+
+Install these modelines replacing 2560 with your desired super resolution. The above resolutions are NTSC only so if you would be playing any PAL content please add PAL modelines:
+
+- 2560 x 192 @ 50.000000
+- 2560 x 200 @ 50.000000
+- 2560 x 240 @ 50.000000
+- 2560 x 224 @ 50.000000
+- 2560 x 288 @ 50.000000
+- 2560 x 237 @ 50.000000
+- 2560 x 254 @ 55.000000
+- 2560 x 448 @ 50.000000
+- 2560 x 480 @ 50.000000
+
+Some games will require higher PAL resolutions which should also be installed:
+
+- 2560 x 512 @ 50.000000
+- 2560 x 576 @ 50.000000
+
+Ideally install all these modelines and everything will work great.
+
+## Super Resolutions
+
+The default super resolution is 2560. It is displayed just under the CRT switch option, which can be found in video settings. This can be changed within the retroarch.cfg. The only compatible resolutions are 1920, 2560 and 3840. Any other resolutions will be ignored and native switching will be activated.
+
+## Native Resolutions
+
+If native resolutions are activated you will need a whole new set of modelines:
+
+- 512 x 240 @ 50.006977 SNESpal
+- 512 x 224 @ 50.006977 SNESpal
+- 512 x 448 @ 50.006977 SNESpal
+- 512 x 240 @ 60.098812 SNESntsc
+- 512 x 224 @ 60.098812 SNESntsc
+- 512 x 448 @ 60.098812 SNESntsc
+- 256 x 240 @ 50.006977 SNESpal
+- 256 x 448 @ 50.006977 SNESpal
+- 256 x 240 @ 60.098812 SNESntsc
+- 256 x 448 @ 60.098812 SNESntsc
+- 320 x 240 @ 59.922745 MDntsc
+- 320 x 448 @ 59.922745 MDntp
+- 320 x 480 @ 59.922745 MDntsc
+- 256 x 192 @ 59.922745 MDntsc
+- 320 x 224 @ 59.922745 MDntsc
+- 256 x 224 @ 59.922745 MDntsc
+- 320 x 288 @ 49.701458 MDpal
+- 320 x 576 @ 49.701458 MDpal
+- 256 x 192 @ 49.701458 MDpal
+- 320 x 224 @ 49.701458 MDpal
+- 320 x 240 @ 49.701458 MDpal
+- 320 x 448 @ 49.701458 MDpal
+- 320 x 480 @ 49.701458 MDpal
+- 256 x 224 @ 49.701458 MDpal
+- 256 x 288 @ 49.701458 MSYSpal
+- 256 x 240 @ 60.098812 NESntsc
+- 256 x 240 @ 50.006977 NESpal
+
+- 640 x 480 @ 60.130001 N64ntsc
+- 640 x 237 @ 60.130001 N64ntsc
+- 640 x 240 @ 60.130001 N64ntsc
+- 640 x 480 @ 50.000000 N64pal
+- 640 x 576 @ 50.000000 n64pal
+- 640 x 288 @ 50.000000 n64pal
+
+- 256 x 252 @ 49.759998 PSXpal
+- 384 x 252 @ 49.759998 PSXpal
+- 640 x 540 @ 49.759998 PSXpal
+- 320 x 252 @ 49.759998 PSXpal
+- 640 x 252 @ 49.759998 PSXpal
+
+- 384 x 240 @ 59.941002 PSXntsc
+- 256 x 480 @ 59.941002 PSXntsc
+
+- 352 x 240 @ 59.820000 Saturn/SGFX_NTSCp
+- 704 x 240 @ 59.820000 SaturnNTSCp
+- 352 x 480 @ 59.820000 SaturnNTSCi
+- 704 x 480 @ 59.820000 SaturnNTSCi
+- 352 x 288 @ 49.701458 SaturnPALp
+- 704 x 288 @ 49.701458 SaturnPALp
+- 352 x 576 @ 49.701458 SaturnPALi
+- 704 x 576 @ 49.701458 SaturnPALi
+
+- 240 x 160 @ 59.730000 GBA
+- 320 x 200 @ 60.000000 Doom
+
+// Arcade
+
+- 400 x 254 @ 54.706841 MK
+- 384 x 224 @ 59.637405 CPS1
+
+These modelines are more accurate giving exact hz. However, some games may have unwanted results. This is due to mid-scanline resolution changes on the original hardware. For the best results super resolutions are the way to go.
+
+## CRT resolution switching & MAME
+
+Some arcade resolutions can be very different from consumer CRTs. There is resolution detection to ensure MAME games will be displayed in the closest available resolution but drawn at their native resolution within this resolution. Meaning that the MAME game will look just like the original hardware.
+
+MAME ROMs that run in a vertical aspect like DoDonPachi need to be rotated within MAME before resolution switching and aspect correction will work. Do this before enabling CRT SwitchRes so that RetroArch will run in your desktop resolution. Once you have rotated any games that may need it turn CRT SwitchRes on.
diff --git a/audio/audio_driver.c b/audio/audio_driver.c
index fb06d65ffb..e35fbd7951 100644
--- a/audio/audio_driver.c
+++ b/audio/audio_driver.c
@@ -45,7 +45,15 @@
#define AUDIO_BUFFER_FREE_SAMPLES_COUNT (8 * 1024)
-#define AUDIO_MIXER_MAX_STREAMS 8
+/**
+ * db_to_gain:
+ * @db : Decibels.
+ *
+ * Converts decibels to voltage gain.
+ *
+ * Returns: voltage gain value.
+ **/
+#define db_to_gain(db) (powf(10.0f, (db) / 20.0f))
static const audio_driver_t *audio_drivers[] = {
#ifdef HAVE_ALSA
@@ -122,18 +130,6 @@ static const audio_driver_t *audio_drivers[] = {
NULL,
};
-struct audio_mixer_stream
-{
- audio_mixer_sound_t *handle;
- audio_mixer_voice_t *voice;
- audio_mixer_stop_cb_t stop_cb;
- enum audio_mixer_state state;
- float volume;
- void *buf;
- size_t bufsize;
-};
-
-static unsigned audio_mixer_current_max_idx = 0;
static struct audio_mixer_stream audio_mixer_streams[AUDIO_MIXER_MAX_STREAMS] = {{0}};
static size_t audio_driver_chunk_size = 0;
@@ -183,6 +179,11 @@ static void *audio_driver_context_audio_data = NULL;
static bool audio_suspended = false;
+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);
+
enum resampler_quality audio_driver_get_resampler_quality(void)
{
settings_t *settings = config_get_ptr();
@@ -193,6 +194,22 @@ enum resampler_quality audio_driver_get_resampler_quality(void)
return (enum resampler_quality)settings->uints.audio_resampler_quality;
}
+audio_mixer_stream_t *audio_driver_mixer_get_stream(unsigned i)
+{
+ if (i > (AUDIO_MIXER_MAX_STREAMS-1))
+ return NULL;
+ return &audio_mixer_streams[i];
+}
+
+const char *audio_driver_mixer_get_stream_name(unsigned i)
+{
+ if (i > (AUDIO_MIXER_MAX_STREAMS-1))
+ return "N/A";
+ if (!string_is_empty(audio_mixer_streams[i].name))
+ return audio_mixer_streams[i].name;
+ return "N/A";
+}
+
/**
* compute_audio_buffer_statistics:
*
@@ -213,7 +230,7 @@ bool compute_audio_buffer_statistics(audio_statistics_t *stats)
if (!stats || samples < 3)
return false;
- stats->samples = audio_driver_free_samples_count;
+ stats->samples = (unsigned)audio_driver_free_samples_count;
#ifdef WARPUP
/* uint64 to double not implemented, fair chance
@@ -368,6 +385,12 @@ static bool audio_driver_deinit_internal(void)
return true;
}
+static void audio_driver_mixer_init(unsigned out_rate)
+{
+ audio_mixer_init(out_rate);
+}
+
+
static bool audio_driver_init_internal(bool audio_cb_inited)
{
unsigned new_rate = 0;
@@ -524,7 +547,7 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
{
audio_driver_buffer_size =
current_audio->buffer_size(audio_driver_context_audio_data);
- audio_driver_control = true;
+ audio_driver_control = true;
}
else
RARCH_WARN("Audio rate control was desired, but driver does not support needed features.\n");
@@ -534,7 +557,7 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
audio_driver_free_samples_count = 0;
- audio_mixer_init(settings->uints.audio_out_rate);
+ audio_driver_mixer_init(settings->uints.audio_out_rate);
/* Threaded driver is initially stopped. */
if (
@@ -576,20 +599,17 @@ void audio_driver_set_nonblocking_state(bool enable)
static void audio_driver_flush(const int16_t *data, size_t samples)
{
struct resampler_data src_data;
- bool is_perfcnt_enable = false;
- bool is_paused = false;
- bool is_idle = false;
- bool is_slowmotion = false;
- const void *output_data = NULL;
- unsigned output_frames = 0;
- float audio_volume_gain = !audio_driver_mute_enable ?
+ bool is_perfcnt_enable = false;
+ bool is_paused = false;
+ bool is_idle = false;
+ bool is_slowmotion = false;
+ const void *output_data = NULL;
+ unsigned output_frames = 0;
+ float audio_volume_gain = !audio_driver_mute_enable ?
audio_driver_volume_gain : 0.0f;
- src_data.data_in = NULL;
- src_data.data_out = NULL;
- src_data.input_frames = 0;
- src_data.output_frames = 0;
- src_data.ratio = 0.0f;
+ src_data.data_out = NULL;
+ src_data.output_frames = 0;
if (recording_data)
recording_push_audio(data, samples);
@@ -606,8 +626,8 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
convert_s16_to_float(audio_driver_input_data, data, samples,
audio_volume_gain);
- src_data.data_in = audio_driver_input_data;
- src_data.input_frames = samples >> 1;
+ src_data.data_in = audio_driver_input_data;
+ src_data.input_frames = samples >> 1;
if (audio_driver_dsp)
@@ -662,7 +682,7 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
#endif
}
- src_data.ratio = audio_source_ratio_current;
+ src_data.ratio = audio_source_ratio_current;
if (is_slowmotion)
{
@@ -675,7 +695,7 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
if (audio_mixer_active)
{
bool override = audio_driver_mixer_mute_enable ? true :
- (audio_driver_mixer_volume_gain != 0.0f) ? true : false;
+ (audio_driver_mixer_volume_gain != 1.0f) ? true : false;
float mixer_gain = !audio_driver_mixer_mute_enable ?
audio_driver_mixer_volume_gain : 0.0f;
audio_mixer_mix(audio_driver_output_samples_buf,
@@ -725,6 +745,22 @@ void audio_driver_sample(int16_t left, int16_t right)
audio_driver_data_ptr = 0;
}
+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 =
+ (const struct retro_system_timing*)&av_info->timing;
+ unsigned sample_count = (info->sample_rate / info->fps) * 2;
+ while (sample_count > 1024)
+ {
+ audio_driver_flush(samples_buf, 1024);
+ sample_count -= 1024;
+ }
+ audio_driver_flush(samples_buf, sample_count);
+}
+
/**
* audio_driver_sample_batch:
* @data : pointer to audio buffer.
@@ -840,13 +876,13 @@ void audio_driver_monitor_adjust_system_rates(void)
{
float timing_skew;
settings_t *settings = config_get_ptr();
- struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
float video_refresh_rate = settings->floats.video_refresh_rate;
float max_timing_skew = settings->floats.audio_max_timing_skew;
- const struct retro_system_timing *info = av_info ?
- (const struct retro_system_timing*)&av_info->timing : NULL;
+ 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;
- if (!info || info->sample_rate <= 0.0)
+ if (info->sample_rate <= 0.0)
return;
timing_skew = fabs(1.0f - info->fps / video_refresh_rate);
@@ -976,6 +1012,12 @@ bool audio_driver_mixer_extension_supported(const char *ext)
string_list_append(str_list, "mod", attr);
string_list_append(str_list, "s3m", attr);
string_list_append(str_list, "xm", attr);
+#endif
+#ifdef HAVE_DR_FLAC
+ string_list_append(str_list, "flac", attr);
+#endif
+#ifdef HAVE_DR_MP3
+ string_list_append(str_list, "mp3", attr);
#endif
string_list_append(str_list, "wav", attr);
@@ -1021,18 +1063,16 @@ static void audio_mixer_play_stop_cb(
{
unsigned i = (unsigned)idx;
-#if 0
- if (audio_mixer_streams[i].buf != NULL)
- free(audio_mixer_streams[i].buf);
-#endif
+ if (!string_is_empty(audio_mixer_streams[i].name))
+ free(audio_mixer_streams[i].name);
+ audio_mixer_streams[i].name = NULL;
audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE;
audio_mixer_streams[i].volume = 0.0f;
audio_mixer_streams[i].buf = NULL;
audio_mixer_streams[i].stop_cb = NULL;
audio_mixer_streams[i].handle = NULL;
audio_mixer_streams[i].voice = NULL;
- audio_mixer_current_max_idx--;
}
break;
case AUDIO_MIXER_SOUND_STOPPED:
@@ -1042,15 +1082,75 @@ static void audio_mixer_play_stop_cb(
}
}
+static void audio_mixer_play_stop_sequential_cb(
+ audio_mixer_sound_t *sound, unsigned reason)
+{
+ int idx = audio_mixer_find_index(sound);
+
+ switch (reason)
+ {
+ case AUDIO_MIXER_SOUND_FINISHED:
+ audio_mixer_destroy(sound);
+
+ if (idx >= 0)
+ {
+ unsigned i = (unsigned)idx;
+
+ if (!string_is_empty(audio_mixer_streams[i].name))
+ free(audio_mixer_streams[i].name);
+
+ audio_mixer_streams[i].name = NULL;
+ audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE;
+ audio_mixer_streams[i].volume = 0.0f;
+ audio_mixer_streams[i].buf = NULL;
+ audio_mixer_streams[i].stop_cb = NULL;
+ audio_mixer_streams[i].handle = NULL;
+ audio_mixer_streams[i].voice = NULL;
+
+ i++;
+
+ for (; i < AUDIO_MIXER_MAX_STREAMS; i++)
+ {
+ if (audio_mixer_streams[i].state == AUDIO_STREAM_STATE_STOPPED)
+ {
+ audio_driver_mixer_play_stream_sequential(i);
+ break;
+ }
+ }
+ }
+ break;
+ case AUDIO_MIXER_SOUND_STOPPED:
+ break;
+ case AUDIO_MIXER_SOUND_REPEATED:
+ break;
+ }
+}
+
+bool audio_driver_mixer_get_free_stream_slot(unsigned *id)
+{
+ unsigned i;
+ for (i = 0; i < AUDIO_MIXER_MAX_STREAMS; i++)
+ {
+ if (audio_mixer_streams[i].state == AUDIO_STREAM_STATE_NONE)
+ {
+ *id = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
{
+ unsigned free_slot = 0;
audio_mixer_voice_t *voice = NULL;
audio_mixer_sound_t *handle = NULL;
audio_mixer_stop_cb_t stop_cb = audio_mixer_play_stop_cb;
bool looped = false;
void *buf = NULL;
-
- if (audio_mixer_current_max_idx >= AUDIO_MIXER_MAX_STREAMS)
+
+ if (!audio_driver_mixer_get_free_stream_slot(&free_slot))
return false;
if (params->state == AUDIO_STREAM_STATE_NONE)
@@ -1074,9 +1174,18 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
case AUDIO_MIXER_TYPE_MOD:
handle = audio_mixer_load_mod(buf, (int32_t)params->bufsize);
break;
+ case AUDIO_MIXER_TYPE_FLAC:
+#ifdef HAVE_DR_FLAC
+ handle = audio_mixer_load_flac(buf, (int32_t)params->bufsize);
+#endif
+ break;
+ case AUDIO_MIXER_TYPE_MP3:
+#ifdef HAVE_DR_MP3
+ handle = audio_mixer_load_mp3(buf, (int32_t)params->bufsize);
+#endif
+ break;
case AUDIO_MIXER_TYPE_NONE:
- free(buf);
- return false;
+ break;
}
if (!handle)
@@ -1085,74 +1194,193 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
return false;
}
- if (params->state == AUDIO_STREAM_STATE_PLAYING)
+ switch (params->state)
{
- voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
- audio_set_bool(AUDIO_ACTION_MIXER, true);
- }
- else if (params->state == AUDIO_STREAM_STATE_PLAYING_LOOPED)
- {
- looped = true;
- voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
- audio_set_bool(AUDIO_ACTION_MIXER, true);
+ case AUDIO_STREAM_STATE_PLAYING_LOOPED:
+ looped = true;
+ voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
+ break;
+ case AUDIO_STREAM_STATE_PLAYING:
+ voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
+ break;
+ case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
+ stop_cb = audio_mixer_play_stop_sequential_cb;
+ voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
+ break;
+ default:
+ break;
}
- audio_mixer_streams[audio_mixer_current_max_idx].buf = buf;
- audio_mixer_streams[audio_mixer_current_max_idx].handle = handle;
- audio_mixer_streams[audio_mixer_current_max_idx].voice = voice;
- audio_mixer_streams[audio_mixer_current_max_idx].state = params->state;
- audio_mixer_streams[audio_mixer_current_max_idx].volume = params->volume;
- audio_mixer_streams[audio_mixer_current_max_idx].stop_cb = stop_cb;
+ audio_mixer_active = true;
- audio_mixer_current_max_idx++;
+ 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].state = params->state;
+ audio_mixer_streams[free_slot].volume = params->volume;
+ audio_mixer_streams[free_slot].stop_cb = stop_cb;
return true;
}
-static void audio_driver_mixer_remove_stream(unsigned i)
+enum audio_mixer_state audio_driver_mixer_get_stream_state(unsigned i)
{
- audio_mixer_sound_t *handle = audio_mixer_streams[i].handle;
- audio_mixer_voice_t *voice = audio_mixer_streams[i].voice;
+ if (i >= AUDIO_MIXER_MAX_STREAMS)
+ return AUDIO_STREAM_STATE_NONE;
+
+ return audio_mixer_streams[i].state;
+}
+
+static void audio_driver_mixer_play_stream_internal(unsigned i, unsigned type)
+{
+ bool set_state = false;
+
+ if (i >= AUDIO_MIXER_MAX_STREAMS)
+ return;
+
+ switch (audio_mixer_streams[i].state)
+ {
+ case AUDIO_STREAM_STATE_STOPPED:
+ audio_mixer_streams[i].voice = audio_mixer_play(audio_mixer_streams[i].handle,
+ (type == AUDIO_STREAM_STATE_PLAYING_LOOPED) ? true : false,
+ 1.0f, audio_mixer_streams[i].stop_cb);
+ set_state = true;
+ break;
+ case AUDIO_STREAM_STATE_PLAYING:
+ case AUDIO_STREAM_STATE_PLAYING_LOOPED:
+ case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
+ case AUDIO_STREAM_STATE_NONE:
+ break;
+ }
+
+ if (set_state)
+ audio_mixer_streams[i].state = (enum audio_mixer_state)type;
+}
+
+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_stream_looped(unsigned i)
+{
+ audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_cb;
+ audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING_LOOPED);
+}
+
+void audio_driver_mixer_play_stream_sequential(unsigned i)
+{
+ audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_sequential_cb;
+ audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL);
+}
+
+float audio_driver_mixer_get_stream_volume(unsigned i)
+{
+ if (i >= AUDIO_MIXER_MAX_STREAMS)
+ return 0.0f;
+
+ return audio_mixer_streams[i].volume;
+}
+
+void audio_driver_mixer_set_stream_volume(unsigned i, float vol)
+{
+ audio_mixer_voice_t *voice = NULL;
+
+ if (i >= AUDIO_MIXER_MAX_STREAMS)
+ return;
+
+ audio_mixer_streams[i].volume = vol;
+
+ voice = audio_mixer_streams[i].voice;
+
+ if (voice)
+ audio_mixer_voice_set_volume(voice, db_to_gain(vol));
+}
+
+void audio_driver_mixer_stop_stream(unsigned i)
+{
+ bool set_state = false;
+
+ if (i >= AUDIO_MIXER_MAX_STREAMS)
+ return;
switch (audio_mixer_streams[i].state)
{
case AUDIO_STREAM_STATE_PLAYING:
- if (voice)
- audio_mixer_stop(voice);
- if (handle)
- audio_mixer_destroy(handle);
- break;
case AUDIO_STREAM_STATE_PLAYING_LOOPED:
- if (voice)
- audio_mixer_stop(voice);
- if (handle)
- audio_mixer_destroy(handle);
+ case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
+ set_state = true;
break;
case AUDIO_STREAM_STATE_STOPPED:
- if (handle)
- audio_mixer_destroy(handle);
+ case AUDIO_STREAM_STATE_NONE:
+ break;
+ }
+
+ if (set_state)
+ {
+ audio_mixer_voice_t *voice = audio_mixer_streams[i].voice;
+
+ if (voice)
+ audio_mixer_stop(voice);
+ audio_mixer_streams[i].state = AUDIO_STREAM_STATE_STOPPED;
+ audio_mixer_streams[i].volume = 1.0f;
+ }
+}
+
+void audio_driver_mixer_remove_stream(unsigned i)
+{
+ bool destroy = false;
+
+ if (i >= AUDIO_MIXER_MAX_STREAMS)
+ return;
+
+ switch (audio_mixer_streams[i].state)
+ {
+ case AUDIO_STREAM_STATE_PLAYING:
+ case AUDIO_STREAM_STATE_PLAYING_LOOPED:
+ case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
+ audio_driver_mixer_stop_stream(i);
+ destroy = true;
+ break;
+ case AUDIO_STREAM_STATE_STOPPED:
+ destroy = true;
break;
case AUDIO_STREAM_STATE_NONE:
break;
}
- audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE;
- audio_mixer_streams[i].volume = 0.0f;
- audio_mixer_streams[i].stop_cb = NULL;
- audio_mixer_streams[i].handle = NULL;
- audio_mixer_streams[i].voice = NULL;
+ if (destroy)
+ {
+ audio_mixer_sound_t *handle = audio_mixer_streams[i].handle;
+ if (handle)
+ audio_mixer_destroy(handle);
+
+ if (!string_is_empty(audio_mixer_streams[i].name))
+ free(audio_mixer_streams[i].name);
+
+ audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE;
+ audio_mixer_streams[i].stop_cb = NULL;
+ audio_mixer_streams[i].volume = 0.0f;
+ audio_mixer_streams[i].handle = NULL;
+ audio_mixer_streams[i].voice = NULL;
+ audio_mixer_streams[i].name = NULL;
+ }
}
static void audio_driver_mixer_deinit(void)
{
unsigned i;
- audio_set_bool(AUDIO_ACTION_MIXER, false);
+ audio_mixer_active = false;
for (i = 0; i < AUDIO_MIXER_MAX_STREAMS; i++)
+ {
+ audio_driver_mixer_stop_stream(i);
audio_driver_mixer_remove_stream(i);
+ }
- audio_mixer_current_max_idx = 0;
audio_mixer_done();
}
@@ -1351,15 +1579,6 @@ void audio_set_bool(enum audio_action action, bool val)
}
}
-/**
- * db_to_gain:
- * @db : Decibels.
- *
- * Converts decibels to voltage gain.
- *
- * Returns: voltage gain value.
- **/
-#define db_to_gain(db) (powf(10.0f, (db) / 20.0f))
void audio_set_float(enum audio_action action, float val)
{
diff --git a/audio/audio_driver.h b/audio/audio_driver.h
index 6dfacaa89f..a2cdad4f41 100644
--- a/audio/audio_driver.h
+++ b/audio/audio_driver.h
@@ -35,6 +35,8 @@ RETRO_BEGIN_DECLS
#define AUDIO_MAX_RATIO 16
+#define AUDIO_MIXER_MAX_STREAMS 16
+
enum audio_action
{
AUDIO_ACTION_NONE = 0,
@@ -46,6 +48,27 @@ enum audio_action
AUDIO_ACTION_MIXER
};
+enum audio_mixer_state
+{
+ AUDIO_STREAM_STATE_NONE = 0,
+ AUDIO_STREAM_STATE_STOPPED,
+ AUDIO_STREAM_STATE_PLAYING,
+ AUDIO_STREAM_STATE_PLAYING_LOOPED,
+ AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL
+};
+
+typedef struct audio_mixer_stream
+{
+ audio_mixer_sound_t *handle;
+ audio_mixer_voice_t *voice;
+ audio_mixer_stop_cb_t stop_cb;
+ enum audio_mixer_state state;
+ float volume;
+ void *buf;
+ char *name;
+ size_t bufsize;
+} audio_mixer_stream_t;
+
typedef struct audio_statistics
{
float average_buffer_saturation;
@@ -137,20 +160,13 @@ typedef struct audio_driver
size_t (*buffer_size)(void *data);
} audio_driver_t;
-enum audio_mixer_state
-{
- AUDIO_STREAM_STATE_NONE = 0,
- AUDIO_STREAM_STATE_STOPPED,
- AUDIO_STREAM_STATE_PLAYING,
- AUDIO_STREAM_STATE_PLAYING_LOOPED
-};
-
typedef struct audio_mixer_stream_params
{
float volume;
enum audio_mixer_type type;
enum audio_mixer_state state;
void *buf;
+ char *basename;
size_t bufsize;
audio_mixer_stop_cb_t cb;
} audio_mixer_stream_params_t;
@@ -271,10 +287,32 @@ bool audio_driver_deinit(void);
bool audio_driver_init(void);
+void audio_driver_menu_sample(void);
+
+audio_mixer_stream_t *audio_driver_mixer_get_stream(unsigned i);
+
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_stream_sequential(unsigned i);
+
+void audio_driver_mixer_play_stream_looped(unsigned i);
+
+void audio_driver_mixer_stop_stream(unsigned i);
+
+float audio_driver_mixer_get_stream_volume(unsigned i);
+
+void audio_driver_mixer_set_stream_volume(unsigned i, float vol);
+
+void audio_driver_mixer_remove_stream(unsigned i);
+
enum resampler_quality audio_driver_get_resampler_quality(void);
+enum audio_mixer_state audio_driver_mixer_get_stream_state(unsigned i);
+
+const char *audio_driver_mixer_get_stream_name(unsigned i);
+
bool compute_audio_buffer_statistics(audio_statistics_t *stats);
extern audio_driver_t audio_rsound;
diff --git a/audio/drivers/wiiu_audio.c b/audio/drivers/wiiu_audio.c
index 437ee310bf..0ea9106206 100644
--- a/audio/drivers/wiiu_audio.c
+++ b/audio/drivers/wiiu_audio.c
@@ -84,7 +84,7 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency,
u16 setup_buf[0x30] = {0};
setup_buf[0x25] = 2; /* we request 2 channels */
AXInitParams init = {AX_INIT_RENDERER_48KHZ, 0, 0};
- AXVoiceVeData ve = {0xF000, 0};
+ AXVoiceVeData ve = {0x8000, 0};
ax_audio_t* ax = (ax_audio_t*)calloc(1, sizeof(ax_audio_t));
if (!ax)
diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c
index 57f027641f..c542783d29 100644
--- a/cheevos/cheevos.c
+++ b/cheevos/cheevos.c
@@ -107,6 +107,8 @@
#define CHEEVOS_JSON_KEY_LEADERBOARDS 0xf1247d2dU
#define CHEEVOS_JSON_KEY_MEM 0x0b8807e4U
#define CHEEVOS_JSON_KEY_FORMAT 0xb341208eU
+#define CHEEVOS_JSON_KEY_SUCCESS 0x110461deU
+#define CHEEVOS_JSON_KEY_ERROR 0x0d2011cfU
typedef struct
{
@@ -284,6 +286,8 @@ static cheevos_locals_t cheevos_locals =
};
bool cheevos_loaded = false;
+bool cheevos_hardcore_active = false;
+bool cheevos_hardcore_paused = false;
int cheats_are_enabled = 0;
int cheats_were_enabled = 0;
@@ -299,6 +303,15 @@ int cheats_were_enabled = 0;
Supporting functions.
*****************************************************************************/
+#ifndef CHEEVOS_VERBOSE
+
+void cheevos_log(const char *fmt, ...)
+{
+ (void)fmt;
+}
+
+#endif
+
static unsigned size_in_megabytes(unsigned val)
{
return (val * 1024 * 1024);
@@ -308,7 +321,7 @@ static unsigned size_in_megabytes(unsigned val)
static void cheevos_log_url(const char* format, const char* url)
{
#ifdef CHEEVOS_LOG_PASSWORD
- RARCH_LOG(format, url);
+ CHEEVOS_LOG(format, url);
#else
char copy[256];
char* aux = NULL;
@@ -359,340 +372,11 @@ static void cheevos_log_url(const char* format, const char* url)
*aux = 0;
}
- RARCH_LOG(format, copy);
+ CHEEVOS_LOG(format, copy);
#endif
}
#endif
-#ifdef CHEEVOS_VERBOSE
-static void cheevos_add_char(char** aux, size_t* left, char k)
-{
- if (*left >= 1)
- {
- **aux = k;
- (*aux)++;
- (*left)--;
- }
-}
-
-static void cheevos_add_string(char** aux, size_t* left, const char* s)
-{
- size_t len = strlen(s);
-
- if (*left >= len)
- {
- strcpy(*aux, s);
- *aux += len;
- *left -= len;
- }
-}
-
-static void cheevos_add_hex(char** aux, size_t* left, unsigned v)
-{
- char buffer[32];
-
- snprintf(buffer, sizeof(buffer), "%06x", v);
- buffer[sizeof(buffer) - 1] = 0;
-
- cheevos_add_string(aux, left, buffer);
-}
-
-static void cheevos_add_uint(char** aux, size_t* left, unsigned v)
-{
- char buffer[32];
-
- snprintf(buffer, sizeof(buffer), "%u", v);
- buffer[sizeof(buffer) - 1] = 0;
-
- cheevos_add_string(aux, left, buffer);
-}
-
-static void cheevos_add_int(char** aux, size_t* left, int v)
-{
- char buffer[32];
-
- snprintf(buffer, sizeof(buffer), "%d", v);
- buffer[sizeof(buffer) - 1] = 0;
-
- cheevos_add_string(aux, left, buffer);
-}
-
-static void cheevos_log_var(const cheevos_var_t* var)
-{
- if (!var)
- return;
-
- RARCH_LOG("[CHEEVOS]: size: %s\n",
- var->size == CHEEVOS_VAR_SIZE_BIT_0 ? "bit 0" :
- var->size == CHEEVOS_VAR_SIZE_BIT_1 ? "bit 1" :
- var->size == CHEEVOS_VAR_SIZE_BIT_2 ? "bit 2" :
- var->size == CHEEVOS_VAR_SIZE_BIT_3 ? "bit 3" :
- var->size == CHEEVOS_VAR_SIZE_BIT_4 ? "bit 4" :
- var->size == CHEEVOS_VAR_SIZE_BIT_5 ? "bit 5" :
- var->size == CHEEVOS_VAR_SIZE_BIT_6 ? "bit 6" :
- var->size == CHEEVOS_VAR_SIZE_BIT_7 ? "bit 7" :
- var->size == CHEEVOS_VAR_SIZE_NIBBLE_LOWER ? "low nibble" :
- var->size == CHEEVOS_VAR_SIZE_NIBBLE_UPPER ? "high nibble" :
- var->size == CHEEVOS_VAR_SIZE_EIGHT_BITS ? "byte" :
- var->size == CHEEVOS_VAR_SIZE_SIXTEEN_BITS ? "word" :
- var->size == CHEEVOS_VAR_SIZE_THIRTYTWO_BITS ? "dword" :
- "?"
- );
- RARCH_LOG("[CHEEVOS]: type: %s\n",
- var->type == CHEEVOS_VAR_TYPE_ADDRESS ? "address" :
- var->type == CHEEVOS_VAR_TYPE_VALUE_COMP ? "value" :
- var->type == CHEEVOS_VAR_TYPE_DELTA_MEM ? "delta" :
- var->type == CHEEVOS_VAR_TYPE_DYNAMIC_VAR ? "dynamic" :
- "?"
- );
- RARCH_LOG("[CHEEVOS]: value: %u\n", var->value);
-}
-
-static void cheevos_log_cond(const cheevos_cond_t* cond)
-{
- if (!cond)
- return;
-
- RARCH_LOG("[CHEEVOS]: condition %p\n", cond);
- RARCH_LOG("[CHEEVOS]: type: %s\n",
- cond->type == CHEEVOS_COND_TYPE_STANDARD ? "standard" :
- cond->type == CHEEVOS_COND_TYPE_PAUSE_IF ? "pause" :
- cond->type == CHEEVOS_COND_TYPE_RESET_IF ? "reset" :
- cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE ? "add source" :
- cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE ? "sub source" :
- cond->type == CHEEVOS_COND_TYPE_ADD_HITS ? "add hits" :
- "?"
- );
- RARCH_LOG("[CHEEVOS]: req_hits: %u\n", cond->req_hits);
- RARCH_LOG("[CHEEVOS]: source:\n");
- cheevos_log_var(&cond->source);
- RARCH_LOG("[CHEEVOS]: op: %s\n",
- cond->op == CHEEVOS_COND_OP_EQUALS ? "==" :
- cond->op == CHEEVOS_COND_OP_LESS_THAN ? "<" :
- cond->op == CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL ? "<=" :
- cond->op == CHEEVOS_COND_OP_GREATER_THAN ? ">" :
- cond->op == CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL ? ">=" :
- cond->op == CHEEVOS_COND_OP_NOT_EQUAL_TO ? "!=" :
- "?"
- );
- RARCH_LOG("[CHEEVOS]: target:\n");
- cheevos_log_var(&cond->target);
-}
-
-static void cheevos_log_cheevo(const cheevo_t* cheevo,
- const cheevos_field_t* memaddr_ud)
-{
- if (!cheevo || !memaddr_ud)
- return;
-
- RARCH_LOG("[CHEEVOS]: cheevo %p\n", cheevo);
- RARCH_LOG("[CHEEVOS]: id: %u\n", cheevo->id);
- RARCH_LOG("[CHEEVOS]: title: %s\n", cheevo->title);
- RARCH_LOG("[CHEEVOS]: desc: %s\n", cheevo->description);
- RARCH_LOG("[CHEEVOS]: author: %s\n", cheevo->author);
- RARCH_LOG("[CHEEVOS]: badge: %s\n", cheevo->badge);
- RARCH_LOG("[CHEEVOS]: points: %u\n", cheevo->points);
- RARCH_LOG("[CHEEVOS]: sets: TBD\n");
- RARCH_LOG("[CHEEVOS]: memaddr: %.*s\n",
- (int)memaddr_ud->length, memaddr_ud->string);
-}
-
-static void cheevos_add_var_size(char** aux, size_t* left,
- const cheevos_var_t* var)
-{
- if (!var)
- return;
-
- switch( var->size )
- {
- case CHEEVOS_VAR_SIZE_BIT_0:
- cheevos_add_char(aux, left, 'M');
- break;
- case CHEEVOS_VAR_SIZE_BIT_1:
- cheevos_add_char(aux, left, 'N');
- break;
- case CHEEVOS_VAR_SIZE_BIT_2:
- cheevos_add_char(aux, left, 'O');
- break;
- case CHEEVOS_VAR_SIZE_BIT_3:
- cheevos_add_char(aux, left, 'P');
- break;
- case CHEEVOS_VAR_SIZE_BIT_4:
- cheevos_add_char(aux, left, 'Q');
- break;
- case CHEEVOS_VAR_SIZE_BIT_5:
- cheevos_add_char(aux, left, 'R');
- break;
- case CHEEVOS_VAR_SIZE_BIT_6:
- cheevos_add_char(aux, left, 'S');
- break;
- case CHEEVOS_VAR_SIZE_BIT_7:
- cheevos_add_char(aux, left, 'T');
- break;
- case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
- cheevos_add_char(aux, left, 'L');
- break;
- case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
- cheevos_add_char(aux, left, 'U');
- break;
- case CHEEVOS_VAR_SIZE_EIGHT_BITS:
- cheevos_add_char(aux, left, 'H');
- break;
- case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
- cheevos_add_char(aux, left, 'X');
- break;
- case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
- default:
- cheevos_add_char(aux, left, ' ');
- break;
- }
-}
-
-static void cheevos_add_var(const cheevos_var_t* var, char** memaddr,
- size_t *left)
-{
- if (!var)
- return;
-
- if ( var->type == CHEEVOS_VAR_TYPE_ADDRESS
- || var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
- {
- if (var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
- cheevos_add_char(memaddr, left, 'd');
- else if (var->is_bcd)
- cheevos_add_char(memaddr, left, 'b');
-
- cheevos_add_string(memaddr, left, "0x");
- cheevos_add_var_size(memaddr, left, var);
- cheevos_add_hex(memaddr, left, var->value);
- }
- else if (var->type == CHEEVOS_VAR_TYPE_VALUE_COMP)
- {
- cheevos_add_uint(memaddr, left, var->value);
- }
-}
-
-static void cheevos_build_memaddr(const cheevos_condition_t* condition,
- char* memaddr, size_t left)
-{
- size_t i, j;
- const cheevos_cond_t* cond;
- const cheevos_condset_t *condset;
- char *aux = memaddr;
-
- left--; /* reserve one char for the null terminator */
-
- for (i = 0, condset = condition->condsets;
- i < condition->count; i++, condset++)
- {
- if (i != 0)
- cheevos_add_char(&aux, &left, 'S');
-
- for (j = 0, cond = condset->conds;
- j < condset->count; j++, cond++)
- {
- if (j != 0)
- cheevos_add_char(&aux, &left, '_');
-
- if (cond->type == CHEEVOS_COND_TYPE_RESET_IF)
- cheevos_add_string(&aux, &left, "R:");
- else if (cond->type == CHEEVOS_COND_TYPE_PAUSE_IF)
- cheevos_add_string(&aux, &left, "P:");
- else if (cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE)
- cheevos_add_string(&aux, &left, "A:");
- else if (cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE)
- cheevos_add_string(&aux, &left, "B:");
- else if (cond->type == CHEEVOS_COND_TYPE_ADD_HITS)
- cheevos_add_string(&aux, &left, "C:");
-
- cheevos_add_var(&cond->source, &aux, &left);
-
- switch (cond->op)
- {
- case CHEEVOS_COND_OP_EQUALS:
- cheevos_add_char(&aux, &left, '=');
- break;
- case CHEEVOS_COND_OP_GREATER_THAN:
- cheevos_add_char(&aux, &left, '>');
- break;
- case CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL:
- cheevos_add_string(&aux, &left, ">=");
- break;
- case CHEEVOS_COND_OP_LESS_THAN:
- cheevos_add_char(&aux, &left, '<');
- break;
- case CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL:
- cheevos_add_string(&aux, &left, "<=");
- break;
- case CHEEVOS_COND_OP_NOT_EQUAL_TO:
- cheevos_add_string(&aux, &left, "!=");
- break;
- }
-
- cheevos_add_var(&cond->target, &aux, &left);
-
- if (cond->req_hits > 0)
- {
- cheevos_add_char(&aux, &left, '.');
- cheevos_add_uint(&aux, &left, cond->req_hits);
- cheevos_add_char(&aux, &left, '.');
- }
- }
- }
-
- *aux = 0;
-}
-
-static void cheevos_post_log_cheevo(const cheevo_t* cheevo)
-{
- char memaddr[256];
- if (!cheevo)
- return;
- cheevos_build_memaddr(&cheevo->condition, memaddr, sizeof(memaddr));
- RARCH_LOG("[CHEEVOS]: memaddr (computed): %s\n", memaddr);
-}
-
-static void cheevos_log_lboard(const cheevos_leaderboard_t* lb)
-{
- unsigned i;
- char mem[256];
- char* aux = NULL;
- size_t left = 0;
-
- if (!lb)
- return;
-
- RARCH_LOG("[CHEEVOS]: leaderboard %p\n", lb);
- RARCH_LOG("[CHEEVOS]: id: %u\n", lb->id);
- RARCH_LOG("[CHEEVOS]: title: %s\n", lb->title);
- RARCH_LOG("[CHEEVOS]: desc: %s\n", lb->description);
-
- cheevos_build_memaddr(&lb->start, mem, sizeof(mem));
- RARCH_LOG("[CHEEVOS]: start: %s\n", mem);
-
- cheevos_build_memaddr(&lb->cancel, mem, sizeof(mem));
- RARCH_LOG("[CHEEVOS]: cancel: %s\n", mem);
-
- cheevos_build_memaddr(&lb->submit, mem, sizeof(mem));
- RARCH_LOG("[CHEEVOS]: submit: %s\n", mem);
-
- left = sizeof(mem);
- aux = mem;
-
- for (i = 0; i < lb->value.count; i++)
- {
- if (i != 0)
- cheevos_add_char(&aux, &left, '_');
-
- cheevos_add_var(&lb->value.terms[i].var, &aux, &left);
- cheevos_add_char(&aux, &left, '*');
- cheevos_add_int(&aux, &left, lb->value.terms[i].multiplier);
- }
-
- RARCH_LOG("[CHEEVOS]: value: %s\n", mem);
-}
-#endif
-
static uint32_t cheevos_djb2(const char* str, size_t length)
{
const unsigned char *aux = (const unsigned char*)str;
@@ -962,10 +646,8 @@ static int cheevos_parse_condition(
cheevos_cond_count_in_set(memaddr, set);
condset->conds = NULL;
-#ifdef CHEEVOS_VERBOSE
- RARCH_LOG("[CHEEVOS]: set %p (index=%u)\n", condset, set);
- RARCH_LOG("[CHEEVOS]: conds: %u\n", condset->count);
-#endif
+ CHEEVOS_LOG("[CHEEVOS]: set %p (index=%u)\n", condset, set);
+ CHEEVOS_LOG("[CHEEVOS]: conds: %u\n", condset->count);
if (condset->count)
{
@@ -1210,23 +892,15 @@ static int cheevos_new_cheevo(cheevos_readud_t *ud)
cheevo->last = 1;
cheevo->modified = 0;
- if ( !cheevo->title ||
- !cheevo->description ||
- !cheevo->author ||
+ if ( !cheevo->title ||
+ !cheevo->description ||
+ !cheevo->author ||
!cheevo->badge)
goto error;
-#ifdef CHEEVOS_VERBOSE
- cheevos_log_cheevo(cheevo, &ud->memaddr);
-#endif
-
if (cheevos_parse_condition(&cheevo->condition, ud->memaddr.string))
goto error;
-#ifdef CHEEVOS_VERBOSE
- cheevos_post_log_cheevo(cheevo);
-#endif
-
return 0;
error:
@@ -1334,12 +1008,10 @@ static int cheevos_new_lboard(cheevos_readud_t *ud)
if (!ldb || !ud)
return -1;
+
lboard = ldb + ud->lboard_count++;
- if (!lboard)
- return -1;
-
- lboard->id = strtol(ud->id.string, NULL, 10);
+ lboard->id = (unsigned)strtol(ud->id.string, NULL, 10);
lboard->format = cheevos_parse_format(&ud->format);
lboard->title = cheevos_dupstr(&ud->title);
lboard->description = cheevos_dupstr(&ud->desc);
@@ -1350,10 +1022,6 @@ static int cheevos_new_lboard(cheevos_readud_t *ud)
if (cheevos_parse_mem(lboard, ud->memaddr.string))
goto error;
-#ifdef CHEEVOS_VERBOSE
- cheevos_log_lboard(lboard);
-#endif
-
return 0;
error:
@@ -1548,7 +1216,7 @@ static int cheevos_parse(const char *json)
calloc(lboard_count, sizeof(cheevos_leaderboard_t));
cheevos_locals.lboard_count = lboard_count;
- if ( !cheevos_locals.core.cheevos ||
+ if ( !cheevos_locals.core.cheevos ||
!cheevos_locals.unofficial.cheevos ||
!cheevos_locals.leaderboards)
{
@@ -1596,7 +1264,7 @@ static int cheevos_test_condition(cheevos_cond_t *cond)
if (!cond)
return 0;
- sval = cheevos_var_get_value(&cond->source) +
+ sval = cheevos_var_get_value(&cond->source) +
cheevos_locals.add_buffer;
tval = cheevos_var_get_value(&cond->target);
@@ -1621,62 +1289,31 @@ static int cheevos_test_condition(cheevos_cond_t *cond)
return 1;
}
-static int cheevos_test_cond_set(const cheevos_condset_t *condset,
- int *dirty_conds, int *reset_conds, int match_any)
+static int cheevos_test_pause_cond_set(const cheevos_condset_t *condset,
+ int *dirty_conds, int *reset_conds, int process_pause)
{
int cond_valid = 0;
- int set_valid = 1;
- const cheevos_cond_t *end = NULL;
+ int set_valid = 1; /* must start true so AND logic works */
cheevos_cond_t *cond = NULL;
-
- if (!condset)
- return 0;
-
- end = condset->conds + condset->count;
+ const cheevos_cond_t *end = condset->conds + condset->count;
cheevos_locals.add_buffer = 0;
cheevos_locals.add_hits = 0;
- /* Now, read all Pause conditions, and if any are true,
- * do not process further (retain old state). */
-
for (cond = condset->conds; cond < end; cond++)
{
- if (cond->type != CHEEVOS_COND_TYPE_PAUSE_IF)
- continue;
-
- /* Reset by default, set to 1 if hit! */
- cond->curr_hits = 0;
-
- if (cheevos_test_condition(cond))
- {
- cond->curr_hits = 1;
- *dirty_conds = 1;
-
- /* Early out: this achievement is paused,
- * do not process any further! */
- return 0;
- }
- }
-
- /* Read all standard conditions, and process as normal: */
- for (cond = condset->conds; cond < end; cond++)
- {
- if ( cond->type == CHEEVOS_COND_TYPE_PAUSE_IF ||
- cond->type == CHEEVOS_COND_TYPE_RESET_IF)
+ if (cond->pause != process_pause)
continue;
if (cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE)
{
cheevos_locals.add_buffer += cheevos_var_get_value(&cond->source);
- set_valid &= 1;
continue;
}
if (cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE)
{
cheevos_locals.add_buffer -= cheevos_var_get_value(&cond->source);
- set_valid &= 1;
continue;
}
@@ -1692,17 +1329,17 @@ static int cheevos_test_cond_set(const cheevos_condset_t *condset,
continue;
}
- if ( (cond->req_hits != 0) &&
- (cond->curr_hits + cheevos_locals.add_hits) >= cond->req_hits)
- {
- cheevos_locals.add_buffer = 0;
- cheevos_locals.add_hits = 0;
- continue;
- }
-
+ /* always evaluate the condition to ensure delta values get tracked correctly */
cond_valid = cheevos_test_condition(cond);
- if (cond_valid)
+ /* if the condition has a target hit count that has already been met,
+ * it's automatically true, even if not currently true. */
+ if ( (cond->req_hits != 0) &&
+ (cond->curr_hits + cheevos_locals.add_hits) >= cond->req_hits)
+ {
+ cond_valid = 1;
+ }
+ else if (cond_valid)
{
cond->curr_hits++;
*dirty_conds = 1;
@@ -1711,38 +1348,100 @@ static int cheevos_test_cond_set(const cheevos_condset_t *condset,
if (cond->req_hits == 0)
; /* Not a hit-based requirement: ignore any additional logic! */
else if ((cond->curr_hits + cheevos_locals.add_hits) < cond->req_hits)
- cond_valid = 0; /* Not entirely valid yet! */
-
- if (match_any)
- break;
+ cond_valid = 0; /* HitCount target has not yet been met, condition is not yet valid. */
}
cheevos_locals.add_buffer = 0;
cheevos_locals.add_hits = 0;
- /* Sequential or non-sequential? */
- set_valid &= cond_valid;
- }
-
- /* Now, ONLY read reset conditions! */
- for (cond = condset->conds; cond < end; cond++)
- {
- if (cond->type != CHEEVOS_COND_TYPE_RESET_IF)
- continue;
-
- cond_valid = cheevos_test_condition(cond);
-
- if (cond_valid)
+ if (cond->type == CHEEVOS_COND_TYPE_PAUSE_IF)
{
- *reset_conds = 1; /* Resets all hits found so far */
- set_valid = 0; /* Cannot be valid if we've hit a reset condition. */
- break; /* No point processing any further reset conditions. */
+ /* as soon as we find a PauseIf that evaluates to true,
+ * stop processing the rest of the group. */
+ if (cond_valid)
+ return 1;
+
+ /* if we make it to the end of the function, make sure we are
+ * indicating nothing matched. if we do find a later PauseIf match,
+ * it'll automatically return true via the previous condition. */
+ set_valid = 0;
+
+ if (cond->req_hits == 0)
+ {
+ /* PauseIf didn't evaluate true, and doesn't have a HitCount,
+ * reset the HitCount to indicate the condition didn't match. */
+ if (cond->curr_hits != 0)
+ {
+ cond->curr_hits = 0;
+ *dirty_conds = 1;
+ }
+ }
+ else
+ {
+ /* PauseIf has a HitCount that hasn't been met, ignore it for now. */
+ }
}
+ else if (cond->type == CHEEVOS_COND_TYPE_RESET_IF)
+ {
+ if (cond_valid)
+ {
+ *reset_conds = 1; /* Resets all hits found so far */
+ set_valid = 0; /* Cannot be valid if we've hit a reset condition. */
+ }
+ }
+ else /* Sequential or non-sequential? */
+ set_valid &= cond_valid;
}
return set_valid;
}
+static int cheevos_test_cond_set(const cheevos_condset_t *condset,
+ int *dirty_conds, int *reset_conds)
+{
+ int in_pause = 0;
+ int has_pause = 0;
+ cheevos_cond_t *cond = NULL;
+
+ if (!condset)
+ return 1; /* important: empty group must evaluate true */
+
+ /* the ints below are used for Pause conditions and their dependent AddSource/AddHits. */
+
+ /* this loop needs to go backwards to check AddSource/AddHits */
+ cond = condset->conds + condset->count - 1;
+ for (; cond >= condset->conds; cond--)
+ {
+ if (cond->type == CHEEVOS_COND_TYPE_PAUSE_IF)
+ {
+ has_pause = 1;
+ in_pause = 1;
+ cond->pause = 1;
+ }
+ else if (cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE ||
+ cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE ||
+ cond->type == CHEEVOS_COND_TYPE_ADD_HITS)
+ {
+ cond->pause = in_pause;
+ }
+ else
+ {
+ in_pause = 0;
+ cond->pause = 0;
+ }
+ }
+
+ if (has_pause)
+ { /* one or more Pause conditions exists, if any of them are true,
+ * stop processing this group. */
+ if (cheevos_test_pause_cond_set(condset, dirty_conds, reset_conds, 1))
+ return 0;
+ }
+
+ /* process the non-Pause conditions to see if the group is true */
+ return cheevos_test_pause_cond_set(condset, dirty_conds, reset_conds, 0);
+}
+
static int cheevos_reset_cond_set(cheevos_condset_t *condset, int deltas)
{
int dirty = 0;
@@ -1801,14 +1500,14 @@ static int cheevos_test_cheevo(cheevo_t *cheevo)
if (condset < end)
{
- ret_val = cheevos_test_cond_set(condset, &dirty_conds, &reset_conds, 0);
+ ret_val = cheevos_test_cond_set(condset, &dirty_conds, &reset_conds);
condset++;
}
while (condset < end)
{
ret_val_sub_cond |= cheevos_test_cond_set(
- condset, &dirty_conds, &reset_conds, 0);
+ condset, &dirty_conds, &reset_conds);
condset++;
}
@@ -1879,7 +1578,7 @@ static void cheevos_make_unlock_url(const cheevo_t *cheevo,
settings->arrays.cheevos_username,
cheevos_locals.token,
cheevo->id,
- settings->bools.cheevos_hardcore_mode_enable ? 1 : 0
+ settings->bools.cheevos_hardcore_mode_enable && !cheevos_hardcore_paused ? 1 : 0
);
url[url_size - 1] = 0;
@@ -1896,14 +1595,14 @@ static void cheevos_unlocked(void *task_data, void *user_data,
if (!error)
{
- RARCH_LOG("[CHEEVOS]: awarded achievement %u.\n", cheevo->id);
+ CHEEVOS_LOG("[CHEEVOS]: awarded achievement %u.\n", cheevo->id);
}
else
{
char url[256];
url[0] = '\0';
- RARCH_ERR("[CHEEVOS]: error awarding achievement %u, retrying...\n", cheevo->id);
+ CHEEVOS_ERR("[CHEEVOS]: error awarding achievement %u, retrying...\n", cheevo->id);
cheevos_make_unlock_url(cheevo, url, sizeof(url));
task_push_http_transfer(url, true, NULL, cheevos_unlocked, cheevo);
@@ -1922,7 +1621,7 @@ static void cheevos_test_cheevo_set(const cheevoset_t *set)
end = set->cheevos + set->count;
- if (settings && settings->bools.cheevos_hardcore_mode_enable)
+ if (settings && settings->bools.cheevos_hardcore_mode_enable && !cheevos_hardcore_paused)
mode = CHEEVOS_ACTIVE_HARDCORE;
for (cheevo = set->cheevos; cheevo < end; cheevo++)
@@ -1934,7 +1633,7 @@ static void cheevos_test_cheevo_set(const cheevoset_t *set)
if (cheevo->last)
{
cheevos_condset_t* condset = cheevo->condition.condsets;
- const cheevos_condset_t* end = cheevo->condition.condsets
+ const cheevos_condset_t* end = cheevo->condition.condsets
+ cheevo->condition.count;
for (; condset < end; condset++)
@@ -1951,7 +1650,7 @@ static void cheevos_test_cheevo_set(const cheevoset_t *set)
if (mode == CHEEVOS_ACTIVE_HARDCORE)
cheevo->active &= ~CHEEVOS_ACTIVE_SOFTCORE;
- RARCH_LOG("[CHEEVOS]: awarding cheevo %u: %s (%s).\n",
+ CHEEVOS_LOG("[CHEEVOS]: awarding cheevo %u: %s (%s).\n",
cheevo->id, cheevo->title, cheevo->description);
snprintf(msg, sizeof(msg), "Achievement Unlocked: %s",
@@ -1976,9 +1675,9 @@ static void cheevos_test_cheevo_set(const cheevoset_t *set)
if (take_screenshot(shotname, true,
video_driver_cached_frame_has_valid_framebuffer()))
- RARCH_LOG("[CHEEVOS]: got a screenshot for cheevo %u\n", cheevo->id);
+ CHEEVOS_LOG("[CHEEVOS]: got a screenshot for cheevo %u\n", cheevo->id);
else
- RARCH_LOG("[CHEEVOS]: failed to get screenshot for cheevo %u\n", cheevo->id);
+ CHEEVOS_LOG("[CHEEVOS]: failed to get screenshot for cheevo %u\n", cheevo->id);
}
}
@@ -2006,14 +1705,14 @@ static int cheevos_test_lboard_condition(const cheevos_condition_t* condition)
if (condset < end)
{
ret_val = cheevos_test_cond_set(
- condset, &dirty_conds, &reset_conds, 0);
+ condset, &dirty_conds, &reset_conds);
condset++;
}
while (condset < end)
{
ret_val_sub_cond |= cheevos_test_cond_set(
- condset, &dirty_conds, &reset_conds, 0);
+ condset, &dirty_conds, &reset_conds);
condset++;
}
@@ -2044,7 +1743,7 @@ static int cheevos_expr_value(cheevos_expr_t* expr)
if (expr->compare_count >= ARRAY_SIZE(values))
{
- RARCH_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", expr->compare_count);
+ CHEEVOS_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", expr->compare_count);
return 0;
}
@@ -2054,11 +1753,11 @@ static int cheevos_expr_value(cheevos_expr_t* expr)
{
if (current_value >= ARRAY_SIZE(values))
{
- RARCH_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", current_value);
+ CHEEVOS_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", current_value);
return 0;
}
- values[current_value] +=
+ values[current_value] +=
cheevos_var_get_value(&term->var) * term->multiplier;
if (term->compare_next)
@@ -2128,11 +1827,11 @@ static void cheevos_lboard_submit(void *task_data, void *user_data,
if (!error)
{
- RARCH_ERR("[CHEEVOS]: error submitting leaderboard %u\n", lboard->id);
+ CHEEVOS_ERR("[CHEEVOS]: error submitting leaderboard %u\n", lboard->id);
return;
}
- RARCH_LOG("[CHEEVOS]: submitted leaderboard %u.\n", lboard->id);
+ CHEEVOS_LOG("[CHEEVOS]: submitted leaderboard %u.\n", lboard->id);
}
static void cheevos_test_leaderboards(void)
@@ -2151,10 +1850,8 @@ static void cheevos_test_leaderboards(void)
if (value != lboard->last_value)
{
-#ifdef CHEEVOS_VERBOSE
- RARCH_LOG("[CHEEVOS]: value lboard %s %u\n",
+ CHEEVOS_LOG("[CHEEVOS]: value lboard %s %u\n",
lboard->title, value);
-#endif
lboard->last_value = value;
}
@@ -2165,7 +1862,7 @@ static void cheevos_test_leaderboards(void)
/* failsafe for improper LBs */
if (value == 0)
{
- RARCH_LOG("[CHEEVOS]: error: lboard %s tried to submit 0\n",
+ CHEEVOS_LOG("[CHEEVOS]: error: lboard %s tried to submit 0\n",
lboard->title);
runloop_msg_queue_push("Leaderboard attempt cancelled!",
0, 2 * 60, false);
@@ -2179,7 +1876,7 @@ static void cheevos_test_leaderboards(void)
cheevos_make_lboard_url(lboard, url, sizeof(url));
task_push_http_transfer(url, true, NULL,
cheevos_lboard_submit, lboard);
- RARCH_LOG("[CHEEVOS]: submit lboard %s\n", lboard->title);
+ CHEEVOS_LOG("[CHEEVOS]: submit lboard %s\n", lboard->title);
cheevos_format_value(value, lboard->format,
formatted_value, sizeof(formatted_value));
@@ -2192,7 +1889,7 @@ static void cheevos_test_leaderboards(void)
if (cheevos_test_lboard_condition(&lboard->cancel))
{
- RARCH_LOG("[CHEEVOS]: cancel lboard %s\n", lboard->title);
+ CHEEVOS_LOG("[CHEEVOS]: cancel lboard %s\n", lboard->title);
lboard->active = 0;
runloop_msg_queue_push("Leaderboard attempt cancelled!",
0, 2 * 60, false);
@@ -2204,7 +1901,7 @@ static void cheevos_test_leaderboards(void)
{
char msg[256];
- RARCH_LOG("[CHEEVOS]: start lboard %s\n", lboard->title);
+ CHEEVOS_LOG("[CHEEVOS]: start lboard %s\n", lboard->title);
lboard->active = 1;
lboard->last_value = -1;
@@ -2317,10 +2014,10 @@ static int cheevos_deactivate__json_number(void *userdata,
}
if (found)
- RARCH_LOG("[CHEEVOS]: deactivated unlocked cheevo %u (%s).\n",
+ CHEEVOS_LOG("[CHEEVOS]: deactivated unlocked cheevo %u (%s).\n",
cheevo->id, cheevo->title);
else
- RARCH_ERR("[CHEEVOS]: unknown cheevo to deactivate: %u.\n", id);
+ CHEEVOS_ERR("[CHEEVOS]: unknown cheevo to deactivate: %u.\n", id);
}
return 0;
@@ -2359,7 +2056,7 @@ void cheevos_reset_game(void)
if (!cheevo)
return;
-
+
end = cheevo + cheevos_locals.core.count;
for (; cheevo < end; cheevo++)
@@ -2375,7 +2072,7 @@ void cheevos_reset_game(void)
void cheevos_populate_menu(void *data)
{
#ifdef HAVE_MENU
- unsigned i;
+ unsigned i = 0;
unsigned items_found = 0;
settings_t *settings = config_get_ptr();
menu_displaylist_info_t *info = (menu_displaylist_info_t*)data;
@@ -2383,40 +2080,55 @@ void cheevos_populate_menu(void *data)
cheevo_t *cheevo = cheevos_locals.core.cheevos;
end = cheevo + cheevos_locals.core.count;
+ if(settings->bools.cheevos_enable && settings->bools.cheevos_hardcore_mode_enable
+ && cheevos_loaded)
+ {
+ if (!cheevos_hardcore_paused)
+ menu_entries_append_enum(info->list,
+ msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
+ msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE),
+ MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE,
+ MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
+ else
+ menu_entries_append_enum(info->list,
+ msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
+ msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_RESUME),
+ MENU_ENUM_LABEL_ACHIEVEMENT_RESUME,
+ MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
+ }
+
if (cheevo)
{
for (i = 0; cheevo < end; i++, cheevo++)
{
if (!(cheevo->active & CHEEVOS_ACTIVE_HARDCORE))
{
- menu_entries_append_enum(info->list, cheevo->title,
+ menu_entries_append_enum(info->list, cheevo->title,
cheevo->description,
MENU_ENUM_LABEL_CHEEVOS_UNLOCKED_ENTRY_HARDCORE,
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
- items_found++;
- set_badge_info(&badges_ctx, i, cheevo->badge,
+ set_badge_info(&badges_ctx, i, cheevo->badge,
(cheevo->active & CHEEVOS_ACTIVE_HARDCORE));
}
else if (!(cheevo->active & CHEEVOS_ACTIVE_SOFTCORE))
{
- menu_entries_append_enum(info->list, cheevo->title,
+ menu_entries_append_enum(info->list, cheevo->title,
cheevo->description,
MENU_ENUM_LABEL_CHEEVOS_UNLOCKED_ENTRY,
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
- items_found++;
- set_badge_info(&badges_ctx, i, cheevo->badge,
+ set_badge_info(&badges_ctx, i, cheevo->badge,
(cheevo->active & CHEEVOS_ACTIVE_SOFTCORE));
}
else
{
- menu_entries_append_enum(info->list, cheevo->title,
+ menu_entries_append_enum(info->list, cheevo->title,
cheevo->description,
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
- items_found++;
- set_badge_info(&badges_ctx, i, cheevo->badge,
+ set_badge_info(&badges_ctx, i, cheevo->badge,
(cheevo->active & CHEEVOS_ACTIVE_SOFTCORE));
}
+ items_found++;
}
}
@@ -2426,7 +2138,7 @@ void cheevos_populate_menu(void *data)
{
end = cheevo + cheevos_locals.unofficial.count;
- for (i = cheevos_locals.core.count; cheevo < end; i++, cheevo++)
+ for (i = items_found; cheevo < end; i++, cheevo++)
{
if (!(cheevo->active & CHEEVOS_ACTIVE_HARDCORE))
{
@@ -2434,7 +2146,6 @@ void cheevos_populate_menu(void *data)
cheevo->description,
MENU_ENUM_LABEL_CHEEVOS_UNLOCKED_ENTRY_HARDCORE,
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
- items_found++;
set_badge_info(&badges_ctx, i, cheevo->badge,
(cheevo->active & CHEEVOS_ACTIVE_HARDCORE));
}
@@ -2444,7 +2155,6 @@ void cheevos_populate_menu(void *data)
cheevo->description,
MENU_ENUM_LABEL_CHEEVOS_UNLOCKED_ENTRY,
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
- items_found++;
set_badge_info(&badges_ctx, i, cheevo->badge,
(cheevo->active & CHEEVOS_ACTIVE_SOFTCORE));
}
@@ -2454,10 +2164,10 @@ void cheevos_populate_menu(void *data)
cheevo->description,
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
- items_found++;
set_badge_info(&badges_ctx, i, cheevo->badge,
(cheevo->active & CHEEVOS_ACTIVE_SOFTCORE));
}
+ items_found++;
}
}
@@ -2487,7 +2197,7 @@ bool cheevos_get_description(cheevos_ctx_desc_t *desc)
if (desc->idx >= cheevos_locals.core.count)
{
cheevos = cheevos_locals.unofficial.cheevos;
- desc->idx -= cheevos_locals.unofficial.count;
+ desc->idx -= cheevos_locals.core.count;
}
if (!string_is_empty(cheevos[desc->idx].description))
@@ -2516,9 +2226,7 @@ bool cheevos_unload(void)
if (running)
{
-#ifdef CHEEVOS_VERBOSE
- RARCH_LOG("[CHEEVOS]: Asked the load thread to terminate\n");
-#endif
+ CHEEVOS_LOG("[CHEEVOS]: Asked the load thread to terminate\n");
task_queue_cancel_task(cheevos_locals.task);
#ifdef HAVE_THREADS
@@ -2544,6 +2252,7 @@ bool cheevos_unload(void)
cheevos_locals.unofficial.count = 0;
cheevos_loaded = false;
+ cheevos_hardcore_paused = false;
return true;
}
@@ -2556,19 +2265,19 @@ bool cheevos_toggle_hardcore_mode(void)
return false;
/* reset and deinit rewind to avoid cheat the score */
- if (settings->bools.cheevos_hardcore_mode_enable)
+ if (settings->bools.cheevos_hardcore_mode_enable && !cheevos_hardcore_paused)
{
const char *msg = msg_hash_to_str(
MSG_CHEEVOS_HARDCORE_MODE_ENABLE);
- /* send reset core cmd to avoid any user
+ /* send reset core cmd to avoid any user
* savestate previusly loaded. */
command_event(CMD_EVENT_RESET, NULL);
if (settings->bools.rewind_enable)
command_event(CMD_EVENT_REWIND_DEINIT, NULL);
- RARCH_LOG("%s\n", msg);
+ CHEEVOS_LOG("%s\n", msg);
runloop_msg_queue_push(msg, 0, 3 * 60, true);
}
else
@@ -2583,7 +2292,7 @@ bool cheevos_toggle_hardcore_mode(void)
static void cheevos_patch_addresses(cheevoset_t* set)
{
unsigned i;
- cheevo_t* cheevo = NULL;
+ cheevo_t* cheevo = NULL;
if (!set)
return;
@@ -2612,7 +2321,7 @@ static void cheevos_patch_addresses(cheevoset_t* set)
cheevos_var_patch_addr(&cond->source,
cheevos_locals.console_id);
#ifdef CHEEVOS_DUMP_ADDRS
- RARCH_LOG("[CHEEVOS]: s-var %03d:%08X\n",
+ CHEEVOS_LOG("[CHEEVOS]: s-var %03d:%08X\n",
cond->source.bank_id + 1, cond->source.value);
#endif
break;
@@ -2628,7 +2337,7 @@ static void cheevos_patch_addresses(cheevoset_t* set)
cheevos_var_patch_addr(&cond->target,
cheevos_locals.console_id);
#ifdef CHEEVOS_DUMP_ADDRS
- RARCH_LOG("[CHEEVOS]: t-var %03d:%08X\n",
+ CHEEVOS_LOG("[CHEEVOS]: t-var %03d:%08X\n",
cond->target.bank_id + 1, cond->target.value);
#endif
break;
@@ -2665,7 +2374,7 @@ static void cheevos_patch_lb_conditions(cheevos_condition_t* condition)
cheevos_var_patch_addr(&cond->source,
cheevos_locals.console_id);
#ifdef CHEEVOS_DUMP_ADDRS
- RARCH_LOG("[CHEEVOS]: s-var %03d:%08X\n",
+ CHEEVOS_LOG("[CHEEVOS]: s-var %03d:%08X\n",
cond->source.bank_id + 1, cond->source.value);
#endif
break;
@@ -2679,7 +2388,7 @@ static void cheevos_patch_lb_conditions(cheevos_condition_t* condition)
cheevos_var_patch_addr(&cond->target,
cheevos_locals.console_id);
#ifdef CHEEVOS_DUMP_ADDRS
- RARCH_LOG("[CHEEVOS]: t-var %03d:%08X\n",
+ CHEEVOS_LOG("[CHEEVOS]: t-var %03d:%08X\n",
cond->target.bank_id + 1, cond->target.value);
#endif
break;
@@ -2708,7 +2417,7 @@ static void cheevos_patch_lb_expressions(cheevos_expr_t* expression)
case CHEEVOS_VAR_TYPE_DELTA_MEM:
cheevos_var_patch_addr(&term->var, cheevos_locals.console_id);
#ifdef CHEEVOS_DUMP_ADDRS
- RARCH_LOG("[CHEEVOS]: s-var %03d:%08X\n",
+ CHEEVOS_LOG("[CHEEVOS]: s-var %03d:%08X\n",
term->var.bank_id + 1, term->var.value);
#endif
break;
@@ -2756,8 +2465,9 @@ void cheevos_test(void)
if (settings->bools.cheevos_test_unofficial)
cheevos_test_cheevo_set(&cheevos_locals.unofficial);
- if (settings->bools.cheevos_hardcore_mode_enable &&
- settings->bools.cheevos_leaderboards_enable)
+ if (settings->bools.cheevos_hardcore_mode_enable &&
+ settings->bools.cheevos_leaderboards_enable &&
+ !cheevos_hardcore_paused)
cheevos_test_leaderboards();
}
}
@@ -2787,14 +2497,14 @@ cheevos_console_t cheevos_get_console(void)
/* Uncomment the following two lines to debug cheevos_iterate, this will
* disable the coroutine yielding.
- *
+ *
* The code is very easy to understand. It's meant to be like BASIC:
* CORO_GOTO will jump execution to another label, CORO_GOSUB will
* call another label, and CORO_RET will return from a CORO_GOSUB.
- *
+ *
* This coroutine code is inspired in a very old pure C implementation
* that runs everywhere:
- *
+ *
* https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
*/
/*#undef CORO_YIELD
@@ -2911,6 +2621,8 @@ static int cheevos_iterate(coro_t *coro)
CORO_ENTER();
+
+
cheevos_locals.addrs_patched = false;
coro->settings = config_get_ptr();
@@ -2927,26 +2639,26 @@ static int cheevos_iterate(coro_t *coro)
cheevos_locals.meminfo[3].id = RETRO_MEMORY_RTC;
core_get_memory(&cheevos_locals.meminfo[3]);
- RARCH_LOG("[CHEEVOS]: system RAM: %p %u\n",
+ CHEEVOS_LOG("[CHEEVOS]: system RAM: %p %u\n",
cheevos_locals.meminfo[0].data,
cheevos_locals.meminfo[0].size);
- RARCH_LOG("[CHEEVOS]: save RAM: %p %u\n",
+ CHEEVOS_LOG("[CHEEVOS]: save RAM: %p %u\n",
cheevos_locals.meminfo[1].data,
cheevos_locals.meminfo[1].size);
- RARCH_LOG("[CHEEVOS]: video RAM: %p %u\n",
+ CHEEVOS_LOG("[CHEEVOS]: video RAM: %p %u\n",
cheevos_locals.meminfo[2].data,
cheevos_locals.meminfo[2].size);
- RARCH_LOG("[CHEEVOS]: RTC: %p %u\n",
+ CHEEVOS_LOG("[CHEEVOS]: RTC: %p %u\n",
cheevos_locals.meminfo[3].data,
cheevos_locals.meminfo[3].size);
/* Bail out if cheevos are disabled.
- * But set the above anyways,
+ * But set the above anyways,
* command_read_ram needs it. */
if (!coro->settings->bools.cheevos_enable)
CORO_STOP();
- /* Load the content into memory, or copy it
+ /* Load the content into memory, or copy it
* over to our own buffer */
if (!coro->data)
{
@@ -3034,7 +2746,7 @@ static int cheevos_iterate(coro_t *coro)
{
if (finders[coro->i].ext_hashes[coro->j] == hash)
{
- RARCH_LOG("[CHEEVOS]: testing %s.\n",
+ CHEEVOS_LOG("[CHEEVOS]: testing %s.\n",
finders[coro->i].name);
/*
@@ -3059,7 +2771,7 @@ static int cheevos_iterate(coro_t *coro)
if (finders[coro->i].ext_hashes)
continue;
- RARCH_LOG("[CHEEVOS]: testing %s.\n",
+ CHEEVOS_LOG("[CHEEVOS]: testing %s.\n",
finders[coro->i].name);
/*
@@ -3072,7 +2784,7 @@ static int cheevos_iterate(coro_t *coro)
goto found;
}
- RARCH_LOG("[CHEEVOS]: this game doesn't feature achievements.\n");
+ CHEEVOS_LOG("[CHEEVOS]: this game doesn't feature achievements.\n");
CORO_STOP();
found:
@@ -3098,7 +2810,7 @@ found:
if (!coro->json)
{
runloop_msg_queue_push("Error loading achievements.", 0, 5 * 60, false);
- RARCH_ERR("[CHEEVOS]: error loading achievements.\n");
+ CHEEVOS_ERR("[CHEEVOS]: error loading achievements.\n");
CORO_STOP();
}
#endif
@@ -3137,6 +2849,7 @@ found:
cheevos_locals.unofficial.count = 0;
cheevos_loaded = false;
+ cheevos_hardcore_paused = false;
CORO_STOP();
}
@@ -3162,7 +2875,7 @@ found:
const cheevo_t* end = cheevo + cheevos_locals.core.count;
int number_of_unlocked = cheevos_locals.core.count;
- if (coro->settings->bools.cheevos_hardcore_mode_enable)
+ if (coro->settings->bools.cheevos_hardcore_mode_enable && !cheevos_hardcore_paused)
mode = CHEEVOS_ACTIVE_HARDCORE;
for (; cheevo < end; cheevo++)
@@ -3317,7 +3030,7 @@ found:
/* from FCEU core - check if Trainer included in ROM data */
MD5_Init(&coro->md5);
- coro->offset = sizeof(coro->header) + (coro->header.rom_type & 4
+ coro->offset = sizeof(coro->header) + (coro->header.rom_type & 4
? sizeof(coro->header) : 0);
coro->count = 0x4000 * coro->bytes;
CORO_GOSUB(EVAL_MD5);
@@ -3428,7 +3141,7 @@ found:
{
char gameid[16];
- RARCH_LOG(
+ CHEEVOS_LOG(
"[CHEEVOS]: getting game id for hash %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
coro->hash[ 0], coro->hash[ 1], coro->hash[ 2], coro->hash[ 3],
coro->hash[ 4], coro->hash[ 5], coro->hash[ 6], coro->hash[ 7],
@@ -3461,14 +3174,14 @@ found:
{
if ((void*)coro->json)
free((void*)coro->json);
- RARCH_ERR("[CHEEVOS]: error getting game_id.\n");
+ CHEEVOS_ERR("[CHEEVOS]: error getting game_id.\n");
CORO_RET();
}
if ((void*)coro->json)
free((void*)coro->json);
- RARCH_LOG("[CHEEVOS]: got game id %s.\n", gameid);
- coro->gameid = strtol(gameid, NULL, 10);
+ CHEEVOS_LOG("[CHEEVOS]: got game id %s.\n", gameid);
+ coro->gameid = (unsigned)strtol(gameid, NULL, 10);
CORO_RET();
}
@@ -3497,11 +3210,11 @@ found:
if (!coro->json)
{
- RARCH_ERR("[CHEEVOS]: error getting achievements for game id %u.\n", coro->gameid);
+ CHEEVOS_ERR("[CHEEVOS]: error getting achievements for game id %u.\n", coro->gameid);
CORO_STOP();
}
- RARCH_LOG("[CHEEVOS]: got achievements for game id %u.\n", coro->gameid);
+ CHEEVOS_LOG("[CHEEVOS]: got achievements for game id %u.\n", coro->gameid);
CORO_RET();
/**************************************************************************
@@ -3554,7 +3267,7 @@ found:
if (!badge_exists(coro->badge_fullpath))
{
#ifdef CHEEVOS_LOG_BADGES
- RARCH_LOG(
+ CHEEVOS_LOG(
"[CHEEVOS]: downloading badge %s\n",
coro->badge_fullpath);
#endif
@@ -3569,7 +3282,7 @@ found:
{
if (!filestream_write_file(coro->badge_fullpath,
coro->json, coro->k))
- RARCH_ERR("[CHEEVOS]: error writing badge %s\n", coro->badge_fullpath);
+ CHEEVOS_ERR("[CHEEVOS]: error writing badge %s\n", coro->badge_fullpath);
else
free(coro->json);
}
@@ -3589,29 +3302,43 @@ found:
{
char urle_user[64];
- char urle_pwd[64];
+ char urle_login[64];
const char *username = coro ? coro->settings->arrays.cheevos_username : NULL;
- const char *password = coro ? coro->settings->arrays.cheevos_password : NULL;
+ const char *login = NULL;
+ bool via_token = false;
- if (!username || !*username || !password || !*password)
+ if (coro)
+ {
+ if (string_is_empty(coro->settings->arrays.cheevos_password))
+ {
+ via_token = true;
+ login = coro->settings->arrays.cheevos_token;
+ }
+ else
+ login = coro->settings->arrays.cheevos_password;
+ }
+ else
+ login = NULL;
+
+ if (string_is_empty(username) || string_is_empty(login))
{
runloop_msg_queue_push(
- "Missing Retro Achievements account information.",
+ "Missing RetroAchievements account information.",
0, 5 * 60, false);
runloop_msg_queue_push(
"Please fill in your account information in Settings.",
0, 5 * 60, false);
- RARCH_ERR("[CHEEVOS]: username and/or password not informed.\n");
+ CHEEVOS_ERR("[CHEEVOS]: login info not informed.\n");
CORO_STOP();
}
cheevos_url_encode(username, urle_user, sizeof(urle_user));
- cheevos_url_encode(password, urle_pwd, sizeof(urle_pwd));
+ cheevos_url_encode(login, urle_login, sizeof(urle_login));
snprintf(
coro->url, sizeof(coro->url),
- "http://retroachievements.org/dorequest.php?r=login&u=%s&p=%s",
- urle_user, urle_pwd
+ "http://retroachievements.org/dorequest.php?r=login&u=%s&%c=%s",
+ urle_user, via_token ? 't' : 'p', urle_login
);
coro->url[sizeof(coro->url) - 1] = 0;
@@ -3626,32 +3353,67 @@ found:
if (coro->json)
{
- int res = cheevos_get_value(
+ char error_response[64];
+ char error_message[256];
+
+ cheevos_get_value(
+ coro->json,
+ CHEEVOS_JSON_KEY_ERROR,
+ error_response,
+ sizeof(error_response)
+ );
+
+ /* No error, continue with login */
+ if (string_is_empty(error_response))
+ {
+ int res = cheevos_get_value(
coro->json,
CHEEVOS_JSON_KEY_TOKEN,
cheevos_locals.token,
sizeof(cheevos_locals.token));
+ if ((void*)coro->json)
+ free((void*)coro->json);
+
+ if (!res)
+ {
+ if (coro->settings->bools.cheevos_verbose_enable)
+ {
+ char msg[256];
+ snprintf(msg, sizeof(msg),
+ "RetroAchievements: Logged in as \"%s\".",
+ coro->settings->arrays.cheevos_username);
+ msg[sizeof(msg) - 1] = 0;
+ runloop_msg_queue_push(msg, 0, 3 * 60, false);
+ }
+
+ /* Save token to config and clear pass on success */
+ *coro->settings->arrays.cheevos_password = '\0';
+ strncpy(
+ coro->settings->arrays.cheevos_token,
+ cheevos_locals.token, sizeof(cheevos_locals.token)
+ );
+ CORO_RET();
+ }
+ }
+
if ((void*)coro->json)
free((void*)coro->json);
- if (!res)
- {
- if (coro->settings->bools.cheevos_verbose_enable)
- {
- char msg[256];
- snprintf(msg, sizeof(msg),
- "RetroAchievements: logged in as \"%s\".",
- coro->settings->arrays.cheevos_username);
- msg[sizeof(msg) - 1] = 0;
- runloop_msg_queue_push(msg, 0, 3 * 60, false);
- }
- CORO_RET();
- }
+ /* Site returned error, display it */
+ snprintf(error_message, sizeof(error_message),
+ "RetroAchievements: %s",
+ error_response);
+ error_message[sizeof(error_message) - 1] = 0;
+ runloop_msg_queue_push(error_message, 0, 5 * 60, false);
+ *coro->settings->arrays.cheevos_token = '\0';
+
+ CORO_STOP();
}
- runloop_msg_queue_push("Retro Achievements login error.", 0, 5 * 60, false);
- RARCH_ERR("[CHEEVOS]: error getting user token.\n");
+ runloop_msg_queue_push("RetroAchievements: Error contacting server.", 0, 5 * 60, false);
+ CHEEVOS_ERR("[CHEEVOS]: error getting user token.\n");
+
CORO_STOP();
/**************************************************************************
@@ -3682,7 +3444,7 @@ found:
for (coro->k = 0; coro->k < 5; coro->k++)
{
if (coro->k != 0)
- RARCH_LOG("[CHEEVOS]: Retrying HTTP request: %u of 5\n", coro->k + 1);
+ CHEEVOS_LOG("[CHEEVOS]: Retrying HTTP request: %u of 5\n", coro->k + 1);
coro->json = NULL;
coro->conn = net_http_connection_new(
@@ -3733,7 +3495,7 @@ found:
coro->json[length] = 0;
}
- coro->k = length;
+ coro->k = (unsigned)length;
net_http_delete(coro->http);
net_http_connection_free(coro->conn);
CORO_RET();
@@ -3744,7 +3506,7 @@ found:
net_http_connection_free(coro->conn);
}
- RARCH_LOG("[CHEEVOS]: Couldn't connect to server after 5 tries\n");
+ CHEEVOS_LOG("[CHEEVOS]: Couldn't connect to server after 5 tries\n");
CORO_RET();
/**************************************************************************
@@ -3762,7 +3524,7 @@ found:
coro->url, sizeof(coro->url),
"http://retroachievements.org/dorequest.php?r=unlocks&u=%s&t=%s&g=%u&h=0",
coro->settings->arrays.cheevos_username,
- cheevos_locals.token, coro->gameid
+ cheevos_locals.token, coro->gameid
);
coro->url[sizeof(coro->url) - 1] = 0;
@@ -3776,15 +3538,15 @@ found:
if (coro->json)
{
if (!cheevos_deactivate_unlocks(coro->json, CHEEVOS_ACTIVE_SOFTCORE))
- RARCH_LOG("[CHEEVOS]: deactivated unlocked achievements in softcore mode.\n");
+ CHEEVOS_LOG("[CHEEVOS]: deactivated unlocked achievements in softcore mode.\n");
else
- RARCH_ERR("[CHEEVOS]: error deactivating unlocked achievements in softcore mode.\n");
+ CHEEVOS_ERR("[CHEEVOS]: error deactivating unlocked achievements in softcore mode.\n");
if ((void*)coro->json)
free((void*)coro->json);
}
else
- RARCH_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in softcore mode.\n");
+ CHEEVOS_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in softcore mode.\n");
/* Deactivate achievements in hardcore mode. */
snprintf(
@@ -3805,15 +3567,15 @@ found:
if (coro->json)
{
if (!cheevos_deactivate_unlocks(coro->json, CHEEVOS_ACTIVE_HARDCORE))
- RARCH_LOG("[CHEEVOS]: deactivated unlocked achievements in hardcore mode.\n");
+ CHEEVOS_LOG("[CHEEVOS]: deactivated unlocked achievements in hardcore mode.\n");
else
- RARCH_ERR("[CHEEVOS]: error deactivating unlocked achievements in hardcore mode.\n");
+ CHEEVOS_ERR("[CHEEVOS]: error deactivating unlocked achievements in hardcore mode.\n");
if ((void*)coro->json)
free((void*)coro->json);
}
else
- RARCH_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in hardcore mode.\n");
+ CHEEVOS_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in hardcore mode.\n");
#endif
CORO_RET();
@@ -3829,7 +3591,7 @@ found:
coro->url, sizeof(coro->url),
"http://retroachievements.org/dorequest.php?r=postactivity&u=%s&t=%s&a=3&m=%u",
coro->settings->arrays.cheevos_username,
- cheevos_locals.token, coro->gameid
+ cheevos_locals.token, coro->gameid
);
coro->url[sizeof(coro->url) - 1] = 0;
@@ -3842,14 +3604,14 @@ found:
if (coro->json)
{
- RARCH_LOG("[CHEEVOS]: posted playing activity.\n");
+ CHEEVOS_LOG("[CHEEVOS]: posted playing activity.\n");
if ((void*)coro->json)
free((void*)coro->json);
}
else
- RARCH_ERR("[CHEEVOS]: error posting playing activity.\n");
+ CHEEVOS_ERR("[CHEEVOS]: error posting playing activity.\n");
- RARCH_LOG("[CHEEVOS]: posted playing activity.\n");
+ CHEEVOS_LOG("[CHEEVOS]: posted playing activity.\n");
CORO_RET();
CORO_LEAVE();
@@ -3870,16 +3632,14 @@ static void cheevos_task_handler(retro_task_t *task)
cheevos_locals.task = NULL;
CHEEVOS_UNLOCK(cheevos_locals.task_lock);
-#ifdef CHEEVOS_VERBOSE
if (task_get_cancelled(task))
{
- RARCH_LOG("[CHEEVOS]: Load task cancelled\n");
+ CHEEVOS_LOG("[CHEEVOS]: Load task cancelled\n");
}
else
{
- RARCH_LOG("[CHEEVOS]: Load task finished\n");
+ CHEEVOS_LOG("[CHEEVOS]: Load task finished\n");
}
-#endif
if (coro->data)
free(coro->data);
@@ -3898,6 +3658,7 @@ bool cheevos_load(const void *data)
coro_t *coro = NULL;
cheevos_loaded = false;
+ cheevos_hardcore_paused = false;
if (!cheevos_locals.core_supports || !data)
return false;
diff --git a/cheevos/cheevos.h b/cheevos/cheevos.h
index dd070ef441..45c799dfe3 100644
--- a/cheevos/cheevos.h
+++ b/cheevos/cheevos.h
@@ -38,6 +38,20 @@ End of setup
#define CHEEVOS_TAG "[CHEEVOS]: "
+#ifdef CHEEVOS_VERBOSE
+
+#define CHEEVOS_LOG RARCH_LOG
+#define CHEEVOS_ERR RARCH_ERR
+
+#else
+
+void cheevos_log(const char *fmt, ...);
+
+#define CHEEVOS_LOG cheevos_log
+#define CHEEVOS_ERR cheevos_log
+
+#endif
+
typedef struct cheevos_ctx_desc
{
unsigned idx;
@@ -139,6 +153,8 @@ bool cheevos_get_support_cheevos(void);
cheevos_console_t cheevos_get_console(void);
extern bool cheevos_loaded;
+extern bool cheevos_hardcore_active;
+extern bool cheevos_hardcore_paused;
extern int cheats_are_enabled;
extern int cheats_were_enabled;
diff --git a/cheevos/cond.c b/cheevos/cond.c
index 3566f8e6bf..9f665900c9 100644
--- a/cheevos/cond.c
+++ b/cheevos/cond.c
@@ -65,7 +65,7 @@ static cheevos_cond_op_t cheevos_cond_parse_operator(const char** memaddr)
}
else
{
- RARCH_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str);
+ CHEEVOS_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str);
op = CHEEVOS_COND_OP_EQUALS;
}
@@ -168,9 +168,6 @@ void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsign
if (index == which)
{
cheevos_cond_parse(cond, &memaddr);
-#ifdef CHEEVOS_VERBOSE
- /*cheevos_log_cond(cond);*/
-#endif
cond++;
}
else
diff --git a/cheevos/cond.h b/cheevos/cond.h
index 5fc0e532b6..ee7cb668a1 100644
--- a/cheevos/cond.h
+++ b/cheevos/cond.h
@@ -47,6 +47,7 @@ typedef struct
cheevos_cond_type_t type;
unsigned req_hits;
unsigned curr_hits;
+ char pause;
cheevos_var_t source;
cheevos_cond_op_t op;
diff --git a/cheevos/var.c b/cheevos/var.c
index 41884a72b6..5f13c2b8b6 100644
--- a/cheevos/var.c
+++ b/cheevos/var.c
@@ -24,17 +24,6 @@
#include "../core.h"
#include "../verbosity.h"
-static void STUB_LOG(const char *fmt, ...)
-{
- (void)fmt;
-}
-
-#ifdef CHEEVOS_VERBOSE
-#define CHEEVOS_LOG RARCH_LOG
-#else
-#define CHEEVOS_LOG STUB_LOG
-#endif
-
/*****************************************************************************
Parsing
*****************************************************************************/
@@ -191,12 +180,6 @@ void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console)
var->value -= 0x2000;
}
}
- else if (console == CHEEVOS_CONSOLE_NEOGEO_POCKET)
- {
- if (var->value >= 0x4000 && var->value <= 0x7fff)
- CHEEVOS_LOG(CHEEVOS_TAG "NGP memory address %X adjusted to %X\n", var->value, var->value - 0x004000);
- var->value -= 0x4000;
- }
if (system->mmaps.num_descriptors != 0)
{
@@ -333,7 +316,7 @@ uint8_t* cheevos_var_get_memory(const cheevos_var_t* var)
meminfo.id = RETRO_MEMORY_RTC;
break;
default:
- RARCH_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id);
+ CHEEVOS_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id);
break;
}
diff --git a/command.c b/command.c
index ab871166c0..a33f8e1faf 100644
--- a/command.c
+++ b/command.c
@@ -44,6 +44,12 @@
#include "cheevos/var.h"
#endif
+#ifdef HAVE_DISCORD
+#include "discord/discord.h"
+#endif
+
+#include "midi/midi_driver.h"
+
#ifdef HAVE_MENU
#include "menu/menu_driver.h"
#include "menu/menu_content.h"
@@ -169,6 +175,7 @@ static const struct cmd_map map[] = {
{ "DISK_NEXT", RARCH_DISK_NEXT },
{ "DISK_PREV", RARCH_DISK_PREV },
{ "GRAB_MOUSE_TOGGLE", RARCH_GRAB_MOUSE_TOGGLE },
+ { "UI_COMPANION_TOGGLE", RARCH_UI_COMPANION_TOGGLE },
{ "GAME_FOCUS_TOGGLE", RARCH_GAME_FOCUS_TOGGLE },
{ "MENU_TOGGLE", RARCH_MENU_TOGGLE },
{ "MENU_UP", RETRO_DEVICE_ID_JOYPAD_UP },
@@ -1015,7 +1022,7 @@ static void command_event_init_controllers(void)
/* Ideally these checks shouldn't be required but if we always
* call core_set_controller_port_device input won't work on
* cores that don't set port information properly */
- if (info && info->ports.size != 0 && i < info->ports.size)
+ if (info && info->ports.size != 0)
set_controller = true;
break;
default:
@@ -1029,7 +1036,7 @@ static void command_event_init_controllers(void)
break;
}
- if (set_controller)
+ if (set_controller && i < info->ports.size)
{
pad.device = device;
pad.port = i;
@@ -1087,7 +1094,7 @@ static void command_event_load_auto_state(void)
#endif
#ifdef HAVE_CHEEVOS
- if (cheevos_loaded && settings->bools.cheevos_hardcore_mode_enable)
+ if (cheevos_hardcore_active)
goto error;
#endif
@@ -1274,8 +1281,8 @@ static bool command_event_init_core(enum rarch_core_type *data)
if (!core_load(settings->uints.input_poll_type_behavior))
return false;
- rarch_ctl(RARCH_CTL_SET_FRAME_LIMIT, NULL);
+ rarch_ctl(RARCH_CTL_SET_FRAME_LIMIT, NULL);
return true;
}
@@ -1296,7 +1303,9 @@ static void command_event_restore_default_shader_preset(void)
static void command_event_restore_remaps(void)
{
- if (rarch_ctl(RARCH_CTL_IS_REMAPS_GAME_ACTIVE, NULL))
+ if (rarch_ctl(RARCH_CTL_IS_REMAPS_CORE_ACTIVE, NULL) ||
+ rarch_ctl(RARCH_CTL_IS_REMAPS_CONTENT_DIR_ACTIVE, NULL) ||
+ rarch_ctl(RARCH_CTL_IS_REMAPS_GAME_ACTIVE, NULL))
input_remapping_set_defaults(true);
}
@@ -1325,7 +1334,7 @@ static bool command_event_save_auto_state(void)
goto error;
#ifdef HAVE_CHEEVOS
- if (cheevos_loaded && settings->bools.cheevos_hardcore_mode_enable)
+ if (cheevos_hardcore_active)
goto error;
#endif
@@ -1386,7 +1395,6 @@ static bool command_event_save_config(
static bool command_event_save_core_config(void)
{
char msg[128];
- bool ret = false;
bool found_path = false;
bool overrides_active = false;
const char *core_path = NULL;
@@ -1493,7 +1501,7 @@ static bool command_event_save_core_config(void)
free(config_dir);
free(config_name);
free(config_path);
- return ret;
+ return true;
}
/**
@@ -1519,6 +1527,7 @@ static void command_event_save_current_config(enum override_type type)
break;
case OVERRIDE_GAME:
case OVERRIDE_CORE:
+ case OVERRIDE_CONTENT_DIR:
if (config_save_overrides(type))
{
strlcpy(msg, msg_hash_to_str(MSG_OVERRIDES_SAVED_SUCCESSFULLY), sizeof(msg));
@@ -1705,17 +1714,11 @@ void command_playlist_update_write(
const char *core_path,
const char *core_display_name,
const char *crc32,
- const char *db_name)
+ const char *db_name)
{
playlist_t *plist = (playlist_t*)data;
- playlist_t *playlist = NULL;
+ playlist_t *playlist = plist ? plist : playlist_get_cached();
- if (plist)
- playlist = plist;
-#ifdef HAVE_MENU
- else
- menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &playlist);
-#endif
if (!playlist)
return;
@@ -1742,8 +1745,8 @@ void command_playlist_update_write(
**/
bool command_event(enum event_command cmd, void *data)
{
- settings_t *settings = config_get_ptr();
- bool boolean = false;
+ static bool discord_inited = false;
+ bool boolean = false;
switch (cmd)
{
@@ -1793,10 +1796,11 @@ bool command_event(enum event_command cmd, void *data)
return false;
#endif
- libretro_get_system_info(
+ if (!libretro_get_system_info(
core_path,
system,
- &system_info->load_no_content);
+ &system_info->load_no_content))
+ return false;
info_find.path = core_path;
if (!core_info_load(&info_find))
@@ -1809,11 +1813,17 @@ bool command_event(enum event_command cmd, void *data)
}
break;
case CMD_EVENT_LOAD_CORE:
- command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
+ {
+ bool success = command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
+
#ifndef HAVE_DYNAMIC
command_event(CMD_EVENT_QUIT, NULL);
+#else
+ if (!success)
+ return false;
#endif
break;
+ }
case CMD_EVENT_LOAD_STATE:
/* Immutable - disallow savestate load when
* we absolutely cannot change game state. */
@@ -1821,20 +1831,24 @@ bool command_event(enum event_command cmd, void *data)
return false;
#ifdef HAVE_CHEEVOS
- {
- settings_t *settings = config_get_ptr();
- if (cheevos_loaded && settings->bools.cheevos_hardcore_mode_enable)
- return false;
- }
+ if (cheevos_hardcore_active)
+ return false;
#endif
-
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_UNDO_LOAD_STATE:
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_UNDO_SAVE_STATE:
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_RESIZE_WINDOWED_SCALE:
- return command_event_resize_windowed_scale();
+ if (!command_event_resize_windowed_scale())
+ return false;
+ break;
case CMD_EVENT_MENU_TOGGLE:
#ifdef HAVE_MENU
if (menu_driver_is_alive())
@@ -1860,12 +1874,12 @@ bool command_event(enum event_command cmd, void *data)
#if HAVE_NETWORKING
netplay_driver_ctl(RARCH_NETPLAY_CTL_RESET, NULL);
#endif
- return command_event_main_state(cmd);
+ return false;
case CMD_EVENT_SAVE_STATE:
{
settings_t *settings = config_get_ptr();
#ifdef HAVE_CHEEVOS
- if (cheevos_loaded && settings->bools.cheevos_hardcore_mode_enable)
+ if (cheevos_hardcore_active)
return false;
#endif
@@ -1875,7 +1889,9 @@ bool command_event(enum event_command cmd, void *data)
configuration_set_int(settings, settings->ints.state_slot, new_state_slot);
}
}
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_SAVE_STATE_DECREMENT:
{
settings_t *settings = config_get_ptr();
@@ -1925,36 +1941,39 @@ bool command_event(enum event_command cmd, void *data)
}
break;
case CMD_EVENT_QUIT:
- return retroarch_main_quit();
+ if (!retroarch_main_quit())
+ return false;
+ break;
case CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE:
#ifdef HAVE_CHEEVOS
cheevos_toggle_hardcore_mode();
#endif
break;
- /* this fallthrough is on purpose, it should do
+ /* this fallthrough is on purpose, it should do
a CMD_EVENT_REINIT too */
case CMD_EVENT_REINIT_FROM_TOGGLE:
retroarch_unset_forced_fullscreen();
case CMD_EVENT_REINIT:
+ video_driver_reinit();
{
- video_driver_reinit();
- {
- const input_driver_t *input_drv = input_get_ptr();
- void *input_data = input_get_data();
- /* Poll input to avoid possibly stale data to corrupt things. */
- if (input_drv && input_drv->poll)
- input_drv->poll(input_data);
- }
- command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, (void*)(intptr_t)-1);
+ const input_driver_t *input_drv = input_get_ptr();
+ void *input_data = input_get_data();
+ /* Poll input to avoid possibly stale data to corrupt things. */
+ if (input_drv && input_drv->poll)
+ input_drv->poll(input_data);
+ }
+ command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, (void*)(intptr_t)-1);
#ifdef HAVE_MENU
+ {
+ settings_t *settings = config_get_ptr();
menu_display_set_framebuffer_dirty_flag();
if (settings->bools.video_fullscreen)
video_driver_hide_mouse();
if (menu_driver_is_alive())
command_event(CMD_EVENT_VIDEO_SET_BLOCKING_STATE, NULL);
-#endif
}
+#endif
break;
case CMD_EVENT_CHEATS_DEINIT:
cheat_manager_state_free();
@@ -1967,21 +1986,17 @@ bool command_event(enum event_command cmd, void *data)
cheat_manager_apply_cheats();
break;
case CMD_EVENT_REWIND_DEINIT:
- {
#ifdef HAVE_CHEEVOS
- settings_t *settings = config_get_ptr();
- if (cheevos_loaded && settings->bools.cheevos_hardcore_mode_enable)
- return false;
+ if (cheevos_hardcore_active)
+ return false;
#endif
-
- state_manager_event_deinit();
- }
+ state_manager_event_deinit();
break;
case CMD_EVENT_REWIND_INIT:
{
settings_t *settings = config_get_ptr();
#ifdef HAVE_CHEEVOS
- if (cheevos_loaded && settings->bools.cheevos_hardcore_mode_enable)
+ if (cheevos_hardcore_active)
return false;
#endif
if (settings->bools.rewind_enable)
@@ -1992,7 +2007,7 @@ TODO: Add a setting for these tweaks */
if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
#endif
{
- state_manager_event_init((unsigned)settings->rewind_buffer_size);
+ state_manager_event_init((unsigned)settings->sizes.rewind_buffer_size);
}
}
}
@@ -2016,7 +2031,7 @@ TODO: Add a setting for these tweaks */
case CMD_EVENT_AUTOSAVE_INIT:
command_event(CMD_EVENT_AUTOSAVE_DEINIT, NULL);
#ifdef HAVE_THREADS
- {
+ {
#ifdef HAVE_NETWORKING
/* Only enable state manager if netplay is not underway
TODO: Add a setting for these tweaks */
@@ -2030,16 +2045,21 @@ TODO: Add a setting for these tweaks */
else
runloop_unset(RUNLOOP_ACTION_AUTOSAVE);
}
- }
+ }
#endif
break;
case CMD_EVENT_AUTOSAVE_STATE:
command_event_save_auto_state();
break;
case CMD_EVENT_AUDIO_STOP:
- return audio_driver_stop();
+ midi_driver_set_all_sounds_off();
+ if (!audio_driver_stop())
+ return false;
+ break;
case CMD_EVENT_AUDIO_START:
- return audio_driver_start(rarch_ctl(RARCH_CTL_IS_SHUTDOWN, NULL));
+ if (!audio_driver_start(rarch_ctl(RARCH_CTL_IS_SHUTDOWN, NULL)))
+ return false;
+ break;
case CMD_EVENT_AUDIO_MUTE_TOGGLE:
{
bool audio_mute_enable = *(audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE));
@@ -2128,7 +2148,7 @@ TODO: Add a setting for these tweaks */
}
g_defaults.music_history = NULL;
-#ifdef HAVE_FFMPEG
+#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
if (g_defaults.video_history)
{
playlist_write_file(g_defaults.video_history);
@@ -2178,7 +2198,7 @@ TODO: Add a setting for these tweaks */
settings->paths.path_content_music_history,
content_history_size);
-#ifdef HAVE_FFMPEG
+#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
RARCH_LOG("%s: [%s].\n",
msg_hash_to_str(MSG_LOADING_HISTORY_FILE),
settings->paths.path_content_video_history);
@@ -2202,11 +2222,22 @@ TODO: Add a setting for these tweaks */
break;
case CMD_EVENT_CORE_INFO_INIT:
{
+ char ext_name[255];
settings_t *settings = config_get_ptr();
+
+ ext_name[0] = '\0';
+
command_event(CMD_EVENT_CORE_INFO_DEINIT, NULL);
+ if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name)))
+ return false;
+
if (!string_is_empty(settings->paths.directory_libretro))
- core_info_init_list();
+ core_info_init_list(settings->paths.path_libretro_info,
+ settings->paths.directory_libretro,
+ ext_name,
+ settings->bools.show_hidden_files
+ );
}
break;
case CMD_EVENT_CORE_DEINIT:
@@ -2301,7 +2332,7 @@ TODO: Add a setting for these tweaks */
case CMD_EVENT_RESUME:
rarch_menu_running_finished();
if (ui_companion_is_on_foreground())
- ui_companion_driver_toggle();
+ ui_companion_driver_toggle(false);
break;
case CMD_EVENT_ADD_TO_FAVORITES:
{
@@ -2350,7 +2381,7 @@ TODO: Add a setting for these tweaks */
runloop_msg_queue_push(msg_hash_to_str(MSG_RESET_CORE_ASSOCIATION), 1, 180, true);
break;
- }
+ }
case CMD_EVENT_RESTART_RETROARCH:
if (!frontend_driver_set_fork(FRONTEND_FORK_RESTART))
return false;
@@ -2364,6 +2395,9 @@ TODO: Add a setting for these tweaks */
case CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_CORE:
command_event_save_current_config(OVERRIDE_CORE);
break;
+ case CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR:
+ command_event_save_current_config(OVERRIDE_CONTENT_DIR);
+ break;
case CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_GAME:
command_event_save_current_config(OVERRIDE_GAME);
break;
@@ -2496,17 +2530,18 @@ TODO: Add a setting for these tweaks */
/* buf is expected to be address|port */
char *buf = (char *)data;
static struct string_list *hostname = NULL;
+ settings_t *settings = config_get_ptr();
hostname = string_split(buf, "|");
command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
RARCH_LOG("[netplay] connecting to %s:%d\n",
hostname->elems[0].data, !string_is_empty(hostname->elems[1].data)
- ? atoi(hostname->elems[1].data) : 55435);
+ ? atoi(hostname->elems[1].data) : settings->uints.netplay_port);
if (!init_netplay(NULL, hostname->elems[0].data,
!string_is_empty(hostname->elems[1].data)
- ? atoi(hostname->elems[1].data) : 55435))
+ ? atoi(hostname->elems[1].data) : settings->uints.netplay_port))
{
command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
string_list_free(hostname);
@@ -2529,17 +2564,18 @@ TODO: Add a setting for these tweaks */
/* buf is expected to be address|port */
char *buf = (char *)data;
static struct string_list *hostname = NULL;
+ settings_t *settings = config_get_ptr();
hostname = string_split(buf, "|");
command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
RARCH_LOG("[netplay] connecting to %s:%d\n",
hostname->elems[0].data, !string_is_empty(hostname->elems[1].data)
- ? atoi(hostname->elems[1].data) : 55435);
+ ? atoi(hostname->elems[1].data) : settings->uints.netplay_port);
if (!init_netplay_deferred(hostname->elems[0].data,
!string_is_empty(hostname->elems[1].data)
- ? atoi(hostname->elems[1].data) : 55435))
+ ? atoi(hostname->elems[1].data) : settings->uints.netplay_port))
{
command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
string_list_free(hostname);
@@ -2572,7 +2608,7 @@ TODO: Add a setting for these tweaks */
case CMD_EVENT_FULLSCREEN_TOGGLE:
{
settings_t *settings = config_get_ptr();
- bool new_fullscreen_state = !settings->bools.video_fullscreen
+ bool new_fullscreen_state = !settings->bools.video_fullscreen
&& !retroarch_is_forced_fullscreen();
if (!video_driver_has_windowed())
return false;
@@ -2608,14 +2644,13 @@ TODO: Add a setting for these tweaks */
command_event(CMD_EVENT_REMOTE_DEINIT, NULL);
input_driver_init_remote();
break;
-
case CMD_EVENT_MAPPER_DEINIT:
input_driver_deinit_mapper();
break;
case CMD_EVENT_MAPPER_INIT:
command_event(CMD_EVENT_MAPPER_DEINIT, NULL);
input_driver_init_mapper();
- break;
+ break;
case CMD_EVENT_LOG_FILE_DEINIT:
retro_main_log_file_deinit();
break;
@@ -2624,8 +2659,10 @@ TODO: Add a setting for these tweaks */
const char *path = (const char*)data;
if (string_is_empty(path))
return false;
- return command_event_disk_control_append_image(path);
+ if (!command_event_disk_control_append_image(path))
+ return false;
}
+ break;
case CMD_EVENT_DISK_EJECT_TOGGLE:
{
rarch_system_info_t *info = runloop_get_system_info();
@@ -2731,6 +2768,9 @@ TODO: Add a setting for these tweaks */
video_driver_show_mouse();
}
break;
+ case CMD_EVENT_UI_COMPANION_TOGGLE:
+ ui_companion_driver_toggle(true);
+ break;
case CMD_EVENT_GAME_FOCUS_TOGGLE:
{
static bool game_focus_state = false;
@@ -2803,6 +2843,41 @@ TODO: Add a setting for these tweaks */
#if HAVE_LIBUI
extern int libui_main(void);
libui_main();
+#endif
+ break;
+ case CMD_EVENT_DISCORD_INIT:
+#ifdef HAVE_DISCORD
+ {
+ settings_t *settings = config_get_ptr();
+
+ if (!settings->bools.discord_enable)
+ return false;
+ if (discord_inited)
+ return true;
+
+ discord_init();
+ discord_inited = true;
+ }
+#endif
+ break;
+ case CMD_EVENT_DISCORD_DEINIT:
+#ifdef HAVE_DISCORD
+ if (!discord_inited)
+ return false;
+
+ discord_shutdown();
+ discord_inited = false;
+#endif
+ break;
+ case CMD_EVENT_DISCORD_UPDATE:
+#ifdef HAVE_DISCORD
+ if (!data || !discord_inited)
+ return false;
+
+ {
+ discord_userdata_t *userdata = (discord_userdata_t*)data;
+ discord_update(userdata->status);
+ }
#endif
break;
case CMD_EVENT_NONE:
diff --git a/command.h b/command.h
index 9cc3e3ce17..6b50d6f3eb 100644
--- a/command.h
+++ b/command.h
@@ -139,7 +139,7 @@ enum event_command
/* Add a playlist entry to favorites. */
CMD_EVENT_ADD_TO_FAVORITES,
/* Reset playlist entry associated core to DETECT */
- CMD_EVENT_RESET_CORE_ASSOCIATION,
+ CMD_EVENT_RESET_CORE_ASSOCIATION,
/* Toggles pause. */
CMD_EVENT_PAUSE_TOGGLE,
/* Pauses RetroArch. */
@@ -149,6 +149,7 @@ enum event_command
CMD_EVENT_PAUSE_CHECKS,
CMD_EVENT_MENU_SAVE_CURRENT_CONFIG,
CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_CORE,
+ CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR,
CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_GAME,
CMD_EVENT_MENU_SAVE_CONFIG,
CMD_EVENT_MENU_PAUSE_LIBRETRO,
@@ -218,6 +219,8 @@ enum event_command
CMD_EVENT_GRAB_MOUSE_TOGGLE,
/* Toggles game focus. */
CMD_EVENT_GAME_FOCUS_TOGGLE,
+ /* Toggles desktop menu. */
+ CMD_EVENT_UI_COMPANION_TOGGLE,
/* Toggles fullscreen mode. */
CMD_EVENT_FULLSCREEN_TOGGLE,
CMD_EVENT_PERFCNT_REPORT_FRONTEND_LOG,
@@ -228,6 +231,9 @@ enum event_command
CMD_EVENT_DISABLE_OVERRIDES,
CMD_EVENT_RESTORE_REMAPS,
CMD_EVENT_RESTORE_DEFAULT_SHADER_PRESET,
+ CMD_EVENT_DISCORD_INIT,
+ CMD_EVENT_DISCORD_DEINIT,
+ CMD_EVENT_DISCORD_UPDATE,
CMD_EVENT_LIBUI_TEST
};
@@ -271,7 +277,7 @@ void command_playlist_push_write(
void command_playlist_update_write(
void *data,
size_t idx,
- const char *path,
+ const char *path,
const char *label,
const char *core_path,
const char *core_display_name,
diff --git a/config.def.h b/config.def.h
index 48041da022..189449b793 100644
--- a/config.def.h
+++ b/config.def.h
@@ -67,6 +67,10 @@ static bool bundle_assets_extract_enable = false;
static bool materialui_icons_enable = true;
#endif
+static const bool crt_switch_resolution = false;
+static const int crt_switch_resolution_super = 2560;
+
+
static const bool def_history_list_enable = true;
static const bool def_playlist_entry_remove = true;
static const bool def_playlist_entry_rename = true;
@@ -177,7 +181,7 @@ static unsigned swap_interval = 1;
static const bool video_threaded = false;
#if defined(HAVE_THREADS)
-#if defined(GEKKO) || defined(PSP) || defined(_3DS)
+#if defined(GEKKO) || defined(PSP)
/* For single-core consoles right now it's better to have this be disabled. */
static const bool threaded_data_runloop_enable = false;
#else
@@ -257,10 +261,12 @@ static bool quick_menu_show_options = true;
static bool quick_menu_show_controls = true;
static bool quick_menu_show_cheats = true;
static bool quick_menu_show_shaders = true;
-static bool quick_menu_show_save_core_overrides = true;
-static bool quick_menu_show_save_game_overrides = true;
static bool quick_menu_show_information = true;
+static bool quick_menu_show_save_core_overrides = true;
+static bool quick_menu_show_save_game_overrides = true;
+static bool quick_menu_show_save_content_dir_overrides = true;
+
static bool kiosk_mode_enable = false;
static bool menu_show_online_updater = true;
@@ -271,6 +277,7 @@ static bool menu_show_configurations = true;
static bool menu_show_help = true;
static bool menu_show_quit_retroarch = true;
static bool menu_show_reboot = true;
+static bool menu_show_shutdown = true;
#if defined(HAVE_LAKKA) || defined(VITA) || defined(_3DS)
static bool menu_show_core_updater = false;
#else
@@ -283,7 +290,7 @@ static bool content_show_favorites = true;
static bool content_show_images = true;
#endif
static bool content_show_music = true;
-#ifdef HAVE_FFMPEG
+#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
static bool content_show_video = true;
#endif
#ifdef HAVE_NETWORKING
@@ -293,6 +300,7 @@ static bool content_show_history = true;
#ifdef HAVE_LIBRETRODB
static bool content_show_add = true;
#endif
+static bool content_show_playlists = true;
#ifdef HAVE_XMB
static unsigned xmb_scale_factor = 100;
@@ -300,6 +308,7 @@ static unsigned xmb_alpha_factor = 75;
static unsigned menu_font_color_red = 255;
static unsigned menu_font_color_green = 255;
static unsigned menu_font_color_blue = 255;
+static unsigned xmb_menu_layout = 0;
static unsigned xmb_icon_theme = XMB_ICON_THEME_MONOCHROME;
static unsigned xmb_theme = XMB_THEME_ELECTRIC_BLUE;
#if defined(HAVE_LAKKA) || defined(__arm__) || defined(__PPC64__) || defined(__ppc64__) || defined(__powerpc64__) || defined(__powerpc__) || defined(__ppc__) || defined(__POWERPC__)
@@ -515,6 +524,9 @@ static const bool rewind_enable = false;
* 15-20MB per minute. Very game dependant. */
static const unsigned rewind_buffer_size = 20 << 20; /* 20MiB */
+/* The amount of MB to increase/decrease the rewind_buffer_size when it is changed via the UI. */
+static const unsigned rewind_buffer_size_step = 10; /* 10MB */
+
/* How many frames to rewind at a time. */
static const unsigned rewind_granularity = 1;
@@ -595,6 +607,9 @@ static const unsigned run_ahead_frames = 1;
/* When using the Run Ahead feature, use a secondary instance of the core. */
static const bool run_ahead_secondary_instance = true;
+/* Hide warning messages when using the Run Ahead feature. */
+static const bool run_ahead_hide_warnings = false;
+
/* Enable stdin/network command interface. */
static const bool network_cmd_enable = false;
static const uint16_t network_cmd_port = 55355;
@@ -650,6 +665,8 @@ static const unsigned input_poll_type_behavior = 2;
static const unsigned input_bind_timeout = 5;
+static const unsigned input_bind_hold = 2;
+
static const unsigned menu_thumbnails_default = 3;
static const unsigned menu_left_thumbnails_default = 0;
@@ -664,6 +681,12 @@ static const bool ui_companion_start_on_boot = true;
static const bool ui_companion_enable = false;
+/* Currently only used to show the WIMP UI on startup */
+static const bool ui_companion_toggle = false;
+
+/* Only init the WIMP UI for this session if this is enabled */
+static const bool desktop_menu_enable = true;
+
#if defined(__QNX__) || defined(_XBOX1) || defined(_XBOX360) || defined(__CELLOS_LV2__) || (defined(__MACH__) && defined(IOS)) || defined(ANDROID) || defined(WIIU) || defined(HAVE_NEON) || defined(GEKKO) || defined(__ARM_NEON__)
static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_LOWER;
#elif defined(PSP) || defined(_3DS) || defined(VITA)
@@ -672,13 +695,25 @@ static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_
static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_NORMAL;
#endif
+/* MIDI */
+static const char *midi_input = "Off";
+static const char *midi_output = "Off";
+static const unsigned midi_volume = 100;
+
+/* Only applies to Android 7.0 (API 24) and up */
+static const bool sustained_performance_mode = false;
+
#if defined(ANDROID)
-#if defined(ANDROID_ARM)
+#if defined(ANDROID_ARM_V7)
static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/armeabi-v7a/";
+#elif defined(ANDROID_ARM)
+static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/armeabi/";
#elif defined(ANDROID_AARCH64)
static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/arm64-v8a/";
#elif defined(ANDROID_X86)
static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/x86/";
+#elif defined(ANDROID_X64)
+static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/x86_64/";
#else
static char buildbot_server_url[] = "";
#endif
diff --git a/config.def.keybinds.h b/config.def.keybinds.h
index 298f9971a6..d941a210cf 100644
--- a/config.def.keybinds.h
+++ b/config.def.keybinds.h
@@ -97,6 +97,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
{ true, RARCH_DISK_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_GRAB_MOUSE_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GRAB_MOUSE_TOGGLE, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_GAME_FOCUS_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GAME_FOCUS_TOGGLE, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
+ { true, RARCH_UI_COMPANION_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_UI_COMPANION_TOGGLE, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_MENU_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE, RETROK_SPACE, NO_BTN, NO_BTN, 0, AXIS_NONE },
#else
{ true, RETRO_DEVICE_ID_JOYPAD_B, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B, RETROK_z, NO_BTN, NO_BTN, 0, AXIS_NONE },
@@ -172,6 +173,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
{ true, RARCH_DISK_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_GRAB_MOUSE_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GRAB_MOUSE_TOGGLE, RETROK_F11, NO_BTN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_GAME_FOCUS_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GAME_FOCUS_TOGGLE, RETROK_SCROLLOCK, NO_BTN, NO_BTN, 0, AXIS_NONE },
+ { true, RARCH_UI_COMPANION_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_UI_COMPANION_TOGGLE, RETROK_F5, NO_BTN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_MENU_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE, RETROK_F1, NO_BTN, NO_BTN, 0, AXIS_NONE },
#endif
};
diff --git a/config.features.h b/config.features.h
index 96b06539ba..f05836d122 100644
--- a/config.features.h
+++ b/config.features.h
@@ -80,6 +80,12 @@ static const bool _vulkan_supp = true;
static const bool _vulkan_supp = false;
#endif
+#ifdef HAVE_METAL
+static const bool _metal_supp = true;
+#else
+static const bool _metal_supp = false;
+#endif
+
#if defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES3) || defined(HAVE_OPENGLES_3_1) || defined(HAVE_OPENGLES_3_2)
static const bool _opengles_supp = true;
#else
@@ -272,6 +278,12 @@ static const bool _ffmpeg_supp = true;
static const bool _ffmpeg_supp = false;
#endif
+#ifdef HAVE_MPV
+static const bool _mpv_supp = true;
+#else
+static const bool _mpv_supp = false;
+#endif
+
#ifdef HAVE_FREETYPE
static const bool _freetype_supp = true;
#else
diff --git a/configuration.c b/configuration.c
index f3a2f5b6f3..c681a2ab1e 100644
--- a/configuration.c
+++ b/configuration.c
@@ -52,6 +52,8 @@
#include "tasks/tasks_internal.h"
+#include "../list_special.h"
+
static const char* invalid_filename_chars[] = {
/* https://support.microsoft.com/en-us/help/905231/information-about-the-characters-that-you-cannot-use-in-site-names--fo */
"~", "#", "%", "&", "*", "{", "}", "\\", ":", "[", "]", "?", "/", "|", "\'", "\"",
@@ -90,6 +92,16 @@ struct config_uint_setting
enum rarch_override_setting override;
};
+struct config_size_setting
+{
+ const char *ident;
+ size_t *ptr;
+ bool def_enable;
+ size_t def;
+ bool handle;
+ enum rarch_override_setting override;
+};
+
struct config_float_setting
{
const char *ident;
@@ -123,6 +135,7 @@ enum video_driver_enum
{
VIDEO_GL = 0,
VIDEO_VULKAN,
+ VIDEO_METAL,
VIDEO_DRM,
VIDEO_XVIDEO,
VIDEO_SDL,
@@ -282,9 +295,16 @@ enum record_driver_enum
RECORD_NULL
};
+enum midi_driver_enum
+{
+ MIDI_WINMM = RECORD_NULL + 1,
+ MIDI_NULL
+};
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__)
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
+#elif defined(HAVE_METAL)
+static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
#elif defined(GEKKO)
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WII;
#elif defined(WIIU)
@@ -387,6 +407,12 @@ static enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_FFMPEG;
static enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_NULL;
#endif
+#ifdef HAVE_WINMM
+static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_WINMM;
+#else
+static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_NULL;
+#endif
+
#if defined(XENON)
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_XENON360;
#elif defined(_XBOX360) || defined(_XBOX) || defined(HAVE_XINPUT2) || defined(HAVE_XINPUT_XBOX1)
@@ -537,6 +563,9 @@ static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_NULL;
#define SETTING_UINT(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_uint_setting, handle_setting)
+#define SETTING_SIZE(key, configval, default_enable, default_setting, handle_setting) \
+ GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_size_setting, handle_setting)
+
#define SETTING_PATH(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_path_setting, handle_setting)
@@ -701,6 +730,8 @@ const char *config_get_default_video(void)
return "gl";
case VIDEO_VULKAN:
return "vulkan";
+ case VIDEO_METAL:
+ return "metal";
case VIDEO_DRM:
return "drm";
case VIDEO_WII:
@@ -1010,6 +1041,26 @@ const char *config_get_default_menu(void)
return "null";
}
+const char *config_get_default_midi(void)
+{
+ enum midi_driver_enum default_driver = MIDI_DEFAULT_DRIVER;
+
+ switch (default_driver)
+ {
+ case MIDI_WINMM:
+ return "winmm";
+ case MIDI_NULL:
+ break;
+ }
+
+ return "null";
+}
+
+const char *config_get_midi_driver_options(void)
+{
+ return char_list_new_special(STRING_LIST_MIDI_DRIVERS, NULL);
+}
+
bool config_overlay_enable_default(void)
{
if (g_defaults.overlay.set)
@@ -1038,6 +1089,7 @@ static struct config_array_setting *populate_settings_array(settings_t *settings
#ifdef HAVE_CHEEVOS
SETTING_ARRAY("cheevos_username", settings->arrays.cheevos_username, false, NULL, true);
SETTING_ARRAY("cheevos_password", settings->arrays.cheevos_password, false, NULL, true);
+ SETTING_ARRAY("cheevos_token", settings->arrays.cheevos_token, false, NULL, true);
#endif
SETTING_ARRAY("video_context_driver", settings->arrays.video_context_driver, false, NULL, true);
SETTING_ARRAY("audio_driver", settings->arrays.audio_driver, false, NULL, true);
@@ -1050,6 +1102,9 @@ static struct config_array_setting *populate_settings_array(settings_t *settings
SETTING_ARRAY("bundle_assets_dst_path_subdir", settings->arrays.bundle_assets_dst_subdir, false, NULL, true);
SETTING_ARRAY("led_driver", settings->arrays.led_driver, false, NULL, true);
SETTING_ARRAY("netplay_mitm_server", settings->arrays.netplay_mitm_server, false, NULL, true);
+ SETTING_ARRAY("midi_driver", settings->arrays.midi_driver, false, NULL, true);
+ SETTING_ARRAY("midi_input", settings->arrays.midi_input, true, midi_input, true);
+ SETTING_ARRAY("midi_output", settings->arrays.midi_output, true, midi_output, true);
*size = count;
return tmp;
@@ -1184,6 +1239,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("automatically_add_content_to_playlist", &settings->bools.automatically_add_content_to_playlist, true, automatically_add_content_to_playlist, false);
SETTING_BOOL("ui_companion_start_on_boot", &settings->bools.ui_companion_start_on_boot, true, ui_companion_start_on_boot, false);
SETTING_BOOL("ui_companion_enable", &settings->bools.ui_companion_enable, true, ui_companion_enable, false);
+ SETTING_BOOL("ui_companion_toggle", &settings->bools.ui_companion_toggle, false, ui_companion_toggle, false);
+ SETTING_BOOL("desktop_menu_enable", &settings->bools.desktop_menu_enable, true, desktop_menu_enable, false);
SETTING_BOOL("video_gpu_record", &settings->bools.video_gpu_record, true, gpu_record, false);
SETTING_BOOL("input_remap_binds_enable", &settings->bools.input_remap_binds_enable, true, true, false);
SETTING_BOOL("all_users_control_menu", &settings->bools.input_all_users_control_menu, true, all_users_control_menu, false);
@@ -1227,6 +1284,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("rewind_enable", &settings->bools.rewind_enable, true, rewind_enable, false);
SETTING_BOOL("run_ahead_enabled", &settings->bools.run_ahead_enabled, true, false, false);
SETTING_BOOL("run_ahead_secondary_instance", &settings->bools.run_ahead_secondary_instance, true, false, false);
+ SETTING_BOOL("run_ahead_hide_warnings", &settings->bools.run_ahead_hide_warnings, true, false, false);
SETTING_BOOL("audio_sync", &settings->bools.audio_sync, true, audio_sync, false);
SETTING_BOOL("video_shader_enable", &settings->bools.video_shader_enable, true, shader_enable, false);
SETTING_BOOL("video_shader_watch_files", &settings->bools.video_shader_watch_files, true, video_shader_watch_files, false);
@@ -1249,6 +1307,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, vsync, false);
SETTING_BOOL("video_hard_sync", &settings->bools.video_hard_sync, true, hard_sync, false);
SETTING_BOOL("video_black_frame_insertion", &settings->bools.video_black_frame_insertion, true, black_frame_insertion, false);
+ SETTING_BOOL("crt_switch_resolution", &settings->bools.crt_switch_resolution, true, crt_switch_resolution, false);
SETTING_BOOL("video_disable_composition", &settings->bools.video_disable_composition, true, disable_composition, false);
SETTING_BOOL("pause_nonactive", &settings->bools.pause_nonactive, true, pause_nonactive, false);
SETTING_BOOL("video_gpu_screenshot", &settings->bools.video_gpu_screenshot, true, gpu_screenshot, false);
@@ -1256,12 +1315,14 @@ 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_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);
SETTING_BOOL("video_font_enable", &settings->bools.video_font_enable, true, font_enable, false);
SETTING_BOOL("core_updater_auto_extract_archive", &settings->bools.network_buildbot_auto_extract_archive, true, true, false);
SETTING_BOOL("camera_allow", &settings->bools.camera_allow, true, false, false);
+ SETTING_BOOL("discord_allow", &settings->bools.discord_enable, true, false, false);
#if defined(VITA)
SETTING_BOOL("input_backtouch_enable", &settings->bools.input_backtouch_enable, false, false, false);
SETTING_BOOL("input_backtouch_toggle", &settings->bools.input_backtouch_toggle, false, false, false);
@@ -1298,6 +1359,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("quick_menu_show_shaders", &settings->bools.quick_menu_show_shaders, true, quick_menu_show_shaders, false);
SETTING_BOOL("quick_menu_show_save_core_overrides", &settings->bools.quick_menu_show_save_core_overrides, true, quick_menu_show_save_core_overrides, false);
SETTING_BOOL("quick_menu_show_save_game_overrides", &settings->bools.quick_menu_show_save_game_overrides, true, quick_menu_show_save_game_overrides, false);
+ SETTING_BOOL("quick_menu_show_save_content_dir_overrides", &settings->bools.quick_menu_show_save_content_dir_overrides, true, quick_menu_show_save_content_dir_overrides, false);
SETTING_BOOL("quick_menu_show_information", &settings->bools.quick_menu_show_information, true, quick_menu_show_information, false);
SETTING_BOOL("kiosk_mode_enable", &settings->bools.kiosk_mode_enable, true, kiosk_mode_enable, false);
SETTING_BOOL("content_show_settings", &settings->bools.menu_content_show_settings, true, content_show_settings, false);
@@ -1306,7 +1368,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("content_show_images", &settings->bools.menu_content_show_images, true, content_show_images, false);
#endif
SETTING_BOOL("content_show_music", &settings->bools.menu_content_show_music, true, content_show_music, false);
-#ifdef HAVE_FFMPEG
+#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
SETTING_BOOL("content_show_video", &settings->bools.menu_content_show_video, true, content_show_video, false);
#endif
#ifdef HAVE_NETWORKING
@@ -1316,13 +1378,18 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
#ifdef HAVE_LIBRETRODB
SETTING_BOOL("content_show_add", &settings->bools.menu_content_show_add, true, content_show_add, false);
#endif
+ SETTING_BOOL("content_show_playlists", &settings->bools.menu_content_show_playlists, true, content_show_playlists, false);
SETTING_BOOL("menu_show_load_core", &settings->bools.menu_show_load_core, true, menu_show_load_core, false);
SETTING_BOOL("menu_show_load_content", &settings->bools.menu_show_load_content, true, menu_show_load_content, false);
SETTING_BOOL("menu_show_information", &settings->bools.menu_show_information, true, menu_show_information, false);
SETTING_BOOL("menu_show_configurations", &settings->bools.menu_show_configurations, true, menu_show_configurations, false);
+ SETTING_BOOL("menu_show_latency", &settings->bools.menu_show_latency, true, true, false);
+ SETTING_BOOL("menu_show_rewind", &settings->bools.menu_show_rewind, true, true, false);
+ SETTING_BOOL("menu_show_overlays", &settings->bools.menu_show_overlays, true, true, false);
SETTING_BOOL("menu_show_help", &settings->bools.menu_show_help, true, menu_show_help, false);
SETTING_BOOL("menu_show_quit_retroarch", &settings->bools.menu_show_quit_retroarch, true, menu_show_quit_retroarch, false);
SETTING_BOOL("menu_show_reboot", &settings->bools.menu_show_reboot, true, menu_show_reboot, false);
+ SETTING_BOOL("menu_show_shutdown", &settings->bools.menu_show_shutdown, true, menu_show_shutdown, false);
SETTING_BOOL("menu_show_online_updater", &settings->bools.menu_show_online_updater, true, menu_show_online_updater, false);
SETTING_BOOL("menu_show_core_updater", &settings->bools.menu_show_core_updater, true, menu_show_core_updater, false);
SETTING_BOOL("filter_by_current_core", &settings->bools.filter_by_current_core, false, false /* TODO */, false);
@@ -1334,6 +1401,11 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
#ifdef HAVE_MATERIALUI
SETTING_BOOL("materialui_icons_enable", &settings->bools.menu_materialui_icons_enable, true, materialui_icons_enable, false);
#endif
+#ifdef HAVE_RGUI
+ SETTING_BOOL("rgui_background_filler_thickness_enable", &settings->bools.menu_rgui_background_filler_thickness_enable, true, true, false);
+ SETTING_BOOL("rgui_border_filler_thickness_enable", &settings->bools.menu_rgui_border_filler_thickness_enable, true, true, false);
+ SETTING_BOOL("rgui_border_filler_enable", &settings->bools.menu_rgui_border_filler_enable, true, true, false);
+#endif
#ifdef HAVE_XMB
SETTING_BOOL("xmb_shadows_enable", &settings->bools.menu_xmb_shadows_enable, true, xmb_shadows_enable, false);
SETTING_BOOL("xmb_vertical_thumbnails", &settings->bools.menu_xmb_vertical_thumbnails, true, xmb_vertical_thumbnails, false);
@@ -1363,9 +1435,6 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
#ifdef HAVE_NETWORKGAMEPAD
SETTING_BOOL("network_remote_enable", &settings->bools.network_remote_enable, false, false /* TODO */, false);
#endif
-#ifdef HAVE_KEYMAPPER
- SETTING_BOOL("keymapper_enable", &settings->bools.keymapper_enable, true, true /* TODO */, false);
-#endif
#ifdef HAVE_NETWORKING
SETTING_BOOL("netplay_nat_traversal", &settings->bools.netplay_nat_traversal, true, true, false);
#endif
@@ -1400,6 +1469,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("video_msg_bgcolor_enable", &settings->bools.video_msg_bgcolor_enable, true, message_bgcolor_enable, false);
SETTING_BOOL("video_window_show_decorations", &settings->bools.video_window_show_decorations, true, window_decorations, false);
+ SETTING_BOOL("sustained_performance_mode", &settings->bools.sustained_performance_mode, true, sustained_performance_mode, false);
+
*size = count;
return tmp;
@@ -1446,6 +1517,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
struct config_uint_setting *tmp = (struct config_uint_setting*)malloc((*size + 1) * sizeof(struct config_uint_setting));
SETTING_UINT("input_bind_timeout", &settings->uints.input_bind_timeout, true, input_bind_timeout, false);
+ SETTING_UINT("input_bind_hold", &settings->uints.input_bind_hold, true, input_bind_hold, false);
SETTING_UINT("input_turbo_period", &settings->uints.input_turbo_period, true, turbo_period, false);
SETTING_UINT("input_duty_cycle", &settings->uints.input_turbo_duty_cycle, true, turbo_duty_cycle, false);
SETTING_UINT("input_max_users", input_driver_get_uint(INPUT_ACTION_MAX_USERS), true, input_max_users, false);
@@ -1454,6 +1526,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("audio_resampler_quality", &settings->uints.audio_resampler_quality, true, audio_resampler_quality_level, false);
SETTING_UINT("audio_block_frames", &settings->uints.audio_block_frames, true, 0, false);
SETTING_UINT("rewind_granularity", &settings->uints.rewind_granularity, true, rewind_granularity, false);
+ SETTING_UINT("rewind_buffer_size_step", &settings->uints.rewind_buffer_size_step, true, rewind_buffer_size_step, false);
SETTING_UINT("autosave_interval", &settings->uints.autosave_interval, true, autosave_interval, false);
SETTING_UINT("libretro_log_level", &settings->uints.libretro_log_level, true, libretro_log_level, false);
SETTING_UINT("keyboard_gamepad_mapping_type",&settings->uints.input_keyboard_gamepad_mapping_type, true, 1, false);
@@ -1470,9 +1543,6 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
#ifdef HAVE_NETWORKGAMEPAD
SETTING_UINT("network_remote_base_port", &settings->uints.network_remote_base_port, true, network_remote_base_port, false);
#endif
-#ifdef HAVE_KEYMAPPER
- SETTING_UINT("keymapper_port", &settings->uints.keymapper_port, true, 0, false);
-#endif
#ifdef GEKKO
SETTING_UINT("video_viwidth", &settings->uints.video_viwidth, true, video_viwidth, false);
#endif
@@ -1483,6 +1553,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("menu_left_thumbnails", &settings->uints.menu_left_thumbnails, true, menu_left_thumbnails_default, false);
SETTING_UINT("xmb_alpha_factor", &settings->uints.menu_xmb_alpha_factor, true, xmb_alpha_factor, false);
SETTING_UINT("xmb_scale_factor", &settings->uints.menu_xmb_scale_factor, true, xmb_scale_factor, false);
+ SETTING_UINT("xmb_layout", &settings->uints.menu_xmb_layout, true, xmb_menu_layout, false);
SETTING_UINT("xmb_theme", &settings->uints.menu_xmb_theme, true, xmb_icon_theme, false);
SETTING_UINT("xmb_menu_color_theme", &settings->uints.menu_xmb_color_theme, true, xmb_theme, false);
SETTING_UINT("menu_font_color_red", &settings->uints.menu_font_color_red, true, menu_font_color_red, false);
@@ -1494,6 +1565,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
#endif
SETTING_UINT("audio_out_rate", &settings->uints.audio_out_rate, true, out_rate, false);
SETTING_UINT("custom_viewport_width", &settings->video_viewport_custom.width, false, 0 /* TODO */, false);
+ SETTING_UINT("crt_switch_resolution_super", &settings->uints.crt_switch_resolution_super, true, crt_switch_resolution_super, false);
SETTING_UINT("custom_viewport_height", &settings->video_viewport_custom.height, false, 0 /* TODO */, false);
SETTING_UINT("custom_viewport_x", (unsigned*)&settings->video_viewport_custom.x, false, 0 /* TODO */, false);
SETTING_UINT("custom_viewport_y", (unsigned*)&settings->video_viewport_custom.y, false, 0 /* TODO */, false);
@@ -1524,6 +1596,20 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("run_ahead_frames", &settings->uints.run_ahead_frames, true, 1, false);
+ SETTING_UINT("midi_volume", &settings->uints.midi_volume, true, midi_volume, false);
+
+ *size = count;
+
+ return tmp;
+}
+
+static struct config_size_setting *populate_settings_size(settings_t *settings, int *size)
+{
+ unsigned count = 0;
+ struct config_size_setting *tmp = (struct config_size_setting*)malloc((*size + 1) * sizeof(struct config_size_setting));
+
+ SETTING_SIZE("rewind_buffer_size", &settings->sizes.rewind_buffer_size, true, rewind_buffer_size, false);
+
*size = count;
return tmp;
@@ -1564,6 +1650,7 @@ static void config_set_defaults(void)
int float_settings_size = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
const char *def_video = config_get_default_video();
const char *def_audio = config_get_default_audio();
const char *def_audio_resampler = config_get_default_audio_resampler();
@@ -1577,11 +1664,13 @@ static void config_set_defaults(void)
const char *def_led = config_get_default_led();
const char *def_location = config_get_default_location();
const char *def_record = config_get_default_record();
+ const char *def_midi = config_get_default_midi();
const char *def_mitm = netplay_mitm_server;
struct config_float_setting *float_settings = populate_settings_float (settings, &float_settings_size);
struct config_bool_setting *bool_settings = populate_settings_bool (settings, &bool_settings_size);
struct config_int_setting *int_settings = populate_settings_int (settings, &int_settings_size);
struct config_uint_setting *uint_settings = populate_settings_uint (settings, &uint_settings_size);
+ struct config_size_setting *size_settings = populate_settings_size (settings, &size_settings_size);
if (bool_settings && (bool_settings_size > 0))
{
@@ -1616,6 +1705,17 @@ static void config_set_defaults(void)
free(uint_settings);
}
+ if (size_settings && (size_settings_size > 0))
+ {
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ {
+ if (size_settings[i].def_enable)
+ *size_settings[i].ptr = size_settings[i].def;
+ }
+
+ free(size_settings);
+ }
+
if (float_settings && (float_settings_size > 0))
{
for (i = 0; i < (unsigned)float_settings_size; i++)
@@ -1657,6 +1757,9 @@ static void config_set_defaults(void)
if (def_record)
strlcpy(settings->arrays.record_driver,
def_record, sizeof(settings->arrays.record_driver));
+ if (def_midi)
+ strlcpy(settings->arrays.midi_driver,
+ def_midi, sizeof(settings->arrays.midi_driver));
if (def_mitm)
strlcpy(settings->arrays.netplay_mitm_server,
def_mitm, sizeof(settings->arrays.netplay_mitm_server));
@@ -1674,7 +1777,7 @@ static void config_set_defaults(void)
#endif
#endif
-#ifdef HAVE_FFMPEG
+#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
configuration_set_bool(settings, settings->bools.multimedia_builtin_mediaplayer_enable, true);
#else
configuration_set_bool(settings, settings->bools.multimedia_builtin_mediaplayer_enable, false);
@@ -1704,8 +1807,6 @@ static void config_set_defaults(void)
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, settings->floats.audio_volume);
audio_set_float(AUDIO_ACTION_MIXER_VOLUME_GAIN, settings->floats.audio_mixer_volume);
- settings->rewind_buffer_size = rewind_buffer_size;
-
#ifdef HAVE_LAKKA
settings->bools.ssh_enable = filestream_exists(LAKKA_SSH_PATH);
settings->bools.samba_enable = filestream_exists(LAKKA_SAMBA_PATH);
@@ -1723,6 +1824,7 @@ static void config_set_defaults(void)
#ifdef HAVE_CHEEVOS
*settings->arrays.cheevos_username = '\0';
*settings->arrays.cheevos_password = '\0';
+ *settings->arrays.cheevos_token = '\0';
#endif
input_config_reset();
@@ -1973,6 +2075,13 @@ static void config_set_defaults(void)
free(temp_str);
}
+ if (midi_input)
+ strlcpy(settings->arrays.midi_input,
+ midi_input, sizeof(settings->arrays.midi_input));
+ if (midi_output)
+ strlcpy(settings->arrays.midi_output,
+ midi_output, sizeof(settings->arrays.midi_output));
+
/* Avoid reloading config on every content load */
if (default_block_config_read)
rarch_ctl(RARCH_CTL_SET_BLOCK_CONFIG_READ, NULL);
@@ -2006,7 +2115,7 @@ static config_file_t *open_default_config_file(void)
(void)path_size;
-#if defined(_WIN32) && !defined(_XBOX)
+#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
fill_pathname_application_path(app_path, path_size);
fill_pathname_resolve_relative(conf_path, app_path,
file_path_str(FILE_PATH_MAIN_CONFIG), path_size);
@@ -2295,6 +2404,7 @@ static bool check_shader_compatibility(enum file_path_enum enum_idx)
settings_t *settings = config_get_ptr();
if (string_is_equal(settings->arrays.video_driver, "vulkan") ||
+ string_is_equal(settings->arrays.video_driver, "metal") ||
string_is_equal(settings->arrays.video_driver, "d3d11") ||
string_is_equal(settings->arrays.video_driver, "d3d12") ||
string_is_equal(settings->arrays.video_driver, "gx2"))
@@ -2395,12 +2505,14 @@ static bool config_load_file(const char *path, bool set_defaults,
int float_settings_size = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
int array_settings_size = sizeof(settings->arrays) / sizeof(settings->arrays.placeholder);
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
struct config_bool_setting *bool_settings = populate_settings_bool (settings, &bool_settings_size);
struct config_float_setting *float_settings = populate_settings_float (settings, &float_settings_size);
struct config_int_setting *int_settings = populate_settings_int (settings, &int_settings_size);
struct config_uint_setting *uint_settings = populate_settings_uint (settings, &uint_settings_size);
+ struct config_size_setting *size_settings = populate_settings_size (settings, &size_settings_size);
struct config_array_setting *array_settings = populate_settings_array (settings, &array_settings_size);
struct config_path_setting *path_settings = populate_settings_path (settings, &path_settings_size);
@@ -2525,6 +2637,23 @@ static bool config_load_file(const char *path, bool set_defaults,
*uint_settings[i].ptr = tmp;
}
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ {
+ size_t tmp = 0;
+ if (config_get_size_t(conf, size_settings[i].ident, &tmp))
+ *size_settings[i].ptr = tmp ;
+ /* Special case for rewind_buffer_size - need to convert low values to what they were
+ * intended to be based on the default value in config.def.h
+ * If the value is less than 10000 then multiple by 1MB because if the retroarch.cfg
+ * file contains rewind_buffer_size = "100" then that ultimately gets interpreted as
+ * 100MB, so ensure the internal values represent that.*/
+ if ( strcmp(size_settings[i].ident, "rewind_buffer_size") == 0 ) {
+ if ( *size_settings[i].ptr < 10000) {
+ *size_settings[i].ptr = *size_settings[i].ptr * 1024 * 1024 ;
+ }
+ }
+ }
+
for (i = 0; i < MAX_USERS; i++)
{
char buf[64];
@@ -2556,13 +2685,6 @@ static bool config_load_file(const char *path, bool set_defaults,
CONFIG_GET_INT_BASE(conf, settings, uints.led_map[i], buf);
}
- {
- /* ugly hack around C89 not allowing mixing declarations and code */
- int buffer_size = 0;
- if (config_get_int(conf, "rewind_buffer_size", &buffer_size))
- settings->rewind_buffer_size = buffer_size * UINT64_C(1000000);
- }
-
/* Hexadecimal settings */
@@ -2883,8 +3005,10 @@ static bool config_load_file(const char *path, bool set_defaults,
settings->arrays.video_driver);
settings->paths.path_shader[0] = '\0';
break;
+ }
}
-}
+
+ frontend_driver_set_sustained_performance_mode(settings->bools.sustained_performance_mode);
ret = true;
@@ -2933,6 +3057,7 @@ bool config_load_override(void)
char *buf = NULL;
char *core_path = NULL;
char *game_path = NULL;
+ char *content_path = NULL;
char *config_directory = NULL;
config_file_t *new_conf = NULL;
bool should_append = false;
@@ -2940,6 +3065,10 @@ bool config_load_override(void)
const char *core_name = system ?
system->info.library_name : NULL;
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
+ char content_dir_name[PATH_MAX_LENGTH];
+
+ if (!string_is_empty(path_get(RARCH_PATH_BASENAME)))
+ fill_pathname_parent_dir_name(content_dir_name, path_get(RARCH_PATH_BASENAME), sizeof(content_dir_name));
if (string_is_empty(core_name) || string_is_empty(game_name))
return false;
@@ -2948,6 +3077,8 @@ bool config_load_override(void)
malloc(PATH_MAX_LENGTH * sizeof(char));
core_path = (char*)
malloc(PATH_MAX_LENGTH * sizeof(char));
+ content_path = (char*)
+ malloc(PATH_MAX_LENGTH * sizeof(char));
buf = (char*)
malloc(PATH_MAX_LENGTH * sizeof(char));
config_directory = (char*)
@@ -2957,23 +3088,29 @@ bool config_load_override(void)
fill_pathname_application_special(config_directory, path_size,
APPLICATION_SPECIAL_DIRECTORY_CONFIG);
- /* Concatenate strings into full paths for core_path, game_path */
+ /* Concatenate strings into full paths for core_path, game_path, content_path */
fill_pathname_join_special_ext(game_path,
config_directory, core_name,
game_name,
file_path_str(FILE_PATH_CONFIG_EXTENSION),
path_size);
+ fill_pathname_join_special_ext(content_path,
+ config_directory, core_name,
+ content_dir_name,
+ file_path_str(FILE_PATH_CONFIG_EXTENSION),
+ path_size);
+
fill_pathname_join_special_ext(core_path,
config_directory, core_name,
core_name,
file_path_str(FILE_PATH_CONFIG_EXTENSION),
path_size);
+ /* per-core overrides */
/* Create a new config file from core_path */
new_conf = config_file_new(core_path);
- /* If a core override exists, add its location to append_config_path */
if (new_conf)
{
RARCH_LOG("[overrides] core-specific overrides found at %s.\n",
@@ -2988,10 +3125,45 @@ bool config_load_override(void)
RARCH_LOG("[overrides] no core-specific overrides found at %s.\n",
core_path);
+ /* per-content-dir overrides */
+ /* Create a new config file from content_path */
+ new_conf = config_file_new(content_path);
+
+ if (new_conf)
+ {
+ char *temp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
+
+ temp_path[0] = '\0';
+
+ config_file_free(new_conf);
+
+ RARCH_LOG("[overrides] content-dir-specific overrides found at %s.\n",
+ game_path);
+
+ if (should_append)
+ {
+ RARCH_LOG("[overrides] content-dir-specific overrides stacking on top of previous overrides.\n");
+ strlcpy(temp_path, path_get(RARCH_PATH_CONFIG_APPEND), path_size);
+ strlcat(temp_path, "|", path_size);
+ strlcat(temp_path, content_path, path_size);
+ }
+ else
+ strlcpy(temp_path, content_path, path_size);
+
+ path_set(RARCH_PATH_CONFIG_APPEND, temp_path);
+
+ free(temp_path);
+
+ should_append = true;
+ }
+ else
+ RARCH_LOG("[overrides] no content-dir-specific overrides found at %s.\n",
+ content_path);
+
+ /* per-game overrides */
/* Create a new config file from game_path */
new_conf = config_file_new(game_path);
- /* If a game override exists, add it's location to append_config_path */
if (new_conf)
{
char *temp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
@@ -3005,6 +3177,7 @@ bool config_load_override(void)
if (should_append)
{
+ RARCH_LOG("[overrides] game-specific overrides stacking on top of previous overrides\n");
strlcpy(temp_path, path_get(RARCH_PATH_CONFIG_APPEND), path_size);
strlcat(temp_path, "|", path_size);
strlcat(temp_path, game_path, path_size);
@@ -3055,6 +3228,7 @@ bool config_load_override(void)
free(buf);
free(config_directory);
free(core_path);
+ free(content_path);
free(game_path);
return true;
@@ -3062,6 +3236,7 @@ error:
free(buf);
free(config_directory);
free(core_path);
+ free(content_path);
free(game_path);
return false;
}
@@ -3113,11 +3288,16 @@ bool config_load_remap(void)
char *remap_directory = NULL;
char *core_path = NULL;
char *game_path = NULL;
+ char *content_path = NULL;
config_file_t *new_conf = NULL;
settings_t *settings = config_get_ptr();
rarch_system_info_t *system = runloop_get_system_info();
const char *core_name = system ? system->info.library_name : NULL;
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
+ char content_dir_name[PATH_MAX_LENGTH];
+
+ if (!string_is_empty(path_get(RARCH_PATH_BASENAME)))
+ fill_pathname_parent_dir_name(content_dir_name, path_get(RARCH_PATH_BASENAME), sizeof(content_dir_name));
if (string_is_empty(core_name) || string_is_empty(game_name))
return false;
@@ -3136,8 +3316,12 @@ bool config_load_remap(void)
/* final path for game-specific configuration (prefix+suffix) */
game_path = (char*)
malloc(PATH_MAX_LENGTH * sizeof(char));
+ /* final path for content-dir-specific configuration (prefix+suffix) */
+ content_path = (char*)
+ malloc(PATH_MAX_LENGTH * sizeof(char));
remap_directory[0] = core_path[0] = game_path[0] = '\0';
+
strlcpy(remap_directory,
settings->paths.directory_input_remapping,
path_size);
@@ -3150,6 +3334,12 @@ bool config_load_remap(void)
file_path_str(FILE_PATH_REMAP_EXTENSION),
path_size);
+ fill_pathname_join_special_ext(content_path,
+ remap_directory, core_name,
+ content_dir_name,
+ file_path_str(FILE_PATH_REMAP_EXTENSION),
+ path_size);
+
fill_pathname_join_special_ext(game_path,
remap_directory, core_name,
game_name,
@@ -3177,6 +3367,28 @@ bool config_load_remap(void)
input_remapping_set_defaults(false);
}
+ /* Create a new config file from content_path */
+ new_conf = config_file_new(content_path);
+
+ /* If a content-dir remap file exists, load it. */
+ if (new_conf)
+ {
+ RARCH_LOG("Remaps: content-dir-specific remap found at %s.\n", content_path);
+ if (input_remapping_load_file(new_conf, content_path))
+ {
+ runloop_msg_queue_push(msg_hash_to_str(
+ MSG_GAME_REMAP_FILE_LOADED), 1, 100, true);
+ rarch_ctl(RARCH_CTL_SET_REMAPS_CONTENT_DIR_ACTIVE, NULL);
+ goto success;
+ }
+ }
+ else
+ {
+ RARCH_LOG("Remaps: no content-dir-specific remap found at %s.\n", content_path);
+ input_remapping_set_defaults(false);
+ }
+
+
/* Create a new config file from core_path */
new_conf = config_file_new(core_path);
@@ -3228,21 +3440,21 @@ success:
bool config_load_shader_preset(void)
{
unsigned idx;
- char parent_name[PATH_MAX_LENGTH];
size_t path_size = PATH_MAX_LENGTH * sizeof(char);
config_file_t *new_conf = NULL;
char *shader_directory = NULL;
char *core_path = NULL;
char *game_path = NULL;
- char *parent_path = NULL;
+ char *content_path = NULL;
settings_t *settings = config_get_ptr();
rarch_system_info_t *system = runloop_get_system_info();
const char *core_name = system
? system->info.library_name : NULL;
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
+ char content_dir_name[PATH_MAX_LENGTH];
if (!string_is_empty(path_get(RARCH_PATH_BASENAME)))
- fill_pathname_parent_dir_name(parent_name, path_get(RARCH_PATH_BASENAME), sizeof(parent_name));
+ fill_pathname_parent_dir_name(content_dir_name, path_get(RARCH_PATH_BASENAME), sizeof(content_dir_name));
if (string_is_empty(core_name) || string_is_empty(game_name))
return false;
@@ -3262,7 +3474,7 @@ bool config_load_shader_preset(void)
game_path = (char*)
malloc(PATH_MAX_LENGTH * sizeof(char));
/* final path for parent-dir-specific configuration (prefix+suffix) */
- parent_path = (char*)
+ content_path = (char*)
malloc(PATH_MAX_LENGTH * sizeof(char));
shader_directory[0] = core_path[0] = game_path[0] = '\0';
@@ -3313,26 +3525,26 @@ bool config_load_shader_preset(void)
if (!check_shader_compatibility((enum file_path_enum)(idx)))
continue;
/* Concatenate strings into full paths for core_path, parent path */
- fill_pathname_join_special_ext(parent_path,
+ fill_pathname_join_special_ext(content_path,
shader_directory, core_name,
- parent_name,
+ content_dir_name,
file_path_str((enum file_path_enum)(idx)),
path_size);
/* Create a new config file from parent path */
- new_conf = config_file_new(parent_path);
+ new_conf = config_file_new(content_path);
if (!new_conf)
{
- RARCH_LOG("Shaders: no parent-dir-specific preset found at %s.\n",
- parent_path);
+ RARCH_LOG("Shaders: no content-dir-specific preset found at %s.\n",
+ content_path);
continue;
}
/* Parent-dir shader preset exists, load it. */
- RARCH_LOG("Shaders: parent-dir-specific shader preset found at %s.\n",
- parent_path);
- retroarch_set_shader_preset(parent_path);
+ RARCH_LOG("Shaders: content-dir-specific shader preset found at %s.\n",
+ content_path);
+ retroarch_set_shader_preset(content_path);
goto success;
}
@@ -3367,14 +3579,14 @@ bool config_load_shader_preset(void)
free(shader_directory);
free(core_path);
free(game_path);
- free(parent_path);
+ free(content_path);
return false;
success:
free(shader_directory);
free(core_path);
free(game_path);
- free(parent_path);
+ free(content_path);
config_file_free(new_conf);
return true;
}
@@ -3522,14 +3734,14 @@ static void save_keybind_mbutton(config_file_t *conf,
const char *base,
const struct retro_keybind *bind, bool save_empty)
{
- char key[64];
+ char key[64];
- key[0] = '\0';
+ key[0] = '\0';
- fill_pathname_join_delim_concat(key, prefix,
- base, '_', "_mbtn", sizeof(key));
+ fill_pathname_join_delim_concat(key, prefix,
+ base, '_', "_mbtn", sizeof(key));
- switch ( bind->mbutton )
+ switch ( bind->mbutton )
{
case RETRO_DEVICE_ID_MOUSE_LEFT:
config_set_uint64(conf, key, 1);
@@ -3775,8 +3987,7 @@ bool config_save_autoconf_profile(const char *path, unsigned user)
error:
free(buf);
free(autoconf_file);
- if (path_new)
- free(path_new);
+ free(path_new);
return false;
}
@@ -3797,6 +4008,7 @@ bool config_save_file(const char *path)
struct config_bool_setting *bool_settings = NULL;
struct config_int_setting *int_settings = NULL;
struct config_uint_setting *uint_settings = NULL;
+ struct config_size_setting *size_settings = NULL;
struct config_float_setting *float_settings = NULL;
struct config_array_setting *array_settings = NULL;
struct config_path_setting *path_settings = NULL;
@@ -3806,6 +4018,7 @@ bool config_save_file(const char *path)
int float_settings_size = sizeof(settings->floats)/ sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
int array_settings_size = sizeof(settings->arrays)/ sizeof(settings->arrays.placeholder);
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
@@ -3822,6 +4035,7 @@ bool config_save_file(const char *path)
bool_settings = populate_settings_bool (settings, &bool_settings_size);
int_settings = populate_settings_int (settings, &int_settings_size);
uint_settings = populate_settings_uint (settings, &uint_settings_size);
+ size_settings = populate_settings_size (settings, &size_settings_size);
float_settings = populate_settings_float (settings, &float_settings_size);
array_settings = populate_settings_array (settings, &array_settings_size);
path_settings = populate_settings_path (settings, &path_settings_size);
@@ -3899,6 +4113,18 @@ bool config_save_file(const char *path)
free(uint_settings);
}
+ if (size_settings && (size_settings_size > 0))
+ {
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ if (!size_settings[i].override ||
+ !retroarch_override_setting_is_set(size_settings[i].override, NULL))
+ config_set_int(conf,
+ size_settings[i].ident,
+ *size_settings[i].ptr);
+
+ free(size_settings);
+ }
+
for (i = 0; i < MAX_USERS; i++)
{
char cfg[64];
@@ -4018,8 +4244,10 @@ bool config_save_overrides(int override_type)
struct config_bool_setting *bool_overrides = NULL;
struct config_int_setting *int_settings = NULL;
struct config_uint_setting *uint_settings = NULL;
+ struct config_size_setting *size_settings = NULL;
struct config_int_setting *int_overrides = NULL;
struct config_uint_setting *uint_overrides = NULL;
+ struct config_size_setting *size_overrides = NULL;
struct config_float_setting *float_settings = NULL;
struct config_float_setting *float_overrides= NULL;
struct config_array_setting *array_settings = NULL;
@@ -4030,16 +4258,22 @@ bool config_save_overrides(int override_type)
char *override_directory = NULL;
char *core_path = NULL;
char *game_path = NULL;
+ char *content_path = NULL;
settings_t *overrides = config_get_ptr();
int bool_settings_size = sizeof(settings->bools) / sizeof(settings->bools.placeholder);
int float_settings_size = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
int array_settings_size = sizeof(settings->arrays) / sizeof(settings->arrays.placeholder);
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
rarch_system_info_t *system = runloop_get_system_info();
const char *core_name = system ? system->info.library_name : NULL;
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
+ char content_dir_name[PATH_MAX_LENGTH];
+
+ if (!string_is_empty(path_get(RARCH_PATH_BASENAME)))
+ fill_pathname_parent_dir_name(content_dir_name, path_get(RARCH_PATH_BASENAME), sizeof(content_dir_name));
if (string_is_empty(core_name) || string_is_empty(game_name))
return false;
@@ -4049,6 +4283,7 @@ bool config_save_overrides(int override_type)
override_directory = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
core_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
game_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
+ content_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
config_directory[0] = override_directory[0] = core_path[0] = game_path[0] = '\0';
@@ -4068,6 +4303,12 @@ bool config_save_overrides(int override_type)
file_path_str(FILE_PATH_CONFIG_EXTENSION),
path_size);
+ fill_pathname_join_special_ext(content_path,
+ config_directory, core_name,
+ content_dir_name,
+ file_path_str(FILE_PATH_CONFIG_EXTENSION),
+ path_size);
+
fill_pathname_join_special_ext(core_path,
config_directory, core_name,
core_name,
@@ -4092,6 +4333,10 @@ bool config_save_overrides(int override_type)
tmp_i = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
uint_overrides = populate_settings_uint (overrides, &tmp_i);
+ size_settings = populate_settings_size(settings, &size_settings_size);
+ tmp_i = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
+ size_overrides = populate_settings_size (overrides, &tmp_i);
+
float_settings = populate_settings_float(settings, &float_settings_size);
tmp_i = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
float_overrides = populate_settings_float(overrides, &tmp_i);
@@ -4144,6 +4389,18 @@ bool config_save_overrides(int override_type)
(*uint_overrides[i].ptr));
}
}
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ {
+ if ((*size_settings[i].ptr) != (*size_overrides[i].ptr))
+ {
+ RARCH_LOG(" original: %s=%d\n",
+ size_settings[i].ident, (*size_settings[i].ptr));
+ RARCH_LOG(" override: %s=%d\n",
+ size_overrides[i].ident, (*size_overrides[i].ptr));
+ config_set_int(conf, size_overrides[i].ident,
+ (*size_overrides[i].ptr));
+ }
+ }
for (i = 0; i < (unsigned)float_settings_size; i++)
{
if ((*float_settings[i].ptr) != (*float_overrides[i].ptr))
@@ -4172,6 +4429,11 @@ bool config_save_overrides(int override_type)
for (i = 0; i < (unsigned)path_settings_size; i++)
{
+
+ /* blacklist video_shader, better handled by shader presets*/
+ /* to-do: add setting to control blacklisting */
+ if (string_is_equal(path_settings[i].ident, "video_shader"))
+ continue;
if (!string_is_equal(path_settings[i].ptr, path_overrides[i].ptr))
{
RARCH_LOG(" original: %s=%s\n",
@@ -4202,6 +4464,9 @@ bool config_save_overrides(int override_type)
config_set_int(conf, cfg, overrides->uints.input_joypad_map[i]);
}
+
+ /* blacklist these since they are handled by remaps */
+ /* to-do: add setting to control blacklisting
if (settings->uints.input_libretro_device[i]
!= overrides->uints.input_libretro_device[i])
{
@@ -4215,6 +4480,7 @@ bool config_save_overrides(int override_type)
snprintf(cfg, sizeof(cfg), "input_player%u_analog_dpad_mode", i + 1);
config_set_int(conf, cfg, overrides->uints.input_analog_dpad_mode[i]);
}
+ */
}
ret = false;
@@ -4231,6 +4497,11 @@ bool config_save_overrides(int override_type)
RARCH_LOG ("[overrides] path %s\n", game_path);
ret = config_file_write(conf, game_path);
break;
+ case OVERRIDE_CONTENT_DIR:
+ /* Create a new config file from content_path */
+ RARCH_LOG ("[overrides] path %s\n", content_path);
+ ret = config_file_write(conf, content_path);
+ break;
default:
break;
}
@@ -4246,6 +4517,8 @@ bool config_save_overrides(int override_type)
free(int_settings);
if (uint_settings)
free(uint_settings);
+ if (size_settings)
+ free(size_settings);
if (int_overrides)
free(int_overrides);
if (uint_overrides)
diff --git a/configuration.h b/configuration.h
index b43facf5f6..8955319959 100644
--- a/configuration.h
+++ b/configuration.h
@@ -57,6 +57,7 @@ enum override_type
{
OVERRIDE_NONE = 0,
OVERRIDE_CORE,
+ OVERRIDE_CONTENT_DIR,
OVERRIDE_GAME
};
@@ -95,9 +96,11 @@ typedef struct settings
bool video_statistics_show;
bool video_framecount_show;
bool video_msg_bgcolor_enable;
+ bool crt_switch_resolution;
/* Audio */
bool audio_enable;
+ bool audio_enable_menu;
bool audio_sync;
bool audio_rate_control;
bool audio_wasapi_exclusive_mode;
@@ -146,7 +149,14 @@ typedef struct settings
bool menu_show_help;
bool menu_show_quit_retroarch;
bool menu_show_reboot;
+ bool menu_show_shutdown;
+ bool menu_show_latency;
+ bool menu_show_rewind;
+ bool menu_show_overlays;
bool menu_materialui_icons_enable;
+ bool menu_rgui_background_filler_thickness_enable;
+ bool menu_rgui_border_filler_thickness_enable;
+ bool menu_rgui_border_filler_enable;
bool menu_xmb_shadows_enable;
bool menu_xmb_vertical_thumbnails;
bool menu_content_show_settings;
@@ -157,6 +167,7 @@ typedef struct settings
bool menu_content_show_netplay;
bool menu_content_show_history;
bool menu_content_show_add;
+ bool menu_content_show_playlists;
bool menu_unified_controls;
bool quick_menu_show_take_screenshot;
bool quick_menu_show_save_load_state;
@@ -168,6 +179,7 @@ typedef struct settings
bool quick_menu_show_shaders;
bool quick_menu_show_save_core_overrides;
bool quick_menu_show_save_game_overrides;
+ bool quick_menu_show_save_content_dir_overrides;
bool quick_menu_show_information;
bool kiosk_mode_enable;
@@ -189,6 +201,8 @@ typedef struct settings
bool ui_suspend_screensaver_enable;
bool ui_companion_start_on_boot;
bool ui_companion_enable;
+ bool ui_companion_toggle;
+ bool desktop_menu_enable;
/* Cheevos */
bool cheevos_enable;
@@ -217,6 +231,7 @@ typedef struct settings
bool bundle_assets_extract_enable;
/* Misc. */
+ bool discord_enable;
bool threaded_data_runloop_enable;
bool set_supports_no_game_enable;
bool auto_screenshot_filename;
@@ -226,6 +241,7 @@ typedef struct settings
bool rewind_enable;
bool run_ahead_enabled;
bool run_ahead_secondary_instance;
+ bool run_ahead_hide_warnings;
bool pause_nonactive;
bool block_sram_overwrite;
bool savestate_auto_index;
@@ -260,6 +276,8 @@ typedef struct settings
bool automatically_add_content_to_playlist;
bool video_window_show_decorations;
+
+ bool sustained_performance_mode;
} bools;
struct
@@ -315,6 +333,7 @@ typedef struct settings
unsigned input_turbo_duty_cycle;
unsigned input_bind_timeout;
+ unsigned input_bind_hold;
unsigned input_menu_toggle_gamepad_combo;
unsigned input_keyboard_gamepad_mapping_type;
@@ -329,6 +348,7 @@ typedef struct settings
unsigned content_history_size;
unsigned libretro_log_level;
unsigned rewind_granularity;
+ unsigned rewind_buffer_size_step;
unsigned autosave_interval;
unsigned network_cmd_port;
unsigned network_remote_base_port;
@@ -336,6 +356,7 @@ typedef struct settings
unsigned video_window_x;
unsigned video_window_y;
unsigned video_window_opacity;
+ unsigned crt_switch_resolution_super;
unsigned video_monitor_index;
unsigned video_fullscreen_x;
unsigned video_fullscreen_y;
@@ -356,6 +377,7 @@ typedef struct settings
unsigned menu_entry_normal_color;
unsigned menu_entry_hover_color;
unsigned menu_title_color;
+ unsigned menu_xmb_layout;
unsigned menu_xmb_shader_pipeline;
unsigned menu_xmb_scale_factor;
unsigned menu_xmb_alpha_factor;
@@ -379,15 +401,23 @@ typedef struct settings
unsigned input_libretro_device[MAX_USERS];
unsigned input_analog_dpad_mode[MAX_USERS];
- unsigned input_keymapper_ids[RARCH_CUSTOM_BIND_LIST_END];
+ unsigned input_keymapper_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
unsigned input_remap_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
unsigned led_map[MAX_LEDS];
unsigned run_ahead_frames;
+
+ unsigned midi_volume;
} uints;
+ struct
+ {
+ size_t placeholder;
+ size_t rewind_buffer_size;
+ } sizes;
+
struct
{
char placeholder;
@@ -401,11 +431,13 @@ typedef struct settings
char menu_driver[32];
char cheevos_username[32];
char cheevos_password[32];
+ char cheevos_token[32];
char video_context_driver[32];
char audio_driver[32];
char audio_resampler[32];
char input_driver[32];
char input_joypad_driver[32];
+ char midi_driver[32];
char input_keyboard_layout[64];
@@ -419,6 +451,9 @@ typedef struct settings
char bundle_assets_dst_subdir[PATH_MAX_LENGTH];
char netplay_mitm_server[255];
+
+ char midi_input[32];
+ char midi_output[32];
} arrays;
struct
@@ -481,7 +516,6 @@ typedef struct settings
video_viewport_t video_viewport_custom;
- size_t rewind_buffer_size;
} settings_t;
/**
@@ -565,6 +599,9 @@ const char *config_get_default_joypad(void);
**/
const char *config_get_default_menu(void);
+const char *config_get_default_midi(void);
+const char *config_get_midi_driver_options(void);
+
const char *config_get_default_record(void);
/**
diff --git a/content.h b/content.h
index ad4211c5a0..5e25e47c64 100644
--- a/content.h
+++ b/content.h
@@ -92,17 +92,16 @@ void content_clear_subsystem(void);
void content_set_subsystem(unsigned subsystem);
/* Get the current subsystem*/
-int content_get_subsystem();
+int content_get_subsystem(void);
/* Add a rom to the subsystem rom buffer */
void content_add_subsystem(const char* path);
/* Get the current subsystem rom id */
-int content_get_subsystem_rom_id();
+unsigned content_get_subsystem_rom_id(void);
/* Set environment variables before a subsystem load */
-void content_set_subsystem_info();
-
+void content_set_subsystem_info(void);
RETRO_END_DECLS
diff --git a/core_impl.c b/core_impl.c
index 7c2585a0c2..f1516fab7c 100644
--- a/core_impl.c
+++ b/core_impl.c
@@ -290,6 +290,8 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info)
bool contentless = false;
bool is_inited = false;
+ video_driver_set_cached_frame_ptr(NULL);
+
#ifdef HAVE_RUNAHEAD
set_load_content_info(load_info);
clear_controller_port_map();
@@ -373,12 +375,16 @@ bool core_get_system_av_info(struct retro_system_av_info *av_info)
bool core_reset(void)
{
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_reset();
return true;
}
bool core_init(void)
{
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_init();
current_core.inited = true;
return true;
@@ -386,6 +392,8 @@ bool core_init(void)
bool core_unload(void)
{
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_deinit();
return true;
}
@@ -396,9 +404,12 @@ bool core_unload_game(void)
video_driver_free_hw_context();
audio_driver_stop();
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_unload_game();
current_core.game_loaded = false;
+
return true;
}
diff --git a/core_info.c b/core_info.c
index 76b979046b..18bcfeffec 100644
--- a/core_info.c
+++ b/core_info.c
@@ -17,6 +17,7 @@
#include
#include
+#include
#include
#include
#include
@@ -26,14 +27,10 @@
#include "config.h"
#endif
-#include "retroarch.h"
#include "verbosity.h"
-#include "config.def.h"
#include "core_info.h"
-#include "configuration.h"
#include "file_path_special.h"
-#include "list_special.h"
static const char *core_info_tmp_path = NULL;
static const struct string_list *core_info_tmp_list = NULL;
@@ -154,6 +151,7 @@ static void core_info_list_free(core_info_list_t *core_info_list)
free(info->systemname);
free(info->system_manufacturer);
free(info->display_name);
+ free(info->display_version);
free(info->supported_extensions);
free(info->authors);
free(info->permissions);
@@ -224,21 +222,23 @@ static bool core_info_list_iterate(
return true;
}
-static core_info_list_t *core_info_list_new(const char *path)
+static core_info_list_t *core_info_list_new(const char *path,
+ const char *libretro_info_dir,
+ const char *exts,
+ bool show_hidden_files)
{
size_t i;
core_info_t *core_info = NULL;
core_info_list_t *core_info_list = NULL;
- struct string_list *contents = dir_list_new_special(
- path, DIR_LIST_CORES, NULL);
- settings_t *settings = config_get_ptr();
- const char *path_basedir = !string_is_empty(settings->paths.path_libretro_info) ?
- settings->paths.path_libretro_info : settings->paths.directory_libretro;
-
+ const char *path_basedir = libretro_info_dir;
+ struct string_list *contents = dir_list_new(
+ path, exts,
+ false,
+ show_hidden_files,
+ false, false);
if (!contents)
return NULL;
-
core_info_list = (core_info_list_t*)calloc(1, sizeof(*core_info_list));
if (!core_info_list)
goto error;
@@ -279,6 +279,13 @@ static core_info_list_t *core_info_list_new(const char *path)
free(tmp);
tmp = NULL;
}
+ if (config_get_string(conf, "display_version", &tmp)
+ && !string_is_empty(tmp))
+ {
+ core_info[i].display_version = strdup(tmp);
+ free(tmp);
+ tmp = NULL;
+ }
if (config_get_string(conf, "corename", &tmp)
&& !string_is_empty(tmp))
{
@@ -518,7 +525,8 @@ static core_info_t *core_info_find_internal(
static bool core_info_list_update_missing_firmware_internal(
core_info_list_t *core_info_list,
const char *core,
- const char *systemdir)
+ const char *systemdir,
+ bool *set_missing_bios)
{
size_t i;
core_info_t *info = NULL;
@@ -535,7 +543,6 @@ static bool core_info_list_update_missing_firmware_internal(
path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
path[0] = '\0';
- rarch_ctl(RARCH_CTL_UNSET_MISSING_BIOS, NULL);
for (i = 0; i < info->firmware_count; i++)
{
@@ -547,7 +554,7 @@ static bool core_info_list_update_missing_firmware_internal(
info->firmware[i].missing = !filestream_exists(path);
if (info->firmware[i].missing && !info->firmware[i].optional)
{
- rarch_ctl(RARCH_CTL_SET_MISSING_BIOS, NULL);
+ *set_missing_bios = true;
RARCH_WARN("Firmware missing: %s\n", info->firmware[i].path);
}
}
@@ -635,14 +642,13 @@ void core_info_deinit_list(void)
core_info_curr_list = NULL;
}
-bool core_info_init_list(void)
+bool core_info_init_list(const char *path_info, const char *dir_cores,
+ const char *exts, bool show_hidden_files)
{
- settings_t *settings = config_get_ptr();
-
- if (settings)
- core_info_curr_list = core_info_list_new(settings->paths.directory_libretro);
-
- if (!core_info_curr_list)
+ if (!(core_info_curr_list = core_info_list_new(dir_cores,
+ !string_is_empty(path_info) ? path_info : dir_cores,
+ exts,
+ show_hidden_files)))
return false;
return true;
}
@@ -655,13 +661,15 @@ bool core_info_get_list(core_info_list_t **core)
return true;
}
-bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info)
+bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info,
+ bool *set_missing_bios)
{
if (!info)
return false;
return core_info_list_update_missing_firmware_internal(
core_info_curr_list,
- info->path, info->directory.system);
+ info->path, info->directory.system,
+ set_missing_bios);
}
bool core_info_load(core_info_ctx_find_t *info)
@@ -751,16 +759,15 @@ void core_info_list_get_supported_cores(core_info_list_t *core_info_list,
*num_infos = supported;
}
-void core_info_get_name(const char *path, char *s, size_t len)
+void core_info_get_name(const char *path, char *s, size_t len,
+ const char *path_info, const char *dir_cores,
+ const char *exts, bool show_hidden_files)
{
size_t i;
- settings_t *settings = config_get_ptr();
- struct string_list *contents = dir_list_new_special(
- settings->paths.directory_libretro,
- DIR_LIST_CORES, NULL);
- const char *path_basedir = !string_is_empty(settings->paths.path_libretro_info) ?
- settings->paths.path_libretro_info : settings->paths.directory_libretro;
-
+ const char *path_basedir = !string_is_empty(path_info) ?
+ path_info : dir_cores;
+ struct string_list *contents = dir_list_new(
+ dir_cores, exts, false, show_hidden_files, false, false);
if (!contents)
return;
@@ -786,7 +793,7 @@ void core_info_get_name(const char *path, char *s, size_t len)
continue;
}
- conf = config_file_new(info_path);
+ conf = config_file_new(info_path);
if (!conf)
{
diff --git a/core_info.h b/core_info.h
index c058e8d937..f87805e605 100644
--- a/core_info.h
+++ b/core_info.h
@@ -43,6 +43,7 @@ typedef struct
char *path;
void *config_data;
char *display_name;
+ char *display_version;
char *core_name;
char *system_manufacturer;
char *systemname;
@@ -97,7 +98,9 @@ bool core_info_list_get_display_name(core_info_list_t *list,
bool core_info_get_display_name(const char *path, char *s, size_t len);
-void core_info_get_name(const char *path, char *s, size_t len);
+void core_info_get_name(const char *path, char *s, size_t len,
+ const char *path_info, const char *dir_cores,
+ const char *exts, bool show_hidden_files);
core_info_t *core_info_get(core_info_list_t *list, size_t i);
@@ -109,11 +112,13 @@ bool core_info_get_current_core(core_info_t **core);
void core_info_deinit_list(void);
-bool core_info_init_list(void);
+bool core_info_init_list(const char *path_info, const char *dir_cores,
+ const char *exts, bool show_hidden_files);
bool core_info_get_list(core_info_list_t **core);
-bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info);
+bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info,
+ bool *set_missing_bios);
bool core_info_find(core_info_ctx_find_t *info, const char *name);
diff --git a/core_type.h b/core_type.h
index e4a66058e5..e8933de6bd 100644
--- a/core_type.h
+++ b/core_type.h
@@ -21,6 +21,7 @@ enum rarch_core_type
CORE_TYPE_PLAIN = 0,
CORE_TYPE_DUMMY,
CORE_TYPE_FFMPEG,
+ CORE_TYPE_MPV,
CORE_TYPE_IMAGEVIEWER,
CORE_TYPE_NETRETROPAD,
CORE_TYPE_VIDEO_PROCESSOR
diff --git a/cores/internal_cores.h b/cores/internal_cores.h
index 6ef7d74f8c..08e916d63e 100644
--- a/cores/internal_cores.h
+++ b/cores/internal_cores.h
@@ -136,6 +136,62 @@ size_t libretro_ffmpeg_retro_get_memory_size(unsigned id);
#endif
+#ifdef HAVE_MPV
+/* Internal mpv core. */
+
+void libretro_mpv_retro_init(void);
+
+void libretro_mpv_retro_deinit(void);
+
+unsigned libretro_mpv_retro_api_version(void);
+
+void libretro_mpv_retro_get_system_info(struct retro_system_info *info);
+
+void libretro_mpv_retro_get_system_av_info(struct retro_system_av_info *info);
+
+void libretro_mpv_retro_set_environment(retro_environment_t cb);
+
+void libretro_mpv_retro_set_video_refresh(retro_video_refresh_t cb);
+
+void libretro_mpv_retro_set_audio_sample(retro_audio_sample_t cb);
+
+void libretro_mpv_retro_set_audio_sample_batch(retro_audio_sample_batch_t cb);
+
+void libretro_mpv_retro_set_input_poll(retro_input_poll_t cb);
+
+void libretro_mpv_retro_set_input_state(retro_input_state_t cb);
+
+void libretro_mpv_retro_set_controller_port_device(unsigned port, unsigned device);
+
+void libretro_mpv_retro_reset(void);
+
+void libretro_mpv_retro_run(void);
+
+size_t libretro_mpv_retro_serialize_size(void);
+
+bool libretro_mpv_retro_serialize(void *data, size_t size);
+
+bool libretro_mpv_retro_unserialize(const void *data, size_t size);
+
+void libretro_mpv_retro_cheat_reset(void);
+
+void libretro_mpv_retro_cheat_set(unsigned index, bool enabled, const char *code);
+
+bool libretro_mpv_retro_load_game(const struct retro_game_info *game);
+
+bool libretro_mpv_retro_load_game_special(unsigned game_type,
+ const struct retro_game_info *info, size_t num_info);
+
+void libretro_mpv_retro_unload_game(void);
+
+unsigned libretro_mpv_retro_get_region(void);
+
+void *libretro_mpv_retro_get_memory_data(unsigned id);
+
+size_t libretro_mpv_retro_get_memory_size(unsigned id);
+
+#endif
+
#ifdef HAVE_IMAGEVIEWER
/* Internal image viewer core. */
diff --git a/cores/libretro-mpv/Makefile b/cores/libretro-mpv/Makefile
index 5b84e98581..a48ea471a7 100644
--- a/cores/libretro-mpv/Makefile
+++ b/cores/libretro-mpv/Makefile
@@ -114,7 +114,7 @@ endif
CFLAGS += -I../../libretro-common/include
OBJECTS := mpv-libretro.o
-LDFLAGS += -lmpv -ldl -lm
+LDFLAGS += -lmpv -lm
CFLAGS += -Wall -pedantic
all: $(TARGET)
diff --git a/cores/libretro-mpv/README.md b/cores/libretro-mpv/README.md
index 9ef302196c..369cc730ee 100644
--- a/cores/libretro-mpv/README.md
+++ b/cores/libretro-mpv/README.md
@@ -1,17 +1,46 @@
# libretro-mpv
-mpv media player as a libretro core. A proof of concept release is now available.
+mpv media player as a libretro core. A proof of concept release is now
+available.
-Aims to use features already established in mpv that are not currently available in Retroarch movieplayer.
+Aims to use features already established in mpv that are not currently
+available in Retroarch movieplayer.
-I want to be able to use Retroarch as my movie player on my embedded devices (Raspberry Pi) and desktop using hardware acceleration without having to use Kodi or mpv directly. Thus allowing for a more integrated experience, and smaller root filesystem.
+I want to be able to use Retroarch as my movie player on my embedded devices
+(Raspberry Pi) and desktop using hardware acceleration without having to use
+Kodi or mpv directly. Thus allowing for a more integrated experience, and
+smaller root filesystem.
## Compiling
-Retroarch must be compiled with `--disable-ffmpeg` to stop the integrated movieplayer from playing the input file.
+### Overview
+
+Retroarch must be compiled with `--disable-ffmpeg` to stop the integrated
+movieplayer from playing the input file.
FFmpeg (preferably master branch) must be compiled with `--enable-shared`.
mpv must be compiled with `--enable-libmpv-shared`.
Then run `make` in the mpv-libretro folder.
+
+### Compiling with Mingw-w64 on Windows
+
+RetroArch must be compiled with `--disable-ffmpeg` and have OpenGL or
+OpenGLES enabled. Compiling RetroArch is not described here.
+
+1. Open `Minwg-w64 64 bit` (not MSYS2 shell).
+2. Install ffmpeg using `pacman -S mingw64/mingw-w64-x86_64-ffmpeg`.
+3. Clone the ao_cb branch of https://github.com/deltabeard/mpv.git . This fork has the audio
+callback patches required for libretro-mpv.
+4. Follow the instructions at https://github.com/mpv-player/mpv/blob/master/DOCS/compile-windows.md#native-compilation-with-msys2 to compile mpv.
+5. Download libretro-mpv release 0.3.alpha by either checking out the
+ `audio-cb-new` branch of `https://github.com/libretro/libretro-mpv.git` or
+ by downloading
+ https://github.com/libretro/libretro-mpv/archive/0.3.alpha.tar.gz .
+6. Run `make` in the libretro-mpv folder. If using OpenGLES, run `make
+ platform=gles` instead.
+
+Overall, the dependencies required to build libretro-mpv are:
+- ffmpeg 4.0 (provided by mingw64/mingw-w64-x86_64-ffmpeg)
+- mpv from https://github.com/deltabeard/mpv.git fork.
diff --git a/cores/libretro-mpv/internal_cores.h b/cores/libretro-mpv/internal_cores.h
new file mode 100644
index 0000000000..7e1a2aab98
--- /dev/null
+++ b/cores/libretro-mpv/internal_cores.h
@@ -0,0 +1 @@
+#include "../internal_cores.h"
diff --git a/cores/libretro-mpv/mpv-libretro.c b/cores/libretro-mpv/mpv-libretro.c
index 3f95acc50e..c84ebd2561 100644
--- a/cores/libretro-mpv/mpv-libretro.c
+++ b/cores/libretro-mpv/mpv-libretro.c
@@ -14,26 +14,28 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
+
#include
#include
#include
#include
#include
-#include
-
-#ifdef HAVE_OPENGLES
-#include
-#endif
#ifdef HAVE_LOCALE
#include
#endif
#include
-#include
+#include
#include
+#ifdef RARCH_INTERNAL
+#include "internal_cores.h"
+#define CORE_PREFIX(s) libretro_mpv_##s
+#else
+#define CORE_PREFIX(s) s
+#endif
+
#include "version.h"
static struct retro_hw_render_callback hw_render;
@@ -41,28 +43,25 @@ static struct retro_hw_render_callback hw_render;
static struct retro_log_callback logging;
static retro_log_printf_t log_cb;
-static retro_video_refresh_t video_cb;
-static retro_audio_sample_t audio_cb;
-static retro_audio_sample_batch_t audio_batch_cb;
-static retro_environment_t environ_cb;
-static retro_input_poll_t input_poll_cb;
-static retro_input_state_t input_state_cb;
+static retro_video_refresh_t CORE_PREFIX(video_cb);
+static retro_audio_sample_t CORE_PREFIX(audio_cb);
+static retro_audio_sample_batch_t CORE_PREFIX(audio_batch_cb);
+static retro_environment_t CORE_PREFIX(environ_cb);
+static retro_input_poll_t CORE_PREFIX(input_poll_cb);
+static retro_input_state_t CORE_PREFIX(input_state_cb);
static mpv_handle *mpv;
-static mpv_opengl_cb_context *mpv_gl;
-
-/* Keep track of the number of events in mpv queue */
-static unsigned int event_waiting = 0;
+static mpv_render_context *mpv_gl;
/* Save the current playback time for context changes */
-static int64_t *playback_time = 0;
+static int64_t playback_time = 0;
/* filepath required globaly as mpv is reopened on context change */
static char *filepath = NULL;
static volatile int frame_queue = 0;
-void queue_new_frame(void *cb_ctx)
+void on_mpv_redraw(void *cb_ctx)
{
frame_queue++;
}
@@ -76,52 +75,59 @@ static void fallback_log(enum retro_log_level level, const char *fmt, ...)
va_end(va);
}
-static void print_mpv_logs(void)
+/**
+ * Process various events triggered by mpv, such as printing log messages.
+ *
+ * \param event_block Wait until the mpv triggers specified event. Should be
+ * NULL if no wait is required.
+ */
+static void process_mpv_events(mpv_event_id event_block)
{
- /* Print out mpv logs */
- if(event_waiting > 0)
+ do
{
- while(1)
+ mpv_event *mp_event = mpv_wait_event(mpv, 0);
+ if(event_block == MPV_EVENT_NONE &&
+ mp_event->event_id == MPV_EVENT_NONE)
+ break;
+
+ if(mp_event->event_id == event_block)
+ event_block = MPV_EVENT_NONE;
+
+ if(mp_event->event_id == MPV_EVENT_LOG_MESSAGE)
{
- mpv_event *mp_event = mpv_wait_event(mpv, 0);
- if(mp_event->event_id == MPV_EVENT_NONE)
- break;
-
- if(mp_event->event_id == MPV_EVENT_LOG_MESSAGE)
- {
- struct mpv_event_log_message *msg =
- (struct mpv_event_log_message *)mp_event->data;
- log_cb(RETRO_LOG_INFO, "mpv: [%s] %s: %s",
- msg->prefix, msg->level, msg->text);
- }
- else if(mp_event->event_id == MPV_EVENT_END_FILE)
- {
- struct mpv_event_end_file *eof =
- (struct mpv_event_end_file *)mp_event->data;
-
- if(eof->reason == MPV_END_FILE_REASON_EOF)
- environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, NULL);
-#if 0
- /* The following could be done instead if the file was not
- * closed once the end was reached - allowing the user to seek
- * back without reopening the file.
- */
- struct retro_message ra_msg = {
- "Finished playing file", 60 * 5, /* 5 seconds */
- };
-
- environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &ra_msg);RETRO_ENVIRONMENT_SHUTDOWN
-#endif
- }
- else
- {
- log_cb(RETRO_LOG_INFO, "mpv: %s\n",
- mpv_event_name(mp_event->event_id));
- }
+ struct mpv_event_log_message *msg =
+ (struct mpv_event_log_message *)mp_event->data;
+ log_cb(RETRO_LOG_INFO, "mpv: [%s] %s: %s",
+ msg->prefix, msg->level, msg->text);
}
+ else if(mp_event->event_id == MPV_EVENT_END_FILE)
+ {
+ struct mpv_event_end_file *eof =
+ (struct mpv_event_end_file *)mp_event->data;
- event_waiting = 0;
+ if(eof->reason == MPV_END_FILE_REASON_EOF)
+ CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SHUTDOWN, NULL);
+#if 0
+ /* The following could be done instead if the file was not
+ * closed once the end was reached - allowing the user to seek
+ * back without reopening the file.
+ */
+ struct retro_message ra_msg = {
+ "Finished playing file", 60 * 5, /* 5 seconds */
+ };
+
+ CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_MESSAGE, &ra_msg);RETRO_ENVIRONMENT_SHUTDOWN
+#endif
+ }
+ else if(mp_event->event_id == MPV_EVENT_NONE)
+ continue;
+ else
+ {
+ log_cb(RETRO_LOG_INFO, "mpv: %s\n",
+ mpv_event_name(mp_event->event_id));
+ }
}
+ while(1);
}
static void *get_proc_address_mpv(void *fn_ctx, const char *name)
@@ -134,58 +140,38 @@ static void *get_proc_address_mpv(void *fn_ctx, const char *name)
void *proc_addr = (void *) hw_render.get_proc_address(name);
#pragma GCC diagnostic pop
-#ifdef HAVE_OPENGLES
- /* EGL 1.4 (supported by the RPI firmware) does not necessarily return
- * function pointers for core functions.
- */
- if (!proc_addr)
- {
- void *h = dlopen("/opt/vc/lib/libGLESv2.so", RTLD_LAZY);
-
- if (!h)
- h = dlopen("/usr/lib/libGLESv2.so", RTLD_LAZY);
-
- if (h)
- {
- proc_addr = dlsym(h, name);
- dlclose(h);
- }
- }
-#endif
-
if(proc_addr == NULL)
log_cb(RETRO_LOG_ERROR, "Failure obtaining %s proc address\n", name);
return proc_addr;
}
-static void on_mpv_events(void *mpv)
+void CORE_PREFIX(retro_init)(void)
{
- event_waiting++;
-}
+ if(mpv_client_api_version() != MPV_CLIENT_API_VERSION)
+ {
+ log_cb(RETRO_LOG_WARN, "libmpv version mismatch. Please update or "
+ "recompile mpv-libretro after updating libmpv.");
+ }
-void retro_init(void)
-{
return;
}
-void retro_deinit(void)
-{
- return;
-}
+void CORE_PREFIX(retro_deinit)(void)
+{}
-unsigned retro_api_version(void)
+unsigned CORE_PREFIX(retro_api_version)(void)
{
return RETRO_API_VERSION;
}
-void retro_set_controller_port_device(unsigned port, unsigned device)
+void CORE_PREFIX(retro_set_controller_port_device)(unsigned port, unsigned device)
{
log_cb(RETRO_LOG_INFO, "Plugging device %u into port %u.\n", device, port);
return;
}
-void retro_get_system_info(struct retro_system_info *info)
+void CORE_PREFIX(retro_get_system_info)(struct retro_system_info *info)
{
memset(info, 0, sizeof(*info));
info->library_name = "mpv";
@@ -206,18 +192,19 @@ void retro_get_system_info(struct retro_system_info *info)
"vtt|wav|wsd|xl|xm|xmgz|xmr|xmv|xmz|xvag|y4m|yop|yuv|yuv10";
}
-void retro_get_system_av_info(struct retro_system_av_info *info)
+void CORE_PREFIX(retro_get_system_av_info)(struct retro_system_av_info *info)
{
float sampling_rate = 48000.0f;
+#if 0
struct retro_variable var = { .key = "test_aspect" };
- environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
+ CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
var.key = "test_samplerate";
- if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ if(CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
sampling_rate = strtof(var.value, NULL);
-
+#endif
info->timing = (struct retro_system_timing) {
.fps = 60.0,
.sample_rate = sampling_rate,
@@ -235,15 +222,17 @@ void retro_get_system_av_info(struct retro_system_av_info *info)
};
}
-void retro_set_environment(retro_environment_t cb)
+void CORE_PREFIX(retro_set_environment)(retro_environment_t cb)
{
- environ_cb = cb;
+ CORE_PREFIX(environ_cb) = cb;
static const struct retro_variable vars[] = {
- { "test_samplerate", "Sample Rate; 48000|30000|20000" },
+#if 0
+ { "test_samplerate", "Sample Rate; 48000" },
{ "test_opt0", "Test option #0; false|true" },
{ "test_opt1", "Test option #1; 0" },
{ "test_opt2", "Test option #2; 0|1|foo|3" },
+#endif
{ NULL, NULL },
};
@@ -258,6 +247,7 @@ void retro_set_environment(retro_environment_t cb)
static void context_reset(void)
{
const char *cmd[] = {"loadfile", filepath, NULL};
+ int ret;
#ifdef HAVE_LOCALE
setlocale(LC_NUMERIC, "C");
@@ -265,66 +255,68 @@ static void context_reset(void)
mpv = mpv_create();
- if(mpv == NULL)
+ if(!mpv)
{
log_cb(RETRO_LOG_ERROR, "failed creating context\n");
exit(EXIT_FAILURE);
}
- if(mpv_initialize(mpv) < 0)
+ if((ret = mpv_initialize(mpv)) < 0)
{
- log_cb(RETRO_LOG_ERROR, "mpv init failed\n");
+ log_cb(RETRO_LOG_ERROR, "mpv init failed: %s\n", mpv_error_string(ret));
exit(EXIT_FAILURE);
}
- /* When normal mpv events are available. */
- mpv_set_wakeup_callback(mpv, on_mpv_events, NULL);
-
- if(mpv_request_log_messages(mpv, "v") < 0)
- log_cb(RETRO_LOG_ERROR, "mpv logging failed\n");
-
- /* The OpenGL API is somewhat separate from the normal mpv API. This only
- * returns NULL if no OpenGL support is compiled.
- */
- mpv_gl = mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
-
- if(mpv_gl == NULL)
+ if((ret = mpv_request_log_messages(mpv, "v")) < 0)
{
- log_cb(RETRO_LOG_ERROR, "failed to create mpv GL API handle\n");
+ log_cb(RETRO_LOG_ERROR, "mpv logging failed: %s\n",
+ mpv_error_string(ret));
+ }
+
+ mpv_render_param params[] = {
+ {MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL},
+ {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &(mpv_opengl_init_params){
+ .get_proc_address = get_proc_address_mpv,
+ }},
+ {0}
+ };
+
+ if((ret = mpv_render_context_create(&mpv_gl, mpv, params)) < 0)
+ {
+ log_cb(RETRO_LOG_ERROR, "failed to initialize mpv GL context: %s\n",
+ mpv_error_string(ret));
goto err;
}
- if(mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address_mpv, NULL) < 0)
- {
- log_cb(RETRO_LOG_ERROR, "failed to initialize mpv GL context\n");
- goto err;
- }
+ mpv_render_context_set_update_callback(mpv_gl, on_mpv_redraw, NULL);
- /* Actually using the opengl_cb state has to be explicitly requested.
- * Otherwise, mpv will create a separate platform window.
- */
- if(mpv_set_option_string(mpv, "vo", "opengl-cb") < 0)
- {
- log_cb(RETRO_LOG_ERROR, "failed to set video output to OpenGL\n");
- goto err;
- }
-
- mpv_opengl_cb_set_update_callback(mpv_gl, queue_new_frame, NULL);
-
- mpv_set_option_string(mpv, "ao", "audio-cb");
+ mpv_set_option_string(mpv, "ao", "libmpv");
/* Attempt to enable hardware acceleration. MPV will fallback to software
* decoding on failure.
*/
- if(mpv_set_option_string(mpv, "hwdec", "auto") < 0)
- log_cb(RETRO_LOG_ERROR, "failed to set hwdec option\n");
-
- if(mpv_command(mpv, cmd) != 0)
+ if((ret = mpv_set_option_string(mpv, "hwdec", "auto")) < 0)
{
- log_cb(RETRO_LOG_ERROR, "failed to issue mpv_command to load file\n");
+ log_cb(RETRO_LOG_ERROR, "failed to set hwdec option: %s\n",
+ mpv_error_string(ret));
+ }
+
+ if((ret = mpv_command(mpv, cmd)) != 0)
+ {
+ log_cb(RETRO_LOG_ERROR, "mpv_command failed to load input file: %s\n",
+ mpv_error_string(ret));
goto err;
}
+ /* TODO #2: Check for the highest samplerate in audio stream, and use that.
+ * Fall back to 48kHz otherwise.
+ * We currently force the audio to be sampled at 48KHz.
+ */
+ mpv_set_option_string(mpv, "af", "format=s16:48000:stereo");
+ //mpv_set_option_string(mpv, "opengl-swapinterval", "0");
+
+ /* Process any events whilst we wait for playback to begin. */
+ process_mpv_events(MPV_EVENT_NONE);
/* Keep trying until mpv accepts the property. This is done to seek to the
* point in the file after the previous context was destroyed. If no
@@ -332,20 +324,14 @@ static void context_reset(void)
*
* This also seems to fix some black screen issues.
*/
- while(mpv_set_property(mpv,
- "playback-time", MPV_FORMAT_INT64, &playback_time) < 0)
+ if(playback_time != 0)
{
- /* Garbage fix to overflowing log */
- usleep(10);
+ process_mpv_events(MPV_EVENT_PLAYBACK_RESTART);
+ while(mpv_set_property(mpv,
+ "playback-time", MPV_FORMAT_INT64, &playback_time) < 0)
+ {}
}
- /* TODO #2: Check for the highest samplerate in audio stream, and use that.
- * Fall back to 48kHz otherwise.
- * We currently force the audio to be sampled at 48KHz.
- */
- mpv_set_option_string(mpv, "audio-samplerate", "48000");
- mpv_set_option_string(mpv, "opengl-swapinterval", "0");
-
/* The following works best when vsync is switched off in Retroarch. */
//mpv_set_option_string(mpv, "video-sync", "display-resample");
//mpv_set_option_string(mpv, "display-fps", "60");
@@ -356,14 +342,14 @@ static void context_reset(void)
err:
/* Print mpv logs to see why mpv failed. */
- print_mpv_logs();
+ process_mpv_events(MPV_EVENT_NONE);
exit(EXIT_FAILURE);
}
static void context_destroy(void)
{
mpv_get_property(mpv, "playback-time", MPV_FORMAT_INT64, &playback_time);
- mpv_opengl_cb_uninit_gl(mpv_gl);
+ mpv_render_context_free(mpv_gl);
mpv_terminate_destroy(mpv);
log_cb(RETRO_LOG_INFO, "Context destroyed.\n");
}
@@ -378,60 +364,77 @@ static bool retro_init_hw_context(void)
hw_render.context_reset = context_reset;
hw_render.context_destroy = context_destroy;
- if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render))
+ if (!CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render))
return false;
return true;
}
-void retro_set_audio_sample(retro_audio_sample_t cb)
+void CORE_PREFIX(retro_set_audio_sample)(retro_audio_sample_t cb)
{
- audio_cb = cb;
+ CORE_PREFIX(audio_cb) = cb;
}
-void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
+void CORE_PREFIX(retro_set_audio_sample_batch)(retro_audio_sample_batch_t cb)
{
- audio_batch_cb = cb;
+ CORE_PREFIX(audio_batch_cb) = cb;
}
-void retro_set_input_poll(retro_input_poll_t cb)
+void CORE_PREFIX(retro_set_input_poll)(retro_input_poll_t cb)
{
- input_poll_cb = cb;
+ CORE_PREFIX(input_poll_cb) = cb;
}
-void retro_set_input_state(retro_input_state_t cb)
+void CORE_PREFIX(retro_set_input_state)(retro_input_state_t cb)
{
- input_state_cb = cb;
+ CORE_PREFIX(input_state_cb) = cb;
}
-void retro_set_video_refresh(retro_video_refresh_t cb)
+void CORE_PREFIX(retro_set_video_refresh)(retro_video_refresh_t cb)
{
- video_cb = cb;
+ CORE_PREFIX(video_cb) = cb;
}
-void retro_reset(void)
+void CORE_PREFIX(retro_reset)(void)
{
- return;
}
static void audio_callback(double fps)
{
/* Obtain len samples to reduce lag. */
int len = 48000 / (int)floor(fps);
- static int16_t frames[512];
+ const unsigned int buff_len = 1024;
+ uint8_t buff[buff_len];
- while(len > 0)
+ if(len < 4)
+ len = 4;
+
+ do
{
- int mpv_len = mpv_audio_callback(&frames, len > 512 ? 512*2 : len*2);
- //printf("mpv cb: %d\n", mpv_len);
- if(mpv_len < 1)
- return;
+ len = len - (len % 4);
- len -= mpv_len;
+ int ret = mpv_audio_callback(mpv, &buff,
+ len > buff_len ? buff_len : len);
- //printf("acb: %lu\n", audio_batch_cb(frames, mpv_len));
- audio_batch_cb(frames, mpv_len);
+ if(ret < 0)
+ {
+#if 0
+ log_cb(RETRO_LOG_ERROR, "mpv encountered an error in audio "
+ "callback: %d.\n", ret);
+#endif
+ return;
+ }
+
+ /* mpv may refuse to buffer audio if the first video frame has not
+ * displayed yet. */
+ if(ret == 0)
+ return;
+
+ len -= ret;
+
+ CORE_PREFIX(audio_batch_cb)((const int16_t*)buff, ret);
}
+ while(len > 4);
}
static void retropad_update_input(void)
@@ -445,7 +448,7 @@ static void retropad_update_input(void)
struct Input current;
static struct Input last;
- input_poll_cb();
+ CORE_PREFIX(input_poll_cb)();
/* Commands that are called on rising edge only */
@@ -456,11 +459,11 @@ static void retropad_update_input(void)
* Unsure if saving the memory is worth the extra checks, costing CPU time,
* but both are incredibly miniscule anyway.
*/
- current.l = input_state_cb(0, RETRO_DEVICE_JOYPAD,
+ current.l = CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD,
0, RETRO_DEVICE_ID_JOYPAD_L) != 0 ? 1 : 0;
- current.r = input_state_cb(0, RETRO_DEVICE_JOYPAD,
+ current.r = CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD,
0, RETRO_DEVICE_ID_JOYPAD_R) != 0 ? 1 : 0;
- current.a = input_state_cb(0, RETRO_DEVICE_JOYPAD,
+ current.a = CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD,
0, RETRO_DEVICE_ID_JOYPAD_A) != 0 ? 1 : 0;
if(current.l == 1 && last.l == 0)
@@ -473,24 +476,24 @@ static void retropad_update_input(void)
mpv_command_string(mpv, "cycle pause");
/* TODO #3: Press and hold commands with small delay */
- if(input_state_cb(0, RETRO_DEVICE_JOYPAD, 0,
+ if (CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD, 0,
RETRO_DEVICE_ID_JOYPAD_LEFT))
mpv_command_string(mpv, "seek -5");
- if(input_state_cb(0, RETRO_DEVICE_JOYPAD, 0,
+ if (CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD, 0,
RETRO_DEVICE_ID_JOYPAD_RIGHT))
mpv_command_string(mpv, "seek 5");
- if(input_state_cb(0, RETRO_DEVICE_JOYPAD, 0,
+ if (CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD, 0,
RETRO_DEVICE_ID_JOYPAD_UP))
mpv_command_string(mpv, "seek 60");
- if(input_state_cb(0, RETRO_DEVICE_JOYPAD, 0,
+ if (CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD, 0,
RETRO_DEVICE_ID_JOYPAD_DOWN))
mpv_command_string(mpv, "seek -60");
/* Press and hold commands */
- if(input_state_cb(0, RETRO_DEVICE_JOYPAD, 0,
+ if (CORE_PREFIX(input_state_cb)(0, RETRO_DEVICE_JOYPAD, 0,
RETRO_DEVICE_ID_JOYPAD_X))
mpv_command_string(mpv, "show-progress");
@@ -502,7 +505,7 @@ static void retropad_update_input(void)
last.a = current.a;
}
-void retro_run(void)
+void CORE_PREFIX(retro_run)(void)
{
/* We only need to update the base video size once, and we do it here since
* the input file is not processed during the first
@@ -546,51 +549,60 @@ void retro_run(void)
};
if(width > 0 && height > 0)
- environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &av_info);
+ CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &av_info);
updated_video_dimensions = true;
}
- print_mpv_logs();
-
retropad_update_input();
/* TODO #2: Implement an audio callback feature in to libmpv */
audio_callback(container_fps);
+ process_mpv_events(MPV_EVENT_NONE);
+
#if 1
if(frame_queue > 0)
{
- mpv_opengl_cb_draw(mpv_gl, hw_render.get_current_framebuffer(), width, height);
- video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
+ mpv_render_param params[] = {
+ {MPV_RENDER_PARAM_OPENGL_FBO, &(mpv_opengl_fbo){
+ .fbo = hw_render.get_current_framebuffer(),
+ .w = width,
+ .h = height,
+ }},
+ {0}
+ };
+ mpv_render_context_render(mpv_gl, params);
+ CORE_PREFIX(video_cb)(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
frame_queue--;
}
else
- video_cb(NULL, width, height, 0);
+ CORE_PREFIX(video_cb)(NULL, width, height, 0);
#else
mpv_opengl_cb_draw(mpv_gl, hw_render.get_current_framebuffer(), width, height);
- video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
+ CORE_PREFIX(video_cb)(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
#endif
+
return;
}
/* No save-state support */
-size_t retro_serialize_size(void)
+size_t CORE_PREFIX(retro_serialize_size)(void)
{
return 0;
}
-bool retro_serialize(void *data_, size_t size)
+bool CORE_PREFIX(retro_serialize)(void *data_, size_t size)
{
return true;
}
-bool retro_unserialize(const void *data_, size_t size)
+bool CORE_PREFIX(retro_unserialize)(const void *data_, size_t size)
{
return true;
}
-bool retro_load_game(const struct retro_game_info *info)
+bool CORE_PREFIX(retro_load_game)(const struct retro_game_info *info)
{
/* Supported on most systems. */
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
@@ -607,21 +619,30 @@ bool retro_load_game(const struct retro_game_info *info)
{ 0 },
};
+ if(info->path == NULL)
+ return false;
+
/* Copy the file path to a global variable as we need it in context_reset()
* where mpv is initialised.
*/
- filepath = strdup(info->path);
+ if((filepath = malloc(strlen(info->path)+1)) == NULL)
+ {
+ log_cb(RETRO_LOG_ERROR, "Unable to allocate memory for filepath\n");
+ return false;
+ }
- environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
+ strcpy(filepath,info->path);
+
+ CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
/* Not bothered if this fails. Assuming the default is selected anyway. */
- if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt) == false)
+ if(CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt) == false)
{
log_cb(RETRO_LOG_ERROR, "XRGB8888 is not supported.\n");
/* Try RGB565 */
fmt = RETRO_PIXEL_FORMAT_RGB565;
- environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt);
+ CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt);
}
if(retro_init_hw_context() == false)
@@ -633,41 +654,39 @@ bool retro_load_game(const struct retro_game_info *info)
return true;
}
-bool retro_load_game_special(unsigned type, const struct retro_game_info *info,
+bool CORE_PREFIX(retro_load_game_special)(unsigned type, const struct retro_game_info *info,
size_t num)
{
return false;
}
-void retro_unload_game(void)
+void CORE_PREFIX(retro_unload_game)(void)
{
free(filepath);
filepath = NULL;
-
- return;
}
-unsigned retro_get_region(void)
+unsigned CORE_PREFIX(retro_get_region)(void)
{
return RETRO_REGION_NTSC;
}
-void *retro_get_memory_data(unsigned id)
+void *CORE_PREFIX(retro_get_memory_data)(unsigned id)
{
return NULL;
}
-size_t retro_get_memory_size(unsigned id)
+size_t CORE_PREFIX(retro_get_memory_size)(unsigned id)
{
return 0;
}
-void retro_cheat_reset(void)
-{
- return;
-}
+void CORE_PREFIX(retro_cheat_reset)(void)
+{}
-void retro_cheat_set(unsigned index, bool enabled, const char *code)
+void CORE_PREFIX(retro_cheat_set)(unsigned index, bool enabled, const char *code)
{
- return;
+ (void)index;
+ (void)enabled;
+ (void)code;
}
diff --git a/cores/libretro-mpv/version.h b/cores/libretro-mpv/version.h
index 203d2c70db..494a513a0b 100644
--- a/cores/libretro-mpv/version.h
+++ b/cores/libretro-mpv/version.h
@@ -1,3 +1,3 @@
#ifndef LIBRETRO_MPV_VERSION
-#define LIBRETRO_MPV_VERSION "0.2.alpha"
+#define LIBRETRO_MPV_VERSION "0.3.alpha"
#endif
diff --git a/ctr/ctr_system.c b/ctr/ctr_system.c
index 29594251e7..9126ba009e 100644
--- a/ctr/ctr_system.c
+++ b/ctr/ctr_system.c
@@ -1,5 +1,6 @@
#include <3ds.h>
#include
+#include <3ds/services/apt.h>
#include
#include
#include
diff --git a/ctr/exec-3dsx/exec_3dsx.c b/ctr/exec-3dsx/exec_3dsx.c
new file mode 100644
index 0000000000..7de5b374e6
--- /dev/null
+++ b/ctr/exec-3dsx/exec_3dsx.c
@@ -0,0 +1,85 @@
+#include
+#include
+#include
+#include
+
+#include "mini-hb-menu/common.h"
+
+
+extern const loaderFuncs_s loader_Ninjhax1;
+extern const loaderFuncs_s loader_Ninjhax2;
+extern const loaderFuncs_s loader_Rosalina;
+
+static void (*launch_3dsx)(const char* path, argData_s* args, executableMetadata_s* em);
+
+
+static int exec_3dsx_actual(const char* path, const char** args, bool appendPath){
+ struct stat sBuff;
+ argData_s newProgramArgs;
+ unsigned int argChars = 0;
+ unsigned int argNum = 0;
+ bool fileExists;
+ bool inited;
+
+ if(path == NULL || path[0] == '\0'){
+ errno = EINVAL;
+ return -1;
+ }
+
+ fileExists = stat(path, &sBuff) == 0;
+ if(!fileExists){
+ errno = ENOENT;
+ return -1;
+ }
+ else if(S_ISDIR(sBuff.st_mode)){
+ errno = EINVAL;
+ return -1;
+ }
+
+ //args the string functions write to the passed string, this will cause a write to read only memory sot the string must be cloned
+ memset(newProgramArgs.buf, '\0', sizeof(newProgramArgs.buf));
+ newProgramArgs.dst = (char*)&newProgramArgs.buf[1];
+ if(appendPath){
+ strcpy(newProgramArgs.dst, path);
+ newProgramArgs.dst += strlen(path) + 1;
+ newProgramArgs.buf[0]++;
+
+ }
+ while(args[argNum] != NULL){
+ strcpy(newProgramArgs.dst, args[argNum]);
+ newProgramArgs.dst += strlen(args[argNum]) + 1;
+ newProgramArgs.buf[0]++;
+ argNum++;
+ }
+
+ inited = loader_Rosalina.init();
+ launch_3dsx = loader_Rosalina.launchFile;
+
+ if(!inited){
+ inited = loader_Ninjhax2.init();
+ launch_3dsx = loader_Ninjhax2.launchFile;
+ }
+
+ if(!inited){
+ inited = loader_Ninjhax1.init();
+ launch_3dsx = loader_Ninjhax1.launchFile;
+ }
+
+ if(inited){
+ osSetSpeedupEnable(false);
+ launch_3dsx(path, &newProgramArgs, NULL);
+ exit(0);
+ }
+
+ //should never be reached
+ errno = ENOTSUP;
+ return -1;
+}
+
+int exec_3dsx(const char* path, const char** args){
+ return exec_3dsx_actual(path, args, true/*appendPath*/);
+}
+
+int exec_3dsx_no_path_in_args(const char* path, const char** args){
+ return exec_3dsx_actual(path, args, false/*appendPath*/);
+}
\ No newline at end of file
diff --git a/ctr/exec-3dsx/exec_3dsx.h b/ctr/exec-3dsx/exec_3dsx.h
new file mode 100644
index 0000000000..d260331cb0
--- /dev/null
+++ b/ctr/exec-3dsx/exec_3dsx.h
@@ -0,0 +1,9 @@
+#ifndef EXEC_3DSX_H
+#define EXEC_3DSX_H
+
+//since 3dsx programs are not guaranteed access to the OS, the 3dsx bootloader run by the exploit must run the next program
+//your program must have no extra threads running when this is called, these limits do not apply to exec_cia
+int exec_3dsx_no_path_in_args(const char* path, const char** args);
+int exec_3dsx(const char* path, const char** args);
+
+#endif
\ No newline at end of file
diff --git a/ctr/exec-3dsx/exec_cia.c b/ctr/exec-3dsx/exec_cia.c
new file mode 100644
index 0000000000..7c4c19551d
--- /dev/null
+++ b/ctr/exec-3dsx/exec_cia.c
@@ -0,0 +1,203 @@
+#include
+#include
+#include
+#include
+#include <3ds.h>
+
+
+#define FILE_CHUNK_SIZE 4096
+
+
+typedef struct{
+ u32 argc;
+ char args[0x300 - 0x4];
+}ciaParam;
+
+
+char argvHmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67};
+
+
+static void errorAndQuit(const char* errorStr){
+ errorConf error;
+
+ errorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN);
+ errorText(&error, errorStr);
+ errorDisp(&error);
+ exit(0);
+}
+
+static int isCiaInstalled(u64 titleId, u16 version){
+ u32 titlesToRetrieve;
+ u32 titlesRetrieved;
+ u64* titleIds;
+ bool titleExists = false;
+ AM_TitleEntry titleInfo;
+ Result failed;
+
+ failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve);
+ if(R_FAILED(failed))
+ return -1;
+
+ titleIds = malloc(titlesToRetrieve * sizeof(uint64_t));
+ if(titleIds == NULL)
+ return -1;
+
+ failed = AM_GetTitleList(&titlesRetrieved, MEDIATYPE_SD, titlesToRetrieve, titleIds);
+ if(R_FAILED(failed))
+ return -1;
+
+ for(u32 titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++){
+ if(titleIds[titlesToCheck] == titleId){
+ titleExists = true;
+ break;
+ }
+ }
+
+ free(titleIds);
+
+ if(titleExists){
+ failed = AM_GetTitleInfo(MEDIATYPE_SD, 1 /*titleCount*/, &titleId, &titleInfo);
+ if(R_FAILED(failed))
+ return -1;
+
+ if(titleInfo.version == version)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int installCia(Handle ciaFile){
+ Result failed;
+ Handle outputHandle;
+ u64 fileSize;
+ u64 fileOffset = 0;
+ u32 bytesRead;
+ u32 bytesWritten;
+ u8 transferBuffer[FILE_CHUNK_SIZE];
+
+ failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle);
+ if(R_FAILED(failed))
+ return -1;
+
+ failed = FSFILE_GetSize(ciaFile, &fileSize);
+ if(R_FAILED(failed))
+ return -1;
+
+ while(fileOffset < fileSize){
+ u64 bytesRemaining = fileSize - fileOffset;
+ failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE);
+ if(R_FAILED(failed)){
+ AM_CancelCIAInstall(outputHandle);
+ return -1;
+ }
+
+ failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0);
+ if(R_FAILED(failed)){
+ AM_CancelCIAInstall(outputHandle);
+ if(R_DESCRIPTION(failed) == RD_ALREADY_EXISTS)
+ return 1;
+ return -1;
+ }
+
+ if(bytesWritten != bytesRead){
+ AM_CancelCIAInstall(outputHandle);
+ return -1;
+ }
+
+ fileOffset += bytesWritten;
+ }
+
+ failed = AM_FinishCiaInstall(outputHandle);
+ if(R_FAILED(failed))
+ return -1;
+
+ return 1;
+}
+
+int exec_cia(const char* path, const char** args){
+ struct stat sBuff;
+ bool fileExists;
+ bool inited;
+
+ if(path == NULL || path[0] == '\0'){
+ errno = EINVAL;
+ return -1;
+ }
+
+ fileExists = stat(path, &sBuff) == 0;
+ if(!fileExists){
+ errno = ENOENT;
+ return -1;
+ }
+ else if(S_ISDIR(sBuff.st_mode)){
+ errno = EINVAL;;
+ return -1;
+ }
+
+ inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit());
+ if(inited){
+ Result res;
+ AM_TitleEntry ciaInfo;
+ FS_Archive ciaArchive;
+ Handle ciaFile;
+ int ciaInstalled;
+ ciaParam param;
+ int argsLength;
+
+ //open cia file
+ res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
+ if(R_FAILED(res))
+ errorAndQuit("Cant open SD FS archive.");
+
+ res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0);
+ if(R_FAILED(res))
+ errorAndQuit("Cant open CIA file.");
+
+ res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile);
+ if(R_FAILED(res))
+ errorAndQuit("Cant get CIA file info.");
+
+ ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version);
+ if(ciaInstalled == -1){
+ //error
+ errorAndQuit("Could not read title id list.");
+ }
+ else if(ciaInstalled == 0){
+ //not installed
+ int error = installCia(ciaFile);
+ if(error == -1)
+ errorAndQuit("Cant install CIA.");
+ }
+
+ FSFILE_Close(ciaFile);
+ FSUSER_CloseArchive(ciaArchive);
+
+ param.argc = 0;
+ argsLength = 0;
+ char* argLocation = param.args;
+ while(args[param.argc] != NULL){
+ strcpy(argLocation, args[param.argc]);
+ argLocation += strlen(args[param.argc]) + 1;
+ argsLength += strlen(args[param.argc]) + 1;
+ param.argc++;
+ }
+
+ res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1);
+ if(R_FAILED(res))
+ errorAndQuit("CIA cant run, cant prepare.");
+
+ res = APT_DoApplicationJump(¶m, sizeof(param.argc) + argsLength, argvHmac);
+ if(R_FAILED(res))
+ errorAndQuit("CIA cant run, cant jump.");
+
+ //wait for application jump, for some reason its not instant
+ while(1);
+ }
+
+ //should never be reached
+ amExit();
+ fsExit();
+ errno = ENOTSUP;
+ return -1;
+}
diff --git a/ctr/exec-3dsx/exec_cia.h b/ctr/exec-3dsx/exec_cia.h
new file mode 100644
index 0000000000..4c751de922
--- /dev/null
+++ b/ctr/exec-3dsx/exec_cia.h
@@ -0,0 +1,6 @@
+#ifndef EXEC_CIA_H
+#define EXEC_CIA_H
+
+int exec_cia(const char* path, const char** args);
+
+#endif
\ No newline at end of file
diff --git a/ctr/exec-3dsx/mini-hb-menu/common.h b/ctr/exec-3dsx/mini-hb-menu/common.h
new file mode 100644
index 0000000000..ef354d46d2
--- /dev/null
+++ b/ctr/exec-3dsx/mini-hb-menu/common.h
@@ -0,0 +1,95 @@
+#pragma once
+
+// C stdlib includes
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// 3DS includes
+#include <3ds.h>
+
+
+#define ENTRY_ARGBUFSIZE 0x400
+#define NUM_SERVICESTHATMATTER 5
+
+typedef enum
+{
+ StrId_Loading = 0,
+ StrId_Directory,
+ StrId_DefaultLongTitle,
+ StrId_DefaultPublisher,
+ StrId_IOError,
+ StrId_CouldNotOpenFile,
+
+ StrId_NoAppsFound_Title,
+ StrId_NoAppsFound_Msg,
+
+ StrId_Reboot,
+ StrId_ReturnToHome,
+
+ StrId_TitleSelector,
+ StrId_ErrorReadingTitleMetadata,
+ StrId_NoTitlesFound,
+ StrId_SelectTitle,
+
+ StrId_NoTargetTitleSupport,
+ StrId_MissingTargetTitle,
+
+ StrId_NetLoader,
+ StrId_NetLoaderUnavailable,
+ StrId_NetLoaderOffline,
+ StrId_NetLoaderError,
+ StrId_NetLoaderActive,
+ StrId_NetLoaderTransferring,
+
+ StrId_Max,
+} StrId;
+
+
+typedef struct
+{
+ char* dst;
+ u32 buf[ENTRY_ARGBUFSIZE/sizeof(u32)];
+} argData_s;
+
+typedef struct
+{
+ bool scanned;
+ u32 sectionSizes[3];
+ bool servicesThatMatter[NUM_SERVICESTHATMATTER];
+} executableMetadata_s;
+
+typedef struct
+{
+ u32 num;
+ u32 text_end;
+ u32 data_address;
+ u32 data_size;
+ u32 processLinearOffset;
+ u32 processHookAddress;
+ u32 processAppCodeAddress;
+ u32 processHookTidLow, processHookTidHigh;
+ u32 mediatype;
+ bool capabilities[0x10]; // {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...}
+} memmap_header_t;
+
+typedef struct
+{
+ u32 src, dst, size;
+} memmap_entry_t;
+
+typedef struct
+{
+ memmap_header_t header;
+ memmap_entry_t map[];
+} memmap_t;
+
+#define memmapSize(m) (sizeof(memmap_header_t) + sizeof(memmap_entry_t)*(m)->header.num)
+
+
+#include "launch.h"
diff --git a/ctr/exec-3dsx/mini-hb-menu/launch.c b/ctr/exec-3dsx/mini-hb-menu/launch.c
new file mode 100644
index 0000000000..e5adf30581
--- /dev/null
+++ b/ctr/exec-3dsx/mini-hb-menu/launch.c
@@ -0,0 +1,22 @@
+#include "common.h"
+
+Handle launchOpenFile(const char* path)
+{
+ if (strncmp(path, "sdmc:/", 6) == 0)
+ path += 5;
+ else if (*path != '/')
+ return 0;
+
+ // Convert the executable path to UTF-16
+ static uint16_t __utf16path[PATH_MAX+1];
+ ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX);
+ if (units < 0 || units >= PATH_MAX) return 0;
+ __utf16path[units] = 0;
+
+ // Open the file directly
+ FS_Path apath = { PATH_EMPTY, 1, (u8*)"" };
+ FS_Path fpath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
+ Handle file;
+ Result res = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, apath, fpath, FS_OPEN_READ, 0);
+ return R_SUCCEEDED(res) ? file : 0;
+}
diff --git a/ctr/exec-3dsx/mini-hb-menu/launch.h b/ctr/exec-3dsx/mini-hb-menu/launch.h
new file mode 100644
index 0000000000..95ba6c95a9
--- /dev/null
+++ b/ctr/exec-3dsx/mini-hb-menu/launch.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "common.h"
+
+extern void (*__system_retAddr)(void);
+
+enum
+{
+ LOADER_SHOW_REBOOT = 0x01,
+ LOADER_NEED_SCAN = 0x02
+};
+
+typedef struct
+{
+ // Mandatory fields
+ const char* name;
+ u32 flags;
+ bool (* init)(void);
+ void (* deinit)(void);
+ void (* launchFile)(const char* path, argData_s* args, executableMetadata_s* em);
+
+ // Optional fields
+ void (* useTitle)(u64 tid, u8 mediatype);
+} loaderFuncs_s;
+
+Handle launchOpenFile(const char* path);
\ No newline at end of file
diff --git a/ctr/exec-3dsx/mini-hb-menu/loaders/hax2.c b/ctr/exec-3dsx/mini-hb-menu/loaders/hax2.c
new file mode 100644
index 0000000000..08522f3b7f
--- /dev/null
+++ b/ctr/exec-3dsx/mini-hb-menu/loaders/hax2.c
@@ -0,0 +1,73 @@
+#include "../common.h"
+
+typedef struct
+{
+ s32 processId;
+ bool capabilities[0x10];
+} processEntry_s;
+
+typedef void (*callBootloader_2x_fn)(Handle file, u32* argbuf, u32 arglength);
+typedef void (*callBootloaderNewProcess_2x_fn)(s32 processId, u32* argbuf, u32 arglength);
+typedef void (*callBootloaderRunTitle_2x_fn)(u8 mediatype, u32* argbuf, u32 argbuflength, u32 tid_low, u32 tid_high);
+typedef void (*callBootloaderRunTitleCustom_2x_fn)(u8 mediatype, u32* argbuf, u32 argbuflength, u32 tid_low, u32 tid_high, memmap_t* mmap);
+typedef void (*getBestProcess_2x_fn)(u32 sectionSizes[3], bool* requirements, int num_requirements, processEntry_s* out, int out_size, int* out_len);
+
+#define callBootloader_2x ((callBootloader_2x_fn)0x00100000)
+#define callBootloaderNewProcess_2x ((callBootloaderNewProcess_2x_fn)0x00100008)
+#define callBootloaderRunTitle_2x ((callBootloaderRunTitle_2x_fn)0x00100010)
+#define callBootloaderRunTitleCustom_2x ((callBootloaderRunTitleCustom_2x_fn)0x00100014)
+#define getBestProcess_2x ((getBestProcess_2x_fn)0x0010000C)
+
+static s32 targetProcess = -1;
+static u64 targetTid;
+static u8 targetMediatype;
+static Handle fileHandle;
+static u32 argBuf[ENTRY_ARGBUFSIZE/sizeof(u32)];
+static u32 argBufLen;
+static u32 memMapBuf[0x40];
+static bool useMemMap;
+
+static bool init(void)
+{
+ return R_SUCCEEDED(amInit());
+}
+
+static void deinit(void)
+{
+ amExit();
+}
+
+static void bootloaderJump(void)
+{
+ if (targetProcess == -1)
+ callBootloader_2x(fileHandle, argBuf, argBufLen);
+ else if (targetProcess == -2)
+ {
+ if (useMemMap)
+ callBootloaderRunTitleCustom_2x(targetMediatype, argBuf, argBufLen, (u32)targetTid, (u32)(targetTid>>32), (memmap_t*)memMapBuf);
+ else
+ callBootloaderRunTitle_2x(targetMediatype, argBuf, argBufLen, (u32)targetTid, (u32)(targetTid>>32));
+ }
+ else
+ callBootloaderNewProcess_2x(targetProcess, argBuf, argBufLen);
+}
+
+static void launchFile(const char* path, argData_s* args, executableMetadata_s* em)
+{
+ fileHandle = launchOpenFile(path);
+ if (fileHandle==0)
+ return;
+ argBufLen = args->dst - (char*)args->buf;
+ memcpy(argBuf, args->buf, argBufLen);
+ __system_retAddr = bootloaderJump;
+}
+
+const loaderFuncs_s loader_Ninjhax2 =
+{
+ .name = "hax 2.x",
+ .flags = LOADER_SHOW_REBOOT | LOADER_NEED_SCAN,
+ .init = init,
+ .deinit = deinit,
+ .launchFile = launchFile,
+ //.useTitle = useTitle,
+};
diff --git a/ctr/exec-3dsx/mini-hb-menu/loaders/ninjhax1.c b/ctr/exec-3dsx/mini-hb-menu/loaders/ninjhax1.c
new file mode 100644
index 0000000000..8fd05663d3
--- /dev/null
+++ b/ctr/exec-3dsx/mini-hb-menu/loaders/ninjhax1.c
@@ -0,0 +1,43 @@
+#include "../common.h"
+
+static void (*callBootloader_1x)(Handle hb, Handle file);
+static void (*setArgs_1x)(u32* src, u32 length);
+static Handle fileHandle;
+
+static bool init(void)
+{
+ Result res = hbInit();
+ if (R_FAILED(res))
+ return false;
+
+ HB_GetBootloaderAddresses((void**)&callBootloader_1x, (void**)&setArgs_1x);
+ return true;
+}
+
+static void deinit(void)
+{
+ hbExit();
+}
+
+static void bootloaderJump(void)
+{
+ callBootloader_1x(0x00000000, fileHandle);
+}
+
+static void launchFile(const char* path, argData_s* args, executableMetadata_s* em)
+{
+ fileHandle = launchOpenFile(path);
+ if (fileHandle==0)
+ return;
+ setArgs_1x(args->buf, sizeof(args->buf));
+ __system_retAddr = bootloaderJump;
+}
+
+const loaderFuncs_s loader_Ninjhax1 =
+{
+ .name = "ninjhax 1.x",
+ .flags = LOADER_SHOW_REBOOT,
+ .init = init,
+ .deinit = deinit,
+ .launchFile = launchFile,
+};
diff --git a/ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.c b/ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.c
new file mode 100644
index 0000000000..fd9046e8fa
--- /dev/null
+++ b/ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.c
@@ -0,0 +1,56 @@
+#include "../common.h"
+
+static Handle hbldrHandle;
+
+static bool init(void)
+{
+ return R_SUCCEEDED(svcConnectToPort(&hbldrHandle, "hb:ldr"));
+}
+
+static Result HBLDR_SetTarget(const char* path)
+{
+ u32 pathLen = strlen(path) + 1;
+ u32* cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(2, 0, 2); //0x20002
+ cmdbuf[1] = IPC_Desc_StaticBuffer(pathLen, 0);
+ cmdbuf[2] = (u32)path;
+
+ Result rc = svcSendSyncRequest(hbldrHandle);
+ if (R_SUCCEEDED(rc)) rc = cmdbuf[1];
+ return rc;
+}
+
+static Result HBLDR_SetArgv(const void* buffer, u32 size)
+{
+ u32* cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(3, 0, 2); //0x30002
+ cmdbuf[1] = IPC_Desc_StaticBuffer(size, 1);
+ cmdbuf[2] = (u32)buffer;
+
+ Result rc = svcSendSyncRequest(hbldrHandle);
+ if (R_SUCCEEDED(rc)) rc = cmdbuf[1];
+ return rc;
+}
+
+static void deinit(void)
+{
+ svcCloseHandle(hbldrHandle);
+}
+
+static void launchFile(const char* path, argData_s* args, executableMetadata_s* em)
+{
+ if (strncmp(path, "sdmc:/",6) == 0)
+ path += 5;
+ HBLDR_SetTarget(path);
+ HBLDR_SetArgv(args->buf, sizeof(args->buf));
+}
+
+const loaderFuncs_s loader_Rosalina =
+{
+ .name = "Rosalina",
+ .init = init,
+ .deinit = deinit,
+ .launchFile = launchFile,
+};
diff --git a/database_info.c b/database_info.c
index 433bd275aa..894ae250ac 100644
--- a/database_info.c
+++ b/database_info.c
@@ -21,11 +21,13 @@
#include
#include
#include
+#include
+#include
#include
#include "libretro-db/libretrodb.h"
-#include "list_special.h"
+#include "core_info.h"
#include "database_info.h"
#include "verbosity.h"
@@ -366,16 +368,22 @@ static void dir_list_prioritize(struct string_list *list)
}
database_info_handle_t *database_info_dir_init(const char *dir,
- enum database_type type, retro_task_t *task)
+ enum database_type type, retro_task_t *task,
+ bool show_hidden_files)
{
- struct string_list *list = NULL;
- database_info_handle_t *db = (database_info_handle_t*)
+ core_info_list_t *core_info_list = NULL;
+ struct string_list *list = NULL;
+ database_info_handle_t *db = (database_info_handle_t*)
calloc(1, sizeof(*db));
if (!db)
return NULL;
- list = dir_list_new_special(dir, DIR_LIST_RECURSIVE, NULL);
+ core_info_get_list(&core_info_list);
+
+ list = dir_list_new(dir, core_info_list->all_ext,
+ false, show_hidden_files,
+ false, true);
if (!list)
{
diff --git a/database_info.h b/database_info.h
index 2664577e6f..aa0f5b8011 100644
--- a/database_info.h
+++ b/database_info.h
@@ -126,7 +126,8 @@ database_info_list_t *database_info_list_new(const char *rdb_path,
void database_info_list_free(database_info_list_t *list);
database_info_handle_t *database_info_dir_init(const char *dir,
- enum database_type type, retro_task_t *task);
+ enum database_type type, retro_task_t *task,
+ bool show_hidden_files);
database_info_handle_t *database_info_file_init(const char *path,
enum database_type type, retro_task_t *task);
diff --git a/defaults.h b/defaults.h
index 2373d0bf00..117e14a39a 100644
--- a/defaults.h
+++ b/defaults.h
@@ -107,7 +107,7 @@ struct defaults
playlist_t *image_history;
#endif
playlist_t *music_history;
-#ifdef HAVE_FFMPEG
+#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
playlist_t *video_history;
#endif
#endif
diff --git a/deps/SPIRV-Cross/.travis.yml b/deps/SPIRV-Cross/.travis.yml
index 26941f43a3..8e09d61957 100644
--- a/deps/SPIRV-Cross/.travis.yml
+++ b/deps/SPIRV-Cross/.travis.yml
@@ -2,32 +2,17 @@ language: cpp
os:
- linux
- osx
-osx_image: xcode8.3
+osx_image: xcode9.3beta
# Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment.
sudo: required
dist: trusty
-# We check out glslang and SPIRV-Tools at specific revisions to avoid test output mismatches
-env:
- - GLSLANG_REV=9c6f8cc29ba303b43ccf36deea6bb38a304f9b92 SPIRV_TOOLS_REV=e28edd458b729da7bbfd51e375feb33103709e6f
-
before_script:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade python3; fi
- - git clone https://github.com/KhronosGroup/glslang.git glslang
- - git clone https://github.com/KhronosGroup/SPIRV-Tools SPIRV-Tools
- - git clone https://github.com/KhronosGroup/SPIRV-Headers.git SPIRV-Tools/external/spirv-headers
+ - ./checkout_glslang_spirv_tools.sh
script:
- - git -C glslang checkout $GLSLANG_REV
- - git -C SPIRV-Tools checkout $SPIRV_TOOLS_REV
- - cd glslang && cmake . && make -j2 && cd ..
- - cd SPIRV-Tools && cmake . && make -j2 && cd ..
+ - ./build_glslang_spirv_tools.sh Debug 2
- make -j2
- - PATH=./glslang/StandAlone:./SPIRV-Tools/tools:$PATH
- - ./test_shaders.py shaders
- - ./test_shaders.py --msl shaders-msl
- - ./test_shaders.py --hlsl shaders-hlsl
- - ./test_shaders.py shaders --opt
- - ./test_shaders.py --msl shaders-msl --opt
- - ./test_shaders.py --hlsl shaders-hlsl --opt
+ - ./test_shaders.sh
diff --git a/deps/SPIRV-Cross/CMakeLists.txt b/deps/SPIRV-Cross/CMakeLists.txt
index 659315c785..2849b6957d 100644
--- a/deps/SPIRV-Cross/CMakeLists.txt
+++ b/deps/SPIRV-Cross/CMakeLists.txt
@@ -93,6 +93,10 @@ spirv_cross_add_library(spirv-cross-cpp spirv_cross_cpp STATIC
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.hpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.cpp)
+spirv_cross_add_library(spirv-cross-reflect spirv_cross_reflect STATIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.hpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.cpp)
+
spirv_cross_add_library(spirv-cross-msl spirv_cross_msl STATIC
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.cpp)
@@ -110,7 +114,7 @@ target_compile_options(spirv-cross PRIVATE ${spirv-compiler-options})
target_compile_definitions(spirv-cross PRIVATE ${spirv-compiler-defines})
install(TARGETS spirv-cross RUNTIME DESTINATION bin)
-target_link_libraries(spirv-cross spirv-cross-glsl spirv-cross-hlsl spirv-cross-cpp spirv-cross-msl spirv-cross-util spirv-cross-core)
+target_link_libraries(spirv-cross spirv-cross-glsl spirv-cross-hlsl spirv-cross-cpp spirv-cross-reflect spirv-cross-msl spirv-cross-util spirv-cross-core)
target_link_libraries(spirv-cross-util spirv-cross-core)
target_link_libraries(spirv-cross-glsl spirv-cross-core)
target_link_libraries(spirv-cross-msl spirv-cross-glsl)
@@ -128,12 +132,21 @@ if (${PYTHONINTERP_FOUND})
add_test(NAME spirv-cross-test
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py
${CMAKE_CURRENT_SOURCE_DIR}/shaders)
+ add_test(NAME spirv-cross-test-no-opt
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/shaders-no-opt)
add_test(NAME spirv-cross-test-metal
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --metal
${CMAKE_CURRENT_SOURCE_DIR}/shaders-msl)
+ add_test(NAME spirv-cross-test-metal-no-opt
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --metal
+ ${CMAKE_CURRENT_SOURCE_DIR}/shaders-msl-no-opt)
add_test(NAME spirv-cross-test-hlsl
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --hlsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders-hlsl)
+ add_test(NAME spirv-cross-test-hlsl-no-opt
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --hlsl
+ ${CMAKE_CURRENT_SOURCE_DIR}/shaders-hlsl-no-opt)
add_test(NAME spirv-cross-test-opt
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --opt
${CMAKE_CURRENT_SOURCE_DIR}/shaders)
diff --git a/deps/SPIRV-Cross/README.md b/deps/SPIRV-Cross/README.md
index a6f5231e7a..d3c1a93a07 100644
--- a/deps/SPIRV-Cross/README.md
+++ b/deps/SPIRV-Cross/README.md
@@ -3,6 +3,7 @@
SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader languages.
[](https://travis-ci.org/KhronosGroup/SPIRV-Cross)
+[](https://ci.appveyor.com/project/HansKristian-ARM/SPIRV-Cross)
## Features
@@ -10,6 +11,7 @@ SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader
- Convert SPIR-V to readable, usable and efficient Metal Shading Language (MSL)
- Convert SPIR-V to readable, usable and efficient HLSL
- Convert SPIR-V to debuggable C++ [EXPERIMENTAL]
+ - Convert SPIR-V to a JSON reflection format [EXPERIMENTAL]
- Reflection API to simplify the creation of Vulkan pipeline layouts
- Reflection API to modify and tweak OpDecorations
- Supports "all" of vertex, fragment, tessellation, geometry and compute shaders.
@@ -24,7 +26,7 @@ However, most missing features are expected to be "trivial" improvements at this
SPIRV-Cross has been tested on Linux, OSX and Windows.
-The make and CMake build flavors offer the option to treat exceptions as assertions. To disable exceptions for make just append SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=1 to the command line. For CMake append -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=ON. By default exceptions are enabled.
+The make and CMake build flavors offer the option to treat exceptions as assertions. To disable exceptions for make just append `SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=1` to the command line. For CMake append `-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=ON`. By default exceptions are enabled.
### Linux and macOS
@@ -38,6 +40,8 @@ MinGW-w64 based compilation works with `make`, and an MSVC 2013 solution is also
### Using the C++ API
+For more in-depth documentation than what's provided in this README, please have a look at the [Wiki](https://github.com/KhronosGroup/SPIRV-Cross/wiki).
+
To perform reflection and convert to other shader languages you can use the SPIRV-Cross API.
For example:
@@ -279,6 +283,7 @@ although there are a couple of convenience script for doing this:
```
./checkout_glslang_spirv_tools.sh # Checks out glslang and SPIRV-Tools at a fixed revision which matches the reference output.
+./build_glslang_spirv_tools.sh # Builds glslang and SPIRV-Tools.
./test_shaders.sh # Runs over all changes and makes sure that there are no deltas compared to reference files.
```
diff --git a/deps/SPIRV-Cross/appveyor.yml b/deps/SPIRV-Cross/appveyor.yml
new file mode 100644
index 0000000000..2f427f1804
--- /dev/null
+++ b/deps/SPIRV-Cross/appveyor.yml
@@ -0,0 +1,31 @@
+
+environment:
+ matrix:
+ - GENERATOR: "Visual Studio 12 2013 Win64"
+ CONFIG: Debug
+
+ - GENERATOR: "Visual Studio 12 2013 Win64"
+ CONFIG: Release
+
+ - GENERATOR: "Visual Studio 14 2015 Win64"
+ CONFIG: Debug
+
+ - GENERATOR: "Visual Studio 14 2015 Win64"
+ CONFIG: Release
+
+ - GENERATOR: "Visual Studio 12 2013"
+ CONFIG: Debug
+
+ - GENERATOR: "Visual Studio 12 2013"
+ CONFIG: Release
+
+ - GENERATOR: "Visual Studio 14 2015"
+ CONFIG: Debug
+
+ - GENERATOR: "Visual Studio 14 2015"
+ CONFIG: Release
+
+build_script:
+ - git submodule update --init
+ - cmake "-G%GENERATOR%" -H. -B_builds
+ - cmake --build _builds --config "%CONFIG%"
diff --git a/deps/SPIRV-Cross/build_glslang_spirv_tools.sh b/deps/SPIRV-Cross/build_glslang_spirv_tools.sh
new file mode 100755
index 0000000000..a966427935
--- /dev/null
+++ b/deps/SPIRV-Cross/build_glslang_spirv_tools.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+PROFILE=Release
+if [ ! -z $1 ]; then
+ PROFILE=$1
+fi
+
+NPROC=$(nproc)
+if [ ! -z $2 ]; then
+ NPROC=$2
+fi
+
+echo "Building glslang."
+mkdir -p external/glslang-build
+cd external/glslang-build
+cmake ../glslang -DCMAKE_BUILD_TYPE=$PROFILE -G"Unix Makefiles"
+make -j$NPROC
+cd ../..
+
+echo "Building SPIRV-Tools."
+mkdir -p external/spirv-tools-build
+cd external/spirv-tools-build
+cmake ../spirv-tools -DCMAKE_BUILD_TYPE=$PROFILE -G"Unix Makefiles" -DSPIRV_WERROR=OFF
+make -j$NPROC
+cd ../..
+
diff --git a/deps/SPIRV-Cross/checkout_glslang_spirv_tools.sh b/deps/SPIRV-Cross/checkout_glslang_spirv_tools.sh
index a4674c14e1..b751fb8e7f 100755
--- a/deps/SPIRV-Cross/checkout_glslang_spirv_tools.sh
+++ b/deps/SPIRV-Cross/checkout_glslang_spirv_tools.sh
@@ -1,7 +1,7 @@
#!/bin/bash
-GLSLANG_REV=9c6f8cc29ba303b43ccf36deea6bb38a304f9b92
-SPIRV_TOOLS_REV=e28edd458b729da7bbfd51e375feb33103709e6f
+GLSLANG_REV=461ea09943e0e88ea854ab9e3b42d17d728af2ad
+SPIRV_TOOLS_REV=53bc1623ecd3cc304d0d6feed8385e70c7ab30d3
if [ -d external/glslang ]; then
echo "Updating glslang to revision $GLSLANG_REV."
@@ -18,13 +18,6 @@ else
fi
cd ../..
-echo "Building glslang."
-mkdir -p external/glslang-build
-cd external/glslang-build
-cmake ../glslang -DCMAKE_BUILD_TYPE=Release -G"Unix Makefiles"
-make -j$(nproc)
-cd ../..
-
if [ -d external/spirv-tools ]; then
echo "Updating SPIRV-Tools to revision $SPIRV_TOOLS_REV."
cd external/spirv-tools
@@ -37,21 +30,15 @@ else
git clone git://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools
cd spirv-tools
git checkout $SPIRV_TOOLS_REV
-
- if [ -d external/spirv-headers ]; then
- cd external/spirv-headers
- git pull origin master
- cd ../..
- else
- git clone git://github.com/KhronosGroup/SPIRV-Headers.git external/spirv-headers
- fi
fi
-cd ../..
-
-echo "Building SPIRV-Tools."
-mkdir -p external/spirv-tools-build
-cd external/spirv-tools-build
-cmake ../spirv-tools -DCMAKE_BUILD_TYPE=Release -G"Unix Makefiles"
-make -j$(nproc)
+
+if [ -d external/spirv-headers ]; then
+ cd external/spirv-headers
+ git pull origin master
+ cd ../..
+else
+ git clone git://github.com/KhronosGroup/SPIRV-Headers.git external/spirv-headers
+fi
+
cd ../..
diff --git a/deps/SPIRV-Cross/format_all.sh b/deps/SPIRV-Cross/format_all.sh
index 05efeb3eae..fcfffc57f8 100755
--- a/deps/SPIRV-Cross/format_all.sh
+++ b/deps/SPIRV-Cross/format_all.sh
@@ -1,6 +1,7 @@
#!/bin/bash
-for file in spirv_*.{cpp,hpp} include/spirv_cross/*.{hpp,h} samples/cpp/*.cpp main.cpp
+#for file in spirv_*.{cpp,hpp} include/spirv_cross/*.{hpp,h} samples/cpp/*.cpp main.cpp
+for file in spirv_*.{cpp,hpp} main.cpp
do
echo "Formatting file: $file ..."
clang-format -style=file -i $file
diff --git a/deps/SPIRV-Cross/main.cpp b/deps/SPIRV-Cross/main.cpp
index 4f0265d1af..69bd135c1a 100644
--- a/deps/SPIRV-Cross/main.cpp
+++ b/deps/SPIRV-Cross/main.cpp
@@ -19,6 +19,7 @@
#include "spirv_glsl.hpp"
#include "spirv_hlsl.hpp"
#include "spirv_msl.hpp"
+#include "spirv_reflect.hpp"
#include
#include
#include
@@ -122,7 +123,7 @@ struct CLIParser
THROW("Tried to parse uint, but nothing left in arguments");
}
- uint32_t val = stoul(*argv);
+ uint64_t val = stoul(*argv);
if (val > numeric_limits::max())
{
THROW("next_uint() out of range");
@@ -131,7 +132,7 @@ struct CLIParser
argc--;
argv++;
- return val;
+ return uint32_t(val);
}
double next_double()
@@ -149,6 +150,22 @@ struct CLIParser
return val;
}
+ // Return a string only if it's not prefixed with `--`, otherwise return the default value
+ const char *next_value_string(const char *default_value)
+ {
+ if (!argc)
+ {
+ return default_value;
+ }
+
+ if (0 == strncmp("--", *argv, 2))
+ {
+ return default_value;
+ }
+
+ return next_string();
+ }
+
const char *next_string()
{
if (!argc)
@@ -212,7 +229,6 @@ static void print_resources(const Compiler &compiler, const char *tag, const vec
for (auto &res : resources)
{
auto &type = compiler.get_type(res.type_id);
- auto mask = compiler.get_decoration_mask(res.id);
if (print_ssbo && compiler.buffer_is_hlsl_counter_buffer(res.id))
continue;
@@ -221,8 +237,8 @@ static void print_resources(const Compiler &compiler, const char *tag, const vec
// for SSBOs and UBOs since those are the only meaningful names to use externally.
// Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant;
- bool is_block = (compiler.get_decoration_mask(type.self) &
- ((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) != 0;
+ bool is_block = compiler.get_decoration_bitset(type.self).get(DecorationBlock) ||
+ compiler.get_decoration_bitset(type.self).get(DecorationBufferBlock);
bool is_sized_block = is_block && (compiler.get_storage_class(res.id) == StorageClassUniform ||
compiler.get_storage_class(res.id) == StorageClassUniformConstant);
uint32_t fallback_id = !is_push_constant && is_block ? res.base_type_id : res.id;
@@ -231,6 +247,12 @@ static void print_resources(const Compiler &compiler, const char *tag, const vec
if (is_sized_block)
block_size = uint32_t(compiler.get_declared_struct_size(compiler.get_type(res.base_type_id)));
+ Bitset mask;
+ if (print_ssbo)
+ mask = compiler.get_buffer_block_flags(res.id);
+ else
+ mask = compiler.get_decoration_bitset(res.id);
+
string array;
for (auto arr : type.array)
array = join("[", arr ? convert_to_string(arr) : "", "]") + array;
@@ -238,17 +260,17 @@ static void print_resources(const Compiler &compiler, const char *tag, const vec
fprintf(stderr, " ID %03u : %s%s", res.id,
!res.name.empty() ? res.name.c_str() : compiler.get_fallback_name(fallback_id).c_str(), array.c_str());
- if (mask & (1ull << DecorationLocation))
+ if (mask.get(DecorationLocation))
fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation));
- if (mask & (1ull << DecorationDescriptorSet))
+ if (mask.get(DecorationDescriptorSet))
fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
- if (mask & (1ull << DecorationBinding))
+ if (mask.get(DecorationBinding))
fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
- if (mask & (1ull << DecorationInputAttachmentIndex))
+ if (mask.get(DecorationInputAttachmentIndex))
fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex));
- if (mask & (1ull << DecorationNonReadable))
+ if (mask.get(DecorationNonReadable))
fprintf(stderr, " writeonly");
- if (mask & (1ull << DecorationNonWritable))
+ if (mask.get(DecorationNonWritable))
fprintf(stderr, " readonly");
if (is_sized_block)
fprintf(stderr, " (BlockSize : %u bytes)", block_size);
@@ -284,7 +306,7 @@ static const char *execution_model_to_str(spv::ExecutionModel model)
static void print_resources(const Compiler &compiler, const ShaderResources &res)
{
- uint64_t modes = compiler.get_execution_mode_mask();
+ auto &modes = compiler.get_execution_mode_bitset();
fprintf(stderr, "Entry points:\n");
auto entry_points = compiler.get_entry_points_and_stages();
@@ -293,11 +315,7 @@ static void print_resources(const Compiler &compiler, const ShaderResources &res
fprintf(stderr, "\n");
fprintf(stderr, "Execution modes:\n");
- for (unsigned i = 0; i < 64; i++)
- {
- if (!(modes & (1ull << i)))
- continue;
-
+ modes.for_each_bit([&](uint32_t i) {
auto mode = static_cast(i);
uint32_t arg0 = compiler.get_execution_mode_argument(mode, 0);
uint32_t arg1 = compiler.get_execution_mode_argument(mode, 1);
@@ -353,7 +371,7 @@ static void print_resources(const Compiler &compiler, const ShaderResources &res
default:
break;
}
- }
+ });
fprintf(stderr, "\n");
print_resources(compiler, "subpass inputs", res.subpass_inputs);
@@ -460,6 +478,7 @@ struct CLIArguments
bool fixup = false;
bool yflip = false;
bool sso = false;
+ bool support_nonzero_baseinstance = true;
vector pls_in;
vector pls_out;
vector remaps;
@@ -480,6 +499,7 @@ struct CLIArguments
uint32_t iterations = 1;
bool cpp = false;
+ string reflect;
bool msl = false;
bool hlsl = false;
bool hlsl_compat = false;
@@ -487,25 +507,49 @@ struct CLIArguments
bool flatten_multidimensional_arrays = false;
bool use_420pack_extension = true;
bool remove_unused = false;
+ bool combined_samplers_inherit_bindings = false;
};
static void print_help()
{
- fprintf(stderr, "Usage: spirv-cross [--output