Merge branch 'master' into stripes

This commit is contained in:
Rob Loach 2018-07-22 13:30:47 -04:00 committed by GitHub
commit aba179a910
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3276 changed files with 454446 additions and 135001 deletions

4
.gitignore vendored
View File

@ -68,6 +68,10 @@ menu/driverspzarch.c
.pc
/media/shaders_glsl/
/obj-w32/
.cproject
.settings
libretro-super
run.sh
# Wii U
*.depend

View File

@ -5,7 +5,23 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@ -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

View File

@ -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
}

43
.vscode/launch.json vendored
View File

@ -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
}
]
}
},
]
}

View File

@ -12,6 +12,8 @@
"files.associations": {
"frontend_driver.h": "c",
"*.in": "c",
"*.rh": "c"
"*.rh": "c",
"array": "c",
},
"C_Cpp.dimInactiveRegions": false,
}

View File

@ -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

View File

@ -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 '$*=$($*)'

View File

@ -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)

View File

@ -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

View File

@ -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=<path to>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 $@

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -18,6 +18,7 @@ HAVE_PYTHON = 0
DYNAMIC = 1
HAVE_XINPUT = 1
HAVE_WINMM = 1
HAVE_SDL := 0
HAVE_SDL2 := 0

135
README.md
View File

@ -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.

View File

@ -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)
{

View File

@ -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;

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

219
command.c
View File

@ -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:

View File

@ -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,

View File

@ -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

View File

@ -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
};

View File

@ -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

View File

@ -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)

View File

@ -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);
/**

View File

@ -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

View File

@ -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;
}

View File

@ -17,6 +17,7 @@
#include <compat/strl.h>
#include <string/stdstring.h>
#include <file/config_file.h>
#include <file/file_path.h>
#include <lists/dir_list.h>
#include <file/archive_file.h>
@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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. */

View File

@ -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)

View File

@ -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.

View File

@ -0,0 +1 @@
#include "../internal_cores.h"

View File

@ -14,26 +14,28 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_OPENGLES
#include <dlfcn.h>
#endif
#ifdef HAVE_LOCALE
#include <locale.h>
#endif
#include <mpv/client.h>
#include <mpv/opengl_cb.h>
#include <mpv/render_gl.h>
#include <libretro.h>
#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;
}

View File

@ -1,3 +1,3 @@
#ifndef LIBRETRO_MPV_VERSION
#define LIBRETRO_MPV_VERSION "0.2.alpha"
#define LIBRETRO_MPV_VERSION "0.3.alpha"
#endif

View File

@ -1,5 +1,6 @@
#include <3ds.h>
#include <sys/iosupport.h>
#include <3ds/services/apt.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

85
ctr/exec-3dsx/exec_3dsx.c Normal file
View File

@ -0,0 +1,85 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#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*/);
}

View File

@ -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

203
ctr/exec-3dsx/exec_cia.c Normal file
View File

@ -0,0 +1,203 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#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(&param, 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;
}

6
ctr/exec-3dsx/exec_cia.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef EXEC_CIA_H
#define EXEC_CIA_H
int exec_cia(const char* path, const char** args);
#endif

View File

@ -0,0 +1,95 @@
#pragma once
// C stdlib includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
// 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"

View File

@ -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;
}

View File

@ -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);

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -21,11 +21,13 @@
#include <compat/strl.h>
#include <retro_endianness.h>
#include <file/file_path.h>
#include <lists/string_list.h>
#include <lists/dir_list.h>
#include <string/stdstring.h>
#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)
{

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -3,6 +3,7 @@
SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader languages.
[![Build Status](https://travis-ci.org/KhronosGroup/SPIRV-Cross.svg?branch=master)](https://travis-ci.org/KhronosGroup/SPIRV-Cross)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/KhronosGroup/SPIRV-Cross?svg=true&branch=master)](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.
```

31
deps/SPIRV-Cross/appveyor.yml vendored Normal file
View File

@ -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%"

26
deps/SPIRV-Cross/build_glslang_spirv_tools.sh vendored Executable file
View File

@ -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 ../..

View File

@ -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 ../..

View File

@ -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

View File

@ -19,6 +19,7 @@
#include "spirv_glsl.hpp"
#include "spirv_hlsl.hpp"
#include "spirv_msl.hpp"
#include "spirv_reflect.hpp"
#include <algorithm>
#include <cstdio>
#include <cstring>
@ -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<uint32_t>::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<ExecutionMode>(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<PLSArg> pls_in;
vector<PLSArg> pls_out;
vector<Remap> 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 <output path>] [SPIR-V file] [--es] [--no-es] "
"[--version <GLSL version>] [--dump-resources] [--help] [--force-temporary] "
"[--vulkan-semantics] [--flatten-ubo] [--fixup-clipspace] [--flip-vert-y] [--iterations iter] "
"[--cpp] [--cpp-interface-name <name>] "
"[--msl] [--msl-version <MMmmpp>]"
"[--hlsl] [--shader-model] [--hlsl-enable-compat] "
"[--separate-shader-objects]"
"[--pls-in format input-name] [--pls-out format output-name] [--remap source_name target_name "
"components] [--extension ext] [--entry name] [--stage <stage (vert, frag, geom, tesc, tese, "
"comp)>] [--remove-unused-variables] "
"[--flatten-multidimensional-arrays] [--no-420pack-extension] "
"[--remap-variable-type <variable_name> <new_variable_type>] "
"[--rename-interface-variable <in|out> <location> <new_variable_name>] "
"[--set-hlsl-vertex-input-semantic <location> <semantic>] "
"[--rename-entry-point <old> <new> <stage>] "
fprintf(stderr, "Usage: spirv-cross\n"
"\t[--output <output path>]\n"
"\t[SPIR-V file]\n"
"\t[--es]\n"
"\t[--no-es]\n"
"\t[--version <GLSL version>]\n"
"\t[--dump-resources]\n"
"\t[--help]\n"
"\t[--force-temporary]\n"
"\t[--vulkan-semantics]\n"
"\t[--flatten-ubo]\n"
"\t[--fixup-clipspace]\n"
"\t[--flip-vert-y]\n"
"\t[--iterations iter]\n"
"\t[--cpp]\n"
"\t[--cpp-interface-name <name>]\n"
"\t[--msl]\n"
"\t[--msl-version <MMmmpp>]\n"
"\t[--hlsl]\n"
"\t[--reflect]\n"
"\t[--shader-model]\n"
"\t[--hlsl-enable-compat]\n"
"\t[--separate-shader-objects]\n"
"\t[--pls-in format input-name]\n"
"\t[--pls-out format output-name]\n"
"\t[--remap source_name target_name components]\n"
"\t[--extension ext]\n"
"\t[--entry name]\n"
"\t[--stage <stage (vert, frag, geom, tesc, tese comp)>]\n"
"\t[--remove-unused-variables]\n"
"\t[--flatten-multidimensional-arrays]\n"
"\t[--no-420pack-extension]\n"
"\t[--remap-variable-type <variable_name> <new_variable_type>]\n"
"\t[--rename-interface-variable <in|out> <location> <new_variable_name>]\n"
"\t[--set-hlsl-vertex-input-semantic <location> <semantic>]\n"
"\t[--rename-entry-point <old> <new> <stage>]\n"
"\t[--combined-samplers-inherit-bindings]\n"
"\t[--no-support-nonzero-baseinstance]\n"
"\n");
}
@ -640,6 +684,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--flip-vert-y", [&args](CLIParser &) { args.yflip = true; });
cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
cbs.add("--reflect", [&args](CLIParser &parser) { args.reflect = parser.next_value_string("json"); });
cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
@ -711,6 +756,10 @@ static int main_inner(int argc, char *argv[])
});
cbs.add("--remove-unused-variables", [&args](CLIParser &) { args.remove_unused = true; });
cbs.add("--combined-samplers-inherit-bindings",
[&args](CLIParser &) { args.combined_samplers_inherit_bindings = true; });
cbs.add("--no-support-nonzero-baseinstance", [&](CLIParser &) { args.support_nonzero_baseinstance = false; });
cbs.default_handler = [&args](const char *value) { args.input = value; };
cbs.error_handler = [] { print_help(); };
@ -732,8 +781,20 @@ static int main_inner(int argc, char *argv[])
return EXIT_FAILURE;
}
unique_ptr<CompilerGLSL> compiler;
// Special case reflection because it has little to do with the path followed by code-outputting compilers
if (!args.reflect.empty())
{
CompilerReflection compiler(read_spirv_file(args.input));
compiler.set_format(args.reflect);
auto json = compiler.compile();
if (args.output)
write_string_to_file(args.output, json.c_str());
else
printf("%s", json.c_str());
return EXIT_SUCCESS;
}
unique_ptr<CompilerGLSL> compiler;
bool combined_image_samplers = false;
bool build_dummy_sampler = false;
@ -748,10 +809,10 @@ static int main_inner(int argc, char *argv[])
compiler = unique_ptr<CompilerMSL>(new CompilerMSL(read_spirv_file(args.input)));
auto *msl_comp = static_cast<CompilerMSL *>(compiler.get());
auto msl_opts = msl_comp->get_options();
auto msl_opts = msl_comp->get_msl_options();
if (args.set_msl_version)
msl_opts.msl_version = args.msl_version;
msl_comp->set_options(msl_opts);
msl_comp->set_msl_options(msl_opts);
}
else if (args.hlsl)
compiler = unique_ptr<CompilerHLSL>(new CompilerHLSL(read_spirv_file(args.input)));
@ -851,14 +912,14 @@ static int main_inner(int argc, char *argv[])
if (!entry_point.empty())
compiler->set_entry_point(entry_point, model);
if (!args.set_version && !compiler->get_options().version)
if (!args.set_version && !compiler->get_common_options().version)
{
fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n");
print_help();
return EXIT_FAILURE;
}
CompilerGLSL::Options opts = compiler->get_options();
CompilerGLSL::Options opts = compiler->get_common_options();
if (args.set_version)
opts.version = args.version;
if (args.set_es)
@ -870,13 +931,14 @@ static int main_inner(int argc, char *argv[])
opts.vulkan_semantics = args.vulkan_semantics;
opts.vertex.fixup_clipspace = args.fixup;
opts.vertex.flip_vert_y = args.yflip;
compiler->set_options(opts);
opts.vertex.support_nonzero_base_instance = args.support_nonzero_baseinstance;
compiler->set_common_options(opts);
// Set HLSL specific options.
if (args.hlsl)
{
auto *hlsl = static_cast<CompilerHLSL *>(compiler.get());
auto hlsl_opts = hlsl->get_options();
auto hlsl_opts = hlsl->get_hlsl_options();
if (args.set_shader_model)
{
if (args.shader_model < 30)
@ -894,11 +956,19 @@ static int main_inner(int argc, char *argv[])
hlsl_opts.point_size_compat = true;
hlsl_opts.point_coord_compat = true;
}
hlsl->set_options(hlsl_opts);
hlsl->set_hlsl_options(hlsl_opts);
}
if (build_dummy_sampler)
compiler->build_dummy_sampler_for_combined_images();
{
uint32_t sampler = compiler->build_dummy_sampler_for_combined_images();
if (sampler != 0)
{
// Set some defaults to make validation happy.
compiler->set_decoration(sampler, DecorationDescriptorSet, 0);
compiler->set_decoration(sampler, DecorationBinding, 0);
}
}
ShaderResources res;
if (args.remove_unused)
@ -961,6 +1031,9 @@ static int main_inner(int argc, char *argv[])
if (combined_image_samplers)
{
compiler->build_combined_image_samplers();
if (args.combined_samplers_inherit_bindings)
spirv_cross_util::inherit_combined_sampler_bindings(*compiler);
// Give the remapped combined samplers new names.
for (auto &remap : compiler->get_combined_image_samplers())
{

View File

@ -127,6 +127,7 @@
<ClCompile Include="..\spirv_cpp.cpp" />
<ClCompile Include="..\spirv_cross.cpp" />
<ClCompile Include="..\spirv_glsl.cpp" />
<ClCompile Include="..\spirv_reflect.cpp" />
<ClCompile Include="..\spirv_hlsl.cpp" />
<ClCompile Include="..\spirv_msl.cpp" />
<ClCompile Include="..\spirv_cfg.cpp" />
@ -138,6 +139,7 @@
<ClInclude Include="..\spirv_cpp.hpp" />
<ClInclude Include="..\spirv_cross.hpp" />
<ClInclude Include="..\spirv_glsl.hpp" />
<ClInclude Include="..\spirv_reflect.hpp" />
<ClInclude Include="..\spirv.hpp" />
<ClInclude Include="..\spirv_hlsl.hpp" />
<ClInclude Include="..\spirv_msl.hpp" />

View File

@ -24,6 +24,9 @@
<ClCompile Include="..\spirv_glsl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\spirv_reflect.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\spirv_cpp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -50,6 +53,9 @@
<ClInclude Include="..\spirv_glsl.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\spirv_reflect.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\spirv.hpp">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -0,0 +1,32 @@
RWByteAddressBuffer bar : register(u0);
RWByteAddressBuffer foo : register(u1);
void comp_main()
{
[unroll]
for (int _135 = 0; _135 < 16; )
{
bar.Store4(_135 * 16 + 0, asuint(asfloat(foo.Load4(_135 * 16 + 0))));
_135++;
continue;
}
[loop]
for (int _136 = 0; _136 < 16; )
{
bar.Store4((15 - _136) * 16 + 0, asuint(asfloat(foo.Load4(_136 * 16 + 0))));
_136++;
continue;
}
[branch]
if (asfloat(bar.Load(160)) > 10.0f)
{
foo.Store4(320, asuint(5.0f.xxxx));
}
foo.Store4(320, asuint(20.0f.xxxx));
}
[numthreads(1, 1, 1)]
void main()
{
comp_main();
}

View File

@ -0,0 +1,30 @@
Texture2D<float4> uTex : register(t1);
SamplerState uSampler : register(s0);
static float4 FragColor;
static float2 vUV;
struct SPIRV_Cross_Input
{
float2 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
FragColor = uTex.Sample(uSampler, vUV);
FragColor += uTex.Sample(uSampler, vUV, int2(1, 1));
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,8 @@
void frag_main()
{
}
void main()
{
frag_main();
}

View File

@ -7,7 +7,7 @@ struct SPIRV_Cross_Output
void frag_main()
{
FragColor = (((1.0f.xxxx + 1.0f.xxxx) + (1.0f.xxx.xyzz + 1.0f.xxxx)) + (1.0f.xxxx + 2.0f.xxxx)) + (1.0f.xx.xyxy + 2.0f.xxxx);
FragColor = 10.0f.xxxx;
}
SPIRV_Cross_Output main()

View File

@ -0,0 +1,31 @@
Texture2D<float4> uTexture : register(t0);
SamplerState _uTexture_sampler : register(s0);
static int2 Size;
struct SPIRV_Cross_Output
{
int2 Size : SV_Target0;
};
uint2 SPIRV_Cross_textureSize(Texture2D<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
void frag_main()
{
uint _19_dummy_parameter;
uint _20_dummy_parameter;
Size = int2(SPIRV_Cross_textureSize(uTexture, uint(0), _19_dummy_parameter)) + int2(SPIRV_Cross_textureSize(uTexture, uint(1), _20_dummy_parameter));
}
SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.Size = Size;
return stage_output;
}

View File

@ -0,0 +1,57 @@
Texture2D<float4> uImage : register(t0);
SamplerState _uImage_sampler : register(s0);
static float4 v0;
static float4 FragColor;
struct SPIRV_Cross_Input
{
float4 v0 : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
float phi;
float4 _36;
int _51;
_51 = 0;
phi = 1.0f;
_36 = float4(1.0f, 2.0f, 1.0f, 2.0f);
for (;;)
{
FragColor = _36;
if (_51 < 4)
{
if (v0[_51] > 0.0f)
{
float2 _48 = phi.xx;
_51++;
phi += 2.0f;
_36 = uImage.SampleLevel(_uImage_sampler, _48, 0.0f);
continue;
}
else
{
break;
}
}
else
{
break;
}
}
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
v0 = stage_input.v0;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,57 @@
static const float _46[16] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f };
static const float4 _76[4] = { 0.0f.xxxx, 1.0f.xxxx, 8.0f.xxxx, 5.0f.xxxx };
static const float4 _90[4] = { 20.0f.xxxx, 30.0f.xxxx, 50.0f.xxxx, 60.0f.xxxx };
static float FragColor;
static int index;
struct SPIRV_Cross_Input
{
nointerpolation int index : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
void frag_main()
{
float4 foobar[4] = _76;
float4 baz[4] = _76;
FragColor = _46[index];
if (index < 10)
{
FragColor += _46[index ^ 1];
}
else
{
FragColor += _46[index & 1];
}
bool _99 = index > 30;
if (_99)
{
FragColor += _76[index & 3].y;
}
else
{
FragColor += _76[index & 1].x;
}
if (_99)
{
foobar[1].z = 20.0f;
}
int _37 = index & 3;
FragColor += foobar[_37].z;
baz = _90;
FragColor += baz[_37].z;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
index = stage_input.index;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,29 @@
static float4 FragColor;
static int4 vA;
static int4 vB;
struct SPIRV_Cross_Input
{
nointerpolation int4 vA : TEXCOORD0;
nointerpolation int4 vB : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
FragColor = float4(vA - vB * (vA / vB));
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vA = stage_input.vA;
vB = stage_input.vB;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,29 @@
Texture2D<float4> uTexture : register(t0);
SamplerState _uTexture_sampler : register(s0);
static float4 gl_FragCoord;
static float4 FragColor;
struct SPIRV_Cross_Input
{
float4 gl_FragCoord : SV_Position;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
FragColor = uTexture.Load(int3(int2(gl_FragCoord.xy), 0));
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
gl_FragCoord = stage_input.gl_FragCoord;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,31 @@
Texture2D<float4> uShadow : register(t0);
SamplerComparisonState _uShadow_sampler : register(s0);
Texture2D<float4> uTexture : register(t1);
SamplerComparisonState uSampler : register(s2);
static float3 vUV;
static float FragColor;
struct SPIRV_Cross_Input
{
float3 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
void frag_main()
{
FragColor = uShadow.SampleCmp(_uShadow_sampler, vUV.xy, vUV.z) + uTexture.SampleCmp(uSampler, vUV.xy, vUV.z);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -11,25 +11,23 @@ struct SPIRV_Cross_Output
float4 FragColor : SV_Target0;
};
float4 _21;
void frag_main()
{
float4 _33;
do
bool _29;
for (;;)
{
if (counter == 10)
_29 = counter == 10;
if (_29)
{
_33 = 10.0f.xxxx;
break;
}
else
{
_33 = 30.0f.xxxx;
break;
}
} while (false);
FragColor = _33;
}
bool4 _35 = _29.xxxx;
FragColor = float4(_35.x ? 10.0f.xxxx.x : 30.0f.xxxx.x, _35.y ? 10.0f.xxxx.y : 30.0f.xxxx.y, _35.z ? 10.0f.xxxx.z : 30.0f.xxxx.z, _35.w ? 10.0f.xxxx.w : 30.0f.xxxx.w);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)

View File

@ -1,8 +0,0 @@
void vert_main()
{
}
void main()
{
vert_main();
}

View File

@ -0,0 +1,37 @@
static const int _7 = -10;
static const uint _8 = 100u;
static const int _20 = (_7 + 2);
static const uint _25 = (_8 % 5u);
static const int4 _30 = int4(20, 30, _20, _20);
static const int2 _32 = int2(_30.y, _30.x);
static const int _33 = _30.y;
static float4 gl_Position;
static int _4;
struct SPIRV_Cross_Output
{
nointerpolation int _4 : TEXCOORD0;
float4 gl_Position : SV_Position;
};
void vert_main()
{
float4 _64 = 0.0f.xxxx;
_64.y = float(_20);
float4 _68 = _64;
_68.z = float(_25);
float4 _52 = _68 + float4(_30);
float2 _56 = _52.xy + float2(_32);
gl_Position = float4(_56.x, _56.y, _52.z, _52.w);
_4 = _33;
}
SPIRV_Cross_Output main()
{
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
stage_output._4 = _4;
return stage_output;
}

View File

@ -0,0 +1,28 @@
static float4 gl_Position;
static int gl_VertexIndex;
static int gl_InstanceIndex;
struct SPIRV_Cross_Input
{
uint gl_VertexIndex : SV_VertexID;
uint gl_InstanceIndex : SV_InstanceID;
};
struct SPIRV_Cross_Output
{
float4 gl_Position : SV_Position;
};
void vert_main()
{
gl_Position = float(uint(gl_VertexIndex) + uint(gl_InstanceIndex)).xxxx;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
gl_VertexIndex = int(stage_input.gl_VertexIndex);
gl_InstanceIndex = int(stage_input.gl_InstanceIndex);
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
return stage_output;
}

View File

@ -1,3 +1,5 @@
static const uint3 gl_WorkGroupSize = uint3(8u, 4u, 2u);
void comp_main()
{
}

View File

@ -0,0 +1,16 @@
globallycoherent RWByteAddressBuffer _29 : register(u3);
ByteAddressBuffer _33 : register(t2);
RWTexture2D<float> uImageIn : register(u0);
globallycoherent RWTexture2D<float> uImageOut : register(u1);
void comp_main()
{
uImageOut[int2(9, 7)] = uImageIn[int2(9, 7)].x;
_29.Store(0, asuint(asfloat(_33.Load(0))));
}
[numthreads(1, 1, 1)]
void main()
{
comp_main();
}

View File

@ -34,24 +34,26 @@ struct SPIRV_Cross_Input
void comp_main()
{
uImageOutF[int2(gl_GlobalInvocationID.xy)] = uImageInF[int2(gl_GlobalInvocationID.xy)].x;
uImageOutI[int2(gl_GlobalInvocationID.xy)] = uImageInI[int2(gl_GlobalInvocationID.xy)].x;
uImageOutU[int2(gl_GlobalInvocationID.xy)] = uImageInU[int2(gl_GlobalInvocationID.xy)].x;
uImageOutBuffer[int(gl_GlobalInvocationID.x)] = uImageInBuffer[int(gl_GlobalInvocationID.x)].x;
uImageOutF2[int2(gl_GlobalInvocationID.xy)] = uImageInF2[int2(gl_GlobalInvocationID.xy)].xy;
uImageOutI2[int2(gl_GlobalInvocationID.xy)] = uImageInI2[int2(gl_GlobalInvocationID.xy)].xy;
uImageOutU2[int2(gl_GlobalInvocationID.xy)] = uImageInU2[int2(gl_GlobalInvocationID.xy)].xy;
float4 _135 = uImageInBuffer2[int(gl_GlobalInvocationID.x)].xyyy;
uImageOutBuffer2[int(gl_GlobalInvocationID.x)] = _135.xy;
uImageOutF4[int2(gl_GlobalInvocationID.xy)] = uImageInF4[int2(gl_GlobalInvocationID.xy)];
int4 _165 = uImageInI4[int2(gl_GlobalInvocationID.xy)];
uImageOutI4[int2(gl_GlobalInvocationID.xy)] = _165;
uint4 _180 = uImageInU4[int2(gl_GlobalInvocationID.xy)];
uImageOutU4[int2(gl_GlobalInvocationID.xy)] = _180;
uImageOutBuffer4[int(gl_GlobalInvocationID.x)] = uImageInBuffer4[int(gl_GlobalInvocationID.x)];
uImageNoFmtF[int2(gl_GlobalInvocationID.xy)] = _135;
uImageNoFmtU[int2(gl_GlobalInvocationID.xy)] = _180;
uImageNoFmtI[int2(gl_GlobalInvocationID.xy)] = _165;
int2 _23 = int2(gl_GlobalInvocationID.xy);
uImageOutF[_23] = uImageInF[_23].x;
uImageOutI[_23] = uImageInI[_23].x;
uImageOutU[_23] = uImageInU[_23].x;
int _74 = int(gl_GlobalInvocationID.x);
uImageOutBuffer[_74] = uImageInBuffer[_74].x;
uImageOutF2[_23] = uImageInF2[_23].xy;
uImageOutI2[_23] = uImageInI2[_23].xy;
uImageOutU2[_23] = uImageInU2[_23].xy;
float4 _135 = uImageInBuffer2[_74].xyyy;
uImageOutBuffer2[_74] = _135.xy;
uImageOutF4[_23] = uImageInF4[_23];
int4 _165 = uImageInI4[_23];
uImageOutI4[_23] = _165;
uint4 _180 = uImageInU4[_23];
uImageOutU4[_23] = _180;
uImageOutBuffer4[_74] = uImageInBuffer4[_74];
uImageNoFmtF[_23] = _135;
uImageNoFmtU[_23] = _180;
uImageNoFmtI[_23] = _165;
}
[numthreads(1, 1, 1)]

View File

@ -0,0 +1,20 @@
RWByteAddressBuffer _11 : register(u0);
void comp_main()
{
_11.Store(0, asuint(asfloat(_11.Load(0)) * asfloat(_11.Load(96))));
_11.Store4(16, asuint(asfloat(_11.Load4(16)) * asfloat(_11.Load4(112))));
float4x4 _35 = asfloat(uint4x4(_11.Load4(128), _11.Load4(144), _11.Load4(160), _11.Load4(176)));
float4x4 _37 = asfloat(uint4x4(_11.Load4(32), _11.Load4(48), _11.Load4(64), _11.Load4(80)));
float4x4 _38 = mul(_35, _37);
_11.Store4(32, asuint(_38[0]));
_11.Store4(48, asuint(_38[1]));
_11.Store4(64, asuint(_38[2]));
_11.Store4(80, asuint(_38[3]));
}
[numthreads(1, 1, 1)]
void main()
{
comp_main();
}

View File

@ -17,7 +17,7 @@ void comp_main()
{
sShared[gl_LocalInvocationIndex] = asfloat(_22.Load(gl_GlobalInvocationID.x * 4 + 0));
GroupMemoryBarrierWithGroupSync();
_44.Store(gl_GlobalInvocationID.x * 4 + 0, asuint(sShared[(4u - gl_LocalInvocationIndex) - 1u]));
_44.Store(gl_GlobalInvocationID.x * 4 + 0, asuint(sShared[3u - gl_LocalInvocationIndex]));
}
[numthreads(4, 1, 1)]

View File

@ -0,0 +1,67 @@
RWByteAddressBuffer _9 : register(u0, space0);
static uint4 gl_SubgroupEqMask;
static uint4 gl_SubgroupGeMask;
static uint4 gl_SubgroupGtMask;
static uint4 gl_SubgroupLeMask;
static uint4 gl_SubgroupLtMask;
void comp_main()
{
_9.Store(0, asuint(float(WaveGetLaneCount())));
_9.Store(0, asuint(float(WaveGetLaneIndex())));
_9.Store(0, asuint(float4(gl_SubgroupEqMask).x));
_9.Store(0, asuint(float4(gl_SubgroupGeMask).x));
_9.Store(0, asuint(float4(gl_SubgroupGtMask).x));
_9.Store(0, asuint(float4(gl_SubgroupLeMask).x));
_9.Store(0, asuint(float4(gl_SubgroupLtMask).x));
uint4 _75 = WaveActiveBallot(true);
float4 _88 = WaveActiveSum(20.0f.xxxx);
int4 _94 = WaveActiveSum(int4(20, 20, 20, 20));
float4 _96 = WaveActiveProduct(20.0f.xxxx);
int4 _98 = WaveActiveProduct(int4(20, 20, 20, 20));
float4 _127 = WavePrefixProduct(_96) * _96;
int4 _129 = WavePrefixProduct(_98) * _98;
}
[numthreads(1, 1, 1)]
void main()
{
gl_SubgroupEqMask = 1u << (WaveGetLaneIndex() - uint4(0, 32, 64, 96));
if (WaveGetLaneIndex() >= 32) gl_SubgroupEqMask.x = 0;
if (WaveGetLaneIndex() >= 64 || WaveGetLaneIndex() < 32) gl_SubgroupEqMask.y = 0;
if (WaveGetLaneIndex() >= 96 || WaveGetLaneIndex() < 64) gl_SubgroupEqMask.z = 0;
if (WaveGetLaneIndex() < 96) gl_SubgroupEqMask.w = 0;
gl_SubgroupGeMask = ~((1u << (WaveGetLaneIndex() - uint4(0, 32, 64, 96))) - 1u);
if (WaveGetLaneIndex() >= 32) gl_SubgroupGeMask.x = 0u;
if (WaveGetLaneIndex() >= 64) gl_SubgroupGeMask.y = 0u;
if (WaveGetLaneIndex() >= 96) gl_SubgroupGeMask.z = 0u;
if (WaveGetLaneIndex() < 32) gl_SubgroupGeMask.y = ~0u;
if (WaveGetLaneIndex() < 64) gl_SubgroupGeMask.z = ~0u;
if (WaveGetLaneIndex() < 96) gl_SubgroupGeMask.w = ~0u;
uint gt_lane_index = WaveGetLaneIndex() + 1;
gl_SubgroupGtMask = ~((1u << (gt_lane_index - uint4(0, 32, 64, 96))) - 1u);
if (gt_lane_index >= 32) gl_SubgroupGtMask.x = 0u;
if (gt_lane_index >= 64) gl_SubgroupGtMask.y = 0u;
if (gt_lane_index >= 96) gl_SubgroupGtMask.z = 0u;
if (gt_lane_index >= 128) gl_SubgroupGtMask.w = 0u;
if (gt_lane_index < 32) gl_SubgroupGtMask.y = ~0u;
if (gt_lane_index < 64) gl_SubgroupGtMask.z = ~0u;
if (gt_lane_index < 96) gl_SubgroupGtMask.w = ~0u;
uint le_lane_index = WaveGetLaneIndex() + 1;
gl_SubgroupLeMask = (1u << (le_lane_index - uint4(0, 32, 64, 96))) - 1u;
if (le_lane_index >= 32) gl_SubgroupLeMask.x = ~0u;
if (le_lane_index >= 64) gl_SubgroupLeMask.y = ~0u;
if (le_lane_index >= 96) gl_SubgroupLeMask.z = ~0u;
if (le_lane_index >= 128) gl_SubgroupLeMask.w = ~0u;
if (le_lane_index < 32) gl_SubgroupLeMask.y = 0u;
if (le_lane_index < 64) gl_SubgroupLeMask.z = 0u;
if (le_lane_index < 96) gl_SubgroupLeMask.w = 0u;
gl_SubgroupLtMask = (1u << (WaveGetLaneIndex() - uint4(0, 32, 64, 96))) - 1u;
if (WaveGetLaneIndex() >= 32) gl_SubgroupLtMask.x = ~0u;
if (WaveGetLaneIndex() >= 64) gl_SubgroupLtMask.y = ~0u;
if (WaveGetLaneIndex() >= 96) gl_SubgroupLtMask.z = ~0u;
if (WaveGetLaneIndex() < 32) gl_SubgroupLtMask.y = 0u;
if (WaveGetLaneIndex() < 64) gl_SubgroupLtMask.z = 0u;
if (WaveGetLaneIndex() < 96) gl_SubgroupLtMask.w = 0u;
comp_main();
}

View File

@ -0,0 +1,34 @@
static const float _17[5] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
static float4 FragColor;
static float4 v0;
struct SPIRV_Cross_Input
{
float4 v0 : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
for (int _46 = 0; _46 < 4; )
{
int _33 = _46 + 1;
FragColor += _17[_33].xxxx;
_46 = _33;
continue;
}
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
v0 = stage_input.v0;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -30,7 +30,7 @@ void frag_main()
lut = _16;
foos = _28;
FragColor = lut[_line].xxxx;
FragColor += (foos[_line].a * (foos[1 - _line].a)).xxxx;
FragColor += (foos[_line].a * foos[1 - _line].a).xxxx;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)

View File

@ -0,0 +1,54 @@
Texture2D<float4> uSampler : register(t0);
SamplerState _uSampler_sampler : register(s0);
static float4 FragColor;
static float4 vInput;
struct SPIRV_Cross_Input
{
float4 vInput : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
FragColor = vInput;
float4 _23 = uSampler.Sample(_uSampler_sampler, vInput.xy);
float4 _26 = ddx(vInput);
float4 _29 = ddy(vInput);
float4 _32 = fwidth(vInput);
float4 _35 = ddx_coarse(vInput);
float4 _38 = ddy_coarse(vInput);
float4 _41 = fwidth(vInput);
float4 _44 = ddx_fine(vInput);
float4 _47 = ddy_fine(vInput);
float4 _50 = fwidth(vInput);
float _56_tmp = uSampler.CalculateLevelOfDetail(_uSampler_sampler, vInput.zw);
if (vInput.y > 10.0f)
{
FragColor += _23;
FragColor += _26;
FragColor += _29;
FragColor += _32;
FragColor += _35;
FragColor += _38;
FragColor += _41;
FragColor += _44;
FragColor += _47;
FragColor += _50;
FragColor += float2(_56_tmp, _56_tmp).xyxy;
}
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vInput = stage_input.vInput;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,45 @@
static min16float4 v4;
static min16float3 v3;
static min16float v1;
static min16float2 v2;
static float o1;
static float2 o2;
static float3 o3;
static float4 o4;
struct SPIRV_Cross_Input
{
min16float v1 : TEXCOORD0;
min16float2 v2 : TEXCOORD1;
min16float3 v3 : TEXCOORD2;
min16float4 v4 : TEXCOORD3;
};
struct SPIRV_Cross_Output
{
float o1 : SV_Target0;
float2 o2 : SV_Target1;
float3 o3 : SV_Target2;
float4 o4 : SV_Target3;
};
void frag_main()
{
min16float4 _324;
min16float4 _387 = modf(v4, _324);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
v4 = stage_input.v4;
v3 = stage_input.v3;
v1 = stage_input.v1;
v2 = stage_input.v2;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.o1 = o1;
stage_output.o2 = o2;
stage_output.o3 = o3;
stage_output.o4 = o4;
return stage_output;
}

View File

@ -2,6 +2,30 @@ Texture1D<uint4> uSampler1DUint : register(t0);
SamplerState _uSampler1DUint_sampler : register(s0);
Texture1D<int4> uSampler1DInt : register(t0);
SamplerState _uSampler1DInt_sampler : register(s0);
Texture1D<float4> uSampler1DFloat : register(t0);
SamplerState _uSampler1DFloat_sampler : register(s0);
Texture2DArray<int4> uSampler2DArray : register(t2);
SamplerState _uSampler2DArray_sampler : register(s2);
Texture3D<float4> uSampler3D : register(t3);
SamplerState _uSampler3D_sampler : register(s3);
TextureCube<float4> uSamplerCube : register(t4);
SamplerState _uSamplerCube_sampler : register(s4);
TextureCubeArray<uint4> uSamplerCubeArray : register(t5);
SamplerState _uSamplerCubeArray_sampler : register(s5);
Buffer<float4> uSamplerBuffer : register(t6);
Texture2DMS<int4> uSamplerMS : register(t7);
SamplerState _uSamplerMS_sampler : register(s7);
Texture2DMSArray<float4> uSamplerMSArray : register(t8);
SamplerState _uSamplerMSArray_sampler : register(s8);
Texture2D<float4> uSampler2D : register(t1);
SamplerState _uSampler2D_sampler : register(s1);
uint SPIRV_Cross_textureSize(Texture1D<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(Level, ret.x, Param);
return ret;
}
uint SPIRV_Cross_textureSize(Texture1D<int4> Tex, uint Level, out uint Param)
{
@ -17,10 +41,87 @@ uint SPIRV_Cross_textureSize(Texture1D<uint4> Tex, uint Level, out uint Param)
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2D<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DArray<int4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture3D<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint SPIRV_Cross_textureSize(Buffer<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(ret.x);
Param = 0u;
return ret;
}
uint2 SPIRV_Cross_textureSize(TextureCube<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(TextureCubeArray<uint4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2DMS<int4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DMSArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(ret.x, ret.y, ret.z, Param);
return ret;
}
void frag_main()
{
uint _17_dummy_parameter;
uint _24_dummy_parameter;
uint _32_dummy_parameter;
uint _42_dummy_parameter;
uint _50_dummy_parameter;
uint _60_dummy_parameter;
uint _68_dummy_parameter;
uint _76_dummy_parameter;
uint _84_dummy_parameter;
uint _92_dummy_parameter;
int _100;
SPIRV_Cross_textureSize(uSampler2D, 0u, _100);
int _104;
SPIRV_Cross_textureSize(uSampler2DArray, 0u, _104);
int _108;
SPIRV_Cross_textureSize(uSampler3D, 0u, _108);
int _112;
SPIRV_Cross_textureSize(uSamplerCube, 0u, _112);
int _116;
SPIRV_Cross_textureSize(uSamplerMS, 0u, _116);
int _120;
SPIRV_Cross_textureSize(uSamplerMSArray, 0u, _120);
}
void main()

View File

@ -1,5 +1,112 @@
Texture1D<float4> uSampler1D : register(t0);
SamplerState _uSampler1D_sampler : register(s0);
Texture2D<float4> uSampler2D : register(t1);
SamplerState _uSampler2D_sampler : register(s1);
Texture2DArray<float4> uSampler2DArray : register(t2);
SamplerState _uSampler2DArray_sampler : register(s2);
Texture3D<float4> uSampler3D : register(t3);
SamplerState _uSampler3D_sampler : register(s3);
TextureCube<float4> uSamplerCube : register(t4);
SamplerState _uSamplerCube_sampler : register(s4);
TextureCubeArray<float4> uSamplerCubeArray : register(t5);
SamplerState _uSamplerCubeArray_sampler : register(s5);
Buffer<float4> uSamplerBuffer : register(t6);
Texture2DMS<float4> uSamplerMS : register(t7);
SamplerState _uSamplerMS_sampler : register(s7);
Texture2DMSArray<float4> uSamplerMSArray : register(t8);
SamplerState _uSamplerMSArray_sampler : register(s8);
uint SPIRV_Cross_textureSize(Texture1D<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(Level, ret.x, Param);
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2D<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture3D<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint SPIRV_Cross_textureSize(Buffer<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(ret.x);
Param = 0u;
return ret;
}
uint2 SPIRV_Cross_textureSize(TextureCube<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(TextureCubeArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2DMS<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DMSArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(ret.x, ret.y, ret.z, Param);
return ret;
}
void frag_main()
{
uint _17_dummy_parameter;
uint _27_dummy_parameter;
uint _37_dummy_parameter;
uint _45_dummy_parameter;
uint _53_dummy_parameter;
uint _61_dummy_parameter;
uint _69_dummy_parameter;
uint _77_dummy_parameter;
uint _85_dummy_parameter;
int _89;
SPIRV_Cross_textureSize(uSampler1D, 0u, _89);
int _93;
SPIRV_Cross_textureSize(uSampler2D, 0u, _93);
int _97;
SPIRV_Cross_textureSize(uSampler2DArray, 0u, _97);
int _101;
SPIRV_Cross_textureSize(uSampler3D, 0u, _101);
int _105;
SPIRV_Cross_textureSize(uSamplerCube, 0u, _105);
int _109;
SPIRV_Cross_textureSize(uSamplerCubeArray, 0u, _109);
int _113;
SPIRV_Cross_textureSize(uSamplerMS, 0u, _113);
int _117;
SPIRV_Cross_textureSize(uSamplerMSArray, 0u, _117);
}
void main()

View File

@ -0,0 +1,57 @@
static const float _16[16] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f };
static const float4 _60[4] = { 0.0f.xxxx, 1.0f.xxxx, 8.0f.xxxx, 5.0f.xxxx };
static const float4 _104[4] = { 20.0f.xxxx, 30.0f.xxxx, 50.0f.xxxx, 60.0f.xxxx };
static float FragColor;
static int index;
struct SPIRV_Cross_Input
{
nointerpolation int index : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
void frag_main()
{
FragColor = _16[index];
if (index < 10)
{
FragColor += _16[index ^ 1];
}
else
{
FragColor += _16[index & 1];
}
bool _63 = index > 30;
if (_63)
{
FragColor += _60[index & 3].y;
}
else
{
FragColor += _60[index & 1].x;
}
float4 foobar[4] = _60;
if (_63)
{
foobar[1].z = 20.0f;
}
int _91 = index & 3;
FragColor += foobar[_91].z;
float4 baz[4] = _60;
baz = _104;
FragColor += baz[_91].z;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
index = stage_input.index;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -1,9 +1,3 @@
struct B
{
float a;
float b;
};
void frag_main()
{
}

View File

@ -4,7 +4,7 @@ cbuffer cbuf : register(b3)
};
cbuffer registers
{
float4 registers_d : packoffset(c0);
float4 registers_a : packoffset(c0);
};
Texture2D<float4> uSampledImage : register(t4);
SamplerState _uSampledImage_sampler : register(s4);
@ -26,7 +26,7 @@ struct SPIRV_Cross_Output
void frag_main()
{
FragColor = (uSampledImage.Sample(_uSampledImage_sampler, vTex) + uTexture.Sample(uSampler, vTex)) + (cbuf_a + registers_d);
FragColor = (uSampledImage.Sample(_uSampledImage_sampler, vTex) + uTexture.Sample(uSampler, vTex)) + (cbuf_a + registers_a);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)

Some files were not shown because too many files have changed in this diff Show More