diff --git a/.travis.yml b/.travis.yml index a67a17b635..5fa1900042 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ matrix: - g++-mingw-w64-i686 - mingw-w64-i686-dev script: - - CROSS_COMPILE=i686-w64-mingw32- ./configure --disable-d3d9 && 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-d3d9 && make HAVE_ZLIB=1 HAVE_BUILTINZLIB=1 HAVE_RPNG=1 + - CROSS_COMPILE=x86_64-w64-mingw32- CFLAGS="-D_WIN32_WINNT=0x0501" ./configure --disable-d3d8 --disable-d3d9 --disable-d3d10 --disable-d3d11 --disable-d3d12 && make HAVE_ZLIB=1 HAVE_BUILTINZLIB=1 HAVE_RPNG=1 - compiler: gcc - compiler: clang addons: @@ -64,3 +64,5 @@ addons: build_command_prepend: "./configure; make clean" build_command: "make" branch_pattern: coverity_scan +notifications: + email: false diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 81c2529184..52c61506df 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,125 +1,127 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "/usr/include", - "/usr/local/include", - "${workspaceRoot}" - ], - "defines": [], - "intelliSenseMode": "clang-x64", - "browse": { - "path": [ - "/usr/include", - "/usr/local/include", - "${workspaceRoot}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - }, - "macFrameworkPath": [ - "/System/Library/Frameworks", - "/Library/Frameworks" - ] - }, - { - "name": "Linux", - "includePath": [ - "/usr/include", - "/usr/local/include", - "${workspaceRoot}" - ], - "defines": [], - "intelliSenseMode": "clang-x64", - "browse": { - "path": [ - "/usr/include", - "/usr/local/include", - "${workspaceRoot}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } - }, - { - "name": "Win32", - "includePath": [ - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um", - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt", - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared", - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt", - "${workspaceRoot}" - ], - "defines": [ - "_DEBUG", - "UNICODE" - ], - "intelliSenseMode": "msvc-x64", - "browse": { - "path": [ - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um", - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt", - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared", - "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt", - "${workspaceRoot}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } - }, - { - "name": "msys2-mingw32", - "includePath": [ - "C:/msys64/mingw32/include", - "C:/msys64/mingw32/i686-w64-mingw32/include", - "${workspaceRoot}/libretro-common/include", - "${workspaceRoot}/include", - "${workspaceRoot}" - ], - "defines": [ - "_DEBUG", - "UNICODE" - ], - "intelliSenseMode": "msvc-x64", - "browse": { - "path": [ - "C:/msys64/mingw32/include", - "C:/msys64/mingw32/i686-w64-mingw32/include", - "${workspaceRoot}/libretro-common/include", - "${workspaceRoot}/include", - "${workspaceRoot}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } - }, - { - "name": "msys2-mingw64", - "includePath": [ - "C:/msys64/mingw64/include", - "C:/msys64/mingw64/x86_64-w64-mingw32/include", - "${workspaceRoot}/libretro-common/include", - "${workspaceRoot}/include", - "${workspaceRoot}" - ], - "defines": [ - "_DEBUG", - "UNICODE" - ], - "intelliSenseMode": "msvc-x64", - "browse": { - "path": [ - "C:/msys64/mingw64/include", - "C:/msys64/mingw64/x86_64-w64-mingw32/include", - "${workspaceRoot}/libretro-common/include", - "${workspaceRoot}/include", - "${workspaceRoot}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } - } - ], - "version": 3 +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "/usr/include", + "/usr/local/include", + "${workspaceRoot}" + ], + "defines": [], + "intelliSenseMode": "clang-x64", + "browse": { + "path": [ + "/usr/include", + "/usr/local/include", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + }, + "macFrameworkPath": [ + "/System/Library/Frameworks", + "/Library/Frameworks" + ] + }, + { + "name": "Linux", + "includePath": [ + "/usr/include", + "/usr/local/include", + "${workspaceRoot}" + ], + "defines": [], + "intelliSenseMode": "clang-x64", + "browse": { + "path": [ + "/usr/include", + "/usr/local/include", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + }, + { + "name": "Win32", + "includePath": [ + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um", + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt", + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared", + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt", + "${workspaceRoot}" + ], + "defines": [ + "_DEBUG", + "UNICODE" + ], + "intelliSenseMode": "msvc-x64", + "browse": { + "path": [ + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um", + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt", + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared", + "C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + }, + "cStandard": "c11", + "cppStandard": "c++17" + }, + { + "name": "msys2-mingw32", + "includePath": [ + "C:/msys64/mingw32/include", + "C:/msys64/mingw32/i686-w64-mingw32/include", + "${workspaceRoot}/libretro-common/include", + "${workspaceRoot}/include", + "${workspaceRoot}" + ], + "defines": [ + "_DEBUG", + "UNICODE" + ], + "intelliSenseMode": "msvc-x64", + "browse": { + "path": [ + "C:/msys64/mingw32/include", + "C:/msys64/mingw32/i686-w64-mingw32/include", + "${workspaceRoot}/libretro-common/include", + "${workspaceRoot}/include", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + }, + { + "name": "msys2-mingw64", + "includePath": [ + "C:/msys64/mingw64/include", + "C:/msys64/mingw64/x86_64-w64-mingw32/include", + "${workspaceRoot}/libretro-common/include", + "${workspaceRoot}/include", + "${workspaceRoot}" + ], + "defines": [ + "_DEBUG", + "UNICODE" + ], + "intelliSenseMode": "msvc-x64", + "browse": { + "path": [ + "C:/msys64/mingw64/include", + "C:/msys64/mingw64/x86_64-w64-mingw32/include", + "${workspaceRoot}/libretro-common/include", + "${workspaceRoot}/include", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + } + ], + "version": 3 } \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 6e1f69631a..e7552247cc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,44 +5,41 @@ "version": "0.2.0", "configurations": [ { - "name": "msys2-mingw64 debug", + "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/retroarch.exe", - "args": [], + "args": ["-v"], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], - "externalConsole": true, + "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } ] }, - { - "name": "msys2-mingw32 debug", + { + "name": "(gdb) Attach", "type": "cppdbg", - "request": "launch", + "request": "attach", "program": "${workspaceFolder}/retroarch.exe", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": true, + "processId": "${command:pickProcess}", "MIMode": "gdb", - "miDebuggerPath": "c:\\msys64\\mingw32\\bin\\gdb.exe", + "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } ] - } + }, + ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index e90ca77e4a..88513c30c2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,4 +14,5 @@ "*.in": "c", "*.rh": "c" }, + "C_Cpp.dimInactiveRegions": false, } \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index cc165987b8..85404e6ac3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,21 +1,58 @@ -# 1.7.2 (future) +# 1.7.3 (future) + +# 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. -- CHEEVOS: Support Atari 2600, Virtual Boy, Neo Geo (Arcade). +- 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. +- 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. -- MENU: Disable XMB shadow icons by default for PowerPC and ARM for performance reasons. +- LOCALIZATION: Update Polish translation. +- 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. @@ -26,8 +63,10 @@ - VULKAN/X11: Fix X11 Vulkan bug from Wayland driver. - VULKAN: Fix multi-line text spacing in menus with Vulkan driver. - WINDOWS XP: Add Cheevos support. -- WINDOWS/MSVC 2005: Add Cheevos support. +- 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 - WIIU: Fix OOB read/write in keyboard driver. # 1.7.1 @@ -68,9 +107,8 @@ - LOCALIZATION: Update Spanish translation. - NETPLAY: Add menu option to select different MITM (relay) server locations. - OSX: Modify HID buttons detection algorithm. -- QB: Added --datarootdir. -- QB: Added --bindir and --mandir and deprecated --with-bin_dir and --with-man_dir. -- QB: Added --docdir. +- QB: Added --datarootdir, --sysconfdir, --bindir, --docdir and --mandir. +- QB: Deprecated --global-config-dir, --with-bin_dir and --with-man_dir. - SHADERS: Allow saving of shader presets based on the parent directory (Saving one for */foo/bar/mario.sfc* would result in *shaders/presets/corename/bar.ext*). We decided it's safer to still isolate the presets to a single core because different cores may treat video output differently. - SHADERS: Don't save the path to the current preset to the main config. This was causing weird behavior, instead it will try to load *currentconfig.ext* and it will save a preset with that name when select *apply shader preset*. The resulting shader will restore properly after restarting and even after core/parent/game specific presets are loaded - SOLARIS: Initial port. @@ -309,7 +347,7 @@ Skipped this one. - MISC: Various frontend optimizations. - NET: Fix bug #4703 (https://github.com/libretro/RetroArch/issues/4703) - OSX/MACOS: Fixes serious memory leak -- THUMBNAILS: Thumbnails show up now in Load Content -> Collection, Information -> Database +- THUMBNAILS: Thumbnails show up now in Load Content -> Collection, Information -> Database - VIDEO: Fix threaded video regression; tickering of menu entries would no longer work. - VITA: Fix 30fps menu (poke into input now instead of reading the entire input buffer which apparently is slow) - VITA: Fix frame throttle diff --git a/Makefile b/Makefile index a9e72cb4b7..e93d97ea95 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ endif include Makefile.common ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang"),1) - DEFINES += -Wno-invalid-source-encoding + DEFINES += -Wno-invalid-source-encoding -Wno-incompatible-ms-struct endif ifeq ($(shell $(CC) -v 2>&1 | grep -c "tcc"),1) @@ -133,7 +133,7 @@ RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ)) ifneq ($(X86),) CFLAGS += -m32 - CXXLAGS += -m32 + CXXFLAGS += -m32 LDFLAGS += -m32 endif diff --git a/Makefile.common b/Makefile.common index a49dfc22dd..d17d8a3562 100644 --- a/Makefile.common +++ b/Makefile.common @@ -147,6 +147,8 @@ ifneq ($(GIT_VERSION),) endif # General object files +DEFINES += -DHAVE_DR_MP3 +CFLAGS += -DHAVE_DR_MP3 OBJ += frontend/frontend.o \ frontend/frontend_driver.o \ @@ -198,7 +200,9 @@ 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 \ @@ -259,7 +263,18 @@ OBJ += frontend/frontend.o \ record/drivers/record_null.o \ $(LIBRETRO_COMM_DIR)/features/features_cpu.o \ performance_counters.o \ - verbosity.o + verbosity.o \ + +ifeq ($(HAVE_RUNAHEAD), 1) +DEFINES += -DHAVE_RUNAHEAD +OBJ += runahead/copy_load_info.o \ + runahead/dirty_input.o \ + runahead/mem_util.o \ + runahead/mylist.o \ + runahead/run_ahead.o \ + runahead/secondary_core.o +endif + ifeq ($(HAVE_CC_RESAMPLER), 1) @@ -1023,9 +1038,6 @@ ifeq ($(HAVE_PLAIN_DRM), 1) 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 \ @@ -1255,7 +1267,9 @@ 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 @@ -1425,6 +1439,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\"" @@ -1451,7 +1467,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) @@ -1462,7 +1479,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 \ @@ -1481,19 +1498,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) @@ -1595,10 +1620,6 @@ ifeq ($(HAVE_NETWORKING), 1) $(LIBRETRO_COMM_DIR)/utils/md5.o endif - ifeq ($(HAVE_KEYMAPPER), 1) - OBJ += input/input_mapper.o - endif - ifeq ($(HAVE_NETWORKGAMEPAD), 1) OBJ += input/input_remote.o \ cores/libretro-net-retropad/net_retropad_core.o diff --git a/Makefile.griffin b/Makefile.griffin index 0f890d36c3..1e8b848e82 100644 --- a/Makefile.griffin +++ b/Makefile.griffin @@ -178,6 +178,7 @@ else ifeq ($(libogc_platform), 1) CFLAGS += -DGEKKO -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int + HAVE_RUNAHEAD := 1 HAVE_FILTERS_BUILTIN := 1 HAVE_THREADS := 1 HAVE_RPNG := 1 @@ -840,6 +841,10 @@ ifeq ($(HAVE_IMAGEVIEWER), 1) CFLAGS += -DHAVE_IMAGEVIEWER endif +ifeq ($(HAVE_RUNAHEAD), 1) + CFLAGS += -DHAVE_RUNAHEAD +endif + ifeq ($(HAVE_7ZIP), 1) CFLAGS += -DHAVE_7ZIP endif diff --git a/Makefile.msvc b/Makefile.msvc index 77d02fc9fa..48405fd5c2 100644 --- a/Makefile.msvc +++ b/Makefile.msvc @@ -53,7 +53,6 @@ HAVE_NETWORK_CMD := 1 HAVE_OVERLAY := 1 HAVE_LANGEXTRA := 1 HAVE_CHEEVOS := 1 -HAVE_KEYMAPPER := 1 HAVE_SHADERPIPELINE := 1 HAVE_IMAGEVIEWER := 1 diff --git a/Makefile.ps3 b/Makefile.ps3 index e4c96fca7a..88f9dfe787 100644 --- a/Makefile.ps3 +++ b/Makefile.ps3 @@ -4,7 +4,7 @@ include version.all #set to GCC for debug builds for use with debugger CELL_BUILD_TOOLS = SNC CELL_GPU_TYPE = RSX -CELL_PSGL_VERSION = ultra-opt +CELL_PSGL_VERSION = opt ASSETS_DIR := media/assets @@ -63,7 +63,7 @@ endif PPU_SRCS = griffin/griffin.c -DEFINES += -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_LIBRETRODB -DHAVE_MATERIALUI -DHAVE_SHADERPIPELINE -DRARCH_INTERNAL -DMSB_FIRST -DHAVE_OVERLAY -DHAVE_CC_RESAMPLER -DHAVE_STB_VORBIS -DHAVE_STB_FONT +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 ifeq ($(DEX_BUILD), 1) DEFINES += -DDEX_BUILD @@ -96,7 +96,7 @@ ifeq ($(CELL_BUILD_TOOLS), SNC) PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe PPU_CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe -else ifneq($(system_platform), win) +else ifneq ($(system_platform), win) PPU_CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe PPU_CXXLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe @@ -119,7 +119,7 @@ DEFINES += -DHAVE_THREADS -DRARCH_CONSOLE -DHAVE_OPENGL -DHAVE_HEADSET -DHAVE_LA ifeq ($(DEBUG), 1) PPU_OPTIMIZE_LV := -O0 -g else - PPU_OPTIMIZE_LV := -O3 -g + PPU_OPTIMIZE_LV := -O2 -g endif ifeq ($(HAVE_LOGGER), 1) diff --git a/Makefile.ps3.cobra b/Makefile.ps3.cobra index ce6f755c0a..3a270b2dd6 100644 --- a/Makefile.ps3.cobra +++ b/Makefile.ps3.cobra @@ -2,7 +2,7 @@ include version.all #which compiler to build with - GCC or SNC #set to GCC for debug builds for use with debugger -CELL_BUILD_TOOLS = SNC +CELL_BUILD_TOOLS = GCC CELL_GPU_TYPE = RSX CELL_PSGL_VERSION = ultra-opt diff --git a/Makefile.ps3.salamander b/Makefile.ps3.salamander index 49c8c9a719..c769ff105c 100644 --- a/Makefile.ps3.salamander +++ b/Makefile.ps3.salamander @@ -1,4 +1,4 @@ -CELL_BUILD_TOOLS = SNC +CELL_BUILD_TOOLS = GCC CELL_SDK ?= /usr/local/cell HAVE_LOGGER = 0 CELL_MK_DIR ?= $(CELL_SDK)/samples/mk diff --git a/Makefile.switch b/Makefile.switch index a477749409..d81bd05b3c 100644 --- a/Makefile.switch +++ b/Makefile.switch @@ -12,6 +12,7 @@ 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 else HAVE_CC_RESAMPLER = 1 HAVE_MENU_COMMON = 1 @@ -29,6 +30,7 @@ else HAVE_STATIC_VIDEO_FILTERS = 1 HAVE_STATIC_AUDIO_FILTERS = 1 HAVE_MENU = 1 + HAVE_RUNAHEAD = 1 include Makefile.common BLACKLIST := diff --git a/Makefile.vita b/Makefile.vita index 25d79a673e..5645c9cabd 100644 --- a/Makefile.vita +++ b/Makefile.vita @@ -16,7 +16,7 @@ DEFINES := ifeq ($(GRIFFIN_BUILD), 1) OBJ += griffin/griffin.o DEFINES += -DHAVE_GRIFFIN=1 - DEFINES += -DHAVE_NEON -DHAVE_MENU -DHAVE_XMB -DHAVE_MATERIALUI -DHAVE_LIBRETRODB + DEFINES += -DHAVE_NEON -DHAVE_MENU -DHAVE_XMB -DHAVE_MATERIALUI -DHAVE_LIBRETRODB DEFINES -DHAVE_KEYMAPPER DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DWANT_ZLIB -DHAVE_CC_RESAMPLER ifeq ($(DEBUG), 1) DEFINES += -DHAVE_NETLOGGER diff --git a/Makefile.wiiu b/Makefile.wiiu index 4b5eeafc02..59b35b388b 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -6,7 +6,8 @@ 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 ?= @@ -32,6 +33,7 @@ OBJ += wiiu/input/wpad_driver.o OBJ += wiiu/input/kpad_driver.o OBJ += wiiu/input/pad_functions.o OBJ += wiiu/system/memory.o +OBJ += wiiu/system/atomic.o OBJ += wiiu/system/exception_handler.o OBJ += wiiu/fs/sd_fat_devoptab.o OBJ += wiiu/fs/fs_utils.o @@ -48,15 +50,11 @@ ifeq ($(WIIU_HID),1) OBJ += wiiu/input/hidpad_driver.o OBJ += wiiu/input/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) @@ -88,6 +86,10 @@ else DEFINES += -DHAVE_SLANG DEFINES += -DHAVE_SHADERPIPELINE +ifeq ($(HAVE_RUNAHEAD),1) + DEFINES += -DHAVE_RUNAHEAD +endif + OBJ += wiiu/system/missing_libc_functions.o OBJ += wiiu/shader_utils.o OBJ += gfx/drivers/gx2_shaders/tex.o @@ -120,7 +122,6 @@ else HAVE_ZLIB = 1 HAVE_7ZIP = 1 HAVE_BUILTINZLIB = 1 - HAVE_KEYMAPPER = 1 HAVE_LIBRETRODB = 1 HAVE_ZARCH = 0 HAVE_MATERIALUI = 1 diff --git a/audio/audio_driver.c b/audio/audio_driver.c index fb06d65ffb..3209354b19 100644 --- a/audio/audio_driver.c +++ b/audio/audio_driver.c @@ -213,7 +213,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 @@ -524,7 +524,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"); @@ -576,20 +576,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 +603,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 +659,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) { @@ -976,6 +973,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); @@ -1074,6 +1077,16 @@ 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; diff --git a/audio/drivers/opensl.c b/audio/drivers/opensl.c index 3e4de301cc..d1ae7446a5 100644 --- a/audio/drivers/opensl.c +++ b/audio/drivers/opensl.c @@ -203,9 +203,6 @@ error: static bool sl_stop(void *data) { sl_t *sl = (sl_t*)data; - - opensl_callback((SLAndroidSimpleBufferQueueItf) 0, data); - sl->is_paused = (SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_STOPPED) == SL_RESULT_SUCCESS) ? true : false; diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index 57f027641f..c4da205828 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -107,6 +107,8 @@ #define CHEEVOS_JSON_KEY_LEADERBOARDS 0xf1247d2dU #define CHEEVOS_JSON_KEY_MEM 0x0b8807e4U #define CHEEVOS_JSON_KEY_FORMAT 0xb341208eU +#define CHEEVOS_JSON_KEY_SUCCESS 0x110461deU +#define CHEEVOS_JSON_KEY_ERROR 0x0d2011cfU typedef struct { @@ -299,6 +301,15 @@ int cheats_were_enabled = 0; Supporting functions. *****************************************************************************/ +#ifndef CHEEVOS_VERBOSE + +void cheevos_log(const char *fmt, ...) +{ + (void)fmt; +} + +#endif + static unsigned size_in_megabytes(unsigned val) { return (val * 1024 * 1024); @@ -308,7 +319,7 @@ static unsigned size_in_megabytes(unsigned val) static void cheevos_log_url(const char* format, const char* url) { #ifdef CHEEVOS_LOG_PASSWORD - RARCH_LOG(format, url); + CHEEVOS_LOG(format, url); #else char copy[256]; char* aux = NULL; @@ -359,340 +370,11 @@ static void cheevos_log_url(const char* format, const char* url) *aux = 0; } - RARCH_LOG(format, copy); + CHEEVOS_LOG(format, copy); #endif } #endif -#ifdef CHEEVOS_VERBOSE -static void cheevos_add_char(char** aux, size_t* left, char k) -{ - if (*left >= 1) - { - **aux = k; - (*aux)++; - (*left)--; - } -} - -static void cheevos_add_string(char** aux, size_t* left, const char* s) -{ - size_t len = strlen(s); - - if (*left >= len) - { - strcpy(*aux, s); - *aux += len; - *left -= len; - } -} - -static void cheevos_add_hex(char** aux, size_t* left, unsigned v) -{ - char buffer[32]; - - snprintf(buffer, sizeof(buffer), "%06x", v); - buffer[sizeof(buffer) - 1] = 0; - - cheevos_add_string(aux, left, buffer); -} - -static void cheevos_add_uint(char** aux, size_t* left, unsigned v) -{ - char buffer[32]; - - snprintf(buffer, sizeof(buffer), "%u", v); - buffer[sizeof(buffer) - 1] = 0; - - cheevos_add_string(aux, left, buffer); -} - -static void cheevos_add_int(char** aux, size_t* left, int v) -{ - char buffer[32]; - - snprintf(buffer, sizeof(buffer), "%d", v); - buffer[sizeof(buffer) - 1] = 0; - - cheevos_add_string(aux, left, buffer); -} - -static void cheevos_log_var(const cheevos_var_t* var) -{ - if (!var) - return; - - RARCH_LOG("[CHEEVOS]: size: %s\n", - var->size == CHEEVOS_VAR_SIZE_BIT_0 ? "bit 0" : - var->size == CHEEVOS_VAR_SIZE_BIT_1 ? "bit 1" : - var->size == CHEEVOS_VAR_SIZE_BIT_2 ? "bit 2" : - var->size == CHEEVOS_VAR_SIZE_BIT_3 ? "bit 3" : - var->size == CHEEVOS_VAR_SIZE_BIT_4 ? "bit 4" : - var->size == CHEEVOS_VAR_SIZE_BIT_5 ? "bit 5" : - var->size == CHEEVOS_VAR_SIZE_BIT_6 ? "bit 6" : - var->size == CHEEVOS_VAR_SIZE_BIT_7 ? "bit 7" : - var->size == CHEEVOS_VAR_SIZE_NIBBLE_LOWER ? "low nibble" : - var->size == CHEEVOS_VAR_SIZE_NIBBLE_UPPER ? "high nibble" : - var->size == CHEEVOS_VAR_SIZE_EIGHT_BITS ? "byte" : - var->size == CHEEVOS_VAR_SIZE_SIXTEEN_BITS ? "word" : - var->size == CHEEVOS_VAR_SIZE_THIRTYTWO_BITS ? "dword" : - "?" - ); - RARCH_LOG("[CHEEVOS]: type: %s\n", - var->type == CHEEVOS_VAR_TYPE_ADDRESS ? "address" : - var->type == CHEEVOS_VAR_TYPE_VALUE_COMP ? "value" : - var->type == CHEEVOS_VAR_TYPE_DELTA_MEM ? "delta" : - var->type == CHEEVOS_VAR_TYPE_DYNAMIC_VAR ? "dynamic" : - "?" - ); - RARCH_LOG("[CHEEVOS]: value: %u\n", var->value); -} - -static void cheevos_log_cond(const cheevos_cond_t* cond) -{ - if (!cond) - return; - - RARCH_LOG("[CHEEVOS]: condition %p\n", cond); - RARCH_LOG("[CHEEVOS]: type: %s\n", - cond->type == CHEEVOS_COND_TYPE_STANDARD ? "standard" : - cond->type == CHEEVOS_COND_TYPE_PAUSE_IF ? "pause" : - cond->type == CHEEVOS_COND_TYPE_RESET_IF ? "reset" : - cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE ? "add source" : - cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE ? "sub source" : - cond->type == CHEEVOS_COND_TYPE_ADD_HITS ? "add hits" : - "?" - ); - RARCH_LOG("[CHEEVOS]: req_hits: %u\n", cond->req_hits); - RARCH_LOG("[CHEEVOS]: source:\n"); - cheevos_log_var(&cond->source); - RARCH_LOG("[CHEEVOS]: op: %s\n", - cond->op == CHEEVOS_COND_OP_EQUALS ? "==" : - cond->op == CHEEVOS_COND_OP_LESS_THAN ? "<" : - cond->op == CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL ? "<=" : - cond->op == CHEEVOS_COND_OP_GREATER_THAN ? ">" : - cond->op == CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL ? ">=" : - cond->op == CHEEVOS_COND_OP_NOT_EQUAL_TO ? "!=" : - "?" - ); - RARCH_LOG("[CHEEVOS]: target:\n"); - cheevos_log_var(&cond->target); -} - -static void cheevos_log_cheevo(const cheevo_t* cheevo, - const cheevos_field_t* memaddr_ud) -{ - if (!cheevo || !memaddr_ud) - return; - - RARCH_LOG("[CHEEVOS]: cheevo %p\n", cheevo); - RARCH_LOG("[CHEEVOS]: id: %u\n", cheevo->id); - RARCH_LOG("[CHEEVOS]: title: %s\n", cheevo->title); - RARCH_LOG("[CHEEVOS]: desc: %s\n", cheevo->description); - RARCH_LOG("[CHEEVOS]: author: %s\n", cheevo->author); - RARCH_LOG("[CHEEVOS]: badge: %s\n", cheevo->badge); - RARCH_LOG("[CHEEVOS]: points: %u\n", cheevo->points); - RARCH_LOG("[CHEEVOS]: sets: TBD\n"); - RARCH_LOG("[CHEEVOS]: memaddr: %.*s\n", - (int)memaddr_ud->length, memaddr_ud->string); -} - -static void cheevos_add_var_size(char** aux, size_t* left, - const cheevos_var_t* var) -{ - if (!var) - return; - - switch( var->size ) - { - case CHEEVOS_VAR_SIZE_BIT_0: - cheevos_add_char(aux, left, 'M'); - break; - case CHEEVOS_VAR_SIZE_BIT_1: - cheevos_add_char(aux, left, 'N'); - break; - case CHEEVOS_VAR_SIZE_BIT_2: - cheevos_add_char(aux, left, 'O'); - break; - case CHEEVOS_VAR_SIZE_BIT_3: - cheevos_add_char(aux, left, 'P'); - break; - case CHEEVOS_VAR_SIZE_BIT_4: - cheevos_add_char(aux, left, 'Q'); - break; - case CHEEVOS_VAR_SIZE_BIT_5: - cheevos_add_char(aux, left, 'R'); - break; - case CHEEVOS_VAR_SIZE_BIT_6: - cheevos_add_char(aux, left, 'S'); - break; - case CHEEVOS_VAR_SIZE_BIT_7: - cheevos_add_char(aux, left, 'T'); - break; - case CHEEVOS_VAR_SIZE_NIBBLE_LOWER: - cheevos_add_char(aux, left, 'L'); - break; - case CHEEVOS_VAR_SIZE_NIBBLE_UPPER: - cheevos_add_char(aux, left, 'U'); - break; - case CHEEVOS_VAR_SIZE_EIGHT_BITS: - cheevos_add_char(aux, left, 'H'); - break; - case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS: - cheevos_add_char(aux, left, 'X'); - break; - case CHEEVOS_VAR_SIZE_SIXTEEN_BITS: - default: - cheevos_add_char(aux, left, ' '); - break; - } -} - -static void cheevos_add_var(const cheevos_var_t* var, char** memaddr, - size_t *left) -{ - if (!var) - return; - - if ( var->type == CHEEVOS_VAR_TYPE_ADDRESS - || var->type == CHEEVOS_VAR_TYPE_DELTA_MEM) - { - if (var->type == CHEEVOS_VAR_TYPE_DELTA_MEM) - cheevos_add_char(memaddr, left, 'd'); - else if (var->is_bcd) - cheevos_add_char(memaddr, left, 'b'); - - cheevos_add_string(memaddr, left, "0x"); - cheevos_add_var_size(memaddr, left, var); - cheevos_add_hex(memaddr, left, var->value); - } - else if (var->type == CHEEVOS_VAR_TYPE_VALUE_COMP) - { - cheevos_add_uint(memaddr, left, var->value); - } -} - -static void cheevos_build_memaddr(const cheevos_condition_t* condition, - char* memaddr, size_t left) -{ - size_t i, j; - const cheevos_cond_t* cond; - const cheevos_condset_t *condset; - char *aux = memaddr; - - left--; /* reserve one char for the null terminator */ - - for (i = 0, condset = condition->condsets; - i < condition->count; i++, condset++) - { - if (i != 0) - cheevos_add_char(&aux, &left, 'S'); - - for (j = 0, cond = condset->conds; - j < condset->count; j++, cond++) - { - if (j != 0) - cheevos_add_char(&aux, &left, '_'); - - if (cond->type == CHEEVOS_COND_TYPE_RESET_IF) - cheevos_add_string(&aux, &left, "R:"); - else if (cond->type == CHEEVOS_COND_TYPE_PAUSE_IF) - cheevos_add_string(&aux, &left, "P:"); - else if (cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE) - cheevos_add_string(&aux, &left, "A:"); - else if (cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE) - cheevos_add_string(&aux, &left, "B:"); - else if (cond->type == CHEEVOS_COND_TYPE_ADD_HITS) - cheevos_add_string(&aux, &left, "C:"); - - cheevos_add_var(&cond->source, &aux, &left); - - switch (cond->op) - { - case CHEEVOS_COND_OP_EQUALS: - cheevos_add_char(&aux, &left, '='); - break; - case CHEEVOS_COND_OP_GREATER_THAN: - cheevos_add_char(&aux, &left, '>'); - break; - case CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL: - cheevos_add_string(&aux, &left, ">="); - break; - case CHEEVOS_COND_OP_LESS_THAN: - cheevos_add_char(&aux, &left, '<'); - break; - case CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL: - cheevos_add_string(&aux, &left, "<="); - break; - case CHEEVOS_COND_OP_NOT_EQUAL_TO: - cheevos_add_string(&aux, &left, "!="); - break; - } - - cheevos_add_var(&cond->target, &aux, &left); - - if (cond->req_hits > 0) - { - cheevos_add_char(&aux, &left, '.'); - cheevos_add_uint(&aux, &left, cond->req_hits); - cheevos_add_char(&aux, &left, '.'); - } - } - } - - *aux = 0; -} - -static void cheevos_post_log_cheevo(const cheevo_t* cheevo) -{ - char memaddr[256]; - if (!cheevo) - return; - cheevos_build_memaddr(&cheevo->condition, memaddr, sizeof(memaddr)); - RARCH_LOG("[CHEEVOS]: memaddr (computed): %s\n", memaddr); -} - -static void cheevos_log_lboard(const cheevos_leaderboard_t* lb) -{ - unsigned i; - char mem[256]; - char* aux = NULL; - size_t left = 0; - - if (!lb) - return; - - RARCH_LOG("[CHEEVOS]: leaderboard %p\n", lb); - RARCH_LOG("[CHEEVOS]: id: %u\n", lb->id); - RARCH_LOG("[CHEEVOS]: title: %s\n", lb->title); - RARCH_LOG("[CHEEVOS]: desc: %s\n", lb->description); - - cheevos_build_memaddr(&lb->start, mem, sizeof(mem)); - RARCH_LOG("[CHEEVOS]: start: %s\n", mem); - - cheevos_build_memaddr(&lb->cancel, mem, sizeof(mem)); - RARCH_LOG("[CHEEVOS]: cancel: %s\n", mem); - - cheevos_build_memaddr(&lb->submit, mem, sizeof(mem)); - RARCH_LOG("[CHEEVOS]: submit: %s\n", mem); - - left = sizeof(mem); - aux = mem; - - for (i = 0; i < lb->value.count; i++) - { - if (i != 0) - cheevos_add_char(&aux, &left, '_'); - - cheevos_add_var(&lb->value.terms[i].var, &aux, &left); - cheevos_add_char(&aux, &left, '*'); - cheevos_add_int(&aux, &left, lb->value.terms[i].multiplier); - } - - RARCH_LOG("[CHEEVOS]: value: %s\n", mem); -} -#endif - static uint32_t cheevos_djb2(const char* str, size_t length) { const unsigned char *aux = (const unsigned char*)str; @@ -962,10 +644,8 @@ static int cheevos_parse_condition( cheevos_cond_count_in_set(memaddr, set); condset->conds = NULL; -#ifdef CHEEVOS_VERBOSE - RARCH_LOG("[CHEEVOS]: set %p (index=%u)\n", condset, set); - RARCH_LOG("[CHEEVOS]: conds: %u\n", condset->count); -#endif + CHEEVOS_LOG("[CHEEVOS]: set %p (index=%u)\n", condset, set); + CHEEVOS_LOG("[CHEEVOS]: conds: %u\n", condset->count); if (condset->count) { @@ -1216,17 +896,9 @@ static int cheevos_new_cheevo(cheevos_readud_t *ud) !cheevo->badge) goto error; -#ifdef CHEEVOS_VERBOSE - cheevos_log_cheevo(cheevo, &ud->memaddr); -#endif - if (cheevos_parse_condition(&cheevo->condition, ud->memaddr.string)) goto error; -#ifdef CHEEVOS_VERBOSE - cheevos_post_log_cheevo(cheevo); -#endif - return 0; error: @@ -1334,12 +1006,10 @@ static int cheevos_new_lboard(cheevos_readud_t *ud) if (!ldb || !ud) return -1; + lboard = ldb + ud->lboard_count++; - if (!lboard) - return -1; - - lboard->id = strtol(ud->id.string, NULL, 10); + lboard->id = (unsigned)strtol(ud->id.string, NULL, 10); lboard->format = cheevos_parse_format(&ud->format); lboard->title = cheevos_dupstr(&ud->title); lboard->description = cheevos_dupstr(&ud->desc); @@ -1350,10 +1020,6 @@ static int cheevos_new_lboard(cheevos_readud_t *ud) if (cheevos_parse_mem(lboard, ud->memaddr.string)) goto error; -#ifdef CHEEVOS_VERBOSE - cheevos_log_lboard(lboard); -#endif - return 0; error: @@ -1896,14 +1562,14 @@ static void cheevos_unlocked(void *task_data, void *user_data, if (!error) { - RARCH_LOG("[CHEEVOS]: awarded achievement %u.\n", cheevo->id); + CHEEVOS_LOG("[CHEEVOS]: awarded achievement %u.\n", cheevo->id); } else { char url[256]; url[0] = '\0'; - RARCH_ERR("[CHEEVOS]: error awarding achievement %u, retrying...\n", cheevo->id); + CHEEVOS_ERR("[CHEEVOS]: error awarding achievement %u, retrying...\n", cheevo->id); cheevos_make_unlock_url(cheevo, url, sizeof(url)); task_push_http_transfer(url, true, NULL, cheevos_unlocked, cheevo); @@ -1951,7 +1617,7 @@ static void cheevos_test_cheevo_set(const cheevoset_t *set) if (mode == CHEEVOS_ACTIVE_HARDCORE) cheevo->active &= ~CHEEVOS_ACTIVE_SOFTCORE; - RARCH_LOG("[CHEEVOS]: awarding cheevo %u: %s (%s).\n", + CHEEVOS_LOG("[CHEEVOS]: awarding cheevo %u: %s (%s).\n", cheevo->id, cheevo->title, cheevo->description); snprintf(msg, sizeof(msg), "Achievement Unlocked: %s", @@ -1976,9 +1642,9 @@ static void cheevos_test_cheevo_set(const cheevoset_t *set) if (take_screenshot(shotname, true, video_driver_cached_frame_has_valid_framebuffer())) - RARCH_LOG("[CHEEVOS]: got a screenshot for cheevo %u\n", cheevo->id); + CHEEVOS_LOG("[CHEEVOS]: got a screenshot for cheevo %u\n", cheevo->id); else - RARCH_LOG("[CHEEVOS]: failed to get screenshot for cheevo %u\n", cheevo->id); + CHEEVOS_LOG("[CHEEVOS]: failed to get screenshot for cheevo %u\n", cheevo->id); } } @@ -2044,7 +1710,7 @@ static int cheevos_expr_value(cheevos_expr_t* expr) if (expr->compare_count >= ARRAY_SIZE(values)) { - RARCH_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", expr->compare_count); + CHEEVOS_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", expr->compare_count); return 0; } @@ -2054,7 +1720,7 @@ static int cheevos_expr_value(cheevos_expr_t* expr) { if (current_value >= ARRAY_SIZE(values)) { - RARCH_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", current_value); + CHEEVOS_ERR("[CHEEVOS]: too many values in the leaderboard expression: %u\n", current_value); return 0; } @@ -2128,11 +1794,11 @@ static void cheevos_lboard_submit(void *task_data, void *user_data, if (!error) { - RARCH_ERR("[CHEEVOS]: error submitting leaderboard %u\n", lboard->id); + CHEEVOS_ERR("[CHEEVOS]: error submitting leaderboard %u\n", lboard->id); return; } - RARCH_LOG("[CHEEVOS]: submitted leaderboard %u.\n", lboard->id); + CHEEVOS_LOG("[CHEEVOS]: submitted leaderboard %u.\n", lboard->id); } static void cheevos_test_leaderboards(void) @@ -2151,10 +1817,8 @@ static void cheevos_test_leaderboards(void) if (value != lboard->last_value) { -#ifdef CHEEVOS_VERBOSE - RARCH_LOG("[CHEEVOS]: value lboard %s %u\n", + CHEEVOS_LOG("[CHEEVOS]: value lboard %s %u\n", lboard->title, value); -#endif lboard->last_value = value; } @@ -2165,7 +1829,7 @@ static void cheevos_test_leaderboards(void) /* failsafe for improper LBs */ if (value == 0) { - RARCH_LOG("[CHEEVOS]: error: lboard %s tried to submit 0\n", + CHEEVOS_LOG("[CHEEVOS]: error: lboard %s tried to submit 0\n", lboard->title); runloop_msg_queue_push("Leaderboard attempt cancelled!", 0, 2 * 60, false); @@ -2179,7 +1843,7 @@ static void cheevos_test_leaderboards(void) cheevos_make_lboard_url(lboard, url, sizeof(url)); task_push_http_transfer(url, true, NULL, cheevos_lboard_submit, lboard); - RARCH_LOG("[CHEEVOS]: submit lboard %s\n", lboard->title); + CHEEVOS_LOG("[CHEEVOS]: submit lboard %s\n", lboard->title); cheevos_format_value(value, lboard->format, formatted_value, sizeof(formatted_value)); @@ -2192,7 +1856,7 @@ static void cheevos_test_leaderboards(void) if (cheevos_test_lboard_condition(&lboard->cancel)) { - RARCH_LOG("[CHEEVOS]: cancel lboard %s\n", lboard->title); + CHEEVOS_LOG("[CHEEVOS]: cancel lboard %s\n", lboard->title); lboard->active = 0; runloop_msg_queue_push("Leaderboard attempt cancelled!", 0, 2 * 60, false); @@ -2204,7 +1868,7 @@ static void cheevos_test_leaderboards(void) { char msg[256]; - RARCH_LOG("[CHEEVOS]: start lboard %s\n", lboard->title); + CHEEVOS_LOG("[CHEEVOS]: start lboard %s\n", lboard->title); lboard->active = 1; lboard->last_value = -1; @@ -2317,10 +1981,10 @@ static int cheevos_deactivate__json_number(void *userdata, } if (found) - RARCH_LOG("[CHEEVOS]: deactivated unlocked cheevo %u (%s).\n", + CHEEVOS_LOG("[CHEEVOS]: deactivated unlocked cheevo %u (%s).\n", cheevo->id, cheevo->title); else - RARCH_ERR("[CHEEVOS]: unknown cheevo to deactivate: %u.\n", id); + CHEEVOS_ERR("[CHEEVOS]: unknown cheevo to deactivate: %u.\n", id); } return 0; @@ -2516,9 +2180,7 @@ bool cheevos_unload(void) if (running) { -#ifdef CHEEVOS_VERBOSE - RARCH_LOG("[CHEEVOS]: Asked the load thread to terminate\n"); -#endif + CHEEVOS_LOG("[CHEEVOS]: Asked the load thread to terminate\n"); task_queue_cancel_task(cheevos_locals.task); #ifdef HAVE_THREADS @@ -2568,7 +2230,7 @@ bool cheevos_toggle_hardcore_mode(void) if (settings->bools.rewind_enable) command_event(CMD_EVENT_REWIND_DEINIT, NULL); - RARCH_LOG("%s\n", msg); + CHEEVOS_LOG("%s\n", msg); runloop_msg_queue_push(msg, 0, 3 * 60, true); } else @@ -2612,7 +2274,7 @@ static void cheevos_patch_addresses(cheevoset_t* set) cheevos_var_patch_addr(&cond->source, cheevos_locals.console_id); #ifdef CHEEVOS_DUMP_ADDRS - RARCH_LOG("[CHEEVOS]: s-var %03d:%08X\n", + CHEEVOS_LOG("[CHEEVOS]: s-var %03d:%08X\n", cond->source.bank_id + 1, cond->source.value); #endif break; @@ -2628,7 +2290,7 @@ static void cheevos_patch_addresses(cheevoset_t* set) cheevos_var_patch_addr(&cond->target, cheevos_locals.console_id); #ifdef CHEEVOS_DUMP_ADDRS - RARCH_LOG("[CHEEVOS]: t-var %03d:%08X\n", + CHEEVOS_LOG("[CHEEVOS]: t-var %03d:%08X\n", cond->target.bank_id + 1, cond->target.value); #endif break; @@ -2665,7 +2327,7 @@ static void cheevos_patch_lb_conditions(cheevos_condition_t* condition) cheevos_var_patch_addr(&cond->source, cheevos_locals.console_id); #ifdef CHEEVOS_DUMP_ADDRS - RARCH_LOG("[CHEEVOS]: s-var %03d:%08X\n", + CHEEVOS_LOG("[CHEEVOS]: s-var %03d:%08X\n", cond->source.bank_id + 1, cond->source.value); #endif break; @@ -2679,7 +2341,7 @@ static void cheevos_patch_lb_conditions(cheevos_condition_t* condition) cheevos_var_patch_addr(&cond->target, cheevos_locals.console_id); #ifdef CHEEVOS_DUMP_ADDRS - RARCH_LOG("[CHEEVOS]: t-var %03d:%08X\n", + CHEEVOS_LOG("[CHEEVOS]: t-var %03d:%08X\n", cond->target.bank_id + 1, cond->target.value); #endif break; @@ -2708,7 +2370,7 @@ static void cheevos_patch_lb_expressions(cheevos_expr_t* expression) case CHEEVOS_VAR_TYPE_DELTA_MEM: cheevos_var_patch_addr(&term->var, cheevos_locals.console_id); #ifdef CHEEVOS_DUMP_ADDRS - RARCH_LOG("[CHEEVOS]: s-var %03d:%08X\n", + CHEEVOS_LOG("[CHEEVOS]: s-var %03d:%08X\n", term->var.bank_id + 1, term->var.value); #endif break; @@ -2927,16 +2589,16 @@ static int cheevos_iterate(coro_t *coro) cheevos_locals.meminfo[3].id = RETRO_MEMORY_RTC; core_get_memory(&cheevos_locals.meminfo[3]); - RARCH_LOG("[CHEEVOS]: system RAM: %p %u\n", + CHEEVOS_LOG("[CHEEVOS]: system RAM: %p %u\n", cheevos_locals.meminfo[0].data, cheevos_locals.meminfo[0].size); - RARCH_LOG("[CHEEVOS]: save RAM: %p %u\n", + CHEEVOS_LOG("[CHEEVOS]: save RAM: %p %u\n", cheevos_locals.meminfo[1].data, cheevos_locals.meminfo[1].size); - RARCH_LOG("[CHEEVOS]: video RAM: %p %u\n", + CHEEVOS_LOG("[CHEEVOS]: video RAM: %p %u\n", cheevos_locals.meminfo[2].data, cheevos_locals.meminfo[2].size); - RARCH_LOG("[CHEEVOS]: RTC: %p %u\n", + CHEEVOS_LOG("[CHEEVOS]: RTC: %p %u\n", cheevos_locals.meminfo[3].data, cheevos_locals.meminfo[3].size); @@ -3034,7 +2696,7 @@ static int cheevos_iterate(coro_t *coro) { if (finders[coro->i].ext_hashes[coro->j] == hash) { - RARCH_LOG("[CHEEVOS]: testing %s.\n", + CHEEVOS_LOG("[CHEEVOS]: testing %s.\n", finders[coro->i].name); /* @@ -3059,7 +2721,7 @@ static int cheevos_iterate(coro_t *coro) if (finders[coro->i].ext_hashes) continue; - RARCH_LOG("[CHEEVOS]: testing %s.\n", + CHEEVOS_LOG("[CHEEVOS]: testing %s.\n", finders[coro->i].name); /* @@ -3072,7 +2734,7 @@ static int cheevos_iterate(coro_t *coro) goto found; } - RARCH_LOG("[CHEEVOS]: this game doesn't feature achievements.\n"); + CHEEVOS_LOG("[CHEEVOS]: this game doesn't feature achievements.\n"); CORO_STOP(); found: @@ -3098,7 +2760,7 @@ found: if (!coro->json) { runloop_msg_queue_push("Error loading achievements.", 0, 5 * 60, false); - RARCH_ERR("[CHEEVOS]: error loading achievements.\n"); + CHEEVOS_ERR("[CHEEVOS]: error loading achievements.\n"); CORO_STOP(); } #endif @@ -3428,7 +3090,7 @@ found: { char gameid[16]; - RARCH_LOG( + CHEEVOS_LOG( "[CHEEVOS]: getting game id for hash %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", coro->hash[ 0], coro->hash[ 1], coro->hash[ 2], coro->hash[ 3], coro->hash[ 4], coro->hash[ 5], coro->hash[ 6], coro->hash[ 7], @@ -3461,14 +3123,14 @@ found: { if ((void*)coro->json) free((void*)coro->json); - RARCH_ERR("[CHEEVOS]: error getting game_id.\n"); + CHEEVOS_ERR("[CHEEVOS]: error getting game_id.\n"); CORO_RET(); } if ((void*)coro->json) free((void*)coro->json); - RARCH_LOG("[CHEEVOS]: got game id %s.\n", gameid); - coro->gameid = strtol(gameid, NULL, 10); + CHEEVOS_LOG("[CHEEVOS]: got game id %s.\n", gameid); + coro->gameid = (unsigned)strtol(gameid, NULL, 10); CORO_RET(); } @@ -3497,11 +3159,11 @@ found: if (!coro->json) { - RARCH_ERR("[CHEEVOS]: error getting achievements for game id %u.\n", coro->gameid); + CHEEVOS_ERR("[CHEEVOS]: error getting achievements for game id %u.\n", coro->gameid); CORO_STOP(); } - RARCH_LOG("[CHEEVOS]: got achievements for game id %u.\n", coro->gameid); + CHEEVOS_LOG("[CHEEVOS]: got achievements for game id %u.\n", coro->gameid); CORO_RET(); /************************************************************************** @@ -3554,7 +3216,7 @@ found: if (!badge_exists(coro->badge_fullpath)) { #ifdef CHEEVOS_LOG_BADGES - RARCH_LOG( + CHEEVOS_LOG( "[CHEEVOS]: downloading badge %s\n", coro->badge_fullpath); #endif @@ -3569,7 +3231,7 @@ found: { if (!filestream_write_file(coro->badge_fullpath, coro->json, coro->k)) - RARCH_ERR("[CHEEVOS]: error writing badge %s\n", coro->badge_fullpath); + CHEEVOS_ERR("[CHEEVOS]: error writing badge %s\n", coro->badge_fullpath); else free(coro->json); } @@ -3589,29 +3251,46 @@ found: { char urle_user[64]; - char urle_pwd[64]; + char urle_login[64]; const char *username = coro ? coro->settings->arrays.cheevos_username : NULL; - const char *password = coro ? coro->settings->arrays.cheevos_password : NULL; + const char *login; + bool via_token; - if (!username || !*username || !password || !*password) + if (coro) + { + if (string_is_empty(coro->settings->arrays.cheevos_password)) + { + via_token = true; + login = coro->settings->arrays.cheevos_token; + } + else + { + via_token = false; + login = coro->settings->arrays.cheevos_password; + } + } + else + login = NULL; + + if (string_is_empty(username) || string_is_empty(login)) { runloop_msg_queue_push( - "Missing Retro Achievements account information.", + "Missing RetroAchievements account information.", 0, 5 * 60, false); runloop_msg_queue_push( "Please fill in your account information in Settings.", 0, 5 * 60, false); - RARCH_ERR("[CHEEVOS]: username and/or password not informed.\n"); + CHEEVOS_ERR("[CHEEVOS]: login info not informed.\n"); CORO_STOP(); } cheevos_url_encode(username, urle_user, sizeof(urle_user)); - cheevos_url_encode(password, urle_pwd, sizeof(urle_pwd)); + cheevos_url_encode(login, urle_login, sizeof(urle_login)); snprintf( coro->url, sizeof(coro->url), - "http://retroachievements.org/dorequest.php?r=login&u=%s&p=%s", - urle_user, urle_pwd + "http://retroachievements.org/dorequest.php?r=login&u=%s&%c=%s", + urle_user, via_token ? 't' : 'p', urle_login ); coro->url[sizeof(coro->url) - 1] = 0; @@ -3626,32 +3305,67 @@ found: if (coro->json) { - int res = cheevos_get_value( + char error_response[64]; + char error_message[256]; + + cheevos_get_value( + coro->json, + CHEEVOS_JSON_KEY_ERROR, + error_response, + sizeof(error_response) + ); + + /* No error, continue with login */ + if (string_is_empty(error_response)) + { + int res = cheevos_get_value( coro->json, CHEEVOS_JSON_KEY_TOKEN, cheevos_locals.token, sizeof(cheevos_locals.token)); + if ((void*)coro->json) + free((void*)coro->json); + + if (!res) + { + if (coro->settings->bools.cheevos_verbose_enable) + { + char msg[256]; + snprintf(msg, sizeof(msg), + "RetroAchievements: Logged in as \"%s\".", + coro->settings->arrays.cheevos_username); + msg[sizeof(msg) - 1] = 0; + runloop_msg_queue_push(msg, 0, 3 * 60, false); + } + + /* Save token to config and clear pass on success */ + *coro->settings->arrays.cheevos_password = '\0'; + strncpy( + coro->settings->arrays.cheevos_token, + cheevos_locals.token, sizeof(cheevos_locals.token) + ); + CORO_RET(); + } + } + if ((void*)coro->json) free((void*)coro->json); - - if (!res) - { - if (coro->settings->bools.cheevos_verbose_enable) - { - char msg[256]; - snprintf(msg, sizeof(msg), - "RetroAchievements: logged in as \"%s\".", - coro->settings->arrays.cheevos_username); - msg[sizeof(msg) - 1] = 0; - runloop_msg_queue_push(msg, 0, 3 * 60, false); - } - CORO_RET(); - } + + /* Site returned error, display it */ + snprintf(error_message, sizeof(error_message), + "RetroAchievements: %s", + error_response); + error_message[sizeof(error_message) - 1] = 0; + runloop_msg_queue_push(error_message, 0, 5 * 60, false); + *coro->settings->arrays.cheevos_token = '\0'; + + CORO_STOP(); } - - runloop_msg_queue_push("Retro Achievements login error.", 0, 5 * 60, false); - RARCH_ERR("[CHEEVOS]: error getting user token.\n"); + + runloop_msg_queue_push("RetroAchievements: Error contacting server.", 0, 5 * 60, false); + CHEEVOS_ERR("[CHEEVOS]: error getting user token.\n"); + CORO_STOP(); /************************************************************************** @@ -3682,7 +3396,7 @@ found: for (coro->k = 0; coro->k < 5; coro->k++) { if (coro->k != 0) - RARCH_LOG("[CHEEVOS]: Retrying HTTP request: %u of 5\n", coro->k + 1); + CHEEVOS_LOG("[CHEEVOS]: Retrying HTTP request: %u of 5\n", coro->k + 1); coro->json = NULL; coro->conn = net_http_connection_new( @@ -3733,7 +3447,7 @@ found: coro->json[length] = 0; } - coro->k = length; + coro->k = (unsigned)length; net_http_delete(coro->http); net_http_connection_free(coro->conn); CORO_RET(); @@ -3744,7 +3458,7 @@ found: net_http_connection_free(coro->conn); } - RARCH_LOG("[CHEEVOS]: Couldn't connect to server after 5 tries\n"); + CHEEVOS_LOG("[CHEEVOS]: Couldn't connect to server after 5 tries\n"); CORO_RET(); /************************************************************************** @@ -3776,15 +3490,15 @@ found: if (coro->json) { if (!cheevos_deactivate_unlocks(coro->json, CHEEVOS_ACTIVE_SOFTCORE)) - RARCH_LOG("[CHEEVOS]: deactivated unlocked achievements in softcore mode.\n"); + CHEEVOS_LOG("[CHEEVOS]: deactivated unlocked achievements in softcore mode.\n"); else - RARCH_ERR("[CHEEVOS]: error deactivating unlocked achievements in softcore mode.\n"); + CHEEVOS_ERR("[CHEEVOS]: error deactivating unlocked achievements in softcore mode.\n"); if ((void*)coro->json) free((void*)coro->json); } else - RARCH_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in softcore mode.\n"); + CHEEVOS_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in softcore mode.\n"); /* Deactivate achievements in hardcore mode. */ snprintf( @@ -3805,15 +3519,15 @@ found: if (coro->json) { if (!cheevos_deactivate_unlocks(coro->json, CHEEVOS_ACTIVE_HARDCORE)) - RARCH_LOG("[CHEEVOS]: deactivated unlocked achievements in hardcore mode.\n"); + CHEEVOS_LOG("[CHEEVOS]: deactivated unlocked achievements in hardcore mode.\n"); else - RARCH_ERR("[CHEEVOS]: error deactivating unlocked achievements in hardcore mode.\n"); + CHEEVOS_ERR("[CHEEVOS]: error deactivating unlocked achievements in hardcore mode.\n"); if ((void*)coro->json) free((void*)coro->json); } else - RARCH_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in hardcore mode.\n"); + CHEEVOS_ERR("[CHEEVOS]: error retrieving list of unlocked achievements in hardcore mode.\n"); #endif CORO_RET(); @@ -3842,14 +3556,14 @@ found: if (coro->json) { - RARCH_LOG("[CHEEVOS]: posted playing activity.\n"); + CHEEVOS_LOG("[CHEEVOS]: posted playing activity.\n"); if ((void*)coro->json) free((void*)coro->json); } else - RARCH_ERR("[CHEEVOS]: error posting playing activity.\n"); + CHEEVOS_ERR("[CHEEVOS]: error posting playing activity.\n"); - RARCH_LOG("[CHEEVOS]: posted playing activity.\n"); + CHEEVOS_LOG("[CHEEVOS]: posted playing activity.\n"); CORO_RET(); CORO_LEAVE(); @@ -3870,16 +3584,14 @@ static void cheevos_task_handler(retro_task_t *task) cheevos_locals.task = NULL; CHEEVOS_UNLOCK(cheevos_locals.task_lock); -#ifdef CHEEVOS_VERBOSE if (task_get_cancelled(task)) { - RARCH_LOG("[CHEEVOS]: Load task cancelled\n"); + CHEEVOS_LOG("[CHEEVOS]: Load task cancelled\n"); } else { - RARCH_LOG("[CHEEVOS]: Load task finished\n"); + CHEEVOS_LOG("[CHEEVOS]: Load task finished\n"); } -#endif if (coro->data) free(coro->data); diff --git a/cheevos/cheevos.h b/cheevos/cheevos.h index dd070ef441..a4f18c7c7f 100644 --- a/cheevos/cheevos.h +++ b/cheevos/cheevos.h @@ -38,6 +38,20 @@ End of setup #define CHEEVOS_TAG "[CHEEVOS]: " +#ifdef CHEEVOS_VERBOSE + +#define CHEEVOS_LOG RARCH_LOG +#define CHEEVOS_ERR RARCH_ERR + +#else + +void cheevos_log(const char *fmt, ...); + +#define CHEEVOS_LOG cheevos_log +#define CHEEVOS_ERR cheevos_log + +#endif + typedef struct cheevos_ctx_desc { unsigned idx; diff --git a/cheevos/cond.c b/cheevos/cond.c index 3566f8e6bf..9f665900c9 100644 --- a/cheevos/cond.c +++ b/cheevos/cond.c @@ -65,7 +65,7 @@ static cheevos_cond_op_t cheevos_cond_parse_operator(const char** memaddr) } else { - RARCH_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str); + CHEEVOS_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str); op = CHEEVOS_COND_OP_EQUALS; } @@ -168,9 +168,6 @@ void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsign if (index == which) { cheevos_cond_parse(cond, &memaddr); -#ifdef CHEEVOS_VERBOSE - /*cheevos_log_cond(cond);*/ -#endif cond++; } else diff --git a/cheevos/var.c b/cheevos/var.c index 41884a72b6..5f13c2b8b6 100644 --- a/cheevos/var.c +++ b/cheevos/var.c @@ -24,17 +24,6 @@ #include "../core.h" #include "../verbosity.h" -static void STUB_LOG(const char *fmt, ...) -{ - (void)fmt; -} - -#ifdef CHEEVOS_VERBOSE -#define CHEEVOS_LOG RARCH_LOG -#else -#define CHEEVOS_LOG STUB_LOG -#endif - /***************************************************************************** Parsing *****************************************************************************/ @@ -191,12 +180,6 @@ void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console) var->value -= 0x2000; } } - else if (console == CHEEVOS_CONSOLE_NEOGEO_POCKET) - { - if (var->value >= 0x4000 && var->value <= 0x7fff) - CHEEVOS_LOG(CHEEVOS_TAG "NGP memory address %X adjusted to %X\n", var->value, var->value - 0x004000); - var->value -= 0x4000; - } if (system->mmaps.num_descriptors != 0) { @@ -333,7 +316,7 @@ uint8_t* cheevos_var_get_memory(const cheevos_var_t* var) meminfo.id = RETRO_MEMORY_RTC; break; default: - RARCH_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id); + CHEEVOS_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id); break; } diff --git a/command.c b/command.c index ab871166c0..1a279788d8 100644 --- a/command.c +++ b/command.c @@ -1015,7 +1015,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 +1029,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; @@ -1708,14 +1708,8 @@ void command_playlist_update_write( 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; @@ -2202,11 +2196,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: diff --git a/config.def.h b/config.def.h index 2aa743544a..55653b7dc8 100644 --- a/config.def.h +++ b/config.def.h @@ -297,6 +297,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; @@ -304,6 +305,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__) @@ -593,6 +595,12 @@ static const float slowmotion_ratio = 3.0; /* Maximum fast forward ratio. */ static const float fastforward_ratio = 0.0; +/* Run core logic one or more frames ahead then load the state back to reduce perceived input lag. */ +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; + /* Enable stdin/network command interface. */ static const bool network_cmd_enable = false; static const uint16_t network_cmd_port = 55355; @@ -605,11 +613,7 @@ static const unsigned default_content_history_size = 100; /* Show Menu start-up screen on boot. */ static const bool default_menu_show_start_screen = true; -#ifdef RARCH_MOBILE static const bool menu_dpi_override_enable = false; -#else -static const bool menu_dpi_override_enable = true; -#endif #ifdef RARCH_MOBILE static const unsigned menu_dpi_override_value = 72; @@ -654,6 +658,10 @@ static const unsigned input_bind_timeout = 5; static const unsigned menu_thumbnails_default = 3; +static const unsigned menu_left_thumbnails_default = 0; + +static const bool xmb_vertical_thumbnails = false; + #ifdef IOS static const bool ui_companion_start_on_boot = false; #else diff --git a/configuration.c b/configuration.c index 85c8ba6a49..5a8a78b8aa 100644 --- a/configuration.c +++ b/configuration.c @@ -1033,6 +1033,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); @@ -1220,6 +1221,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("ui_menubar_enable", &settings->bools.ui_menubar_enable, true, true, false); SETTING_BOOL("suspend_screensaver_enable", &settings->bools.ui_suspend_screensaver_enable, true, true, false); 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("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); @@ -1310,10 +1313,14 @@ 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); @@ -1328,8 +1335,14 @@ 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); #endif #endif #ifdef HAVE_CHEEVOS @@ -1356,9 +1369,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 @@ -1463,9 +1473,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 @@ -1473,8 +1480,10 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings, SETTING_UINT("dpi_override_value", &settings->uints.menu_dpi_override_value, true, menu_dpi_override_value, false); SETTING_UINT("menu_thumbnails", &settings->uints.menu_thumbnails, true, menu_thumbnails_default, false); #ifdef HAVE_XMB + 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); @@ -1515,6 +1524,8 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings, SETTING_UINT("video_msg_bgcolor_green", &settings->uints.video_msg_bgcolor_green, true, message_bgcolor_green, false); SETTING_UINT("video_msg_bgcolor_blue", &settings->uints.video_msg_bgcolor_blue, true, message_bgcolor_blue, false); + SETTING_UINT("run_ahead_frames", &settings->uints.run_ahead_frames, true, 1, false); + *size = count; return tmp; @@ -1714,6 +1725,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(); @@ -2928,7 +2940,7 @@ bool config_load_override(void) config_file_t *new_conf = NULL; bool should_append = false; rarch_system_info_t *system = runloop_get_system_info(); - const char *core_name = system ? + const char *core_name = system ? system->info.library_name : NULL; const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME)); @@ -3016,7 +3028,7 @@ bool config_load_override(void) if (!should_append) goto error; - /* Re-load the configuration with any overrides + /* Re-load the configuration with any overrides * that might have been found */ buf[0] = '\0'; @@ -3101,7 +3113,7 @@ bool config_unload_override(void) bool config_load_remap(void) { size_t path_size = PATH_MAX_LENGTH * sizeof(char); - char *remap_directory = NULL; + char *remap_directory = NULL; char *core_path = NULL; char *game_path = NULL; config_file_t *new_conf = NULL; @@ -3121,12 +3133,12 @@ bool config_load_remap(void) /* path to the directory containing retroarch.cfg (prefix) */ remap_directory = (char*) malloc(PATH_MAX_LENGTH * sizeof(char)); - /* final path for core-specific configuration (prefix+suffix) */ + /* final path for core-specific configuration (prefix+suffix) */ core_path = (char*) malloc(PATH_MAX_LENGTH * sizeof(char)); /* final path for game-specific configuration (prefix+suffix) */ game_path = (char*) - malloc(PATH_MAX_LENGTH * sizeof(char)); + malloc(PATH_MAX_LENGTH * sizeof(char)); remap_directory[0] = core_path[0] = game_path[0] = '\0'; strlcpy(remap_directory, @@ -3228,7 +3240,7 @@ bool config_load_shader_preset(void) char *parent_path = NULL; settings_t *settings = config_get_ptr(); rarch_system_info_t *system = runloop_get_system_info(); - const char *core_name = system + const char *core_name = system ? system->info.library_name : NULL; const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME)); @@ -3766,8 +3778,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; } @@ -4179,28 +4190,28 @@ bool config_save_overrides(int override_type) char cfg[64]; cfg[0] = '\0'; - if (settings->uints.input_device[i] + if (settings->uints.input_device[i] != overrides->uints.input_device[i]) { snprintf(cfg, sizeof(cfg), "input_device_p%u", i + 1); config_set_int(conf, cfg, overrides->uints.input_device[i]); } - if (settings->uints.input_joypad_map[i] + if (settings->uints.input_joypad_map[i] != overrides->uints.input_joypad_map[i]) { snprintf(cfg, sizeof(cfg), "input_player%u_joypad_index", i + 1); config_set_int(conf, cfg, overrides->uints.input_joypad_map[i]); } - if (settings->uints.input_libretro_device[i] + if (settings->uints.input_libretro_device[i] != overrides->uints.input_libretro_device[i]) { snprintf(cfg, sizeof(cfg), "input_libretro_device_p%u", i + 1); config_set_int(conf, cfg, overrides->uints.input_libretro_device[i]); } - if (settings->uints.input_analog_dpad_mode[i] + if (settings->uints.input_analog_dpad_mode[i] != overrides->uints.input_analog_dpad_mode[i]) { snprintf(cfg, sizeof(cfg), "input_player%u_analog_dpad_mode", i + 1); diff --git a/configuration.h b/configuration.h index 3afa6fdc4b..89a53b6b42 100644 --- a/configuration.h +++ b/configuration.h @@ -147,8 +147,15 @@ typedef struct settings bool menu_show_help; bool menu_show_quit_retroarch; bool menu_show_reboot; + 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; bool menu_content_show_favorites; bool menu_content_show_images; @@ -157,6 +164,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; @@ -224,6 +232,8 @@ typedef struct settings bool playlist_entry_remove; bool playlist_entry_rename; bool rewind_enable; + bool run_ahead_enabled; + bool run_ahead_secondary_instance; bool pause_nonactive; bool block_sram_overwrite; bool savestate_auto_index; @@ -350,10 +360,12 @@ typedef struct settings unsigned video_msg_bgcolor_blue; unsigned menu_thumbnails; + unsigned menu_left_thumbnails; unsigned menu_dpi_override_value; 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; @@ -377,11 +389,13 @@ 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; } uints; struct @@ -397,6 +411,7 @@ 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]; diff --git a/content.h b/content.h index ad4211c5a0..5e25e47c64 100644 --- a/content.h +++ b/content.h @@ -92,17 +92,16 @@ void content_clear_subsystem(void); void content_set_subsystem(unsigned subsystem); /* Get the current subsystem*/ -int content_get_subsystem(); +int content_get_subsystem(void); /* Add a rom to the subsystem rom buffer */ void content_add_subsystem(const char* path); /* Get the current subsystem rom id */ -int content_get_subsystem_rom_id(); +unsigned content_get_subsystem_rom_id(void); /* Set environment variables before a subsystem load */ -void content_set_subsystem_info(); - +void content_set_subsystem_info(void); RETRO_END_DECLS diff --git a/core.h b/core.h index 35878206b4..06cdbac698 100644 --- a/core.h +++ b/core.h @@ -170,6 +170,9 @@ bool core_set_poll_type(unsigned *type); /* Runs the core for one frame. */ bool core_run(void); +/* Runs the core for one frame, but does not trigger any input polling */ +bool core_run_no_input_polling(void); + bool core_init(void); bool core_deinit(void *data); diff --git a/core_impl.c b/core_impl.c index 62285e6682..7c2585a0c2 100644 --- a/core_impl.c +++ b/core_impl.c @@ -44,6 +44,11 @@ #include "gfx/video_driver.h" #include "audio/audio_driver.h" +#ifdef HAVE_RUNAHEAD +#include "runahead/copy_load_info.h" +#include "runahead/secondary_core.h" +#endif + struct retro_callbacks retro_ctx; struct retro_core_t current_core; @@ -262,6 +267,11 @@ bool core_set_controller_port_device(retro_ctx_controller_info_t *pad) { if (!pad) return false; + +#ifdef HAVE_RUNAHEAD + remember_controller_port_device(pad->port, pad->device); +#endif + current_core.retro_set_controller_port_device(pad->port, pad->device); return true; } @@ -280,6 +290,11 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info) bool contentless = false; bool is_inited = false; +#ifdef HAVE_RUNAHEAD + set_load_content_info(load_info); + clear_controller_port_map(); +#endif + content_get_status(&contentless, &is_inited); if (load_info && load_info->special) @@ -424,6 +439,12 @@ bool core_run(void) return true; } +bool core_run_no_input_polling(void) +{ + current_core.retro_run(); + return true; +} + bool core_load(unsigned poll_type_behavior) { current_core.poll_type = poll_type_behavior; diff --git a/core_info.c b/core_info.c index 76b979046b..d7ed2041d6 100644 --- a/core_info.c +++ b/core_info.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -26,14 +27,10 @@ #include "config.h" #endif -#include "retroarch.h" #include "verbosity.h" -#include "config.def.h" #include "core_info.h" -#include "configuration.h" #include "file_path_special.h" -#include "list_special.h" static const char *core_info_tmp_path = NULL; static const struct string_list *core_info_tmp_list = NULL; @@ -224,21 +221,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; @@ -518,7 +517,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 +535,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 +546,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 +634,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 +653,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 +751,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 +785,7 @@ void core_info_get_name(const char *path, char *s, size_t len) continue; } - conf = config_file_new(info_path); + conf = config_file_new(info_path); if (!conf) { diff --git a/core_info.h b/core_info.h index c058e8d937..b63fa8df98 100644 --- a/core_info.h +++ b/core_info.h @@ -97,7 +97,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 +111,13 @@ bool core_info_get_current_core(core_info_t **core); void core_info_deinit_list(void); -bool core_info_init_list(void); +bool core_info_init_list(const char *path_info, const char *dir_cores, + const char *exts, bool show_hidden_files); bool core_info_get_list(core_info_list_t **core); -bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info); +bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info, + bool *set_missing_bios); bool core_info_find(core_info_ctx_find_t *info, const char *name); diff --git a/ctr/ctr_system.c b/ctr/ctr_system.c index 29594251e7..9126ba009e 100644 --- a/ctr/ctr_system.c +++ b/ctr/ctr_system.c @@ -1,5 +1,6 @@ #include <3ds.h> #include +#include <3ds/services/apt.h> #include #include #include diff --git a/database_info.c b/database_info.c index 433bd275aa..894ae250ac 100644 --- a/database_info.c +++ b/database_info.c @@ -21,11 +21,13 @@ #include #include #include +#include +#include #include #include "libretro-db/libretrodb.h" -#include "list_special.h" +#include "core_info.h" #include "database_info.h" #include "verbosity.h" @@ -366,16 +368,22 @@ static void dir_list_prioritize(struct string_list *list) } database_info_handle_t *database_info_dir_init(const char *dir, - enum database_type type, retro_task_t *task) + enum database_type type, retro_task_t *task, + bool show_hidden_files) { - struct string_list *list = NULL; - database_info_handle_t *db = (database_info_handle_t*) + core_info_list_t *core_info_list = NULL; + struct string_list *list = NULL; + database_info_handle_t *db = (database_info_handle_t*) calloc(1, sizeof(*db)); if (!db) return NULL; - list = dir_list_new_special(dir, DIR_LIST_RECURSIVE, NULL); + core_info_get_list(&core_info_list); + + list = dir_list_new(dir, core_info_list->all_ext, + false, show_hidden_files, + false, true); if (!list) { diff --git a/database_info.h b/database_info.h index 2664577e6f..aa0f5b8011 100644 --- a/database_info.h +++ b/database_info.h @@ -126,7 +126,8 @@ database_info_list_t *database_info_list_new(const char *rdb_path, void database_info_list_free(database_info_list_t *list); database_info_handle_t *database_info_dir_init(const char *dir, - enum database_type type, retro_task_t *task); + enum database_type type, retro_task_t *task, + bool show_hidden_files); database_info_handle_t *database_info_file_init(const char *path, enum database_type type, retro_task_t *task); diff --git a/deps/dr/dr_flac.h b/deps/dr/dr_flac.h new file mode 100644 index 0000000000..dddba62b83 --- /dev/null +++ b/deps/dr/dr_flac.h @@ -0,0 +1,5463 @@ +#ifndef dr_flac_h +#define dr_flac_h + +#define DR_FLAC_NO_STDIO + +#include +#include +#include + +typedef int8_t drflac_int8; +typedef uint8_t drflac_uint8; +typedef int16_t drflac_int16; +typedef uint16_t drflac_uint16; +typedef int32_t drflac_int32; +typedef uint32_t drflac_uint32; +typedef int64_t drflac_int64; +typedef uint64_t drflac_uint64; +typedef drflac_uint8 drflac_bool8; +typedef drflac_uint32 drflac_bool32; +#define DRFLAC_TRUE 1 +#define DRFLAC_FALSE 0 + +/* As data is read from the client it is placed into an internal buffer for fast access. This controls the + * size of that buffer. Larger values means more speed, but also more memory. In my testing there is diminishing + * returns after about 4KB, but you can fiddle with this to suit your own needs. Must be a multiple of 8. + */ +#ifndef DR_FLAC_BUFFER_SIZE +#define DR_FLAC_BUFFER_SIZE 4096 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Check if we can enable 64-bit optimizations. */ +#if defined(_WIN64) +#define DRFLAC_64BIT +#endif + +#if defined(__GNUC__) +#if defined(__x86_64__) || defined(__ppc64__) +#define DRFLAC_64BIT +#endif +#endif + +#ifdef DRFLAC_64BIT +typedef drflac_uint64 drflac_cache_t; +#else +typedef drflac_uint32 drflac_cache_t; +#endif + +/* The various metadata block types. */ +#define DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO 0 +#define DRFLAC_METADATA_BLOCK_TYPE_PADDING 1 +#define DRFLAC_METADATA_BLOCK_TYPE_APPLICATION 2 +#define DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE 3 +#define DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT 4 +#define DRFLAC_METADATA_BLOCK_TYPE_CUESHEET 5 +#define DRFLAC_METADATA_BLOCK_TYPE_PICTURE 6 +#define DRFLAC_METADATA_BLOCK_TYPE_INVALID 127 + +/* The various picture types specified in the PICTURE block. */ +#define DRFLAC_PICTURE_TYPE_OTHER 0 +#define DRFLAC_PICTURE_TYPE_FILE_ICON 1 +#define DRFLAC_PICTURE_TYPE_OTHER_FILE_ICON 2 +#define DRFLAC_PICTURE_TYPE_COVER_FRONT 3 +#define DRFLAC_PICTURE_TYPE_COVER_BACK 4 +#define DRFLAC_PICTURE_TYPE_LEAFLET_PAGE 5 +#define DRFLAC_PICTURE_TYPE_MEDIA 6 +#define DRFLAC_PICTURE_TYPE_LEAD_ARTIST 7 +#define DRFLAC_PICTURE_TYPE_ARTIST 8 +#define DRFLAC_PICTURE_TYPE_CONDUCTOR 9 +#define DRFLAC_PICTURE_TYPE_BAND 10 +#define DRFLAC_PICTURE_TYPE_COMPOSER 11 +#define DRFLAC_PICTURE_TYPE_LYRICIST 12 +#define DRFLAC_PICTURE_TYPE_RECORDING_LOCATION 13 +#define DRFLAC_PICTURE_TYPE_DURING_RECORDING 14 +#define DRFLAC_PICTURE_TYPE_DURING_PERFORMANCE 15 +#define DRFLAC_PICTURE_TYPE_SCREEN_CAPTURE 16 +#define DRFLAC_PICTURE_TYPE_BRIGHT_COLORED_FISH 17 +#define DRFLAC_PICTURE_TYPE_ILLUSTRATION 18 +#define DRFLAC_PICTURE_TYPE_BAND_LOGOTYPE 19 +#define DRFLAC_PICTURE_TYPE_PUBLISHER_LOGOTYPE 20 + +typedef enum +{ + drflac_container_native, + drflac_container_ogg, + drflac_container_unknown +} drflac_container; + +typedef enum +{ + drflac_seek_origin_start, + drflac_seek_origin_current +} drflac_seek_origin; + +/* Packing is important on this structure because we map this directly to the raw data within the SEEKTABLE metadata block. */ +#pragma pack(2) +typedef struct +{ + drflac_uint64 firstSample; + drflac_uint64 frameOffset; /* The offset from the first byte of the header of the first frame. */ + drflac_uint16 sampleCount; +} drflac_seekpoint; +#pragma pack() + +typedef struct +{ + drflac_uint16 minBlockSize; + drflac_uint16 maxBlockSize; + drflac_uint32 minFrameSize; + drflac_uint32 maxFrameSize; + drflac_uint32 sampleRate; + drflac_uint8 channels; + drflac_uint8 bitsPerSample; + drflac_uint64 totalSampleCount; + drflac_uint8 md5[16]; +} drflac_streaminfo; + +typedef struct +{ + /* The metadata type. Use this to know how to interpret the data below. */ + drflac_uint32 type; + + /* A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to + * not modify the contents of this buffer. Use the structures below for more meaningful and structured + * information about the metadata. It's possible for this to be null. + */ + const void* pRawData; + + /* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */ + drflac_uint32 rawDataSize; + + union + { + drflac_streaminfo streaminfo; + + struct + { + int unused; + } padding; + + struct + { + drflac_uint32 id; + const void* pData; + drflac_uint32 dataSize; + } application; + + struct + { + drflac_uint32 seekpointCount; + const drflac_seekpoint* pSeekpoints; + } seektable; + + struct + { + drflac_uint32 vendorLength; + const char* vendor; + drflac_uint32 commentCount; + const char* comments; + } vorbis_comment; + + struct + { + char catalog[128]; + drflac_uint64 leadInSampleCount; + drflac_bool32 isCD; + drflac_uint8 trackCount; + const drflac_uint8* pTrackData; + } cuesheet; + + struct + { + drflac_uint32 type; + drflac_uint32 mimeLength; + const char* mime; + drflac_uint32 descriptionLength; + const char* description; + drflac_uint32 width; + drflac_uint32 height; + drflac_uint32 colorDepth; + drflac_uint32 indexColorCount; + drflac_uint32 pictureDataSize; + const drflac_uint8* pPictureData; + } picture; + } data; +} drflac_metadata; + + +/* Callback for when data needs to be read from the client. + * + * pUserData [in] The user data that was passed to drflac_open() and family. + * pBufferOut [out] The output buffer. + * bytesToRead [in] The number of bytes to read. + * + * Returns the number of bytes actually read. + * + * A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until + * either the entire bytesToRead is filled or you have reached the end of the stream. + */ +typedef size_t (* drflac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead); + +/* Callback for when data needs to be seeked. + * + * pUserData [in] The user data that was passed to drflac_open() and family. + * offset [in] The number of bytes to move, relative to the origin. Will never be negative. + * origin [in] The origin of the seek - the current position or the start of the stream. + * + * Returns whether or not the seek was successful. + * + * The offset will never be negative. Whether or not it is relative to the beginning or current position is determined + * by the "origin" parameter which will be either drflac_seek_origin_start or drflac_seek_origin_current. + */ +typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin); + +/* Callback for when a metadata block is read. + * + * pUserData [in] The user data that was passed to drflac_open() and family. + * pMetadata [in] A pointer to a structure containing the data of the metadata block. + * + * Use pMetadata->type to determine which metadata block is being handled and how to read the data. + */ +typedef void (* drflac_meta_proc)(void* pUserData, drflac_metadata* pMetadata); + + +/* Structure for internal use. Only used for decoders opened with drflac_open_memory. */ +typedef struct +{ + const drflac_uint8* data; + size_t dataSize; + size_t currentReadPos; +} drflac__memory_stream; + +/* Structure for internal use. Used for bit streaming. */ +typedef struct +{ + /* The function to call when more data needs to be read. */ + drflac_read_proc onRead; + + /* The function to call when the current read position needs to be moved. */ + drflac_seek_proc onSeek; + + /* The user data to pass around to onRead and onSeek. */ + void* pUserData; + + + /* The number of unaligned bytes in the L2 cache. This will always be 0 until the end of the stream is hit. At the end of the + * stream there will be a number of bytes that don't cleanly fit in an L1 cache line, so we use this variable to know whether + * or not the bistreamer needs to run on a slower path to read those last bytes. This will never be more than sizeof(drflac_cache_t). + */ + size_t unalignedByteCount; + + /* The content of the unaligned bytes. */ + drflac_cache_t unalignedCache; + + /* The index of the next valid cache line in the "L2" cache. */ + drflac_uint32 nextL2Line; + + /* The number of bits that have been consumed by the cache. This is used to determine how many valid bits are remaining. */ + drflac_uint32 consumedBits; + + /* The cached data which was most recently read from the client. There are two levels of cache. Data flows as such: + * Client -> L2 -> L1. The L2 -> L1 movement is aligned and runs on a fast path in just a few instructions. */ + drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)]; + drflac_cache_t cache; + + /* CRC-16. This is updated whenever bits are read from the bit stream. Manually set this to 0 to reset the CRC. For FLAC, this + * is reset to 0 at the beginning of each frame. */ + drflac_uint16 crc16; + drflac_cache_t crc16Cache; /* A cache for optimizing CRC calculations. This is filled when when the L1 cache is reloaded. */ + drflac_uint32 crc16CacheIgnoredBytes; /* The number of bytes to ignore when updating the CRC-16 from the CRC-16 cache. */ +} drflac_bs; + +typedef struct +{ + /* The type of the subframe: SUBFRAME_CONSTANT, SUBFRAME_VERBATIM, SUBFRAME_FIXED or SUBFRAME_LPC. */ + drflac_uint8 subframeType; + + /* The number of wasted bits per sample as specified by the sub-frame header. */ + drflac_uint8 wastedBitsPerSample; + + /* The order to use for the prediction stage for SUBFRAME_FIXED and SUBFRAME_LPC. */ + drflac_uint8 lpcOrder; + + /* The number of bits per sample for this subframe. This is not always equal to the current frame's bit per sample because + * an extra bit is required for side channels when interchannel decorrelation is being used. */ + drflac_uint32 bitsPerSample; + + /* A pointer to the buffer containing the decoded samples in the subframe. This pointer is an offset from drflac::pExtraData. Note that + * it's a signed 32-bit integer for each value. */ + drflac_int32* pDecodedSamples; +} drflac_subframe; + +typedef struct +{ + /* If the stream uses variable block sizes, this will be set to the index of the first sample. If fixed block sizes are used, this will + * always be set to 0. */ + drflac_uint64 sampleNumber; + + /* If the stream uses fixed block sizes, this will be set to the frame number. If variable block sizes are used, this will always be 0. */ + drflac_uint32 frameNumber; + + /* The sample rate of this frame. */ + drflac_uint32 sampleRate; + + /* The number of samples in each sub-frame within this frame. */ + drflac_uint16 blockSize; + + /* The channel assignment of this frame. This is not always set to the channel count. If interchannel decorrelation is being used this + * will be set to DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE, DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE or DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE. */ + drflac_uint8 channelAssignment; + + /* The number of bits per sample within this frame. */ + drflac_uint8 bitsPerSample; + + /* The frame's CRC. */ + drflac_uint8 crc8; +} drflac_frame_header; + +typedef struct +{ + /* The header. */ + drflac_frame_header header; + + /* The number of samples left to be read in this frame. This is initially set to the block size multiplied by the channel count. As samples + * are read, this will be decremented. When it reaches 0, the decoder will see this frame as fully consumed and load the next frame. + */ + drflac_uint32 samplesRemaining; + + /* The list of sub-frames within the frame. There is one sub-frame for each channel, and there's a maximum of 8 channels. */ + drflac_subframe subframes[8]; +} drflac_frame; + +typedef struct +{ + /* The function to call when a metadata block is read. */ + drflac_meta_proc onMeta; + + /* The user data posted to the metadata callback function. */ + void* pUserDataMD; + + + /* The sample rate. Will be set to something like 44100. */ + drflac_uint32 sampleRate; + + /* The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. Maximum 8. This is set based on the + * value specified in the STREAMINFO block. */ + drflac_uint8 channels; + + /* The bits per sample. Will be set to somthing like 16, 24, etc. */ + drflac_uint8 bitsPerSample; + + /* The maximum block size, in samples. This number represents the number of samples in each channel (not combined). */ + drflac_uint16 maxBlockSize; + + /* The total number of samples making up the stream. This includes every channel. For example, if the stream has 2 channels, + * with each channel having a total of 4096, this value will be set to 2*4096 = 8192. Can be 0 in which case it's still a + * valid stream, but just means the total sample count is unknown. Likely the case with streams like internet radio. */ + drflac_uint64 totalSampleCount; + + + /* The container type. This is set based on whether or not the decoder was opened from a native or Ogg stream. */ + drflac_container container; + + /* The position of the seektable in the file. */ + drflac_uint64 seektablePos; + + /* The size of the seektable. */ + drflac_uint32 seektableSize; + + + /* Information about the frame the decoder is currently sitting on. */ + drflac_frame currentFrame; + + /* The position of the first frame in the stream. This is only ever used for seeking. */ + drflac_uint64 firstFramePos; + + + /* A hack to avoid a malloc() when opening a decoder with drflac_open_memory(). */ + drflac__memory_stream memoryStream; + + + /* A pointer to the decoded sample data. This is an offset of pExtraData. */ + drflac_int32* pDecodedSamples; + + /* Internal use only. Only used with Ogg containers. Points to a drflac_oggbs object. This is an offset of pExtraData. */ + void* _oggbs; + + /* The bit streamer. The raw FLAC data is fed through this object. */ + drflac_bs bs; + + /* Variable length extra data. We attach this to the end of the object so we can avoid unnecessary mallocs. */ + drflac_uint8 pExtraData[1]; +} drflac; + + +/* Opens a FLAC decoder. + * + * onRead [in] The function to call when data needs to be read from the client. + * onSeek [in] The function to call when the read position of the client data needs to move. + * pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek. + * + * Returns a pointer to an object representing the decoder. + * + * Close the decoder with drflac_close(). + * + * This function will automatically detect whether or not you are attempting to open a native or Ogg encapsulated + * FLAC, both of which should work seamlessly without any manual intervention. Ogg encapsulation also works with + * multiplexed streams which basically means it can play FLAC encoded audio tracks in videos. + * + * This is the lowest level function for opening a FLAC stream. You can also use drflac_open_file() and drflac_open_memory() + * to open the stream from a file or from a block of memory respectively. + * + * The STREAMINFO block must be present for this to succeed. Use drflac_open_relaxed() to open a FLAC stream where + * the header may not be present. + * + * See also: drflac_open_file(), drflac_open_memory(), drflac_open_with_metadata(), drflac_close() + */ +drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData); + +/* The same as drflac_open(), except attempts to open the stream even when a header block is not present. + * + * Because the header is not necessarily available, the caller must explicitly define the container (Native or Ogg). Do + * not set this to drflac_container_unknown - that is for internal use only. + * + * Opening in relaxed mode will continue reading data from onRead until it finds a valid frame. If a frame is never + * found it will continue forever. To abort, force your onRead callback to return 0, which dr_flac will use as an + * indicator that the end of the stream was found. */ +drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData); + +/* Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.). + * + * onRead [in] The function to call when data needs to be read from the client. + * onSeek [in] The function to call when the read position of the client data needs to move. + * onMeta [in] The function to call for every metadata block. + * pUserData [in, optional] A pointer to application defined data that will be passed to onRead, onSeek and onMeta. + * + * Returns a pointer to an object representing the decoder. + * + * Close the decoder with drflac_close(). + * + * This is slower than drflac_open(), so avoid this one if you don't need metadata. Internally, this will do a DRFLAC_MALLOC() + * and DRFLAC_FREE() for every metadata block except for STREAMINFO and PADDING blocks. + * + * The caller is notified of the metadata via the onMeta callback. All metadata blocks will be handled before the function + * returns. + * + * The STREAMINFO block must be present for this to succeed. Use drflac_open_with_metadata_relaxed() to open a FLAC + * stream where the header may not be present. + * + * Note that this will behave inconsistently with drflac_open() if the stream is an Ogg encapsulated stream and a metadata + * block is corrupted. This is due to the way the Ogg stream recovers from corrupted pages. When drflac_open_with_metadata() + * is being used, the open routine will try to read the contents of the metadata block, whereas drflac_open() will simply + * seek past it (for the sake of efficiency). This inconsistency can result in different samples being returned depending on + * whether or not the stream is being opened with metadata. + * + * See also: drflac_open_file_with_metadata(), drflac_open_memory_with_metadata(), drflac_open(), drflac_close() + */ +drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData); + +/* The same as drflac_open_with_metadata(), except attemps to open the stream even when a header block is not present. + * + * See also: drflac_open_with_metadata(), drflac_open_relaxed() + */ +drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData); + +/* Closes the given FLAC decoder. + * + * pFlac [in] The decoder to close. + * + * This will destroy the decoder object. */ +void drflac_close(drflac* pFlac); + + +/* Reads sample data from the given FLAC decoder, output as interleaved signed 32-bit PCM. + * + * pFlac [in] The decoder. + * samplesToRead [in] The number of samples to read. + * pBufferOut [out, optional] A pointer to the buffer that will receive the decoded samples. + * + * Returns the number of samples actually read. + * + * pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of samples + * seeked. */ +drflac_uint64 drflac_read_s32(drflac* pFlac, drflac_uint64 samplesToRead, drflac_int32* pBufferOut); + +/* Same as drflac_read_s32(), except outputs samples as 16-bit integer PCM rather than 32-bit. + * + * pFlac [in] The decoder. + * samplesToRead [in] The number of samples to read. + * pBufferOut [out, optional] A pointer to the buffer that will receive the decoded samples. + * + * Returns the number of samples actually read. + * + * pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of samples + * seeked. + * + * Note that this is lossy for streams where the bits per sample is larger than 16. + */ +drflac_uint64 drflac_read_s16(drflac* pFlac, drflac_uint64 samplesToRead, drflac_int16* pBufferOut); + +/* Same as drflac_read_s32(), except outputs samples as 32-bit floating-point PCM. + * + * pFlac [in] The decoder. + * samplesToRead [in] The number of samples to read. + * pBufferOut [out, optional] A pointer to the buffer that will receive the decoded samples. + * + * Returns the number of samples actually read. + * + * pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of samples + * seeked. + * + * Note that this should be considered lossy due to the nature of floating point numbers not being able to exactly + * represent every possible number. + */ +drflac_uint64 drflac_read_f32(drflac* pFlac, drflac_uint64 samplesToRead, float* pBufferOut); + +/* Seeks to the sample at the given index. + * + * pFlac [in] The decoder. + * sampleIndex [in] The index of the sample to seek to. See notes below. + * + * Returns DRFLAC_TRUE if successful; DRFLAC_FALSE otherwise. + * + * The sample index is based on interleaving. In a stereo stream, for example, the sample at index 0 is the first sample + * in the left channel; the sample at index 1 is the first sample on the right channel, and so on. + * + * When seeking, you will likely want to ensure it's rounded to a multiple of the channel count. You can do this with + * something like drflac_seek_to_sample(pFlac, (mySampleIndex + (mySampleIndex % pFlac->channels))) + */ +drflac_bool32 drflac_seek_to_sample(drflac* pFlac, drflac_uint64 sampleIndex); + + + +#ifndef DR_FLAC_NO_STDIO +/* Opens a FLAC decoder from the file at the given path. + * + * filename [in] The path of the file to open, either absolute or relative to the current directory. + * + * Returns a pointer to an object representing the decoder. + * + * Close the decoder with drflac_close(). + * + * This will hold a handle to the file until the decoder is closed with drflac_close(). Some platforms will restrict the + * number of files a process can have open at any given time, so keep this mind if you have many decoders open at the + * same time. + * + * See also: drflac_open(), drflac_open_file_with_metadata(), drflac_close() + */ +drflac* drflac_open_file(const char* filename); + +/* Opens a FLAC decoder from the file at the given path and notifies the caller of the metadata chunks (album art, etc.) + * + * Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled. + */ +drflac* drflac_open_file_with_metadata(const char* filename, drflac_meta_proc onMeta, void* pUserData); +#endif + +/* Opens a FLAC decoder from a pre-allocated block of memory + * + * This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for + * the lifetime of the decoder. + */ +drflac* drflac_open_memory(const void* data, size_t dataSize); + +/* Opens a FLAC decoder from a pre-allocated block of memory and notifies the caller of the metadata chunks (album art, etc.) + * + * Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled. + */ +drflac* drflac_open_memory_with_metadata(const void* data, size_t dataSize, drflac_meta_proc onMeta, void* pUserData); + +/* High Level APIs */ + +/* Opens a FLAC stream from the given callbacks and fully decodes it in a single operation. The return value is a + * pointer to the sample data as interleaved signed 32-bit PCM. The returned data must be freed with DRFLAC_FREE(). + * + * Sometimes a FLAC file won't keep track of the total sample count. In this situation the function will continuously + * read samples into a dynamically sized buffer on the heap until no samples are left. + * + * Do not call this function on a broadcast type of stream (like internet radio streams and whatnot). + */ +drflac_int32* drflac_open_and_decode_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +/* Same as drflac_open_and_decode_s32(), except returns signed 16-bit integer samples. */ +drflac_int16* drflac_open_and_decode_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +/* Same as drflac_open_and_decode_s32(), except returns 32-bit floating-point samples. */ +float* drflac_open_and_decode_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +#ifndef DR_FLAC_NO_STDIO +/* Same as drflac_open_and_decode_s32() except opens the decoder from a file. */ +drflac_int32* drflac_open_and_decode_file_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +/* Same as drflac_open_and_decode_file_s32(), except returns signed 16-bit integer samples. */ +drflac_int16* drflac_open_and_decode_file_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +/* Same as drflac_open_and_decode_file_f32(), except returns 32-bit floating-point samples. */ +float* drflac_open_and_decode_file_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); +#endif + +/* Same as drflac_open_and_decode_s32() except opens the decoder from a block of memory. */ +drflac_int32* drflac_open_and_decode_memory_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +/* Same as drflac_open_and_decode_memory_s32(), except returns signed 16-bit integer samples. */ +drflac_int16* drflac_open_and_decode_memory_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +/* Same as drflac_open_and_decode_memory_s32(), except returns 32-bit floating-point samples. */ +float* drflac_open_and_decode_memory_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount); + +/* Frees memory that was allocated internally by dr_flac. */ +void drflac_free(void* p); + + +/* Structure representing an iterator for vorbis comments in a VORBIS_COMMENT metadata block. */ +typedef struct +{ + drflac_uint32 countRemaining; + const char* pRunningData; +} drflac_vorbis_comment_iterator; + +/* Initializes a vorbis comment iterator. This can be used for iterating over the vorbis comments in a VORBIS_COMMENT + * metadata block. */ +void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const char* pComments); + +/* Goes to the next vorbis comment in the given iterator. If null is returned it means there are no more comments. The + * returned string is NOT null terminated. */ +const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut); + + + +#ifdef __cplusplus +} +#endif +#endif /* dr_flac_h */ + + +/* + * + * IMPLEMENTATION + * + */ +#ifdef DR_FLAC_IMPLEMENTATION +#include +#include + +/* CPU architecture. */ +#if defined(__x86_64__) || defined(_M_X64) +#define DRFLAC_X64 +#elif defined(__i386) || defined(_M_IX86) +#define DRFLAC_X86 +#elif defined(__arm__) || defined(_M_ARM) +#define DRFLAC_ARM +#endif + +/* Compile-time CPU feature support. */ +#if !defined(DR_FLAC_NO_SIMD) && (defined(DRFLAC_X86) || defined(DRFLAC_X64)) + #ifdef _MSC_VER + #if _MSC_VER >= 1400 + #include + static void drflac__cpuid(int info[4], int fid) + { + __cpuid(info, fid); + } + #else + #define DRFLAC_NO_CPUID + #endif + #else + #if defined(__GNUC__) || defined(__clang__) + static void drflac__cpuid(int info[4], int fid) + { + __asm__ ( + "movl %[fid], %%eax\n\t" + "cpuid\n\t" + "movl %%eax, %[info0]\n\t" + "movl %%ebx, %[info1]\n\t" + "movl %%ecx, %[info2]\n\t" + "movl %%edx, %[info3]\n\t" + : [info0] "=rm"(info[0]), + [info1] "=rm"(info[1]), + [info2] "=rm"(info[2]), + [info3] "=rm"(info[3]) + : [fid] "rm"(fid) + : "eax", "ebx", "ecx", "edx" + ); + } + #else + #define DRFLAC_NO_CPUID + #endif + #endif +#else +#define DRFLAC_NO_CPUID +#endif + + +#ifdef __linux__ +#define _BSD_SOURCE +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1500 && (defined(DRFLAC_X86) || defined(DRFLAC_X64)) +#define DRFLAC_HAS_LZCNT_INTRINSIC +#elif (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) +#define DRFLAC_HAS_LZCNT_INTRINSIC +#elif defined(__clang__) + #if __has_builtin(__builtin_clzll) || __has_builtin(__builtin_clzl) + #define DRFLAC_HAS_LZCNT_INTRINSIC + #endif +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1300 +#define DRFLAC_HAS_BYTESWAP_INTRINSIC +#elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +#define DRFLAC_HAS_BYTESWAP_INTRINSIC +#elif defined(__clang__) + #if __has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64) + #define DRFLAC_HAS_BYTESWAP_INTRINSIC + #endif +#endif + +/* Standard library stuff. */ +#ifndef DRFLAC_ASSERT +#include +#define DRFLAC_ASSERT(expression) assert(expression) +#endif +#ifndef DRFLAC_MALLOC +#define DRFLAC_MALLOC(sz) malloc((sz)) +#endif +#ifndef DRFLAC_REALLOC +#define DRFLAC_REALLOC(p, sz) realloc((p), (sz)) +#endif +#ifndef DRFLAC_FREE +#define DRFLAC_FREE(p) free((p)) +#endif +#ifndef DRFLAC_COPY_MEMORY +#define DRFLAC_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz)) +#endif +#ifndef DRFLAC_ZERO_MEMORY +#define DRFLAC_ZERO_MEMORY(p, sz) memset((p), 0, (sz)) +#endif + +#define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */ + +#ifdef _MSC_VER +#define DRFLAC_INLINE __forceinline +#else +#ifdef __GNUC__ +#define DRFLAC_INLINE INLINE __attribute__((always_inline)) +#else +#define DRFLAC_INLINE INLINE +#endif +#endif + +typedef drflac_int32 drflac_result; +#define DRFLAC_SUCCESS 0 +#define DRFLAC_ERROR -1 /* A generic error. */ +#define DRFLAC_INVALID_ARGS -2 +#define DRFLAC_END_OF_STREAM -128 +#define DRFLAC_CRC_MISMATCH -129 + +#define DRFLAC_SUBFRAME_CONSTANT 0 +#define DRFLAC_SUBFRAME_VERBATIM 1 +#define DRFLAC_SUBFRAME_FIXED 8 +#define DRFLAC_SUBFRAME_LPC 32 +#define DRFLAC_SUBFRAME_RESERVED 255 + +#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE 0 +#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 1 + +#define DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT 0 +#define DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE 8 +#define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE 9 +#define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE 10 + + +#define drflac_align(x, a) ((((x) + (a) - 1) / (a)) * (a)) +#define drflac_assert DRFLAC_ASSERT +#define drflac_copy_memory DRFLAC_COPY_MEMORY +#define drflac_zero_memory DRFLAC_ZERO_MEMORY + +/* CPU caps. */ +static drflac_bool32 drflac__gIsLZCNTSupported = DRFLAC_FALSE; +#ifndef DRFLAC_NO_CPUID +static drflac_bool32 drflac__gIsSSE42Supported = DRFLAC_FALSE; +static void drflac__init_cpu_caps() +{ + int info[4] = {0}; + + /* LZCNT */ + drflac__cpuid(info, 0x80000001); + drflac__gIsLZCNTSupported = (info[2] & (1 << 5)) != 0; + + /* SSE4.2 */ + drflac__cpuid(info, 1); + drflac__gIsSSE42Supported = (info[2] & (1 << 19)) != 0; +} +#endif + + +/* Endian Management */ +static DRFLAC_INLINE drflac_bool32 drflac__is_little_endian() +{ +#if defined(DRFLAC_X86) || defined(DRFLAC_X64) + return DRFLAC_TRUE; +#else + int n = 1; + return (*(char*)&n) == 1; +#endif +} + +static DRFLAC_INLINE drflac_uint16 drflac__swap_endian_uint16(drflac_uint16 n) +{ +#ifdef DRFLAC_HAS_BYTESWAP_INTRINSIC + #if defined(_MSC_VER) + return _byteswap_ushort(n); + #elif defined(__GNUC__) || defined(__clang__) + return __builtin_bswap16(n); + #else + #error "This compiler does not support the byte swap intrinsic." + #endif +#else + return ((n & 0xFF00) >> 8) | + ((n & 0x00FF) << 8); +#endif +} + +static DRFLAC_INLINE drflac_uint32 drflac__swap_endian_uint32(drflac_uint32 n) +{ +#ifdef DRFLAC_HAS_BYTESWAP_INTRINSIC + #if defined(_MSC_VER) + return _byteswap_ulong(n); + #elif defined(__GNUC__) || defined(__clang__) + return __builtin_bswap32(n); + #else + #error "This compiler does not support the byte swap intrinsic." + #endif +#else + return ((n & 0xFF000000) >> 24) | + ((n & 0x00FF0000) >> 8) | + ((n & 0x0000FF00) << 8) | + ((n & 0x000000FF) << 24); +#endif +} + +static DRFLAC_INLINE drflac_uint64 drflac__swap_endian_uint64(drflac_uint64 n) +{ +#ifdef DRFLAC_HAS_BYTESWAP_INTRINSIC + #if defined(_MSC_VER) + return _byteswap_uint64(n); + #elif defined(__GNUC__) || defined(__clang__) + return __builtin_bswap64(n); + #else + #error "This compiler does not support the byte swap intrinsic." + #endif +#else + return ((n & (drflac_uint64)0xFF00000000000000) >> 56) | + ((n & (drflac_uint64)0x00FF000000000000) >> 40) | + ((n & (drflac_uint64)0x0000FF0000000000) >> 24) | + ((n & (drflac_uint64)0x000000FF00000000) >> 8) | + ((n & (drflac_uint64)0x00000000FF000000) << 8) | + ((n & (drflac_uint64)0x0000000000FF0000) << 24) | + ((n & (drflac_uint64)0x000000000000FF00) << 40) | + ((n & (drflac_uint64)0x00000000000000FF) << 56); +#endif +} + + +static DRFLAC_INLINE drflac_uint16 drflac__be2host_16(drflac_uint16 n) +{ +#ifdef __linux__ + return be16toh(n); +#else + if (drflac__is_little_endian()) + return drflac__swap_endian_uint16(n); + + return n; +#endif +} + +static DRFLAC_INLINE drflac_uint32 drflac__be2host_32(drflac_uint32 n) +{ +#ifdef __linux__ + return be32toh(n); +#else + if (drflac__is_little_endian()) + return drflac__swap_endian_uint32(n); + + return n; +#endif +} + +static DRFLAC_INLINE drflac_uint64 drflac__be2host_64(drflac_uint64 n) +{ +#ifdef __linux__ + return be64toh(n); +#else + if (drflac__is_little_endian()) + return drflac__swap_endian_uint64(n); + + return n; +#endif +} + + +static DRFLAC_INLINE drflac_uint32 drflac__le2host_32(drflac_uint32 n) +{ +#ifdef __linux__ + return le32toh(n); +#else + if (!drflac__is_little_endian()) + return drflac__swap_endian_uint32(n); + + return n; +#endif +} + + +static DRFLAC_INLINE drflac_uint32 drflac__unsynchsafe_32(drflac_uint32 n) +{ + drflac_uint32 result = 0; + result |= (n & 0x7F000000) >> 3; + result |= (n & 0x007F0000) >> 2; + result |= (n & 0x00007F00) >> 1; + result |= (n & 0x0000007F) >> 0; + + return result; +} + +/* The CRC code below is based on this document: http://zlib.net/crc_v3.txt */ +static drflac_uint8 drflac__crc8_table[] = { + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, + 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, + 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, + 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, + 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, + 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, + 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, + 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, + 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, + 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, + 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 +}; + +static drflac_uint16 drflac__crc16_table[] = { + 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, + 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, + 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, + 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, + 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, + 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, + 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, + 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, + 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, + 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, + 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, + 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, + 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, + 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, + 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, + 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, + 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 +}; + +static DRFLAC_INLINE drflac_uint8 drflac_crc8_byte(drflac_uint8 crc, drflac_uint8 data) +{ + return drflac__crc8_table[crc ^ data]; +} + +static DRFLAC_INLINE drflac_uint8 drflac_crc8(drflac_uint8 crc, drflac_uint32 data, drflac_uint32 count) +{ + +#ifdef DR_FLAC_NO_CRC + (void)crc; + (void)data; + (void)count; + drflac_assert(count <= 32); + return 0; +#else +#if 0 + /* REFERENCE (use of this implementation requires an explicit flush by doing "drflac_crc8(crc, 0, 8);") */ + drflac_uint8 p = 0x07; + for (int i = count-1; i >= 0; --i) + { + drflac_uint8 bit = (data & (1 << i)) >> i; + if (crc & 0x80) + crc = ((crc << 1) | bit) ^ p; + else + crc = ((crc << 1) | bit); + } + return crc; +#else + static drflac_uint64 leftoverDataMaskTable[8] = { + 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F + }; + drflac_uint32 wholeBytes = count >> 3; + drflac_uint32 leftoverBits = count - (wholeBytes*8); + drflac_uint64 leftoverDataMask = leftoverDataMaskTable[leftoverBits]; + drflac_assert(count <= 32); + + switch (wholeBytes) + { + case 4: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits))); + case 3: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits))); + case 2: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits))); + case 1: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits))); + case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc8_table[(crc >> (8 - leftoverBits)) ^ (data & leftoverDataMask)]; + } + return crc; +#endif +#endif +} + +static DRFLAC_INLINE drflac_uint16 drflac_crc16_byte(drflac_uint16 crc, drflac_uint8 data) +{ + return (crc << 8) ^ drflac__crc16_table[(drflac_uint8)(crc >> 8) ^ data]; +} + +static DRFLAC_INLINE drflac_uint16 drflac_crc16_bytes(drflac_uint16 crc, drflac_cache_t data, drflac_uint32 byteCount) +{ + switch (byteCount) + { +#ifdef DRFLAC_64BIT + case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 56) & 0xFF)); + case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 48) & 0xFF)); + case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 40) & 0xFF)); + case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 32) & 0xFF)); +#endif + case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 24) & 0xFF)); + case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 16) & 0xFF)); + case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 8) & 0xFF)); + case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 0) & 0xFF)); + } + + return crc; +} + +static DRFLAC_INLINE drflac_uint16 drflac_crc16__32bit(drflac_uint16 crc, drflac_uint32 data, drflac_uint32 count) +{ + +#ifdef DR_FLAC_NO_CRC + (void)crc; + (void)data; + (void)count; + drflac_assert(count <= 64); + return 0; +#else +#if 0 + /* REFERENCE (use of this implementation requires an explicit flush by doing "drflac_crc16(crc, 0, 16);") */ + drflac_uint16 p = 0x8005; + for (int i = count-1; i >= 0; --i) + { + drflac_uint16 bit = (data & (1ULL << i)) >> i; + if (r & 0x8000) + r = ((r << 1) | bit) ^ p; + else + r = ((r << 1) | bit); + } + + return crc; +#else + drflac_uint32 wholeBytes = count >> 3; + drflac_uint32 leftoverBits = count - (wholeBytes*8); + + static drflac_uint64 leftoverDataMaskTable[8] = { + 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F + }; + drflac_uint64 leftoverDataMask = leftoverDataMaskTable[leftoverBits]; + + drflac_assert(count <= 64); + + switch (wholeBytes) + { + default: + case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits))); + case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits))); + case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits))); + case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits))); + case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)]; + } + return crc; +#endif +#endif +} + +static DRFLAC_INLINE drflac_uint16 drflac_crc16__64bit(drflac_uint16 crc, drflac_uint64 data, drflac_uint32 count) +{ + +#ifdef DR_FLAC_NO_CRC + (void)crc; + (void)data; + (void)count; + drflac_assert(count <= 64); + return 0; +#else + drflac_uint32 wholeBytes = count >> 3; + drflac_uint32 leftoverBits = count - (wholeBytes*8); + + static drflac_uint64 leftoverDataMaskTable[8] = { + 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F + }; + drflac_uint64 leftoverDataMask = leftoverDataMaskTable[leftoverBits]; + + drflac_assert(count <= 64); + + switch (wholeBytes) + { + default: + case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0xFF00000000000000 << leftoverBits)) >> (56 + leftoverBits))); + case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0x00FF000000000000 << leftoverBits)) >> (48 + leftoverBits))); + case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0x0000FF0000000000 << leftoverBits)) >> (40 + leftoverBits))); + case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0x000000FF00000000 << leftoverBits)) >> (32 + leftoverBits))); + case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0x00000000FF000000 << leftoverBits)) >> (24 + leftoverBits))); + case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0x0000000000FF0000 << leftoverBits)) >> (16 + leftoverBits))); + case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0x000000000000FF00 << leftoverBits)) >> ( 8 + leftoverBits))); + case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & ((drflac_uint64)0x00000000000000FF << leftoverBits)) >> ( 0 + leftoverBits))); + case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)]; + } + return crc; +#endif +} + + +static DRFLAC_INLINE drflac_uint16 drflac_crc16(drflac_uint16 crc, drflac_cache_t data, drflac_uint32 count) +{ +#ifdef DRFLAC_64BIT + return drflac_crc16__64bit(crc, data, count); +#else + return drflac_crc16__32bit(crc, data, count); +#endif +} + + +#ifdef DRFLAC_64BIT +#define drflac__be2host__cache_line drflac__be2host_64 +#else +#define drflac__be2host__cache_line drflac__be2host_32 +#endif + +/* BIT READING ATTEMPT #2 + * + * This uses a 32- or 64-bit bit-shifted cache - as bits are read, the cache is shifted such that the first valid bit is sitting + * on the most significant bit. It uses the notion of an L1 and L2 cache (borrowed from CPU architecture), where the L1 cache + * is a 32- or 64-bit unsigned integer (depending on whether or not a 32- or 64-bit build is being compiled) and the L2 is an + * array of "cache lines", with each cache line being the same size as the L1. The L2 is a buffer of about 4KB and is where data + * from onRead() is read into. + */ +#define DRFLAC_CACHE_L1_SIZE_BYTES(bs) (sizeof((bs)->cache)) +#define DRFLAC_CACHE_L1_SIZE_BITS(bs) (sizeof((bs)->cache)*8) +#define DRFLAC_CACHE_L1_BITS_REMAINING(bs) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - ((bs)->consumedBits)) +#ifdef DRFLAC_64BIT +#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~(((drflac_uint64)-1LL) >> (_bitCount))) +#else +#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~(((drflac_uint32)-1) >> (_bitCount))) +#endif +#define DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (_bitCount)) +#define DRFLAC_CACHE_L1_SELECT(bs, _bitCount) (((bs)->cache) & DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount)) +#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SELECT((bs), _bitCount) >> DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), _bitCount)) +#define DRFLAC_CACHE_L2_SIZE_BYTES(bs) (sizeof((bs)->cacheL2)) +#define DRFLAC_CACHE_L2_LINE_COUNT(bs) (DRFLAC_CACHE_L2_SIZE_BYTES(bs) / sizeof((bs)->cacheL2[0])) +#define DRFLAC_CACHE_L2_LINES_REMAINING(bs) (DRFLAC_CACHE_L2_LINE_COUNT(bs) - (bs)->nextL2Line) + + +#ifndef DR_FLAC_NO_CRC +static DRFLAC_INLINE void drflac__reset_crc16(drflac_bs* bs) +{ + bs->crc16 = 0; + bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3; +} + +static DRFLAC_INLINE void drflac__update_crc16(drflac_bs* bs) +{ + bs->crc16 = drflac_crc16_bytes(bs->crc16, bs->crc16Cache, DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bs->crc16CacheIgnoredBytes); + bs->crc16CacheIgnoredBytes = 0; +} + +static DRFLAC_INLINE drflac_uint16 drflac__flush_crc16(drflac_bs* bs) +{ + /* We should never be flushing in a situation where we are not aligned on a byte boundary. */ + drflac_assert((DRFLAC_CACHE_L1_BITS_REMAINING(bs) & 7) == 0); + + /* The bits that were read from the L1 cache need to be accumulated. The number of bytes needing to be accumulated is determined + * by the number of bits that have been consumed. */ + if (DRFLAC_CACHE_L1_BITS_REMAINING(bs) == 0) + drflac__update_crc16(bs); + else + { + /* We only accumulate the consumed bits. */ + bs->crc16 = drflac_crc16_bytes(bs->crc16, bs->crc16Cache >> DRFLAC_CACHE_L1_BITS_REMAINING(bs), (bs->consumedBits >> 3) - bs->crc16CacheIgnoredBytes); + + /* The bits that we just accumulated should never be accumulated again. We need to keep track of how many bytes were accumulated + * so we can handle that later. */ + bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3; + } + + return bs->crc16; +} +#endif + +static DRFLAC_INLINE drflac_bool32 drflac__reload_l1_cache_from_l2(drflac_bs* bs) +{ + size_t alignedL1LineCount; + size_t bytesRead; + /* Fast path. Try loading straight from L2. */ + if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) + { + bs->cache = bs->cacheL2[bs->nextL2Line++]; + return DRFLAC_TRUE; + } + + /* If we get here it means we've run out of data in the L2 cache. We'll need to fetch more from the client, if there's + * any left. */ + if (bs->unalignedByteCount > 0) + return DRFLAC_FALSE; /* If we have any unaligned bytes it means there's no more aligned bytes left in the client. */ + + bytesRead = bs->onRead(bs->pUserData, bs->cacheL2, DRFLAC_CACHE_L2_SIZE_BYTES(bs)); + + bs->nextL2Line = 0; + if (bytesRead == DRFLAC_CACHE_L2_SIZE_BYTES(bs)) + { + bs->cache = bs->cacheL2[bs->nextL2Line++]; + return DRFLAC_TRUE; + } + + + /* If we get here it means we were unable to retrieve enough data to fill the entire L2 cache. It probably + * means we've just reached the end of the file. We need to move the valid data down to the end of the buffer + * and adjust the index of the next line accordingly. Also keep in mind that the L2 cache must be aligned to + * the size of the L1 so we'll need to seek backwards by any misaligned bytes. + */ + alignedL1LineCount = bytesRead / DRFLAC_CACHE_L1_SIZE_BYTES(bs); + + /* We need to keep track of any unaligned bytes for later use. */ + bs->unalignedByteCount = bytesRead - (alignedL1LineCount * DRFLAC_CACHE_L1_SIZE_BYTES(bs)); + if (bs->unalignedByteCount > 0) + bs->unalignedCache = bs->cacheL2[alignedL1LineCount]; + + if (alignedL1LineCount > 0) + { + size_t i; + size_t offset = DRFLAC_CACHE_L2_LINE_COUNT(bs) - alignedL1LineCount; + for (i = alignedL1LineCount; i > 0; --i) + bs->cacheL2[i-1 + offset] = bs->cacheL2[i-1]; + + bs->nextL2Line = (drflac_uint32)offset; + bs->cache = bs->cacheL2[bs->nextL2Line++]; + return DRFLAC_TRUE; + } + + /* If we get into this branch it means we weren't able to load any L1-aligned data. */ + bs->nextL2Line = DRFLAC_CACHE_L2_LINE_COUNT(bs); + return DRFLAC_FALSE; +} + +static drflac_bool32 drflac__reload_cache(drflac_bs* bs) +{ + size_t bytesRead; + +#ifndef DR_FLAC_NO_CRC + drflac__update_crc16(bs); +#endif + + /* Fast path. Try just moving the next value in the L2 cache to the L1 cache. */ + if (drflac__reload_l1_cache_from_l2(bs)) + { + bs->cache = drflac__be2host__cache_line(bs->cache); + bs->consumedBits = 0; +#ifndef DR_FLAC_NO_CRC + bs->crc16Cache = bs->cache; +#endif + return DRFLAC_TRUE; + } + + /* Slow path. */ + + /* If we get here it means we have failed to load the L1 cache from the L2. Likely we've just reached the end of the stream and the last + * few bytes did not meet the alignment requirements for the L2 cache. In this case we need to fall back to a slower path and read the + * data from the unaligned cache. */ + bytesRead = bs->unalignedByteCount; + if (bytesRead == 0) + return DRFLAC_FALSE; + + drflac_assert(bytesRead < DRFLAC_CACHE_L1_SIZE_BYTES(bs)); + bs->consumedBits = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bytesRead) * 8; + + bs->cache = drflac__be2host__cache_line(bs->unalignedCache); + bs->cache &= DRFLAC_CACHE_L1_SELECTION_MASK(DRFLAC_CACHE_L1_SIZE_BITS(bs) - bs->consumedBits); /* <-- Make sure the consumed bits are always set to zero. Other parts of the library depend on this property. */ + bs->unalignedByteCount = 0; /* <-- At this point the unaligned bytes have been moved into the cache and we thus have no more unaligned bytes. */ + +#ifndef DR_FLAC_NO_CRC + bs->crc16Cache = bs->cache >> bs->consumedBits; + bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3; +#endif + return DRFLAC_TRUE; +} + +static void drflac__reset_cache(drflac_bs* bs) +{ + bs->nextL2Line = DRFLAC_CACHE_L2_LINE_COUNT(bs); /* <-- This clears the L2 cache. */ + bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs); /* <-- This clears the L1 cache. */ + bs->cache = 0; + bs->unalignedByteCount = 0; /* <-- This clears the trailing unaligned bytes. */ + bs->unalignedCache = 0; + +#ifndef DR_FLAC_NO_CRC + bs->crc16Cache = 0; + bs->crc16CacheIgnoredBytes = 0; +#endif +} + + +static DRFLAC_INLINE drflac_bool32 drflac__read_uint32(drflac_bs* bs, unsigned int bitCount, drflac_uint32* pResultOut) +{ + drflac_assert(bs != NULL); + drflac_assert(pResultOut != NULL); + drflac_assert(bitCount > 0); + drflac_assert(bitCount <= 32); + + if (bs->consumedBits == DRFLAC_CACHE_L1_SIZE_BITS(bs)) + { + if (!drflac__reload_cache(bs)) + return DRFLAC_FALSE; + } + + if (bitCount <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) + { + if (bitCount < DRFLAC_CACHE_L1_SIZE_BITS(bs)) + { + *pResultOut = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount); + bs->consumedBits += bitCount; + bs->cache <<= bitCount; + } else { + *pResultOut = (drflac_uint32)bs->cache; + bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs); + bs->cache = 0; + } + return DRFLAC_TRUE; + } else { + /* It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them. */ + drflac_uint32 bitCountHi = DRFLAC_CACHE_L1_BITS_REMAINING(bs); + drflac_uint32 bitCountLo = bitCount - bitCountHi; + drflac_uint32 resultHi = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountHi); + + if (!drflac__reload_cache(bs)) + return DRFLAC_FALSE; + + *pResultOut = (resultHi << bitCountLo) | DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountLo); + bs->consumedBits += bitCountLo; + bs->cache <<= bitCountLo; + return DRFLAC_TRUE; + } +} + +static drflac_bool32 drflac__read_int32(drflac_bs* bs, unsigned int bitCount, drflac_int32* pResult) +{ + drflac_uint32 result; + drflac_uint32 signbit; + + drflac_assert(bs != NULL); + drflac_assert(pResult != NULL); + drflac_assert(bitCount > 0); + drflac_assert(bitCount <= 32); + + if (!drflac__read_uint32(bs, bitCount, &result)) + return DRFLAC_FALSE; + + signbit = ((result >> (bitCount-1)) & 0x01); + result |= (~signbit + 1) << bitCount; + + *pResult = (drflac_int32)result; + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__read_uint64(drflac_bs* bs, unsigned int bitCount, drflac_uint64* pResultOut) +{ + drflac_uint32 resultHi; + drflac_uint32 resultLo; + + drflac_assert(bitCount <= 64); + drflac_assert(bitCount > 32); + + if (!drflac__read_uint32(bs, bitCount - 32, &resultHi)) + return DRFLAC_FALSE; + + if (!drflac__read_uint32(bs, 32, &resultLo)) + return DRFLAC_FALSE; + + *pResultOut = (((drflac_uint64)resultHi) << 32) | ((drflac_uint64)resultLo); + return DRFLAC_TRUE; +} + +/* Function below is unused, but leaving it here in case I need to quickly add it again. */ +#if 0 +static drflac_bool32 drflac__read_int64(drflac_bs* bs, unsigned int bitCount, drflac_int64* pResultOut) +{ + drflac_assert(bitCount <= 64); + + drflac_uint64 result; + if (!drflac__read_uint64(bs, bitCount, &result)) + return DRFLAC_FALSE; + + drflac_uint64 signbit = ((result >> (bitCount-1)) & 0x01); + result |= (~signbit + 1) << bitCount; + + *pResultOut = (drflac_int64)result; + return DRFLAC_TRUE; +} +#endif + +static drflac_bool32 drflac__read_uint16(drflac_bs* bs, unsigned int bitCount, drflac_uint16* pResult) +{ + drflac_uint32 result; + + drflac_assert(bs != NULL); + drflac_assert(pResult != NULL); + drflac_assert(bitCount > 0); + drflac_assert(bitCount <= 16); + + if (!drflac__read_uint32(bs, bitCount, &result)) + return DRFLAC_FALSE; + + *pResult = (drflac_uint16)result; + return DRFLAC_TRUE; +} + +#if 0 +static drflac_bool32 drflac__read_int16(drflac_bs* bs, unsigned int bitCount, drflac_int16* pResult) +{ + drflac_int32 result; + + drflac_assert(bs != NULL); + drflac_assert(pResult != NULL); + drflac_assert(bitCount > 0); + drflac_assert(bitCount <= 16); + + if (!drflac__read_int32(bs, bitCount, &result)) + return DRFLAC_FALSE; + + *pResult = (drflac_int16)result; + return DRFLAC_TRUE; +} +#endif + +static drflac_bool32 drflac__read_uint8(drflac_bs* bs, unsigned int bitCount, drflac_uint8* pResult) +{ + drflac_uint32 result; + + drflac_assert(bs != NULL); + drflac_assert(pResult != NULL); + drflac_assert(bitCount > 0); + drflac_assert(bitCount <= 8); + + if (!drflac__read_uint32(bs, bitCount, &result)) + return DRFLAC_FALSE; + + *pResult = (drflac_uint8)result; + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__read_int8(drflac_bs* bs, unsigned int bitCount, drflac_int8* pResult) +{ + drflac_int32 result; + + drflac_assert(bs != NULL); + drflac_assert(pResult != NULL); + drflac_assert(bitCount > 0); + drflac_assert(bitCount <= 8); + + if (!drflac__read_int32(bs, bitCount, &result)) + return DRFLAC_FALSE; + + *pResult = (drflac_int8)result; + return DRFLAC_TRUE; +} + + +static drflac_bool32 drflac__seek_bits(drflac_bs* bs, size_t bitsToSeek) +{ + if (bitsToSeek <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) + { + bs->consumedBits += (drflac_uint32)bitsToSeek; + bs->cache <<= bitsToSeek; + return DRFLAC_TRUE; + } + + /* It straddles the cached data. This function isn't called too frequently so I'm favouring simplicity here. */ + bitsToSeek -= DRFLAC_CACHE_L1_BITS_REMAINING(bs); + bs->consumedBits += DRFLAC_CACHE_L1_BITS_REMAINING(bs); + bs->cache = 0; + + /* Simple case. Seek in groups of the same number as bits that fit within a cache line. */ +#ifdef DRFLAC_64BIT + while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) + { + drflac_uint64 bin; + if (!drflac__read_uint64(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) + return DRFLAC_FALSE; + bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs); + } +#else + while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) + { + drflac_uint32 bin; + if (!drflac__read_uint32(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) + return DRFLAC_FALSE; + bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs); + } +#endif + + /* Whole leftover bytes. */ + while (bitsToSeek >= 8) + { + drflac_uint8 bin; + if (!drflac__read_uint8(bs, 8, &bin)) + return DRFLAC_FALSE; + bitsToSeek -= 8; + } + + /* Leftover bits. */ + if (bitsToSeek > 0) + { + drflac_uint8 bin; + if (!drflac__read_uint8(bs, (drflac_uint32)bitsToSeek, &bin)) + return DRFLAC_FALSE; + bitsToSeek = 0; /* <-- Necessary for the assert below. */ + } + + drflac_assert(bitsToSeek == 0); + return DRFLAC_TRUE; +} + + +/* This function moves the bit streamer to the first bit after the sync code (bit 15 of the of the frame header). It will also update the CRC-16. */ +static drflac_bool32 drflac__find_and_seek_to_next_sync_code(drflac_bs* bs) +{ + drflac_assert(bs != NULL); + + /* The sync code is always aligned to 8 bits. This is convenient for us because it means we can do byte-aligned movements. The first + * thing to do is align to the next byte. */ + if (!drflac__seek_bits(bs, DRFLAC_CACHE_L1_BITS_REMAINING(bs) & 7)) + return DRFLAC_FALSE; + + for (;;) + { + drflac_uint8 hi; + +#ifndef DR_FLAC_NO_CRC + drflac__reset_crc16(bs); +#endif + + if (!drflac__read_uint8(bs, 8, &hi)) + return DRFLAC_FALSE; + + if (hi == 0xFF) + { + drflac_uint8 lo; + if (!drflac__read_uint8(bs, 6, &lo)) + return DRFLAC_FALSE; + + if (lo == 0x3E) + return DRFLAC_TRUE; + + if (!drflac__seek_bits(bs, DRFLAC_CACHE_L1_BITS_REMAINING(bs) & 7)) + return DRFLAC_FALSE; + } + } + +#if 0 + /* Should never get here. */ + return DRFLAC_FALSE; +#endif +} + + +#if !defined(DR_FLAC_NO_SIMD) && defined(DRFLAC_HAS_LZCNT_INTRINSIC) +#define DRFLAC_IMPLEMENT_CLZ_LZCNT +#endif +#if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(DRFLAC_X64) || defined(DRFLAC_X86)) +#define DRFLAC_IMPLEMENT_CLZ_MSVC +#endif + +static DRFLAC_INLINE drflac_uint32 drflac__clz_software(drflac_cache_t x) +{ + static drflac_uint32 clz_table_4[] = { + 0, + 4, + 3, 3, + 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + drflac_uint32 n = clz_table_4[x >> (sizeof(x)*8 - 4)]; + + if (n == 0) + { +#ifdef DRFLAC_64BIT + if ((x & 0xFFFFFFFF00000000ULL) == 0) { n = 32; x <<= 32; } + if ((x & 0xFFFF000000000000ULL) == 0) { n += 16; x <<= 16; } + if ((x & 0xFF00000000000000ULL) == 0) { n += 8; x <<= 8; } + if ((x & 0xF000000000000000ULL) == 0) { n += 4; x <<= 4; } +#else + if ((x & 0xFFFF0000) == 0) { n = 16; x <<= 16; } + if ((x & 0xFF000000) == 0) { n += 8; x <<= 8; } + if ((x & 0xF0000000) == 0) { n += 4; x <<= 4; } +#endif + n += clz_table_4[x >> (sizeof(x)*8 - 4)]; + } + + return n - 1; +} + +#ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT +static DRFLAC_INLINE drflac_bool32 drflac__is_lzcnt_supported() +{ + /* If the compiler itself does not support the intrinsic then we'll need to return false. */ +#ifdef DRFLAC_HAS_LZCNT_INTRINSIC + return drflac__gIsLZCNTSupported; +#else + return DRFLAC_FALSE; +#endif +} + +static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x) +{ +#if defined(_MSC_VER) && !defined(__clang__) +#ifdef DRFLAC_64BIT + return (drflac_uint32)__lzcnt64(x); +#else + return (drflac_uint32)__lzcnt(x); +#endif +#else +#if defined(__GNUC__) || defined(__clang__) +#ifdef DRFLAC_64BIT + return (drflac_uint32)__builtin_clzll((unsigned long long)x); +#else + return (drflac_uint32)__builtin_clzl((unsigned long)x); +#endif +#else + /* Unsupported compiler. */ +#error "This compiler does not support the lzcnt intrinsic." +#endif +#endif +} +#endif + +#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC +static DRFLAC_INLINE drflac_uint32 drflac__clz_msvc(drflac_cache_t x) +{ + drflac_uint32 n; +#ifdef DRFLAC_64BIT + _BitScanReverse64((unsigned long*)&n, x); +#else + _BitScanReverse((unsigned long*)&n, x); +#endif + return sizeof(x)*8 - n - 1; +} +#endif + +static DRFLAC_INLINE drflac_uint32 drflac__clz(drflac_cache_t x) +{ + /* This function assumes at least one bit is set. Checking for 0 needs to be done at a higher level, outside this function. */ +#ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT + if (drflac__is_lzcnt_supported()) + return drflac__clz_lzcnt(x); +#endif + +#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC + return drflac__clz_msvc(x); +#else + return drflac__clz_software(x); +#endif +} + +static INLINE drflac_bool32 drflac__seek_past_next_set_bit(drflac_bs* bs, unsigned int* pOffsetOut) +{ + drflac_uint32 setBitOffsetPlus1; + drflac_uint32 zeroCounter = 0; + while (bs->cache == 0) + { + zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs); + if (!drflac__reload_cache(bs)) + return DRFLAC_FALSE; + } + + setBitOffsetPlus1 = drflac__clz(bs->cache); + zeroCounter += setBitOffsetPlus1; + setBitOffsetPlus1 += 1; + + bs->consumedBits += setBitOffsetPlus1; + bs->cache <<= setBitOffsetPlus1; + + *pOffsetOut = zeroCounter + setBitOffsetPlus1 - 1; + return DRFLAC_TRUE; +} + + + +static drflac_bool32 drflac__seek_to_byte(drflac_bs* bs, drflac_uint64 offsetFromStart) +{ + drflac_assert(bs != NULL); + drflac_assert(offsetFromStart > 0); + + /* Seeking from the start is not quite as trivial as it sounds because the onSeek callback takes a signed 32-bit integer (which + * is intentional because it simplifies the implementation of the onSeek callbacks), however offsetFromStart is unsigned 64-bit. + * To resolve we just need to do an initial seek from the start, and then a series of offset seeks to make up the remainder. */ + if (offsetFromStart > 0x7FFFFFFF) + { + drflac_uint64 bytesRemaining = offsetFromStart; + if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) + return DRFLAC_FALSE; + bytesRemaining -= 0x7FFFFFFF; + + while (bytesRemaining > 0x7FFFFFFF) + { + if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) + return DRFLAC_FALSE; + bytesRemaining -= 0x7FFFFFFF; + } + + if (bytesRemaining > 0) + { + if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) + return DRFLAC_FALSE; + } + } + else + { + if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) + return DRFLAC_FALSE; + } + + /* The cache should be reset to force a reload of fresh data from the client. */ + drflac__reset_cache(bs); + return DRFLAC_TRUE; +} + + +static drflac_result drflac__read_utf8_coded_number(drflac_bs* bs, drflac_uint64* pNumberOut, drflac_uint8* pCRCOut) +{ + drflac_uint64 result; + int i; + int byteCount = 1; + unsigned char utf8[7] = {0}; + drflac_uint8 crc; + + drflac_assert(bs != NULL); + drflac_assert(pNumberOut != NULL); + + crc = *pCRCOut; + + if (!drflac__read_uint8(bs, 8, utf8)) + { + *pNumberOut = 0; + return DRFLAC_END_OF_STREAM; + } + crc = drflac_crc8(crc, utf8[0], 8); + + if ((utf8[0] & 0x80) == 0) + { + *pNumberOut = utf8[0]; + *pCRCOut = crc; + return DRFLAC_SUCCESS; + } + + if ((utf8[0] & 0xE0) == 0xC0) + byteCount = 2; + else if ((utf8[0] & 0xF0) == 0xE0) + byteCount = 3; + else if ((utf8[0] & 0xF8) == 0xF0) + byteCount = 4; + else if ((utf8[0] & 0xFC) == 0xF8) + byteCount = 5; + else if ((utf8[0] & 0xFE) == 0xFC) + byteCount = 6; + else if ((utf8[0] & 0xFF) == 0xFE) + byteCount = 7; + else + { + *pNumberOut = 0; + return DRFLAC_CRC_MISMATCH; /* Bad UTF-8 encoding. */ + } + + /* Read extra bytes. */ + drflac_assert(byteCount > 1); + + result = (drflac_uint64)(utf8[0] & (0xFF >> (byteCount + 1))); + for (i = 1; i < byteCount; ++i) + { + if (!drflac__read_uint8(bs, 8, utf8 + i)) + { + *pNumberOut = 0; + return DRFLAC_END_OF_STREAM; + } + crc = drflac_crc8(crc, utf8[i], 8); + + result = (result << 6) | (utf8[i] & 0x3F); + } + + *pNumberOut = result; + *pCRCOut = crc; + return DRFLAC_SUCCESS; +} + + + + +/* The next two functions are responsible for calculating the prediction. + * + * When the bits per sample is >16 we need to use 64-bit integer arithmetic because otherwise we'll run out of precision. It's + * safe to assume this will be slower on 32-bit platforms so we use a more optimal solution when the bits per sample is <=16. + */ +static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_32(drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples) +{ + drflac_int32 prediction = 0; + + drflac_assert(order <= 32); + + /* 32-bit version. + + * VC++ optimizes this to a single jmp. I've not yet verified this for other compilers. */ + + switch (order) + { + case 32: prediction += coefficients[31] * pDecodedSamples[-32]; + case 31: prediction += coefficients[30] * pDecodedSamples[-31]; + case 30: prediction += coefficients[29] * pDecodedSamples[-30]; + case 29: prediction += coefficients[28] * pDecodedSamples[-29]; + case 28: prediction += coefficients[27] * pDecodedSamples[-28]; + case 27: prediction += coefficients[26] * pDecodedSamples[-27]; + case 26: prediction += coefficients[25] * pDecodedSamples[-26]; + case 25: prediction += coefficients[24] * pDecodedSamples[-25]; + case 24: prediction += coefficients[23] * pDecodedSamples[-24]; + case 23: prediction += coefficients[22] * pDecodedSamples[-23]; + case 22: prediction += coefficients[21] * pDecodedSamples[-22]; + case 21: prediction += coefficients[20] * pDecodedSamples[-21]; + case 20: prediction += coefficients[19] * pDecodedSamples[-20]; + case 19: prediction += coefficients[18] * pDecodedSamples[-19]; + case 18: prediction += coefficients[17] * pDecodedSamples[-18]; + case 17: prediction += coefficients[16] * pDecodedSamples[-17]; + case 16: prediction += coefficients[15] * pDecodedSamples[-16]; + case 15: prediction += coefficients[14] * pDecodedSamples[-15]; + case 14: prediction += coefficients[13] * pDecodedSamples[-14]; + case 13: prediction += coefficients[12] * pDecodedSamples[-13]; + case 12: prediction += coefficients[11] * pDecodedSamples[-12]; + case 11: prediction += coefficients[10] * pDecodedSamples[-11]; + case 10: prediction += coefficients[ 9] * pDecodedSamples[-10]; + case 9: prediction += coefficients[ 8] * pDecodedSamples[- 9]; + case 8: prediction += coefficients[ 7] * pDecodedSamples[- 8]; + case 7: prediction += coefficients[ 6] * pDecodedSamples[- 7]; + case 6: prediction += coefficients[ 5] * pDecodedSamples[- 6]; + case 5: prediction += coefficients[ 4] * pDecodedSamples[- 5]; + case 4: prediction += coefficients[ 3] * pDecodedSamples[- 4]; + case 3: prediction += coefficients[ 2] * pDecodedSamples[- 3]; + case 2: prediction += coefficients[ 1] * pDecodedSamples[- 2]; + case 1: prediction += coefficients[ 0] * pDecodedSamples[- 1]; + } + + return (drflac_int32)(prediction >> shift); +} + +static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_64(drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples) +{ + drflac_int64 prediction; + drflac_assert(order <= 32); + + /* 64-bit version. + + * This method is faster on the 32-bit build when compiling with VC++. See note below. + */ + +#ifndef DRFLAC_64BIT + if (order == 8) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6]; + prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7]; + prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8]; + } + else if (order == 7) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6]; + prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7]; + } + else if (order == 3) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + } + else if (order == 6) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6]; + } + else if (order == 5) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + } + else if (order == 4) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + } + else if (order == 12) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6]; + prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7]; + prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8]; + prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9]; + prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10]; + prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11]; + prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12]; + } + else if (order == 2) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + } + else if (order == 1) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + } + else if (order == 10) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6]; + prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7]; + prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8]; + prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9]; + prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10]; + } + else if (order == 9) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6]; + prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7]; + prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8]; + prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9]; + } + else if (order == 11) + { + prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1]; + prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2]; + prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3]; + prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4]; + prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5]; + prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6]; + prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7]; + prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8]; + prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9]; + prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10]; + prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11]; + } + else + { + int j; + prediction = 0; + for (j = 0; j < (int)order; ++j) + prediction += coefficients[j] * (drflac_int64)pDecodedSamples[-j-1]; + } +#endif + + /* VC++ optimizes this to a single jmp instruction, but only the 64-bit build. The 32-bit build generates less efficient code for some + * reason. The ugly version above is faster so we'll just switch between the two depending on the target platform. */ +#ifdef DRFLAC_64BIT + prediction = 0; + + switch (order) + { + case 32: prediction += coefficients[31] * (drflac_int64)pDecodedSamples[-32]; + case 31: prediction += coefficients[30] * (drflac_int64)pDecodedSamples[-31]; + case 30: prediction += coefficients[29] * (drflac_int64)pDecodedSamples[-30]; + case 29: prediction += coefficients[28] * (drflac_int64)pDecodedSamples[-29]; + case 28: prediction += coefficients[27] * (drflac_int64)pDecodedSamples[-28]; + case 27: prediction += coefficients[26] * (drflac_int64)pDecodedSamples[-27]; + case 26: prediction += coefficients[25] * (drflac_int64)pDecodedSamples[-26]; + case 25: prediction += coefficients[24] * (drflac_int64)pDecodedSamples[-25]; + case 24: prediction += coefficients[23] * (drflac_int64)pDecodedSamples[-24]; + case 23: prediction += coefficients[22] * (drflac_int64)pDecodedSamples[-23]; + case 22: prediction += coefficients[21] * (drflac_int64)pDecodedSamples[-22]; + case 21: prediction += coefficients[20] * (drflac_int64)pDecodedSamples[-21]; + case 20: prediction += coefficients[19] * (drflac_int64)pDecodedSamples[-20]; + case 19: prediction += coefficients[18] * (drflac_int64)pDecodedSamples[-19]; + case 18: prediction += coefficients[17] * (drflac_int64)pDecodedSamples[-18]; + case 17: prediction += coefficients[16] * (drflac_int64)pDecodedSamples[-17]; + case 16: prediction += coefficients[15] * (drflac_int64)pDecodedSamples[-16]; + case 15: prediction += coefficients[14] * (drflac_int64)pDecodedSamples[-15]; + case 14: prediction += coefficients[13] * (drflac_int64)pDecodedSamples[-14]; + case 13: prediction += coefficients[12] * (drflac_int64)pDecodedSamples[-13]; + case 12: prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12]; + case 11: prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11]; + case 10: prediction += coefficients[ 9] * (drflac_int64)pDecodedSamples[-10]; + case 9: prediction += coefficients[ 8] * (drflac_int64)pDecodedSamples[- 9]; + case 8: prediction += coefficients[ 7] * (drflac_int64)pDecodedSamples[- 8]; + case 7: prediction += coefficients[ 6] * (drflac_int64)pDecodedSamples[- 7]; + case 6: prediction += coefficients[ 5] * (drflac_int64)pDecodedSamples[- 6]; + case 5: prediction += coefficients[ 4] * (drflac_int64)pDecodedSamples[- 5]; + case 4: prediction += coefficients[ 3] * (drflac_int64)pDecodedSamples[- 4]; + case 3: prediction += coefficients[ 2] * (drflac_int64)pDecodedSamples[- 3]; + case 2: prediction += coefficients[ 1] * (drflac_int64)pDecodedSamples[- 2]; + case 1: prediction += coefficients[ 0] * (drflac_int64)pDecodedSamples[- 1]; + } +#endif + + return (drflac_int32)(prediction >> shift); +} + +#if 0 +/* Reference implementation for reading and decoding samples with residual. This is intentionally left unoptimized for the + * sake of readability and should only be used as a reference. */ +static drflac_bool32 drflac__decode_samples_with_residual__rice__reference(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut) +{ + drflac_assert(bs != NULL); + drflac_assert(count > 0); + drflac_assert(pSamplesOut != NULL); + + for (drflac_uint32 i = 0; i < count; ++i) + { + drflac_uint32 zeroCounter = 0; + for (;;) + { + drflac_uint8 bit; + if (!drflac__read_uint8(bs, 1, &bit)) + return DRFLAC_FALSE; + + if (bit == 0) + zeroCounter += 1; + else + break; + } + + drflac_uint32 decodedRice; + if (riceParam > 0) + { + if (!drflac__read_uint32(bs, riceParam, &decodedRice)) + return DRFLAC_FALSE; + } + else + decodedRice = 0; + + decodedRice |= (zeroCounter << riceParam); + if ((decodedRice & 0x01)) + decodedRice = ~(decodedRice >> 1); + else + decodedRice = (decodedRice >> 1); + + + if (bitsPerSample > 16) + pSamplesOut[i] = decodedRice + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i); + else + pSamplesOut[i] = decodedRice + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i); + } + + return DRFLAC_TRUE; +} +#endif + +#if 0 +static drflac_bool32 drflac__read_rice_parts__reference(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut) +{ + drflac_uint32 zeroCounter = 0; + for (;;) { + drflac_uint8 bit; + if (!drflac__read_uint8(bs, 1, &bit)) + return DRFLAC_FALSE; + + if (bit == 0) + zeroCounter += 1; + else + break; + } + + drflac_uint32 decodedRice; + if (riceParam > 0) + { + if (!drflac__read_uint32(bs, riceParam, &decodedRice)) + return DRFLAC_FALSE; + } + else + decodedRice = 0; + + *pZeroCounterOut = zeroCounter; + *pRiceParamPartOut = decodedRice; + return DRFLAC_TRUE; +} +#endif + +static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut) +{ + drflac_uint32 riceLength; + drflac_uint32 riceParamPart; + drflac_uint32 setBitOffsetPlus1; + drflac_cache_t riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParam); + drflac_cache_t resultHiShift = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParam; + drflac_uint32 zeroCounter = 0; + while (bs->cache == 0) { + zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs); + if (!drflac__reload_cache(bs)) + return DRFLAC_FALSE; + } + + setBitOffsetPlus1 = drflac__clz(bs->cache); + zeroCounter += setBitOffsetPlus1; + setBitOffsetPlus1 += 1; + + riceLength = setBitOffsetPlus1 + riceParam; + + if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING(bs)) + { + riceParamPart = (drflac_uint32)((bs->cache & (riceParamMask >> setBitOffsetPlus1)) >> (DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceLength)); + + bs->consumedBits += riceLength; + bs->cache <<= riceLength; + } + else + { + drflac_uint32 bitCountLo; + drflac_cache_t resultHi; + + bs->consumedBits += riceLength; + if (setBitOffsetPlus1 < DRFLAC_CACHE_L1_SIZE_BITS(bs)) + bs->cache <<= setBitOffsetPlus1; + + /* It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them. */ + bitCountLo = bs->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS(bs); + resultHi = bs->cache & riceParamMask; /* <-- This mask is OK because all bits after the first bits are always zero. */ + + if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) { +#ifndef DR_FLAC_NO_CRC + drflac__update_crc16(bs); +#endif + bs->cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]); + bs->consumedBits = 0; +#ifndef DR_FLAC_NO_CRC + bs->crc16Cache = bs->cache; +#endif + } else { + /* Slow path. We need to fetch more data from the client. */ + if (!drflac__reload_cache(bs)) { + return DRFLAC_FALSE; + } + } + + riceParamPart = (drflac_uint32)((resultHi >> resultHiShift) | DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountLo)); + + bs->consumedBits += bitCountLo; + bs->cache <<= bitCountLo; + } + + *pZeroCounterOut = zeroCounter; + *pRiceParamPartOut = riceParamPart; + return DRFLAC_TRUE; +} + + +static drflac_bool32 drflac__decode_samples_with_residual__rice__simple(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut) +{ + drflac_uint32 zeroCountPart; + drflac_uint32 riceParamPart; + drflac_uint32 i = 0; + + drflac_assert(bs != NULL); + drflac_assert(count > 0); + drflac_assert(pSamplesOut != NULL); + + while (i < count) + { + static drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF}; + /* Rice extraction. */ + if (!drflac__read_rice_parts(bs, riceParam, &zeroCountPart, &riceParamPart)) + return DRFLAC_FALSE; + + /* Rice reconstruction. */ + + riceParamPart |= (zeroCountPart << riceParam); + riceParamPart = (riceParamPart >> 1) ^ t[riceParamPart & 0x01]; +#if 0 + riceParamPart = (riceParamPart >> 1) ^ (~(riceParamPart & 0x01) + 1); +#endif + + /* Sample reconstruction. */ + if (bitsPerSample > 16) + { + pSamplesOut[i] = riceParamPart + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i); + } + else + { + pSamplesOut[i] = riceParamPart + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i); + } + + i += 1; + } + + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__decode_samples_with_residual__rice(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut) +{ +#if 0 + return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut); +#else + return drflac__decode_samples_with_residual__rice__simple(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut); +#endif +} + +/* Reads and seeks past a string of residual values as Rice codes. The decoder should be sitting on the first bit of the Rice codes. */ +static drflac_bool32 drflac__read_and_seek_residual__rice(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam) +{ + drflac_uint32 i; + drflac_assert(bs != NULL); + drflac_assert(count > 0); + + for (i = 0; i < count; ++i) + { + drflac_uint32 zeroCountPart; + drflac_uint32 riceParamPart; + if (!drflac__read_rice_parts(bs, riceParam, &zeroCountPart, &riceParamPart)) + return DRFLAC_FALSE; + } + + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 unencodedBitsPerSample, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut) +{ + unsigned int i; + drflac_assert(bs != NULL); + drflac_assert(count > 0); + drflac_assert(unencodedBitsPerSample > 0 && unencodedBitsPerSample <= 32); + drflac_assert(pSamplesOut != NULL); + + for (i = 0; i < count; ++i) + { + if (!drflac__read_int32(bs, unencodedBitsPerSample, pSamplesOut + i)) + return DRFLAC_FALSE; + + if (bitsPerSample > 16) + { + pSamplesOut[i] += drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i); + } + else + { + pSamplesOut[i] += drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i); + } + } + + return DRFLAC_TRUE; +} + + +/* Reads and decodes the residual for the sub-frame the decoder is currently sitting on. This function should be called + * when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be ignored. The + * and parameters are used to determine how many residual values need to be decoded. */ +static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 blockSize, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples) +{ + drflac_uint8 partitionOrder; + drflac_uint8 residualMethod; + drflac_uint32 samplesInPartition; + drflac_uint32 partitionsRemaining; + + drflac_assert(bs != NULL); + drflac_assert(blockSize != 0); + drflac_assert(pDecodedSamples != NULL); /* <-- Should we allow NULL, in which case we just seek past the residual rather than do a full decode? */ + + if (!drflac__read_uint8(bs, 2, &residualMethod)) + return DRFLAC_FALSE; + + if (residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE && residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) + return DRFLAC_FALSE; /* Unknown or unsupported residual coding method. */ + + /* Ignore the first values. */ + pDecodedSamples += order; + + + if (!drflac__read_uint8(bs, 4, &partitionOrder)) + return DRFLAC_FALSE; + + /* From the FLAC spec: + * The Rice partition order in a Rice-coded residual section must be less than or equal to 8. */ + if (partitionOrder > 8) + return DRFLAC_FALSE; + + /* Validation check. */ + if ((blockSize / (1 << partitionOrder)) <= order) + return DRFLAC_FALSE; + + samplesInPartition = (blockSize / (1 << partitionOrder)) - order; + partitionsRemaining = (1 << partitionOrder); + + for (;;) + { + drflac_uint8 riceParam = 0; + if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) + { + if (!drflac__read_uint8(bs, 4, &riceParam)) + return DRFLAC_FALSE; + if (riceParam == 16) + riceParam = 0xFF; + } + else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) + { + if (!drflac__read_uint8(bs, 5, &riceParam)) + return DRFLAC_FALSE; + if (riceParam == 32) + riceParam = 0xFF; + } + + if (riceParam != 0xFF) + { + if (!drflac__decode_samples_with_residual__rice(bs, bitsPerSample, samplesInPartition, riceParam, order, shift, coefficients, pDecodedSamples)) + return DRFLAC_FALSE; + } + else + { + unsigned char unencodedBitsPerSample = 0; + if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) + return DRFLAC_FALSE; + + if (!drflac__decode_samples_with_residual__unencoded(bs, bitsPerSample, samplesInPartition, unencodedBitsPerSample, order, shift, coefficients, pDecodedSamples)) + return DRFLAC_FALSE; + } + + pDecodedSamples += samplesInPartition; + + + if (partitionsRemaining == 1) + break; + + partitionsRemaining -= 1; + + if (partitionOrder != 0) + samplesInPartition = blockSize / (1 << partitionOrder); + } + + return DRFLAC_TRUE; +} + +/* Reads and seeks past the residual for the sub-frame the decoder is currently sitting on. This function should be called + * when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be set to 0. The + * and parameters are used to determine how many residual values need to be decoded. */ +static drflac_bool32 drflac__read_and_seek_residual(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 order) +{ + drflac_uint32 partitionsRemaining; + drflac_uint32 samplesInPartition; + drflac_uint8 partitionOrder; + drflac_uint8 residualMethod; + + drflac_assert(bs != NULL); + drflac_assert(blockSize != 0); + + if (!drflac__read_uint8(bs, 2, &residualMethod)) + return DRFLAC_FALSE; + + if (residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE && residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) + return DRFLAC_FALSE; /* Unknown or unsupported residual coding method. */ + + if (!drflac__read_uint8(bs, 4, &partitionOrder)) + return DRFLAC_FALSE; + + samplesInPartition = (blockSize / (1 << partitionOrder)) - order; + partitionsRemaining = (1 << partitionOrder); + for (;;) + { + drflac_uint8 riceParam = 0; + if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) + { + if (!drflac__read_uint8(bs, 4, &riceParam)) + return DRFLAC_FALSE; + if (riceParam == 16) + riceParam = 0xFF; + } + else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) { + if (!drflac__read_uint8(bs, 5, &riceParam)) + return DRFLAC_FALSE; + if (riceParam == 32) + riceParam = 0xFF; + } + + if (riceParam != 0xFF) + { + if (!drflac__read_and_seek_residual__rice(bs, samplesInPartition, riceParam)) + return DRFLAC_FALSE; + } + else + { + unsigned char unencodedBitsPerSample = 0; + if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) + return DRFLAC_FALSE; + + if (!drflac__seek_bits(bs, unencodedBitsPerSample * samplesInPartition)) + return DRFLAC_FALSE; + } + + if (partitionsRemaining == 1) + break; + + partitionsRemaining -= 1; + samplesInPartition = blockSize / (1 << partitionOrder); + } + + return DRFLAC_TRUE; +} + + +static drflac_bool32 drflac__decode_samples__constant(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_int32* pDecodedSamples) +{ + drflac_uint32 i; + /* Only a single sample needs to be decoded here. */ + drflac_int32 sample; + if (!drflac__read_int32(bs, bitsPerSample, &sample)) + return DRFLAC_FALSE; + + /* We don't really need to expand this, but it does simplify the process of reading samples. If this becomes a performance issue (unlikely) + * we'll want to look at a more efficient way. */ + for (i = 0; i < blockSize; ++i) + pDecodedSamples[i] = sample; + + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__decode_samples__verbatim(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_int32* pDecodedSamples) +{ + drflac_uint32 i; + for (i = 0; i < blockSize; ++i) + { + drflac_int32 sample; + if (!drflac__read_int32(bs, bitsPerSample, &sample)) + return DRFLAC_FALSE; + + pDecodedSamples[i] = sample; + } + + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__decode_samples__fixed(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples) +{ + drflac_uint32 i; + drflac_int32 lpcCoefficientsTable[5][4] = { + {0, 0, 0, 0}, + {1, 0, 0, 0}, + {2, -1, 0, 0}, + {3, -3, 1, 0}, + {4, -6, 4, -1} + }; + + /* Warm up samples and coefficients. */ + for (i = 0; i < lpcOrder; ++i) + { + drflac_int32 sample; + if (!drflac__read_int32(bs, bitsPerSample, &sample)) + return DRFLAC_FALSE; + + pDecodedSamples[i] = sample; + } + + + if (!drflac__decode_samples_with_residual(bs, bitsPerSample, blockSize, lpcOrder, 0, lpcCoefficientsTable[lpcOrder], pDecodedSamples)) + return DRFLAC_FALSE; + + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__decode_samples__lpc(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples) +{ + drflac_uint8 i; + drflac_uint8 lpcPrecision; + drflac_int8 lpcShift; + drflac_int32 coefficients[32]; + + /* Warm up samples. */ + for (i = 0; i < lpcOrder; ++i) + { + drflac_int32 sample; + if (!drflac__read_int32(bs, bitsPerSample, &sample)) + return DRFLAC_FALSE; + + pDecodedSamples[i] = sample; + } + + if (!drflac__read_uint8(bs, 4, &lpcPrecision)) + return DRFLAC_FALSE; + if (lpcPrecision == 15) + return DRFLAC_FALSE; /* Invalid. */ + lpcPrecision += 1; + + + if (!drflac__read_int8(bs, 5, &lpcShift)) + return DRFLAC_FALSE; + + for (i = 0; i < lpcOrder; ++i) + { + if (!drflac__read_int32(bs, lpcPrecision, coefficients + i)) + return DRFLAC_FALSE; + } + + if (!drflac__decode_samples_with_residual(bs, bitsPerSample, blockSize, lpcOrder, lpcShift, coefficients, pDecodedSamples)) + return DRFLAC_FALSE; + + return DRFLAC_TRUE; +} + + +static drflac_bool32 drflac__read_next_frame_header(drflac_bs* bs, drflac_uint8 streaminfoBitsPerSample, drflac_frame_header* header) +{ + const drflac_uint32 sampleRateTable[12] = {0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000}; + const drflac_uint8 bitsPerSampleTable[8] = {0, 8, 12, (drflac_uint8)-1, 16, 20, 24, (drflac_uint8)-1}; /* -1 = reserved. */ + + drflac_assert(bs != NULL); + drflac_assert(header != NULL); + + /* Keep looping until we find a valid sync code. */ + for (;;) + { + drflac_bool32 isVariableBlockSize = false; + drflac_uint8 blockSize = 0; + drflac_uint8 blockingStrategy = 0; + drflac_uint8 crc8 = 0xCE; /* 0xCE = drflac_crc8(0, 0x3FFE, 14); */ + drflac_uint8 reserved = 0; + drflac_uint8 sampleRate = 0; + drflac_uint8 channelAssignment = 0; + drflac_uint8 bitsPerSample = 0; + + if (!drflac__find_and_seek_to_next_sync_code(bs)) + return DRFLAC_FALSE; + + if (!drflac__read_uint8(bs, 1, &reserved)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, reserved, 1); + + if (!drflac__read_uint8(bs, 1, &blockingStrategy)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, blockingStrategy, 1); + + if (!drflac__read_uint8(bs, 4, &blockSize)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, blockSize, 4); + + if (!drflac__read_uint8(bs, 4, &sampleRate)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, sampleRate, 4); + + if (!drflac__read_uint8(bs, 4, &channelAssignment)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, channelAssignment, 4); + + if (!drflac__read_uint8(bs, 3, &bitsPerSample)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, bitsPerSample, 3); + + if (!drflac__read_uint8(bs, 1, &reserved)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, reserved, 1); + + isVariableBlockSize = blockingStrategy == 1; + + if (isVariableBlockSize) + { + drflac_uint64 sampleNumber; + drflac_result result = drflac__read_utf8_coded_number(bs, &sampleNumber, &crc8); + if (result != DRFLAC_SUCCESS) + { + if (result == DRFLAC_END_OF_STREAM) + return DRFLAC_FALSE; + else + continue; + } + header->frameNumber = 0; + header->sampleNumber = sampleNumber; + } + else + { + drflac_uint64 frameNumber = 0; + drflac_result result = drflac__read_utf8_coded_number(bs, &frameNumber, &crc8); + if (result != DRFLAC_SUCCESS) + { + if (result == DRFLAC_END_OF_STREAM) + return DRFLAC_FALSE; + else + continue; + } + header->frameNumber = (drflac_uint32)frameNumber; /* <-- Safe cast. */ + header->sampleNumber = 0; + } + + + if (blockSize == 1) + header->blockSize = 192; + else if (blockSize >= 2 && blockSize <= 5) + header->blockSize = 576 * (1 << (blockSize - 2)); + else if (blockSize == 6) + { + if (!drflac__read_uint16(bs, 8, &header->blockSize)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, header->blockSize, 8); + header->blockSize += 1; + } + else if (blockSize == 7) + { + if (!drflac__read_uint16(bs, 16, &header->blockSize)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, header->blockSize, 16); + header->blockSize += 1; + } + else + header->blockSize = 256 * (1 << (blockSize - 8)); + + if (sampleRate <= 11) + header->sampleRate = sampleRateTable[sampleRate]; + else if (sampleRate == 12) + { + if (!drflac__read_uint32(bs, 8, &header->sampleRate)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, header->sampleRate, 8); + header->sampleRate *= 1000; + } + else if (sampleRate == 13) + { + if (!drflac__read_uint32(bs, 16, &header->sampleRate)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, header->sampleRate, 16); + } + else if (sampleRate == 14) + { + if (!drflac__read_uint32(bs, 16, &header->sampleRate)) + return DRFLAC_FALSE; + crc8 = drflac_crc8(crc8, header->sampleRate, 16); + header->sampleRate *= 10; + } + else + continue; /* Invalid. Assume an invalid block. */ + + header->channelAssignment = channelAssignment; + + header->bitsPerSample = bitsPerSampleTable[bitsPerSample]; + if (header->bitsPerSample == 0) + header->bitsPerSample = streaminfoBitsPerSample; + + if (!drflac__read_uint8(bs, 8, &header->crc8)) + return DRFLAC_FALSE; + +#ifndef DR_FLAC_NO_CRC + if (header->crc8 != crc8) + continue; /* CRC mismatch. Loop back to the top and find the next sync code. */ +#endif + return DRFLAC_TRUE; + } +} + +static drflac_bool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe* pSubframe) +{ + int type; + drflac_uint8 header; + if (!drflac__read_uint8(bs, 8, &header)) + return DRFLAC_FALSE; + + /* First bit should always be 0. */ + if ((header & 0x80) != 0) + return DRFLAC_FALSE; + + type = (header & 0x7E) >> 1; + if (type == 0) + pSubframe->subframeType = DRFLAC_SUBFRAME_CONSTANT; + else if (type == 1) + pSubframe->subframeType = DRFLAC_SUBFRAME_VERBATIM; + else + { + if ((type & 0x20) != 0) { + pSubframe->subframeType = DRFLAC_SUBFRAME_LPC; + pSubframe->lpcOrder = (type & 0x1F) + 1; + } else if ((type & 0x08) != 0) { + pSubframe->subframeType = DRFLAC_SUBFRAME_FIXED; + pSubframe->lpcOrder = (type & 0x07); + if (pSubframe->lpcOrder > 4) { + pSubframe->subframeType = DRFLAC_SUBFRAME_RESERVED; + pSubframe->lpcOrder = 0; + } + } else { + pSubframe->subframeType = DRFLAC_SUBFRAME_RESERVED; + } + } + + if (pSubframe->subframeType == DRFLAC_SUBFRAME_RESERVED) + return DRFLAC_FALSE; + + /* Wasted bits per sample. */ + pSubframe->wastedBitsPerSample = 0; + if ((header & 0x01) == 1) + { + unsigned int wastedBitsPerSample; + if (!drflac__seek_past_next_set_bit(bs, &wastedBitsPerSample)) + return DRFLAC_FALSE; + pSubframe->wastedBitsPerSample = (unsigned char)wastedBitsPerSample + 1; + } + + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex, drflac_int32* pDecodedSamplesOut) +{ + drflac_subframe* pSubframe = NULL; + drflac_assert(bs != NULL); + drflac_assert(frame != NULL); + + pSubframe = frame->subframes + subframeIndex; + if (!drflac__read_subframe_header(bs, pSubframe)) + return DRFLAC_FALSE; + + /* Side channels require an extra bit per sample. Took a while to figure that one out... */ + pSubframe->bitsPerSample = frame->header.bitsPerSample; + if ((frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE) && subframeIndex == 1) { + pSubframe->bitsPerSample += 1; + } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) { + pSubframe->bitsPerSample += 1; + } + + /* Need to handle wasted bits per sample. */ + pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample; + pSubframe->pDecodedSamples = pDecodedSamplesOut; + + switch (pSubframe->subframeType) + { + case DRFLAC_SUBFRAME_CONSTANT: + { + drflac__decode_samples__constant(bs, frame->header.blockSize, pSubframe->bitsPerSample, pSubframe->pDecodedSamples); + } break; + + case DRFLAC_SUBFRAME_VERBATIM: + { + drflac__decode_samples__verbatim(bs, frame->header.blockSize, pSubframe->bitsPerSample, pSubframe->pDecodedSamples); + } break; + + case DRFLAC_SUBFRAME_FIXED: + { + drflac__decode_samples__fixed(bs, frame->header.blockSize, pSubframe->bitsPerSample, pSubframe->lpcOrder, pSubframe->pDecodedSamples); + } break; + + case DRFLAC_SUBFRAME_LPC: + { + drflac__decode_samples__lpc(bs, frame->header.blockSize, pSubframe->bitsPerSample, pSubframe->lpcOrder, pSubframe->pDecodedSamples); + } break; + + default: return DRFLAC_FALSE; + } + + return DRFLAC_TRUE; +} + +static drflac_bool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex) +{ + drflac_subframe *pSubframe; + + drflac_assert(bs != NULL); + drflac_assert(frame != NULL); + + pSubframe = frame->subframes + subframeIndex; + if (!drflac__read_subframe_header(bs, pSubframe)) + return DRFLAC_FALSE; + + /* Side channels require an extra bit per sample. Took a while to figure that one out... */ + pSubframe->bitsPerSample = frame->header.bitsPerSample; + if ((frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE) && subframeIndex == 1) { + pSubframe->bitsPerSample += 1; + } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) { + pSubframe->bitsPerSample += 1; + } + + /* Need to handle wasted bits per sample. */ + pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample; + pSubframe->pDecodedSamples = NULL; + + switch (pSubframe->subframeType) + { + case DRFLAC_SUBFRAME_CONSTANT: + { + if (!drflac__seek_bits(bs, pSubframe->bitsPerSample)) + return DRFLAC_FALSE; + } break; + + case DRFLAC_SUBFRAME_VERBATIM: + { + unsigned int bitsToSeek = frame->header.blockSize * pSubframe->bitsPerSample; + if (!drflac__seek_bits(bs, bitsToSeek)) + return DRFLAC_FALSE; + } break; + + case DRFLAC_SUBFRAME_FIXED: + { + unsigned int bitsToSeek = pSubframe->lpcOrder * pSubframe->bitsPerSample; + if (!drflac__seek_bits(bs, bitsToSeek)) + return DRFLAC_FALSE; + + if (!drflac__read_and_seek_residual(bs, frame->header.blockSize, pSubframe->lpcOrder)) + return DRFLAC_FALSE; + } break; + + case DRFLAC_SUBFRAME_LPC: + { + unsigned char lpcPrecision; + unsigned int bitsToSeek = pSubframe->lpcOrder * pSubframe->bitsPerSample; + if (!drflac__seek_bits(bs, bitsToSeek)) + return DRFLAC_FALSE; + + if (!drflac__read_uint8(bs, 4, &lpcPrecision)) + return DRFLAC_FALSE; + if (lpcPrecision == 15) + return DRFLAC_FALSE; /* Invalid. */ + lpcPrecision += 1; + + + bitsToSeek = (pSubframe->lpcOrder * lpcPrecision) + 5; /* +5 for shift. */ + if (!drflac__seek_bits(bs, bitsToSeek)) + return DRFLAC_FALSE; + + if (!drflac__read_and_seek_residual(bs, frame->header.blockSize, pSubframe->lpcOrder)) + return DRFLAC_FALSE; + } break; + + default: return DRFLAC_FALSE; + } + + return DRFLAC_TRUE; +} + + +static DRFLAC_INLINE drflac_uint8 drflac__get_channel_count_from_channel_assignment(drflac_int8 channelAssignment) +{ + drflac_uint8 lookup[] = {1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2}; + + drflac_assert(channelAssignment <= 10); + return lookup[channelAssignment]; +} + +static drflac_result drflac__decode_frame(drflac* pFlac) +{ + drflac_uint16 actualCRC16; + drflac_uint8 paddingSizeInBits; + drflac_uint16 desiredCRC16; + int i, channelCount; + + /* This function should be called while the stream is sitting on the first byte after the frame header. */ + drflac_zero_memory(pFlac->currentFrame.subframes, sizeof(pFlac->currentFrame.subframes)); + + /* The frame block size must never be larger than the maximum block size defined by the FLAC stream. */ + if (pFlac->currentFrame.header.blockSize > pFlac->maxBlockSize) + return DRFLAC_ERROR; + + /* The number of channels in the frame must match the channel count from the STREAMINFO block. */ + channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment); + if (channelCount != (int)pFlac->channels) + return DRFLAC_ERROR; + + for (i = 0; i < channelCount; ++i) + { + if (!drflac__decode_subframe(&pFlac->bs, &pFlac->currentFrame, i, pFlac->pDecodedSamples + (pFlac->currentFrame.header.blockSize * i))) + return DRFLAC_ERROR; + } + + paddingSizeInBits = DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7; + if (paddingSizeInBits > 0) + { + drflac_uint8 padding = 0; + if (!drflac__read_uint8(&pFlac->bs, paddingSizeInBits, &padding)) + return DRFLAC_END_OF_STREAM; + } + +#ifndef DR_FLAC_NO_CRC + actualCRC16 = drflac__flush_crc16(&pFlac->bs); +#endif + if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) + return DRFLAC_END_OF_STREAM; + +#ifndef DR_FLAC_NO_CRC + if (actualCRC16 != desiredCRC16) + return DRFLAC_CRC_MISMATCH; /* CRC mismatch. */ +#endif + + pFlac->currentFrame.samplesRemaining = pFlac->currentFrame.header.blockSize * channelCount; + + return DRFLAC_SUCCESS; +} + +static drflac_result drflac__seek_frame(drflac* pFlac) +{ +#ifndef DR_FLAC_NO_CRC + drflac_uint16 actualCRC16; +#endif + drflac_uint16 desiredCRC16; + int i; + int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment); + + for (i = 0; i < channelCount; ++i) + { + if (!drflac__seek_subframe(&pFlac->bs, &pFlac->currentFrame, i)) + return DRFLAC_ERROR; + } + + /* Padding. */ + if (!drflac__seek_bits(&pFlac->bs, DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7)) + return DRFLAC_ERROR; + + /* CRC. */ +#ifndef DR_FLAC_NO_CRC + actualCRC16 = drflac__flush_crc16(&pFlac->bs); +#endif + if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) + return DRFLAC_END_OF_STREAM; + +#ifndef DR_FLAC_NO_CRC + if (actualCRC16 != desiredCRC16) + return DRFLAC_CRC_MISMATCH; /* CRC mismatch. */ +#endif + + return DRFLAC_SUCCESS; +} + +static drflac_bool32 drflac__read_and_decode_next_frame(drflac* pFlac) +{ + drflac_assert(pFlac != NULL); + + for (;;) + { + drflac_result result; + + if (!drflac__read_next_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFrame.header)) + return DRFLAC_FALSE; + + result = drflac__decode_frame(pFlac); + if (result != DRFLAC_SUCCESS) + { + if (result == DRFLAC_CRC_MISMATCH) + continue; /* CRC mismatch. Skip to the next frame. */ + return DRFLAC_FALSE; + } + + return DRFLAC_TRUE; + } +} + + +static void drflac__get_current_frame_sample_range(drflac* pFlac, drflac_uint64* pFirstSampleInFrameOut, drflac_uint64* pLastSampleInFrameOut) +{ + unsigned int channelCount; + drflac_uint64 firstSampleInFrame, lastSampleInFrame; + + drflac_assert(pFlac != NULL); + + channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment); + + firstSampleInFrame = pFlac->currentFrame.header.sampleNumber; + if (firstSampleInFrame == 0) + firstSampleInFrame = pFlac->currentFrame.header.frameNumber * pFlac->maxBlockSize*channelCount; + + lastSampleInFrame = firstSampleInFrame + (pFlac->currentFrame.header.blockSize*channelCount); + if (lastSampleInFrame > 0) + lastSampleInFrame -= 1; /* Needs to be zero based. */ + + if (pFirstSampleInFrameOut) + *pFirstSampleInFrameOut = firstSampleInFrame; + if (pLastSampleInFrameOut) + *pLastSampleInFrameOut = lastSampleInFrame; +} + +static drflac_bool32 drflac__seek_to_first_frame(drflac* pFlac) +{ + drflac_bool32 result; + + drflac_assert(pFlac != NULL); + + result = drflac__seek_to_byte(&pFlac->bs, pFlac->firstFramePos); + + drflac_zero_memory(&pFlac->currentFrame, sizeof(pFlac->currentFrame)); + return result; +} + +static DRFLAC_INLINE drflac_result drflac__seek_to_next_frame(drflac* pFlac) +{ + /* This function should only ever be called while the decoder is sitting on the first byte past the FRAME_HEADER section. */ + drflac_assert(pFlac != NULL); + return drflac__seek_frame(pFlac); +} + +static drflac_bool32 drflac__seek_to_sample__brute_force(drflac* pFlac, drflac_uint64 sampleIndex) +{ + drflac_uint64 runningSampleCount = 0; + + /* We need to find the frame that contains the sample. To do this, we iterate over each frame and inspect it's header. If based on the + * header we can determine that the frame contains the sample, we do a full decode of that frame. */ + if (!drflac__seek_to_first_frame(pFlac)) + return DRFLAC_FALSE; + + for (;;) + { + drflac_uint64 sampleCountInThisFrame; + drflac_uint64 firstSampleInFrame = 0; + drflac_uint64 lastSampleInFrame = 0; + + if (!drflac__read_next_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFrame.header)) + return DRFLAC_FALSE; + + drflac__get_current_frame_sample_range(pFlac, &firstSampleInFrame, &lastSampleInFrame); + + sampleCountInThisFrame = (lastSampleInFrame - firstSampleInFrame) + 1; + if (sampleIndex < (runningSampleCount + sampleCountInThisFrame)) + { + /* The sample should be in this frame. We need to fully decode it, however if it's an invalid frame (a CRC mismatch), we need to pretend + * it never existed and keep iterating. */ + drflac_result result = drflac__decode_frame(pFlac); + if (result == DRFLAC_SUCCESS) + { + /* The frame is valid. We just need to skip over some samples to ensure it's sample-exact. */ + drflac_uint64 samplesToDecode = (size_t)(sampleIndex - runningSampleCount); /* <-- Safe cast because the maximum number of samples in a frame is 65535. */ + if (samplesToDecode == 0) + return DRFLAC_TRUE; + return drflac_read_s32(pFlac, samplesToDecode, NULL) != 0; /* <-- If this fails, something bad has happened (it should never fail). */ + } + else + { + if (result == DRFLAC_CRC_MISMATCH) + continue; /* CRC mismatch. Pretend this frame never existed. */ + return DRFLAC_FALSE; + } + } + else + { + /* It's not in this frame. We need to seek past the frame, but check if there was a CRC mismatch. If so, we pretend this + * frame never existed and leave the running sample count untouched. */ + drflac_result result = drflac__seek_to_next_frame(pFlac); + if (result == DRFLAC_SUCCESS) + runningSampleCount += sampleCountInThisFrame; + else + { + if (result == DRFLAC_CRC_MISMATCH) + continue; /* CRC mismatch. Pretend this frame never existed. */ + return DRFLAC_FALSE; + } + } + } +} + + +static drflac_bool32 drflac__seek_to_sample__seek_table(drflac* pFlac, drflac_uint64 sampleIndex) +{ + drflac_seekpoint closestSeekpoint = {0, 0, 0}; + drflac_uint32 seekpointCount; + drflac_uint32 seekpointsRemaining; + drflac_uint64 runningSampleCount; + + drflac_assert(pFlac != NULL); + + if (pFlac->seektablePos == 0) + return DRFLAC_FALSE; + + if (!drflac__seek_to_byte(&pFlac->bs, pFlac->seektablePos)) + return DRFLAC_FALSE; + + /* The number of seek points is derived from the size of the SEEKTABLE block. */ + seekpointCount = pFlac->seektableSize / 18; /* 18 = the size of each seek point. */ + if (seekpointCount == 0) + return DRFLAC_FALSE; /* Would this ever happen? */ + + seekpointsRemaining = seekpointCount; + while (seekpointsRemaining > 0) + { + drflac_seekpoint seekpoint; + if (!drflac__read_uint64(&pFlac->bs, 64, &seekpoint.firstSample)) + break; + if (!drflac__read_uint64(&pFlac->bs, 64, &seekpoint.frameOffset)) + break; + if (!drflac__read_uint16(&pFlac->bs, 16, &seekpoint.sampleCount)) + break; + + /* Note that the seekpoint sample is based on a single channel. The input sample (sampleIndex) is based on interleaving, thus + * we need to multiple the seekpoint's sample by the channel count. */ + if (seekpoint.firstSample*pFlac->channels > sampleIndex) + break; + + closestSeekpoint = seekpoint; + seekpointsRemaining -= 1; + } + + /* At this point we should have found the seekpoint closest to our sample. We need to seek to it using basically the same + * technique as we use with the brute force method. */ + if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFramePos + closestSeekpoint.frameOffset)) + return DRFLAC_FALSE; + + runningSampleCount = closestSeekpoint.firstSample*pFlac->channels; + for (;;) + { + drflac_uint64 sampleCountInThisFrame; + drflac_uint64 firstSampleInFrame = 0; + drflac_uint64 lastSampleInFrame = 0; + + if (!drflac__read_next_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFrame.header)) + return DRFLAC_FALSE; + + drflac__get_current_frame_sample_range(pFlac, &firstSampleInFrame, &lastSampleInFrame); + + sampleCountInThisFrame = (lastSampleInFrame - firstSampleInFrame) + 1; + if (sampleIndex < (runningSampleCount + sampleCountInThisFrame)) + { + /* The sample should be in this frame. We need to fully decode it, however if it's an invalid frame (a CRC mismatch), we need to pretend + * it never existed and keep iterating. */ + drflac_result result = drflac__decode_frame(pFlac); + + if (result == DRFLAC_SUCCESS) + { + /* The frame is valid. We just need to skip over some samples to ensure it's sample-exact. */ + drflac_uint64 samplesToDecode = (size_t)(sampleIndex - runningSampleCount); /* <-- Safe cast because the maximum number of samples in a frame is 65535. */ + if (samplesToDecode == 0) + return DRFLAC_TRUE; + return drflac_read_s32(pFlac, samplesToDecode, NULL) != 0; /* <-- If this fails, something bad has happened (it should never fail). */ + } + else + { + if (result == DRFLAC_CRC_MISMATCH) + continue; /* CRC mismatch. Pretend this frame never existed. */ + return DRFLAC_FALSE; + } + } + else + { + /* It's not in this frame. We need to seek past the frame, but check if there was a CRC mismatch. If so, we pretend this + * frame never existed and leave the running sample count untouched. */ + drflac_result result = drflac__seek_to_next_frame(pFlac); + if (result == DRFLAC_SUCCESS) + runningSampleCount += sampleCountInThisFrame; + else + { + if (result == DRFLAC_CRC_MISMATCH) + continue; /* CRC mismatch. Pretend this frame never existed. */ + return DRFLAC_FALSE; + } + } + } +} + + +#ifndef DR_FLAC_NO_OGG +typedef struct +{ + drflac_uint8 capturePattern[4]; /* Should be "OggS" */ + drflac_uint8 structureVersion; /* Always 0. */ + drflac_uint8 headerType; + drflac_uint64 granulePosition; + drflac_uint32 serialNumber; + drflac_uint32 sequenceNumber; + drflac_uint32 checksum; + drflac_uint8 segmentCount; + drflac_uint8 segmentTable[255]; +} drflac_ogg_page_header; +#endif + +typedef struct +{ + drflac_read_proc onRead; + drflac_seek_proc onSeek; + drflac_meta_proc onMeta; + drflac_container container; + void* pUserData; + void* pUserDataMD; + drflac_uint32 sampleRate; + drflac_uint8 channels; + drflac_uint8 bitsPerSample; + drflac_uint64 totalSampleCount; + drflac_uint16 maxBlockSize; + drflac_uint64 runningFilePos; + drflac_bool32 hasStreamInfoBlock; + drflac_bool32 hasMetadataBlocks; + drflac_bs bs; /* <-- A bit streamer is required for loading data during initialization. */ + drflac_frame_header firstFrameHeader; /* <-- The header of the first frame that was read during relaxed initalization. Only set if there is no STREAMINFO block. */ + +#ifndef DR_FLAC_NO_OGG + drflac_uint32 oggSerial; + drflac_uint64 oggFirstBytePos; + drflac_ogg_page_header oggBosHeader; +#endif +} drflac_init_info; + +static DRFLAC_INLINE void drflac__decode_block_header(drflac_uint32 blockHeader, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize) +{ + blockHeader = drflac__be2host_32(blockHeader); + *isLastBlock = (blockHeader & (0x01 << 31)) >> 31; + *blockType = (blockHeader & (0x7F << 24)) >> 24; + *blockSize = (blockHeader & 0xFFFFFF); +} + +static DRFLAC_INLINE drflac_bool32 drflac__read_and_decode_block_header(drflac_read_proc onRead, void* pUserData, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize) +{ + drflac_uint32 blockHeader; + if (onRead(pUserData, &blockHeader, 4) != 4) { + return DRFLAC_FALSE; + } + + drflac__decode_block_header(blockHeader, isLastBlock, blockType, blockSize); + return DRFLAC_TRUE; +} + +drflac_bool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drflac_streaminfo* pStreamInfo) +{ + drflac_uint32 blockSizes; + drflac_uint64 frameSizes = 0; + drflac_uint64 importantProps; + drflac_uint8 md5[16]; + + /* min/max block size. */ + if (onRead(pUserData, &blockSizes, 4) != 4) + return DRFLAC_FALSE; + + /* min/max frame size. */ + if (onRead(pUserData, &frameSizes, 6) != 6) + return DRFLAC_FALSE; + + /* Sample rate, channels, bits per sample and total sample count. */ + if (onRead(pUserData, &importantProps, 8) != 8) + return DRFLAC_FALSE; + + /* MD5 */ + if (onRead(pUserData, md5, sizeof(md5)) != sizeof(md5)) + return DRFLAC_FALSE; + + blockSizes = drflac__be2host_32(blockSizes); + frameSizes = drflac__be2host_64(frameSizes); + importantProps = drflac__be2host_64(importantProps); + + pStreamInfo->minBlockSize = (blockSizes & 0xFFFF0000) >> 16; + pStreamInfo->maxBlockSize = blockSizes & 0x0000FFFF; + pStreamInfo->minFrameSize = (drflac_uint32)((frameSizes & (drflac_uint64)0xFFFFFF0000000000) >> 40); + pStreamInfo->maxFrameSize = (drflac_uint32)((frameSizes & (drflac_uint64)0x000000FFFFFF0000) >> 16); + pStreamInfo->sampleRate = (drflac_uint32)((importantProps & (drflac_uint64)0xFFFFF00000000000) >> 44); + pStreamInfo->channels = (drflac_uint8 )((importantProps & (drflac_uint64)0x00000E0000000000) >> 41) + 1; + pStreamInfo->bitsPerSample = (drflac_uint8 )((importantProps & (drflac_uint64)0x000001F000000000) >> 36) + 1; + pStreamInfo->totalSampleCount = (importantProps & (drflac_uint64)0x0000000FFFFFFFFF) * pStreamInfo->channels; + drflac_copy_memory(pStreamInfo->md5, md5, sizeof(md5)); + + return DRFLAC_TRUE; +} + +drflac_bool32 drflac__read_and_decode_metadata(drflac* pFlac) +{ + /* We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that + * we'll be sitting on byte 42. */ + drflac_uint64 runningFilePos = 42; + drflac_uint64 seektablePos = 0; + drflac_uint32 seektableSize = 0; + + drflac_assert(pFlac != NULL); + + for (;;) + { + drflac_metadata metadata; + drflac_uint8 isLastBlock = 0; + drflac_uint8 blockType; + drflac_uint32 blockSize; + + if (!drflac__read_and_decode_block_header(pFlac->bs.onRead, pFlac->bs.pUserData, &isLastBlock, &blockType, &blockSize)) + return DRFLAC_FALSE; + runningFilePos += 4; + + + metadata.type = blockType; + metadata.pRawData = NULL; + metadata.rawDataSize = 0; + + switch (blockType) + { + case DRFLAC_METADATA_BLOCK_TYPE_APPLICATION: + { + if (pFlac->onMeta) { + void* pRawData = DRFLAC_MALLOC(blockSize); + if (pRawData == NULL) + return DRFLAC_FALSE; + + if (pFlac->bs.onRead(pFlac->bs.pUserData, pRawData, blockSize) != blockSize) { + DRFLAC_FREE(pRawData); + return DRFLAC_FALSE; + } + + metadata.pRawData = pRawData; + metadata.rawDataSize = blockSize; + metadata.data.application.id = drflac__be2host_32(*(drflac_uint32*)pRawData); + metadata.data.application.pData = (const void*)((drflac_uint8*)pRawData + sizeof(drflac_uint32)); + metadata.data.application.dataSize = blockSize - sizeof(drflac_uint32); + pFlac->onMeta(pFlac->pUserDataMD, &metadata); + + DRFLAC_FREE(pRawData); + } + } break; + + case DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE: + { + seektablePos = runningFilePos; + seektableSize = blockSize; + + if (pFlac->onMeta) + { + drflac_uint32 iSeekpoint; + void* pRawData = DRFLAC_MALLOC(blockSize); + if (pRawData == NULL) + return DRFLAC_FALSE; + + if (pFlac->bs.onRead(pFlac->bs.pUserData, pRawData, blockSize) != blockSize) { + DRFLAC_FREE(pRawData); + return DRFLAC_FALSE; + } + + metadata.pRawData = pRawData; + metadata.rawDataSize = blockSize; + metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint); + metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData; + + /* Endian swap. */ + for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) { + drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint; + pSeekpoint->firstSample = drflac__be2host_64(pSeekpoint->firstSample); + pSeekpoint->frameOffset = drflac__be2host_64(pSeekpoint->frameOffset); + pSeekpoint->sampleCount = drflac__be2host_16(pSeekpoint->sampleCount); + } + + pFlac->onMeta(pFlac->pUserDataMD, &metadata); + + DRFLAC_FREE(pRawData); + } + } break; + + case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT: + { + if (pFlac->onMeta) + { + const char* pRunningData; + void* pRawData = DRFLAC_MALLOC(blockSize); + if (pRawData == NULL) + return DRFLAC_FALSE; + + if (pFlac->bs.onRead(pFlac->bs.pUserData, pRawData, blockSize) != blockSize) { + DRFLAC_FREE(pRawData); + return DRFLAC_FALSE; + } + + metadata.pRawData = pRawData; + metadata.rawDataSize = blockSize; + + pRunningData = (const char*)pRawData; + metadata.data.vorbis_comment.vendorLength = drflac__le2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength; + metadata.data.vorbis_comment.commentCount = drflac__le2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.vorbis_comment.comments = pRunningData; + pFlac->onMeta(pFlac->pUserDataMD, &metadata); + + DRFLAC_FREE(pRawData); + } + } break; + + case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET: + { + if (pFlac->onMeta) + { + const char* pRunningData; + void* pRawData = DRFLAC_MALLOC(blockSize); + if (pRawData == NULL) + return DRFLAC_FALSE; + + if (pFlac->bs.onRead(pFlac->bs.pUserData, pRawData, blockSize) != blockSize) { + DRFLAC_FREE(pRawData); + return DRFLAC_FALSE; + } + + metadata.pRawData = pRawData; + metadata.rawDataSize = blockSize; + + pRunningData = (const char*)pRawData; + drflac_copy_memory(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128; + metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(drflac_uint64*)pRunningData); pRunningData += 4; + metadata.data.cuesheet.isCD = ((pRunningData[0] & 0x80) >> 7) != 0; pRunningData += 259; + metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1; + metadata.data.cuesheet.pTrackData = (const drflac_uint8*)pRunningData; + pFlac->onMeta(pFlac->pUserDataMD, &metadata); + + DRFLAC_FREE(pRawData); + } + } break; + + case DRFLAC_METADATA_BLOCK_TYPE_PICTURE: + { + if (pFlac->onMeta) + { + const char* pRunningData; + void* pRawData = DRFLAC_MALLOC(blockSize); + if (pRawData == NULL) + return DRFLAC_FALSE; + + if (pFlac->bs.onRead(pFlac->bs.pUserData, pRawData, blockSize) != blockSize) { + DRFLAC_FREE(pRawData); + return DRFLAC_FALSE; + } + + metadata.pRawData = pRawData; + metadata.rawDataSize = blockSize; + + pRunningData = (const char*)pRawData; + metadata.data.picture.type = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.mimeLength = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength; + metadata.data.picture.descriptionLength = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.description = pRunningData; + metadata.data.picture.width = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.height = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.colorDepth = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.indexColorCount = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.pictureDataSize = drflac__be2host_32(*(drflac_uint32*)pRunningData); pRunningData += 4; + metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData; + pFlac->onMeta(pFlac->pUserDataMD, &metadata); + + DRFLAC_FREE(pRawData); + } + } break; + + case DRFLAC_METADATA_BLOCK_TYPE_PADDING: + { + if (pFlac->onMeta) + { + metadata.data.padding.unused = 0; + + /* Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback. */ + if (!pFlac->bs.onSeek(pFlac->bs.pUserData, blockSize, drflac_seek_origin_current)) + isLastBlock = DRFLAC_TRUE; /* An error occured while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */ + else + pFlac->onMeta(pFlac->pUserDataMD, &metadata); + } + } + break; + + case DRFLAC_METADATA_BLOCK_TYPE_INVALID: + { + /* Invalid chunk. Just skip over this one. */ + if (pFlac->onMeta) + { + if (!pFlac->bs.onSeek(pFlac->bs.pUserData, blockSize, drflac_seek_origin_current)) + isLastBlock = DRFLAC_TRUE; /* An error occured while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */ + } + } + + default: + { + /* It's an unknown chunk, but not necessarily invalid. There's a chance more metadata blocks might be defined later on, so we + * can at the very least report the chunk to the application and let it look at the raw data. */ + if (pFlac->onMeta) + { + void* pRawData = DRFLAC_MALLOC(blockSize); + if (pRawData == NULL) + return DRFLAC_FALSE; + + if (pFlac->bs.onRead(pFlac->bs.pUserData, pRawData, blockSize) != blockSize) { + DRFLAC_FREE(pRawData); + return DRFLAC_FALSE; + } + + metadata.pRawData = pRawData; + metadata.rawDataSize = blockSize; + pFlac->onMeta(pFlac->pUserDataMD, &metadata); + + DRFLAC_FREE(pRawData); + } + } break; + } + + /* If we're not handling metadata, just skip over the block. If we are, it will have been handled earlier in the switch statement above. */ + if (pFlac->onMeta == NULL && blockSize > 0) + { + if (!pFlac->bs.onSeek(pFlac->bs.pUserData, blockSize, drflac_seek_origin_current)) + isLastBlock = DRFLAC_TRUE; + } + + runningFilePos += blockSize; + if (isLastBlock) + break; + } + + pFlac->seektablePos = seektablePos; + pFlac->seektableSize = seektableSize; + pFlac->firstFramePos = runningFilePos; + + return DRFLAC_TRUE; +} + +drflac_bool32 drflac__init_private__native(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_bool32 relaxed) +{ + drflac_uint8 isLastBlock; + drflac_uint8 blockType; + drflac_uint32 blockSize; + + (void)onSeek; + + /* Pre: The bit stream should be sitting just past the 4-byte id header. */ + + pInit->container = drflac_container_native; + + /* The first metadata block should be the STREAMINFO block. */ + if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) + return DRFLAC_FALSE; + + if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) + { + /* We're opening in strict mode and the first block is not the STREAMINFO block. Error. */ + if (!relaxed) + return DRFLAC_FALSE; + + /* Relaxed mode. To open from here we need to just find the first frame and set the sample rate, etc. to whatever is defined + * for that frame. */ + pInit->hasStreamInfoBlock = DRFLAC_FALSE; + pInit->hasMetadataBlocks = DRFLAC_FALSE; + + if (!drflac__read_next_frame_header(&pInit->bs, 0, &pInit->firstFrameHeader)) + return DRFLAC_FALSE; /* Couldn't find a frame. */ + + if (pInit->firstFrameHeader.bitsPerSample == 0) + return DRFLAC_FALSE; /* Failed to initialize because the first frame depends on the STREAMINFO block, which does not exist. */ + + pInit->sampleRate = pInit->firstFrameHeader.sampleRate; + pInit->channels = drflac__get_channel_count_from_channel_assignment(pInit->firstFrameHeader.channelAssignment); + pInit->bitsPerSample = pInit->firstFrameHeader.bitsPerSample; + pInit->maxBlockSize = 65535; /* <-- See notes here: https://xiph.org/flac/format.html#metadata_block_streaminfo */ + return DRFLAC_TRUE; + } + else + { + drflac_streaminfo streaminfo; + if (!drflac__read_streaminfo(onRead, pUserData, &streaminfo)) + return DRFLAC_FALSE; + + pInit->hasStreamInfoBlock = DRFLAC_TRUE; + pInit->sampleRate = streaminfo.sampleRate; + pInit->channels = streaminfo.channels; + pInit->bitsPerSample = streaminfo.bitsPerSample; + pInit->totalSampleCount = streaminfo.totalSampleCount; + pInit->maxBlockSize = streaminfo.maxBlockSize; /* Don't care about the min block size - only the max (used for determining the size of the memory allocation). */ + pInit->hasMetadataBlocks = !isLastBlock; + + if (onMeta) { + drflac_metadata metadata; + metadata.type = DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO; + metadata.pRawData = NULL; + metadata.rawDataSize = 0; + metadata.data.streaminfo = streaminfo; + onMeta(pUserDataMD, &metadata); + } + + return DRFLAC_TRUE; + } +} + +#ifndef DR_FLAC_NO_OGG +#define DRFLAC_OGG_MAX_PAGE_SIZE 65307 +#define DRFLAC_OGG_CAPTURE_PATTERN_CRC32 1605413199 /* CRC-32 of "OggS". */ + +typedef enum +{ + drflac_ogg_recover_on_crc_mismatch, + drflac_ogg_fail_on_crc_mismatch +} drflac_ogg_crc_mismatch_recovery; + + +static drflac_uint32 drflac__crc32_table[] = { + 0x00000000L, 0x04C11DB7L, 0x09823B6EL, 0x0D4326D9L, + 0x130476DCL, 0x17C56B6BL, 0x1A864DB2L, 0x1E475005L, + 0x2608EDB8L, 0x22C9F00FL, 0x2F8AD6D6L, 0x2B4BCB61L, + 0x350C9B64L, 0x31CD86D3L, 0x3C8EA00AL, 0x384FBDBDL, + 0x4C11DB70L, 0x48D0C6C7L, 0x4593E01EL, 0x4152FDA9L, + 0x5F15ADACL, 0x5BD4B01BL, 0x569796C2L, 0x52568B75L, + 0x6A1936C8L, 0x6ED82B7FL, 0x639B0DA6L, 0x675A1011L, + 0x791D4014L, 0x7DDC5DA3L, 0x709F7B7AL, 0x745E66CDL, + 0x9823B6E0L, 0x9CE2AB57L, 0x91A18D8EL, 0x95609039L, + 0x8B27C03CL, 0x8FE6DD8BL, 0x82A5FB52L, 0x8664E6E5L, + 0xBE2B5B58L, 0xBAEA46EFL, 0xB7A96036L, 0xB3687D81L, + 0xAD2F2D84L, 0xA9EE3033L, 0xA4AD16EAL, 0xA06C0B5DL, + 0xD4326D90L, 0xD0F37027L, 0xDDB056FEL, 0xD9714B49L, + 0xC7361B4CL, 0xC3F706FBL, 0xCEB42022L, 0xCA753D95L, + 0xF23A8028L, 0xF6FB9D9FL, 0xFBB8BB46L, 0xFF79A6F1L, + 0xE13EF6F4L, 0xE5FFEB43L, 0xE8BCCD9AL, 0xEC7DD02DL, + 0x34867077L, 0x30476DC0L, 0x3D044B19L, 0x39C556AEL, + 0x278206ABL, 0x23431B1CL, 0x2E003DC5L, 0x2AC12072L, + 0x128E9DCFL, 0x164F8078L, 0x1B0CA6A1L, 0x1FCDBB16L, + 0x018AEB13L, 0x054BF6A4L, 0x0808D07DL, 0x0CC9CDCAL, + 0x7897AB07L, 0x7C56B6B0L, 0x71159069L, 0x75D48DDEL, + 0x6B93DDDBL, 0x6F52C06CL, 0x6211E6B5L, 0x66D0FB02L, + 0x5E9F46BFL, 0x5A5E5B08L, 0x571D7DD1L, 0x53DC6066L, + 0x4D9B3063L, 0x495A2DD4L, 0x44190B0DL, 0x40D816BAL, + 0xACA5C697L, 0xA864DB20L, 0xA527FDF9L, 0xA1E6E04EL, + 0xBFA1B04BL, 0xBB60ADFCL, 0xB6238B25L, 0xB2E29692L, + 0x8AAD2B2FL, 0x8E6C3698L, 0x832F1041L, 0x87EE0DF6L, + 0x99A95DF3L, 0x9D684044L, 0x902B669DL, 0x94EA7B2AL, + 0xE0B41DE7L, 0xE4750050L, 0xE9362689L, 0xEDF73B3EL, + 0xF3B06B3BL, 0xF771768CL, 0xFA325055L, 0xFEF34DE2L, + 0xC6BCF05FL, 0xC27DEDE8L, 0xCF3ECB31L, 0xCBFFD686L, + 0xD5B88683L, 0xD1799B34L, 0xDC3ABDEDL, 0xD8FBA05AL, + 0x690CE0EEL, 0x6DCDFD59L, 0x608EDB80L, 0x644FC637L, + 0x7A089632L, 0x7EC98B85L, 0x738AAD5CL, 0x774BB0EBL, + 0x4F040D56L, 0x4BC510E1L, 0x46863638L, 0x42472B8FL, + 0x5C007B8AL, 0x58C1663DL, 0x558240E4L, 0x51435D53L, + 0x251D3B9EL, 0x21DC2629L, 0x2C9F00F0L, 0x285E1D47L, + 0x36194D42L, 0x32D850F5L, 0x3F9B762CL, 0x3B5A6B9BL, + 0x0315D626L, 0x07D4CB91L, 0x0A97ED48L, 0x0E56F0FFL, + 0x1011A0FAL, 0x14D0BD4DL, 0x19939B94L, 0x1D528623L, + 0xF12F560EL, 0xF5EE4BB9L, 0xF8AD6D60L, 0xFC6C70D7L, + 0xE22B20D2L, 0xE6EA3D65L, 0xEBA91BBCL, 0xEF68060BL, + 0xD727BBB6L, 0xD3E6A601L, 0xDEA580D8L, 0xDA649D6FL, + 0xC423CD6AL, 0xC0E2D0DDL, 0xCDA1F604L, 0xC960EBB3L, + 0xBD3E8D7EL, 0xB9FF90C9L, 0xB4BCB610L, 0xB07DABA7L, + 0xAE3AFBA2L, 0xAAFBE615L, 0xA7B8C0CCL, 0xA379DD7BL, + 0x9B3660C6L, 0x9FF77D71L, 0x92B45BA8L, 0x9675461FL, + 0x8832161AL, 0x8CF30BADL, 0x81B02D74L, 0x857130C3L, + 0x5D8A9099L, 0x594B8D2EL, 0x5408ABF7L, 0x50C9B640L, + 0x4E8EE645L, 0x4A4FFBF2L, 0x470CDD2BL, 0x43CDC09CL, + 0x7B827D21L, 0x7F436096L, 0x7200464FL, 0x76C15BF8L, + 0x68860BFDL, 0x6C47164AL, 0x61043093L, 0x65C52D24L, + 0x119B4BE9L, 0x155A565EL, 0x18197087L, 0x1CD86D30L, + 0x029F3D35L, 0x065E2082L, 0x0B1D065BL, 0x0FDC1BECL, + 0x3793A651L, 0x3352BBE6L, 0x3E119D3FL, 0x3AD08088L, + 0x2497D08DL, 0x2056CD3AL, 0x2D15EBE3L, 0x29D4F654L, + 0xC5A92679L, 0xC1683BCEL, 0xCC2B1D17L, 0xC8EA00A0L, + 0xD6AD50A5L, 0xD26C4D12L, 0xDF2F6BCBL, 0xDBEE767CL, + 0xE3A1CBC1L, 0xE760D676L, 0xEA23F0AFL, 0xEEE2ED18L, + 0xF0A5BD1DL, 0xF464A0AAL, 0xF9278673L, 0xFDE69BC4L, + 0x89B8FD09L, 0x8D79E0BEL, 0x803AC667L, 0x84FBDBD0L, + 0x9ABC8BD5L, 0x9E7D9662L, 0x933EB0BBL, 0x97FFAD0CL, + 0xAFB010B1L, 0xAB710D06L, 0xA6322BDFL, 0xA2F33668L, + 0xBCB4666DL, 0xB8757BDAL, 0xB5365D03L, 0xB1F740B4L +}; + +static DRFLAC_INLINE drflac_uint32 drflac_crc32_byte(drflac_uint32 crc32, drflac_uint8 data) +{ +#ifndef DR_FLAC_NO_CRC + return (crc32 << 8) ^ drflac__crc32_table[(drflac_uint8)((crc32 >> 24) & 0xFF) ^ data]; +#else + (void)data; + return crc32; +#endif +} + +#if 0 +static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint32(drflac_uint32 crc32, drflac_uint32 data) +{ + crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 24) & 0xFF)); + crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 16) & 0xFF)); + crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 8) & 0xFF)); + crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 0) & 0xFF)); + return crc32; +} + +static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint64(drflac_uint32 crc32, drflac_uint64 data) +{ + crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 32) & 0xFFFFFFFF)); + crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 0) & 0xFFFFFFFF)); + return crc32; +} +#endif + +static DRFLAC_INLINE drflac_uint32 drflac_crc32_buffer(drflac_uint32 crc32, drflac_uint8* pData, drflac_uint32 dataSize) +{ + drflac_uint32 i; + + /* This can be optimized. */ + for (i = 0; i < dataSize; ++i) + crc32 = drflac_crc32_byte(crc32, pData[i]); + return crc32; +} + + +static DRFLAC_INLINE drflac_bool32 drflac_ogg__is_capture_pattern(drflac_uint8 pattern[4]) +{ + return pattern[0] == 'O' && pattern[1] == 'g' && pattern[2] == 'g' && pattern[3] == 'S'; +} + +static DRFLAC_INLINE drflac_uint32 drflac_ogg__get_page_header_size(drflac_ogg_page_header* pHeader) +{ + return 27 + pHeader->segmentCount; +} + +static DRFLAC_INLINE drflac_uint32 drflac_ogg__get_page_body_size(drflac_ogg_page_header* pHeader) +{ + int i; + drflac_uint32 pageBodySize = 0; + + for (i = 0; i < pHeader->segmentCount; ++i) + pageBodySize += pHeader->segmentTable[i]; + + return pageBodySize; +} + +drflac_result drflac_ogg__read_page_header_after_capture_pattern(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, drflac_uint32* pBytesRead, drflac_uint32* pCRC32) +{ + drflac_uint32 i; + drflac_uint8 data[23]; + + drflac_assert(*pCRC32 == DRFLAC_OGG_CAPTURE_PATTERN_CRC32); + + if (onRead(pUserData, data, 23) != 23) + return DRFLAC_END_OF_STREAM; + *pBytesRead += 23; + + pHeader->structureVersion = data[0]; + pHeader->headerType = data[1]; + drflac_copy_memory(&pHeader->granulePosition, &data[ 2], 8); + drflac_copy_memory(&pHeader->serialNumber, &data[10], 4); + drflac_copy_memory(&pHeader->sequenceNumber, &data[14], 4); + drflac_copy_memory(&pHeader->checksum, &data[18], 4); + pHeader->segmentCount = data[22]; + + /* Calculate the CRC. Note that for the calculation the checksum part of the page needs to be set to 0. */ + data[18] = 0; + data[19] = 0; + data[20] = 0; + data[21] = 0; + + for (i = 0; i < 23; ++i) + *pCRC32 = drflac_crc32_byte(*pCRC32, data[i]); + + if (onRead(pUserData, pHeader->segmentTable, pHeader->segmentCount) != pHeader->segmentCount) + return DRFLAC_END_OF_STREAM; + + *pBytesRead += pHeader->segmentCount; + + for (i = 0; i < pHeader->segmentCount; ++i) + *pCRC32 = drflac_crc32_byte(*pCRC32, pHeader->segmentTable[i]); + + return DRFLAC_SUCCESS; +} + +drflac_result drflac_ogg__read_page_header(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, drflac_uint32* pBytesRead, drflac_uint32* pCRC32) +{ + drflac_uint8 id[4]; + + *pBytesRead = 0; + + if (onRead(pUserData, id, 4) != 4) + return DRFLAC_END_OF_STREAM; + *pBytesRead += 4; + + /* We need to read byte-by-byte until we find the OggS capture pattern. */ + for (;;) + { + if (drflac_ogg__is_capture_pattern(id)) + { + drflac_result result; + *pCRC32 = DRFLAC_OGG_CAPTURE_PATTERN_CRC32; + + result = drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, pHeader, pBytesRead, pCRC32); + if (result == DRFLAC_SUCCESS) + return DRFLAC_SUCCESS; + + if (result == DRFLAC_CRC_MISMATCH) + continue; + return result; + } + else + { + /* The first 4 bytes did not equal the capture pattern. Read the next byte and try again. */ + id[0] = id[1]; + id[1] = id[2]; + id[2] = id[3]; + if (onRead(pUserData, &id[3], 1) != 1) + return DRFLAC_END_OF_STREAM; + *pBytesRead += 1; + } + } +} + + +/* The main part of the Ogg encapsulation is the conversion from the physical Ogg bitstream to the native FLAC bitstream. It works + * in three general stages: Ogg Physical Bitstream -> Ogg/FLAC Logical Bitstream -> FLAC Native Bitstream. dr_flac is architecured + * in such a way that the core sections assume everything is delivered in native format. Therefore, for each encapsulation type + * dr_flac is supporting there needs to be a layer sitting on top of the onRead and onSeek callbacks that ensures the bits read from + * the physical Ogg bitstream are converted and delivered in native FLAC format. */ +typedef struct +{ + drflac_read_proc onRead; /* The original onRead callback from drflac_open() and family. */ + drflac_seek_proc onSeek; /* The original onSeek callback from drflac_open() and family. */ + void* pUserData; /* The user data passed on onRead and onSeek. This is the user data that was passed on drflac_open() and family. */ + drflac_uint64 currentBytePos; /* The position of the byte we are sitting on in the physical byte stream. Used for efficient seeking. */ + drflac_uint64 firstBytePos; /* The position of the first byte in the physical bitstream. Points to the start of the "OggS" identifier of the FLAC bos page. */ + drflac_uint32 serialNumber; /* The serial number of the FLAC audio pages. This is determined by the initial header page that was read during initialization. */ + drflac_ogg_page_header bosPageHeader; /* Used for seeking. */ + drflac_ogg_page_header currentPageHeader; + drflac_uint32 bytesRemainingInPage; + drflac_uint32 pageDataSize; + drflac_uint8 pageData[DRFLAC_OGG_MAX_PAGE_SIZE]; +} drflac_oggbs; /* oggbs = Ogg Bitstream */ + +static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut, size_t bytesToRead) +{ + size_t bytesActuallyRead = oggbs->onRead(oggbs->pUserData, bufferOut, bytesToRead); + oggbs->currentBytePos += bytesActuallyRead; + + return bytesActuallyRead; +} + +static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, drflac_uint64 offset, drflac_seek_origin origin) +{ + if (origin == drflac_seek_origin_start) + { + if (offset <= 0x7FFFFFFF) + { + if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) + return DRFLAC_FALSE; + oggbs->currentBytePos = offset; + + return DRFLAC_TRUE; + } + else + { + if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) + return DRFLAC_FALSE; + oggbs->currentBytePos = offset; + + return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current); + } + } + else + { + while (offset > 0x7FFFFFFF) + { + if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) + return DRFLAC_FALSE; + oggbs->currentBytePos += 0x7FFFFFFF; + offset -= 0x7FFFFFFF; + } + + if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_current)) /* <-- Safe cast thanks to the loop above. */ + return DRFLAC_FALSE; + oggbs->currentBytePos += offset; + + return DRFLAC_TRUE; + } +} + +static drflac_bool32 drflac_oggbs__goto_next_page(drflac_oggbs* oggbs, drflac_ogg_crc_mismatch_recovery recoveryMethod) +{ + drflac_ogg_page_header header; + for (;;) { +#ifndef DR_FLAC_NO_CRC + drflac_uint32 actualCRC32; +#endif + drflac_uint32 pageBodySize; + drflac_uint32 crc32 = 0; + drflac_uint32 bytesRead; + if (drflac_ogg__read_page_header(oggbs->onRead, oggbs->pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) + return DRFLAC_FALSE; + oggbs->currentBytePos += bytesRead; + + pageBodySize = drflac_ogg__get_page_body_size(&header); + if (pageBodySize > DRFLAC_OGG_MAX_PAGE_SIZE) + continue; /* Invalid page size. Assume it's corrupted and just move to the next page. */ + + if (header.serialNumber != oggbs->serialNumber) + { + /* It's not a FLAC page. Skip it. */ + if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, drflac_seek_origin_current)) + return DRFLAC_FALSE; + continue; + } + + /* We need to read the entire page and then do a CRC check on it. If there's a CRC mismatch we need to skip this page. */ + if (drflac_oggbs__read_physical(oggbs, oggbs->pageData, pageBodySize) != pageBodySize) + return DRFLAC_FALSE; + oggbs->pageDataSize = pageBodySize; + +#ifndef DR_FLAC_NO_CRC + actualCRC32 = drflac_crc32_buffer(crc32, oggbs->pageData, oggbs->pageDataSize); + if (actualCRC32 != header.checksum) + { + if (recoveryMethod == drflac_ogg_recover_on_crc_mismatch) + continue; /* CRC mismatch. Skip this page. */ + + /* Even though we are failing on a CRC mismatch, we still want our stream to be in a good state. Therefore we + * go to the next valid page to ensure we're in a good state, but return false to let the caller know that the + * seek did not fully complete. */ + drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch); + return DRFLAC_FALSE; + } +#endif + + oggbs->currentPageHeader = header; + oggbs->bytesRemainingInPage = pageBodySize; + return DRFLAC_TRUE; + } +} + +/* Function below is unused at the moment, but I might be re-adding it later. */ +#if 0 +static drflac_uint8 drflac_oggbs__get_current_segment_index(drflac_oggbs* oggbs, drflac_uint8* pBytesRemainingInSeg) +{ + drflac_uint32 bytesConsumedInPage = drflac_ogg__get_page_body_size(&oggbs->currentPageHeader) - oggbs->bytesRemainingInPage; + drflac_uint8 iSeg = 0; + drflac_uint32 iByte = 0; + while (iByte < bytesConsumedInPage) + { + drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg]; + if (iByte + segmentSize > bytesConsumedInPage) + break; + + iSeg += 1; + iByte += segmentSize; + } + + *pBytesRemainingInSeg = oggbs->currentPageHeader.segmentTable[iSeg] - (drflac_uint8)(bytesConsumedInPage - iByte); + return iSeg; +} + +static drflac_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs) +{ + /* The current packet ends when we get to the segment with a lacing value of < 255 which is not at the end of a page. */ + for (;;) { + drflac_bool32 atEndOfPage = DRFLAC_FALSE; + + drflac_uint8 bytesRemainingInSeg; + drflac_uint8 iFirstSeg = drflac_oggbs__get_current_segment_index(oggbs, &bytesRemainingInSeg); + + drflac_uint32 bytesToEndOfPacketOrPage = bytesRemainingInSeg; + for (drflac_uint8 iSeg = iFirstSeg; iSeg < oggbs->currentPageHeader.segmentCount; ++iSeg) { + drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg]; + if (segmentSize < 255) + { + if (iSeg == oggbs->currentPageHeader.segmentCount-1) + atEndOfPage = DRFLAC_TRUE; + + break; + } + + bytesToEndOfPacketOrPage += segmentSize; + } + + /* At this point we will have found either the packet or the end of the page. If were at the end of the page we'll + * want to load the next page and keep searching for the end of the packet. */ + drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, drflac_seek_origin_current); + oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage; + + if (atEndOfPage) + { + /* We're potentially at the next packet, but we need to check the next page first to be sure because the packet may + * straddle pages. */ + if (!drflac_oggbs__goto_next_page(oggbs)) + return DRFLAC_FALSE; + + /* If it's a fresh packet it most likely means we're at the next packet. */ + if ((oggbs->currentPageHeader.headerType & 0x01) == 0) + return DRFLAC_TRUE; + } + else + { + /* We're at the next packet. */ + return DRFLAC_TRUE; + } + } +} + +static drflac_bool32 drflac_oggbs__seek_to_next_frame(drflac_oggbs* oggbs) +{ + /* The bitstream should be sitting on the first byte just after the header of the frame. + + * What we're actually doing here is seeking to the start of the next packet. */ + return drflac_oggbs__seek_to_next_packet(oggbs); +} +#endif + +static size_t drflac__on_read_ogg(void* pUserData, void* bufferOut, size_t bytesToRead) +{ + size_t bytesRead = 0; + drflac_uint8* pRunningBufferOut = NULL; + drflac_oggbs* oggbs = (drflac_oggbs*)pUserData; + + drflac_assert(oggbs != NULL); + + pRunningBufferOut = (drflac_uint8*)bufferOut; + + /* Reading is done page-by-page. If we've run out of bytes in the page we need to move to the next one. */ + while (bytesRead < bytesToRead) + { + size_t bytesRemainingToRead = bytesToRead - bytesRead; + + if (oggbs->bytesRemainingInPage >= bytesRemainingToRead) { + drflac_copy_memory(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), bytesRemainingToRead); + bytesRead += bytesRemainingToRead; + oggbs->bytesRemainingInPage -= (drflac_uint32)bytesRemainingToRead; + break; + } + + /* If we get here it means some of the requested data is contained in the next pages. */ + if (oggbs->bytesRemainingInPage > 0) + { + drflac_copy_memory(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), oggbs->bytesRemainingInPage); + bytesRead += oggbs->bytesRemainingInPage; + pRunningBufferOut += oggbs->bytesRemainingInPage; + oggbs->bytesRemainingInPage = 0; + } + + drflac_assert(bytesRemainingToRead > 0); + if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) + break; /* Failed to go to the next page. Might have simply hit the end of the stream. */ + } + + return bytesRead; +} + +static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_seek_origin origin) +{ + int bytesSeeked = 0; + drflac_oggbs* oggbs = (drflac_oggbs*)pUserData; + + drflac_assert(oggbs != NULL); + drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start)); + + /* Seeking is always forward which makes things a lot simpler. */ + if (origin == drflac_seek_origin_start) + { + if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, drflac_seek_origin_start)) + return DRFLAC_FALSE; + + if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) + return DRFLAC_FALSE; + + return drflac__on_seek_ogg(pUserData, offset, drflac_seek_origin_current); + } + + drflac_assert(origin == drflac_seek_origin_current); + + while (bytesSeeked < offset) + { + int bytesRemainingToSeek = offset - bytesSeeked; + drflac_assert(bytesRemainingToSeek >= 0); + + if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) + { + bytesSeeked += bytesRemainingToSeek; + oggbs->bytesRemainingInPage -= bytesRemainingToSeek; + break; + } + + /* If we get here it means some of the requested data is contained in the next pages. */ + if (oggbs->bytesRemainingInPage > 0) + { + bytesSeeked += (int)oggbs->bytesRemainingInPage; + oggbs->bytesRemainingInPage = 0; + } + + drflac_assert(bytesRemainingToSeek > 0); + + /* Failed to go to the next page. We either hit the end of the stream or had a CRC mismatch. */ + if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) + return DRFLAC_FALSE; + } + + return DRFLAC_TRUE; +} + +drflac_bool32 drflac_ogg__seek_to_sample(drflac* pFlac, drflac_uint64 sampleIndex) +{ + drflac_uint64 runningSampleCount; + drflac_uint64 runningFrameBytePos; + drflac_uint64 runningGranulePosition = 0; + drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs; + + drflac_uint64 originalBytePos = oggbs->currentBytePos; /* For recovery. */ + + /* First seek to the first frame. */ + if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFramePos)) + return DRFLAC_FALSE; + oggbs->bytesRemainingInPage = 0; + + runningFrameBytePos = oggbs->currentBytePos; /* <-- Points to the OggS identifier. */ + for (;;) + { + if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) { + drflac_oggbs__seek_physical(oggbs, originalBytePos, drflac_seek_origin_start); + return DRFLAC_FALSE; /* Never did find that sample... */ + } + + runningFrameBytePos = oggbs->currentBytePos - drflac_ogg__get_page_header_size(&oggbs->currentPageHeader) - oggbs->pageDataSize; + if (oggbs->currentPageHeader.granulePosition*pFlac->channels >= sampleIndex) + break; /* The sample is somewhere in the previous page. */ + + /* At this point we know the sample is not in the previous page. It could possibly be in this page. For simplicity we + * disregard any pages that do not begin a fresh packet. */ + if ((oggbs->currentPageHeader.headerType & 0x01) == 0) + { /* <-- Is it a fresh page? */ + if (oggbs->currentPageHeader.segmentTable[0] >= 2) + { + drflac_uint8 firstBytesInPage[2]; + firstBytesInPage[0] = oggbs->pageData[0]; + firstBytesInPage[1] = oggbs->pageData[1]; + + if ((firstBytesInPage[0] == 0xFF) && (firstBytesInPage[1] & 0xFC) == 0xF8) /* <-- Does the page begin with a frame's sync code? */ + runningGranulePosition = oggbs->currentPageHeader.granulePosition*pFlac->channels; + + continue; + } + } + } + + + /* We found the page that that is closest to the sample, so now we need to find it. The first thing to do is seek to the + * start of that page. In the loop above we checked that it was a fresh page which means this page is also the start of + * a new frame. This property means that after we've seeked to the page we can immediately start looping over frames until + * we find the one containing the target sample. */ + if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, drflac_seek_origin_start)) + return DRFLAC_FALSE; + if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) + return DRFLAC_FALSE; + + /* At this point we'll be sitting on the first byte of the frame header of the first frame in the page. We just keep + * looping over these frames until we find the one containing the sample we're after. */ + runningSampleCount = runningGranulePosition; + for (;;) + { + drflac_uint64 sampleCountInThisFrame; + drflac_uint64 firstSampleInFrame = 0; + drflac_uint64 lastSampleInFrame = 0; + /* There are two ways to find the sample and seek past irrelevant frames: + * 1) Use the native FLAC decoder. + * 2) Use Ogg's framing system. + * + * Both of these options have their own pros and cons. Using the native FLAC decoder is slower because it needs to + * do a full decode of the frame. Using Ogg's framing system is faster, but more complicated and involves some code + * duplication for the decoding of frame headers. + * + * Another thing to consider is that using the Ogg framing system will perform direct seeking of the physical Ogg + * bitstream. This is important to consider because it means we cannot read data from the drflac_bs object using the + * standard drflac__*() APIs because that will read in extra data for it's own internal caching which in turn breaks + * the positioning of the read pointer of the physical Ogg bitstream. Therefore, anything that would normally be read + * using the native FLAC decoding APIs, such as drflac__read_next_frame_header(), need to be re-implemented so as to + * avoid the use of the drflac_bs object. + * + * Considering these issues, I have decided to use the slower native FLAC decoding method for the following reasons: + * 1) Seeking is already partially accellerated using Ogg's paging system in the code block above. + * 2) Seeking in an Ogg encapsulated FLAC stream is probably quite uncommon. + * 3) Simplicity. + */ + if (!drflac__read_next_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFrame.header)) + return DRFLAC_FALSE; + + drflac__get_current_frame_sample_range(pFlac, &firstSampleInFrame, &lastSampleInFrame); + + sampleCountInThisFrame = (lastSampleInFrame - firstSampleInFrame) + 1; + if (sampleIndex < (runningSampleCount + sampleCountInThisFrame)) { + /* The sample should be in this frame. We need to fully decode it, however if it's an invalid frame (a CRC mismatch), we need to pretend + * it never existed and keep iterating. */ + drflac_result result = drflac__decode_frame(pFlac); + if (result == DRFLAC_SUCCESS) { + /* The frame is valid. We just need to skip over some samples to ensure it's sample-exact. */ + drflac_uint64 samplesToDecode = (size_t)(sampleIndex - runningSampleCount); /* <-- Safe cast because the maximum number of samples in a frame is 65535. */ + if (samplesToDecode == 0) + return DRFLAC_TRUE; + return drflac_read_s32(pFlac, samplesToDecode, NULL) != 0; /* <-- If this fails, something bad has happened (it should never fail). */ + } + else + { + if (result == DRFLAC_CRC_MISMATCH) + continue; /* CRC mismatch. Pretend this frame never existed. */ + return DRFLAC_FALSE; + } + } + else + { + /* It's not in this frame. We need to seek past the frame, but check if there was a CRC mismatch. If so, we pretend this + * frame never existed and leave the running sample count untouched. */ + drflac_result result = drflac__seek_to_next_frame(pFlac); + if (result == DRFLAC_SUCCESS) + runningSampleCount += sampleCountInThisFrame; + else + { + if (result == DRFLAC_CRC_MISMATCH) + continue; /* CRC mismatch. Pretend this frame never existed. */ + return DRFLAC_FALSE; + } + } + } +} + + +drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_bool32 relaxed) +{ + /* We'll get here if the first 4 bytes of the stream were the OggS capture pattern, however it doesn't necessarily mean the + * stream includes FLAC encoded audio. To check for this we need to scan the beginning-of-stream page markers and check if + * any match the FLAC specification. Important to keep in mind that the stream may be multiplexed. */ + drflac_ogg_page_header header; + + drflac_uint32 crc32 = DRFLAC_OGG_CAPTURE_PATTERN_CRC32; + drflac_uint32 bytesRead = 0; + /* Pre: The bit stream should be sitting just past the 4-byte OggS capture pattern. */ + (void)relaxed; + + pInit->container = drflac_container_ogg; + pInit->oggFirstBytePos = 0; + + if (drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) + return DRFLAC_FALSE; + pInit->runningFilePos += bytesRead; + + for (;;) + { + int pageBodySize; + /* Break if we're past the beginning of stream page. */ + if ((header.headerType & 0x02) == 0) + return DRFLAC_FALSE; + + /* Check if it's a FLAC header. */ + pageBodySize = drflac_ogg__get_page_body_size(&header); + if (pageBodySize == 51) + { + /* 51 = the lacing value of the FLAC header packet. + * It could be a FLAC page... */ + drflac_uint32 bytesRemainingInPage = pageBodySize; + + drflac_uint8 packetType; + if (onRead(pUserData, &packetType, 1) != 1) + return DRFLAC_FALSE; + + bytesRemainingInPage -= 1; + if (packetType == 0x7F) + { + /* Increasingly more likely to be a FLAC page... */ + drflac_uint8 sig[4]; + if (onRead(pUserData, sig, 4) != 4) + return DRFLAC_FALSE; + + bytesRemainingInPage -= 4; + if (sig[0] == 'F' && sig[1] == 'L' && sig[2] == 'A' && sig[3] == 'C') { + /* Almost certainly a FLAC page... */ + drflac_uint8 mappingVersion[2]; + if (onRead(pUserData, mappingVersion, 2) != 2) + return DRFLAC_FALSE; + + if (mappingVersion[0] != 1) + return DRFLAC_FALSE; /* Only supporting version 1.x of the Ogg mapping. */ + + /* The next 2 bytes are the non-audio packets, not including this one. We don't care about this because we're going to + * be handling it in a generic way based on the serial number and packet types. */ + if (!onSeek(pUserData, 2, drflac_seek_origin_current)) + return DRFLAC_FALSE; + + /* Expecting the native FLAC signature "fLaC". */ + if (onRead(pUserData, sig, 4) != 4) + return DRFLAC_FALSE; + + if (sig[0] == 'f' && sig[1] == 'L' && sig[2] == 'a' && sig[3] == 'C') + { + drflac_streaminfo streaminfo; + /* The remaining data in the page should be the STREAMINFO block. */ + drflac_uint8 isLastBlock; + drflac_uint8 blockType; + drflac_uint32 blockSize; + if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) + return DRFLAC_FALSE; + + if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) + return DRFLAC_FALSE; /* Invalid block type. First block must be the STREAMINFO block. */ + + if (drflac__read_streaminfo(onRead, pUserData, &streaminfo)) { + /* Success! */ + pInit->hasStreamInfoBlock = DRFLAC_TRUE; + pInit->sampleRate = streaminfo.sampleRate; + pInit->channels = streaminfo.channels; + pInit->bitsPerSample = streaminfo.bitsPerSample; + pInit->totalSampleCount = streaminfo.totalSampleCount; + pInit->maxBlockSize = streaminfo.maxBlockSize; + pInit->hasMetadataBlocks = !isLastBlock; + + if (onMeta) { + drflac_metadata metadata; + metadata.type = DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO; + metadata.pRawData = NULL; + metadata.rawDataSize = 0; + metadata.data.streaminfo = streaminfo; + onMeta(pUserDataMD, &metadata); + } + + pInit->runningFilePos += pageBodySize; + pInit->oggFirstBytePos = pInit->runningFilePos - 79; /* Subtracting 79 will place us right on top of the "OggS" identifier of the FLAC bos page. */ + pInit->oggSerial = header.serialNumber; + pInit->oggBosHeader = header; + break; + } + else + { + /* Failed to read STREAMINFO block. Aww, so close... */ + return DRFLAC_FALSE; + } + } + else + { + /* Invalid file. */ + return DRFLAC_FALSE; + } + } + else + { + /* Not a FLAC header. Skip it. */ + if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) + return DRFLAC_FALSE; + } + } + else + { + /* Not a FLAC header. Seek past the entire page and move on to the next. */ + if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) + return DRFLAC_FALSE; + } + } + else + { + if (!onSeek(pUserData, pageBodySize, drflac_seek_origin_current)) + return DRFLAC_FALSE; + } + + pInit->runningFilePos += pageBodySize; + + /* Read the header of the next page. */ + if (drflac_ogg__read_page_header(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) + return DRFLAC_FALSE; + pInit->runningFilePos += bytesRead; + } + + + /* If we get here it means we found a FLAC audio stream. We should be sitting on the first byte of the header of the next page. The next + * packets in the FLAC logical stream contain the metadata. The only thing left to do in the initialiation phase for Ogg is to create the + * Ogg bistream object. */ + pInit->hasMetadataBlocks = DRFLAC_TRUE; /* <-- Always have at least VORBIS_COMMENT metadata block. */ + return DRFLAC_TRUE; +} +#endif + +drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD) +{ + drflac_uint8 id[4]; + drflac_bool32 relaxed; + + if (pInit == NULL || onRead == NULL || onSeek == NULL) + return DRFLAC_FALSE; + + drflac_zero_memory(pInit, sizeof(*pInit)); + pInit->onRead = onRead; + pInit->onSeek = onSeek; + pInit->onMeta = onMeta; + pInit->container = container; + pInit->pUserData = pUserData; + pInit->pUserDataMD = pUserDataMD; + + pInit->bs.onRead = onRead; + pInit->bs.onSeek = onSeek; + pInit->bs.pUserData = pUserData; + drflac__reset_cache(&pInit->bs); + + + /* If the container is explicitly defined then we can try opening in relaxed mode. */ + relaxed = container != drflac_container_unknown; + + /* Skip over any ID3 tags. */ + for (;;) + { + if (onRead(pUserData, id, 4) != 4) + return DRFLAC_FALSE; /* Ran out of data. */ + pInit->runningFilePos += 4; + + if (id[0] == 'I' && id[1] == 'D' && id[2] == '3') + { + drflac_uint8 flags; + drflac_uint32 headerSize; + drflac_uint8 header[6]; + + if (onRead(pUserData, header, 6) != 6) + return DRFLAC_FALSE; /* Ran out of data. */ + pInit->runningFilePos += 6; + + flags = header[1]; + drflac_copy_memory(&headerSize, header+2, 4); + headerSize = drflac__unsynchsafe_32(drflac__be2host_32(headerSize)); + if (flags & 0x10) + headerSize += 10; + + if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) + return DRFLAC_FALSE; /* Failed to seek past the tag. */ + pInit->runningFilePos += headerSize; + } + else + break; + } + + if (id[0] == 'f' && id[1] == 'L' && id[2] == 'a' && id[3] == 'C') { + return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed); + } +#ifndef DR_FLAC_NO_OGG + if (id[0] == 'O' && id[1] == 'g' && id[2] == 'g' && id[3] == 'S') { + return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed); + } +#endif + + /* If we get here it means we likely don't have a header. Try opening in relaxed mode, if applicable. */ + if (relaxed) + { + if (container == drflac_container_native) + return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed); +#ifndef DR_FLAC_NO_OGG + if (container == drflac_container_ogg) + return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed); +#endif + } + + /* Unsupported container. */ + return DRFLAC_FALSE; +} + +void drflac__init_from_info(drflac* pFlac, drflac_init_info* pInit) +{ + drflac_assert(pFlac != NULL); + drflac_assert(pInit != NULL); + + drflac_zero_memory(pFlac, sizeof(*pFlac)); + pFlac->bs = pInit->bs; + pFlac->onMeta = pInit->onMeta; + pFlac->pUserDataMD = pInit->pUserDataMD; + pFlac->maxBlockSize = pInit->maxBlockSize; + pFlac->sampleRate = pInit->sampleRate; + pFlac->channels = (drflac_uint8)pInit->channels; + pFlac->bitsPerSample = (drflac_uint8)pInit->bitsPerSample; + pFlac->totalSampleCount = pInit->totalSampleCount; + pFlac->container = pInit->container; +} + +drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD) +{ + drflac_init_info init; + drflac* pFlac; + drflac_uint32 decodedSamplesAllocationSize; + drflac_uint32 allocationSize; + drflac_uint32 wholeSIMDVectorCountPerChannel; + +#ifndef DRFLAC_NO_CPUID + /* CPU support first. */ + drflac__init_cpu_caps(); +#endif + + if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) + return NULL; + + /* The size of the allocation for the drflac object needs to be large enough to fit the following: + * 1) The main members of the drflac structure + * 2) A block of memory large enough to store the decoded samples of the largest frame in the stream + * 3) If the container is Ogg, a drflac_oggbs object + * + * The complicated part of the allocation is making sure there's enough room the decoded samples, taking into consideration + * the different SIMD instruction sets. + */ + allocationSize = sizeof(drflac); + + /* The allocation size for decoded frames depends on the number of 32-bit integers that fit inside the largest SIMD vector + * we are supporting. */ + if ((init.maxBlockSize % (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) == 0) { + wholeSIMDVectorCountPerChannel = (init.maxBlockSize / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))); + } else { + wholeSIMDVectorCountPerChannel = (init.maxBlockSize / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) + 1; + } + + decodedSamplesAllocationSize = wholeSIMDVectorCountPerChannel * DRFLAC_MAX_SIMD_VECTOR_SIZE * init.channels; + + allocationSize += decodedSamplesAllocationSize; + allocationSize += DRFLAC_MAX_SIMD_VECTOR_SIZE; /* Allocate extra bytes to ensure we have enough for alignment. */ + +#ifndef DR_FLAC_NO_OGG + /* There's additional data required for Ogg streams. */ + if (init.container == drflac_container_ogg) + allocationSize += sizeof(drflac_oggbs); +#endif + + pFlac = (drflac*)DRFLAC_MALLOC(allocationSize); + drflac__init_from_info(pFlac, &init); + pFlac->pDecodedSamples = (drflac_int32*)drflac_align((size_t)pFlac->pExtraData, DRFLAC_MAX_SIMD_VECTOR_SIZE); + +#ifndef DR_FLAC_NO_OGG + if (init.container == drflac_container_ogg) { + drflac_oggbs* oggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize); + oggbs->onRead = onRead; + oggbs->onSeek = onSeek; + oggbs->pUserData = pUserData; + oggbs->currentBytePos = init.oggFirstBytePos; + oggbs->firstBytePos = init.oggFirstBytePos; + oggbs->serialNumber = init.oggSerial; + oggbs->bosPageHeader = init.oggBosHeader; + oggbs->bytesRemainingInPage = 0; + + /* The Ogg bistream needs to be layered on top of the original bitstream. */ + pFlac->bs.onRead = drflac__on_read_ogg; + pFlac->bs.onSeek = drflac__on_seek_ogg; + pFlac->bs.pUserData = (void*)oggbs; + pFlac->_oggbs = (void*)oggbs; + } +#endif + + /* Decode metadata before returning. */ + if (init.hasMetadataBlocks) + { + if (!drflac__read_and_decode_metadata(pFlac)) + { + DRFLAC_FREE(pFlac); + return NULL; + } + } + + /* If we get here, but don't have a STREAMINFO block, it means we've opened the stream in relaxed mode and need to decode + * the first frame. */ + if (!init.hasStreamInfoBlock) + { + pFlac->currentFrame.header = init.firstFrameHeader; + do + { + drflac_result result = drflac__decode_frame(pFlac); + if (result == DRFLAC_SUCCESS) + break; + + if (result == DRFLAC_CRC_MISMATCH) + { + if (drflac__read_next_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFrame.header)) + continue; + } + DRFLAC_FREE(pFlac); + return NULL; + } while (1); + } + + return pFlac; +} + +#ifndef DR_FLAC_NO_STDIO +typedef void* drflac_file; + +#if defined(DR_FLAC_NO_WIN32_IO) || !defined(_WIN32) +#include + +static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead) +{ + return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData); +} + +static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin) +{ + drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start)); + + return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0; +} + +static drflac_file drflac__open_file_handle(const char* filename) +{ + FILE* pFile; +#ifdef _MSC_VER + if (fopen_s(&pFile, filename, "rb") != 0) { + return NULL; + } +#else + pFile = fopen(filename, "rb"); + if (pFile == NULL) { + return NULL; + } +#endif + + return (drflac_file)pFile; +} + +static void drflac__close_file_handle(drflac_file file) +{ + fclose((FILE*)file); +} +#else +#include + +/* This doesn't seem to be defined for VC6. */ +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead) +{ + DWORD bytesRead; + + drflac_assert(bytesToRead < 0xFFFFFFFF); /* dr_flac will never request huge amounts of data at a time. This is a safe assertion. */ + + ReadFile((HANDLE)pUserData, bufferOut, (DWORD)bytesToRead, &bytesRead, NULL); + + return (size_t)bytesRead; +} + +static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin) +{ + drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start)); + + return SetFilePointer((HANDLE)pUserData, offset, NULL, (origin == drflac_seek_origin_current) ? FILE_CURRENT : FILE_BEGIN) != INVALID_SET_FILE_POINTER; +} + +static drflac_file drflac__open_file_handle(const char* filename) +{ + HANDLE hFile = CreateFileA(filename, FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return NULL; + } + + return (drflac_file)hFile; +} + +static void drflac__close_file_handle(drflac_file file) +{ + CloseHandle((HANDLE)file); +} +#endif + + +drflac* drflac_open_file(const char* filename) +{ + drflac_file file = drflac__open_file_handle(filename); + if (file == NULL) { + return NULL; + } + + drflac* pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)file); + if (pFlac == NULL) { + drflac__close_file_handle(file); + return NULL; + } + + return pFlac; +} + +drflac* drflac_open_file_with_metadata(const char* filename, drflac_meta_proc onMeta, void* pUserData) +{ + drflac_file file = drflac__open_file_handle(filename); + if (file == NULL) { + return NULL; + } + + drflac* pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)file, pUserData); + if (pFlac == NULL) { + drflac__close_file_handle(file); + return pFlac; + } + + return pFlac; +} +#endif /* DR_FLAC_NO_STDIO */ + +static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead) +{ + size_t bytesRemaining; + drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData; + drflac_assert(memoryStream != NULL); + drflac_assert(memoryStream->dataSize >= memoryStream->currentReadPos); + + bytesRemaining = memoryStream->dataSize - memoryStream->currentReadPos; + if (bytesToRead > bytesRemaining) + bytesToRead = bytesRemaining; + + if (bytesToRead > 0) + { + drflac_copy_memory(bufferOut, memoryStream->data + memoryStream->currentReadPos, bytesToRead); + memoryStream->currentReadPos += bytesToRead; + } + + return bytesToRead; +} + +static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin) +{ + drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData; + drflac_assert(memoryStream != NULL); + drflac_assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start)); + + if (origin == drflac_seek_origin_current) + { + if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) + memoryStream->currentReadPos += offset; + else + memoryStream->currentReadPos = memoryStream->dataSize; /* Trying to seek too far forward. */ + } else { + if ((drflac_uint32)offset <= memoryStream->dataSize) { + memoryStream->currentReadPos = offset; + } else { + memoryStream->currentReadPos = memoryStream->dataSize; /* Trying to seek too far forward. */ + } + } + + return DRFLAC_TRUE; +} + +drflac* drflac_open_memory(const void* data, size_t dataSize) +{ + drflac__memory_stream memoryStream; + drflac* pFlac; + + memoryStream.data = (const unsigned char*)data; + memoryStream.dataSize = dataSize; + memoryStream.currentReadPos = 0; + pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream); + if (pFlac == NULL) + return NULL; + + pFlac->memoryStream = memoryStream; + + /* This is an awful hack... */ +#ifndef DR_FLAC_NO_OGG + if (pFlac->container == drflac_container_ogg) + { + drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs; + oggbs->pUserData = &pFlac->memoryStream; + } + else +#endif + { + pFlac->bs.pUserData = &pFlac->memoryStream; + } + + return pFlac; +} + +drflac* drflac_open_memory_with_metadata(const void* data, size_t dataSize, drflac_meta_proc onMeta, void* pUserData) +{ + drflac__memory_stream memoryStream; + drflac* pFlac; + + memoryStream.data = (const unsigned char*)data; + memoryStream.dataSize = dataSize; + memoryStream.currentReadPos = 0; + + pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData); + if (pFlac == NULL) + return NULL; + + pFlac->memoryStream = memoryStream; + + /* This is an awful hack... */ +#ifndef DR_FLAC_NO_OGG + if (pFlac->container == drflac_container_ogg) + { + drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs; + oggbs->pUserData = &pFlac->memoryStream; + } + else +#endif + { + pFlac->bs.pUserData = &pFlac->memoryStream; + } + + return pFlac; +} + + + +drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData) +{ + return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData); +} +drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData) +{ + return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData); +} + +drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData) +{ + return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData); +} +drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData) +{ + return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData); +} + +void drflac_close(drflac* pFlac) +{ + if (pFlac == NULL) { + return; + } + +#ifndef DR_FLAC_NO_STDIO + /* If we opened the file with drflac_open_file() we will want to close the file handle. We can know whether or not drflac_open_file() + * was used by looking at the callbacks. */ + if (pFlac->bs.onRead == drflac__on_read_stdio) + drflac__close_file_handle((drflac_file)pFlac->bs.pUserData); + +#ifndef DR_FLAC_NO_OGG + /* Need to clean up Ogg streams a bit differently due to the way the bit streaming is chained. */ + if (pFlac->container == drflac_container_ogg) + { + drflac_assert(pFlac->bs.onRead == drflac__on_read_ogg); + drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs; + if (oggbs->onRead == drflac__on_read_stdio) + drflac__close_file_handle((drflac_file)oggbs->pUserData); + } +#endif +#endif + + DRFLAC_FREE(pFlac); +} + +drflac_uint64 drflac__read_s32__misaligned(drflac* pFlac, drflac_uint64 samplesToRead, drflac_int32* bufferOut) +{ + drflac_uint64 samplesRead = 0; + unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment); + + /* We should never be calling this when the number of samples to read is >= the sample count. */ + drflac_assert(samplesToRead < channelCount); + drflac_assert(pFlac->currentFrame.samplesRemaining > 0 && samplesToRead <= pFlac->currentFrame.samplesRemaining); + + while (samplesToRead > 0) + { + drflac_uint64 totalSamplesInFrame = pFlac->currentFrame.header.blockSize * channelCount; + drflac_uint64 samplesReadFromFrameSoFar = totalSamplesInFrame - pFlac->currentFrame.samplesRemaining; + drflac_uint64 channelIndex = samplesReadFromFrameSoFar % channelCount; + + drflac_uint64 nextSampleInFrame = samplesReadFromFrameSoFar / channelCount; + + int decodedSample = 0; + switch (pFlac->currentFrame.header.channelAssignment) + { + case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE: + { + if (channelIndex == 0) { + decodedSample = pFlac->currentFrame.subframes[channelIndex].pDecodedSamples[nextSampleInFrame]; + } else { + int side = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + int left = pFlac->currentFrame.subframes[channelIndex - 1].pDecodedSamples[nextSampleInFrame]; + decodedSample = left - side; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE: + { + if (channelIndex == 0) { + int side = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + int right = pFlac->currentFrame.subframes[channelIndex + 1].pDecodedSamples[nextSampleInFrame]; + decodedSample = side + right; + } else { + decodedSample = pFlac->currentFrame.subframes[channelIndex].pDecodedSamples[nextSampleInFrame]; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE: + { + int mid; + int side; + if (channelIndex == 0) { + mid = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + side = pFlac->currentFrame.subframes[channelIndex + 1].pDecodedSamples[nextSampleInFrame]; + + mid = (((unsigned int)mid) << 1) | (side & 0x01); + decodedSample = (mid + side) >> 1; + } else { + mid = pFlac->currentFrame.subframes[channelIndex - 1].pDecodedSamples[nextSampleInFrame]; + side = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + + mid = (((unsigned int)mid) << 1) | (side & 0x01); + decodedSample = (mid - side) >> 1; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT: + default: + { + decodedSample = pFlac->currentFrame.subframes[channelIndex].pDecodedSamples[nextSampleInFrame]; + } break; + } + + + decodedSample <<= ((32 - pFlac->bitsPerSample) + pFlac->currentFrame.subframes[channelIndex].wastedBitsPerSample); + + if (bufferOut) { + *bufferOut++ = decodedSample; + } + + samplesRead += 1; + pFlac->currentFrame.samplesRemaining -= 1; + samplesToRead -= 1; + } + + return samplesRead; +} + +drflac_uint64 drflac__seek_forward_by_samples(drflac* pFlac, drflac_uint64 samplesToRead) +{ + drflac_uint64 samplesRead = 0; + while (samplesToRead > 0) { + if (pFlac->currentFrame.samplesRemaining == 0) + { + if (!drflac__read_and_decode_next_frame(pFlac)) + break; /* Couldn't read the next frame, so just break from the loop and return. */ + } + else + { + samplesRead += 1; + pFlac->currentFrame.samplesRemaining -= 1; + samplesToRead -= 1; + } + } + + return samplesRead; +} + +drflac_uint64 drflac_read_s32(drflac* pFlac, drflac_uint64 samplesToRead, drflac_int32* bufferOut) +{ + drflac_uint64 samplesRead = 0; + /* Note that is allowed to be null, in which case this will be treated as something like a seek. */ + if (pFlac == NULL || samplesToRead == 0) + return 0; + + if (bufferOut == NULL) + return drflac__seek_forward_by_samples(pFlac, samplesToRead); + + while (samplesToRead > 0) + { + /* If we've run out of samples in this frame, go to the next. */ + if (pFlac->currentFrame.samplesRemaining == 0) + { + if (!drflac__read_and_decode_next_frame(pFlac)) + break; /* Couldn't read the next frame, so just break from the loop and return. */ + } + else + { + drflac_uint64 alignedSamplesRead; + drflac_uint64 alignedSampleCountPerChannel; + drflac_uint64 firstAlignedSampleInFrame; + unsigned int unusedBitsPerSample; + /* Here is where we grab the samples and interleave them. */ + unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment); + drflac_uint64 totalSamplesInFrame = pFlac->currentFrame.header.blockSize * channelCount; + drflac_uint64 samplesReadFromFrameSoFar = totalSamplesInFrame - pFlac->currentFrame.samplesRemaining; + drflac_uint64 misalignedSampleCount = samplesReadFromFrameSoFar % channelCount; + if (misalignedSampleCount > 0) + { + drflac_uint64 misalignedSamplesRead = drflac__read_s32__misaligned(pFlac, misalignedSampleCount, bufferOut); + samplesRead += misalignedSamplesRead; + samplesReadFromFrameSoFar += misalignedSamplesRead; + bufferOut += misalignedSamplesRead; + samplesToRead -= misalignedSamplesRead; + } + + alignedSampleCountPerChannel = samplesToRead / channelCount; + if (alignedSampleCountPerChannel > pFlac->currentFrame.samplesRemaining / channelCount) + alignedSampleCountPerChannel = pFlac->currentFrame.samplesRemaining / channelCount; + + firstAlignedSampleInFrame = samplesReadFromFrameSoFar / channelCount; + unusedBitsPerSample = 32 - pFlac->bitsPerSample; + + switch (pFlac->currentFrame.header.channelAssignment) + { + case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE: + { + drflac_uint64 i; + const drflac_int32* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const drflac_int32* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (i = 0; i < alignedSampleCountPerChannel; ++i) { + int left = pDecodedSamples0[i]; + int side = pDecodedSamples1[i]; + int right = left - side; + + bufferOut[i*2+0] = left << (unusedBitsPerSample + pFlac->currentFrame.subframes[0].wastedBitsPerSample); + bufferOut[i*2+1] = right << (unusedBitsPerSample + pFlac->currentFrame.subframes[1].wastedBitsPerSample); + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE: + { + drflac_uint64 i; + const drflac_int32* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const drflac_int32* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (i = 0; i < alignedSampleCountPerChannel; ++i) { + int side = pDecodedSamples0[i]; + int right = pDecodedSamples1[i]; + int left = right + side; + + bufferOut[i*2+0] = left << (unusedBitsPerSample + pFlac->currentFrame.subframes[0].wastedBitsPerSample); + bufferOut[i*2+1] = right << (unusedBitsPerSample + pFlac->currentFrame.subframes[1].wastedBitsPerSample); + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE: + { + drflac_uint64 i; + const drflac_int32* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const drflac_int32* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (i = 0; i < alignedSampleCountPerChannel; ++i) { + int side = pDecodedSamples1[i]; + int mid = (((drflac_uint32)pDecodedSamples0[i]) << 1) | (side & 0x01); + + bufferOut[i*2+0] = ((mid + side) >> 1) << (unusedBitsPerSample + pFlac->currentFrame.subframes[0].wastedBitsPerSample); + bufferOut[i*2+1] = ((mid - side) >> 1) << (unusedBitsPerSample + pFlac->currentFrame.subframes[1].wastedBitsPerSample); + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT: + default: + { + if (pFlac->currentFrame.header.channelAssignment == 1) /* 1 = Stereo */ + { + drflac_uint64 i; + /* Stereo optimized inner loop unroll. */ + const drflac_int32* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const drflac_int32* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (i = 0; i < alignedSampleCountPerChannel; ++i) { + bufferOut[i*2+0] = pDecodedSamples0[i] << (unusedBitsPerSample + pFlac->currentFrame.subframes[0].wastedBitsPerSample); + bufferOut[i*2+1] = pDecodedSamples1[i] << (unusedBitsPerSample + pFlac->currentFrame.subframes[1].wastedBitsPerSample); + } + } + else + { + drflac_uint64 i; + + /* Generic interleaving. */ + for (i = 0; i < alignedSampleCountPerChannel; ++i) + { + unsigned j; + for (j = 0; j < channelCount; ++j) + { + bufferOut[(i*channelCount)+j] = (pFlac->currentFrame.subframes[j].pDecodedSamples[firstAlignedSampleInFrame + i]) << (unusedBitsPerSample + pFlac->currentFrame.subframes[j].wastedBitsPerSample); + } + } + } + } break; + } + + alignedSamplesRead = alignedSampleCountPerChannel * channelCount; + samplesRead += alignedSamplesRead; + samplesReadFromFrameSoFar += alignedSamplesRead; + bufferOut += alignedSamplesRead; + samplesToRead -= alignedSamplesRead; + pFlac->currentFrame.samplesRemaining -= (unsigned int)alignedSamplesRead; + + /* At this point we may still have some excess samples left to read. */ + if (samplesToRead > 0 && pFlac->currentFrame.samplesRemaining > 0) { + drflac_uint64 excessSamplesRead = 0; + if (samplesToRead < pFlac->currentFrame.samplesRemaining) { + excessSamplesRead = drflac__read_s32__misaligned(pFlac, samplesToRead, bufferOut); + } else { + excessSamplesRead = drflac__read_s32__misaligned(pFlac, pFlac->currentFrame.samplesRemaining, bufferOut); + } + + samplesRead += excessSamplesRead; + samplesReadFromFrameSoFar += excessSamplesRead; + bufferOut += excessSamplesRead; + samplesToRead -= excessSamplesRead; + } + } + } + + return samplesRead; +} + +drflac_uint64 drflac_read_s16(drflac* pFlac, drflac_uint64 samplesToRead, drflac_int16* pBufferOut) +{ + /* This reads samples in 2 passes and can probably be optimized. */ + drflac_uint64 totalSamplesRead = 0; + + while (samplesToRead > 0) + { + drflac_uint64 i; + drflac_int32 samples32[4096]; + drflac_uint64 samplesJustRead = drflac_read_s32(pFlac, (samplesToRead > 4096) ? 4096 : samplesToRead, samples32); + if (samplesJustRead == 0) + break; /* Reached the end. */ + + /* s32 -> s16 */ + for (i = 0; i < samplesJustRead; ++i) + pBufferOut[i] = (drflac_int16)(samples32[i] >> 16); + + totalSamplesRead += samplesJustRead; + samplesToRead -= samplesJustRead; + pBufferOut += samplesJustRead; + } + + return totalSamplesRead; +} + +drflac_uint64 drflac_read_f32(drflac* pFlac, drflac_uint64 samplesToRead, float* pBufferOut) +{ + /* This reads samples in 2 passes and can probably be optimized. */ + drflac_uint64 totalSamplesRead = 0; + + while (samplesToRead > 0) + { + drflac_uint64 i; + drflac_int32 samples32[4096]; + drflac_uint64 samplesJustRead = drflac_read_s32(pFlac, (samplesToRead > 4096) ? 4096 : samplesToRead, samples32); + if (samplesJustRead == 0) + break; /* Reached the end. */ + + /* s32 -> f32 */ + for (i = 0; i < samplesJustRead; ++i) + pBufferOut[i] = (float)(samples32[i] / 2147483648.0); + + totalSamplesRead += samplesJustRead; + samplesToRead -= samplesJustRead; + pBufferOut += samplesJustRead; + } + + return totalSamplesRead; +} + +drflac_bool32 drflac_seek_to_sample(drflac* pFlac, drflac_uint64 sampleIndex) +{ + if (pFlac == NULL) + return DRFLAC_FALSE; + + /* If we don't know where the first frame begins then we can't seek. This will happen when the STREAMINFO block was not present + * when the decoder was opened. */ + if (pFlac->firstFramePos == 0) + return DRFLAC_FALSE; + + if (sampleIndex == 0) + return drflac__seek_to_first_frame(pFlac); + + /* Clamp the sample to the end. */ + if (sampleIndex >= pFlac->totalSampleCount) + sampleIndex = pFlac->totalSampleCount - 1; + + + /* Different techniques depending on encapsulation. Using the native FLAC seektable with Ogg encapsulation is a bit awkward so + * we'll instead use Ogg's natural seeking facility. */ +#ifndef DR_FLAC_NO_OGG + if (pFlac->container == drflac_container_ogg) + return drflac_ogg__seek_to_sample(pFlac, sampleIndex); + else +#endif + { + /* First try seeking via the seek table. If this fails, fall back to a brute force seek which is much slower. */ + if (!drflac__seek_to_sample__seek_table(pFlac, sampleIndex)) + return drflac__seek_to_sample__brute_force(pFlac, sampleIndex); + } + + + return DRFLAC_TRUE; +} + + + +/* High Level APIs */ + +/* I couldn't figure out where SIZE_MAX was defined for VC6. If anybody knows, let me know. */ +#if defined(_MSC_VER) && _MSC_VER <= 1200 +#ifdef DRFLAC_64BIT +#define SIZE_MAX ((drflac_uint64)0xFFFFFFFFFFFFFFFF) +#else +#define SIZE_MAX 0xFFFFFFFF +#endif +#endif + +/* Using a macro as the definition of the drflac__full_decode_and_close_*() API family. Sue me. */ +#define DRFLAC_DEFINE_FULL_DECODE_AND_CLOSE(extension, type) \ +static type* drflac__full_decode_and_close_ ## extension (drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalSampleCountOut)\ +{ \ + drflac_uint64 totalSampleCount; \ + type* pSampleData = NULL; \ + drflac_assert(pFlac != NULL); \ + totalSampleCount = pFlac->totalSampleCount; \ + if (totalSampleCount == 0) { \ + type buffer[4096]; \ + drflac_uint64 samplesRead; \ + size_t sampleDataBufferSize = sizeof(buffer); \ + pSampleData = (type*)DRFLAC_MALLOC(sampleDataBufferSize); \ + if (pSampleData == NULL) \ + goto on_error; \ + while ((samplesRead = (drflac_uint64)drflac_read_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0]), buffer)) > 0) { \ + if (((totalSampleCount + samplesRead) * sizeof(type)) > sampleDataBufferSize) { \ + type *pNewSampleData; \ + sampleDataBufferSize *= 2; \ + pNewSampleData = (type*)DRFLAC_REALLOC(pSampleData, sampleDataBufferSize); \ + if (pNewSampleData == NULL) { \ + DRFLAC_FREE(pSampleData); \ + goto on_error; \ + } \ + \ + pSampleData = pNewSampleData; \ + } \ + \ + drflac_copy_memory(pSampleData + totalSampleCount, buffer, (size_t)(samplesRead*sizeof(type))); \ + totalSampleCount += samplesRead; \ + } \ + \ + /* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \ + protect those ears from random noise! */ \ + drflac_zero_memory(pSampleData + totalSampleCount, (size_t)(sampleDataBufferSize - totalSampleCount*sizeof(type))); \ + } else { \ + drflac_uint64 dataSize = totalSampleCount * sizeof(type); \ + if (dataSize > SIZE_MAX) { \ + goto on_error; /* The decoded data is too big. */ \ + } \ + \ + pSampleData = (type*)DRFLAC_MALLOC((size_t)dataSize); /* <-- Safe cast as per the check above. */ \ + if (pSampleData == NULL) { \ + goto on_error; \ + } \ + \ + totalSampleCount = drflac_read_##extension(pFlac, pFlac->totalSampleCount, pSampleData); \ + } \ + \ + if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \ + if (channelsOut) *channelsOut = pFlac->channels; \ + if (totalSampleCountOut) *totalSampleCountOut = totalSampleCount; \ + \ + drflac_close(pFlac); \ + return pSampleData; \ + \ +on_error: \ + drflac_close(pFlac); \ + return NULL; \ +} + +DRFLAC_DEFINE_FULL_DECODE_AND_CLOSE(s32, drflac_int32) +DRFLAC_DEFINE_FULL_DECODE_AND_CLOSE(s16, drflac_int16) +DRFLAC_DEFINE_FULL_DECODE_AND_CLOSE(f32, float) + +drflac_int32* drflac_open_and_decode_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + /* Safety. */ + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open(onRead, onSeek, pUserData); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_s32(pFlac, channels, sampleRate, totalSampleCount); +} + +drflac_int16* drflac_open_and_decode_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + /* Safety. */ + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open(onRead, onSeek, pUserData); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_s16(pFlac, channels, sampleRate, totalSampleCount); +} + +float* drflac_open_and_decode_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + /* Safety. */ + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open(onRead, onSeek, pUserData); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_f32(pFlac, channels, sampleRate, totalSampleCount); +} + +#ifndef DR_FLAC_NO_STDIO +drflac_int32* drflac_open_and_decode_file_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open_file(filename); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_s32(pFlac, channels, sampleRate, totalSampleCount); +} + +drflac_int16* drflac_open_and_decode_file_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open_file(filename); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_s16(pFlac, channels, sampleRate, totalSampleCount); +} + +float* drflac_open_and_decode_file_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open_file(filename); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_f32(pFlac, channels, sampleRate, totalSampleCount); +} +#endif + +drflac_int32* drflac_open_and_decode_memory_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac *pFlac; + + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open_memory(data, dataSize); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_s32(pFlac, channels, sampleRate, totalSampleCount); +} + +drflac_int16* drflac_open_and_decode_memory_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open_memory(data, dataSize); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_s16(pFlac, channels, sampleRate, totalSampleCount); +} + +float* drflac_open_and_decode_memory_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalSampleCount) +{ + drflac* pFlac; + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + pFlac = drflac_open_memory(data, dataSize); + if (pFlac == NULL) + return NULL; + + return drflac__full_decode_and_close_f32(pFlac, channels, sampleRate, totalSampleCount); +} + +void drflac_free(void* pSampleDataReturnedByOpenAndDecode) +{ + DRFLAC_FREE(pSampleDataReturnedByOpenAndDecode); +} + + + + +void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const char* pComments) +{ + if (pIter == NULL) + return; + + pIter->countRemaining = commentCount; + pIter->pRunningData = pComments; +} + +const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut) +{ + const char* pComment; + drflac_uint32 length; + /* Safety. */ + if (pCommentLengthOut) *pCommentLengthOut = 0; + + if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) + return NULL; + + length = drflac__le2host_32(*(drflac_uint32*)pIter->pRunningData); + pIter->pRunningData += 4; + + pComment = pIter->pRunningData; + pIter->pRunningData += length; + pIter->countRemaining -= 1; + + if (pCommentLengthOut) *pCommentLengthOut = length; + return pComment; +} +#endif /* DR_FLAC_IMPLEMENTATION */ + +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ diff --git a/deps/dr/dr_mp3.h b/deps/dr/dr_mp3.h new file mode 100644 index 0000000000..9b74cad353 --- /dev/null +++ b/deps/dr/dr_mp3.h @@ -0,0 +1,2745 @@ +#ifndef dr_mp3_h +#define dr_mp3_h + +#define DR_MP3_NO_STDIO + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef int8_t drmp3_int8; +typedef uint8_t drmp3_uint8; +typedef int16_t drmp3_int16; +typedef uint16_t drmp3_uint16; +typedef int32_t drmp3_int32; +typedef uint32_t drmp3_uint32; +typedef int64_t drmp3_int64; +typedef uint64_t drmp3_uint64; +typedef drmp3_uint8 drmp3_bool8; +typedef drmp3_uint32 drmp3_bool32; +#define DRMP3_TRUE 1 +#define DRMP3_FALSE 0 + +#define DRMP3_MAX_SAMPLES_PER_FRAME (1152*2) + + +/* Low Level Push API + * ================== */ +typedef struct +{ + int frame_bytes; + int channels; + int hz; + int layer; + int bitrate_kbps; +} drmp3dec_frame_info; + +typedef struct +{ + float mdct_overlap[2][9*32]; + float qmf_state[15*2*32]; + int reserv; + int free_format_bytes; + unsigned char header[4]; + unsigned char reserv_buf[511]; +} drmp3dec; + +/* Initializes a low level decoder. */ +void drmp3dec_init(drmp3dec *dec); + +/* Reads a frame from a low level decoder. */ +int drmp3dec_decode_frame(drmp3dec *dec, const unsigned char *mp3, int mp3_bytes, short *pcm, drmp3dec_frame_info *info); + + +/* Main API (Pull API) + * ===================*/ + +typedef struct drmp3_src drmp3_src; +typedef drmp3_uint64 (* drmp3_src_read_proc)(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, void* pUserData); /* Returns the number of frames that were read. */ + +typedef enum +{ + drmp3_src_algorithm_none, + drmp3_src_algorithm_linear +} drmp3_src_algorithm; + +#define DRMP3_SRC_CACHE_SIZE_IN_FRAMES 512 +typedef struct +{ + drmp3_src* pSRC; + float pCachedFrames[2 * DRMP3_SRC_CACHE_SIZE_IN_FRAMES]; + drmp3_uint32 cachedFrameCount; + drmp3_uint32 iNextFrame; +} drmp3_src_cache; + +typedef struct +{ + drmp3_uint32 sampleRateIn; + drmp3_uint32 sampleRateOut; + drmp3_uint32 channels; + drmp3_src_algorithm algorithm; + drmp3_uint32 cacheSizeInFrames; /* The number of frames to read from the client at a time. */ +} drmp3_src_config; + +struct drmp3_src +{ + drmp3_src_config config; + drmp3_src_read_proc onRead; + void* pUserData; + float bin[256]; + drmp3_src_cache cache; /* <-- For simplifying and optimizing client -> memory reading. */ + union + { + struct + { + float alpha; + drmp3_bool32 isPrevFramesLoaded : 1; + drmp3_bool32 isNextFramesLoaded : 1; + } linear; + } algo; +}; + +typedef enum +{ + drmp3_seek_origin_start, + drmp3_seek_origin_current +} drmp3_seek_origin; + +/* Callback for when data is read. Return value is the number of bytes actually read. + * + * pUserData [in] The user data that was passed to drmp3_init(), drmp3_open() and family. + * pBufferOut [out] The output buffer. + * bytesToRead [in] The number of bytes to read. + * + * Returns the number of bytes actually read. + * + * A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until + * either the entire bytesToRead is filled or you have reached the end of the stream. + */ +typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead); + +/* Callback for when data needs to be seeked. + * + * pUserData [in] The user data that was passed to drmp3_init(), drmp3_open() and family. + * offset [in] The number of bytes to move, relative to the origin. Will never be negative. + * origin [in] The origin of the seek - the current position or the start of the stream. + * + * Returns whether or not the seek was successful. + * + * Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which + * will be either drmp3_seek_origin_start or drmp3_seek_origin_current. + */ +typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin); + +typedef struct +{ + drmp3_uint32 outputChannels; + drmp3_uint32 outputSampleRate; +} drmp3_config; + +typedef struct +{ + drmp3dec decoder; + drmp3dec_frame_info frameInfo; + drmp3_uint32 channels; + drmp3_uint32 sampleRate; + drmp3_read_proc onRead; + drmp3_seek_proc onSeek; + void* pUserData; + drmp3_uint32 frameChannels; /* The number of channels in the currently loaded MP3 frame. Internal use only. */ + drmp3_uint32 frameSampleRate; /* The sample rate of the currently loaded MP3 frame. Internal use only */ + drmp3_uint32 framesConsumed; + drmp3_uint32 framesRemaining; + drmp3_int16 frames[DRMP3_MAX_SAMPLES_PER_FRAME]; + drmp3_src src; + size_t dataSize; + size_t dataCapacity; + drmp3_uint8* pData; + drmp3_bool32 atEnd : 1; + struct + { + const drmp3_uint8* pData; + size_t dataSize; + size_t currentReadPos; + } memory; /* Only used for decoders that were opened against a block of memory. */ +} drmp3; + +/* Initializes an MP3 decoder. + * + * onRead [in] The function to call when data needs to be read from the client. + * onSeek [in] The function to call when the read position of the client data needs to move. + * pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek. + * + * Returns true if successful; false otherwise. + * + * Close the loader with drmp3_uninit(). + * + * See also: drmp3_init_file(), drmp3_init_memory(), drmp3_uninit() + */ +drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_config* pConfig); + +/* Initializes an MP3 decoder from a block of memory. + * + * This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for + * the lifetime of the drmp3 object. + * + * The buffer should contain the contents of the entire MP3 file. + */ +drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_config* pConfig); + +#ifndef DR_MP3_NO_STDIO +/* Initializes an MP3 decoder from a file. + * + * This holds the internal FILE object until drmp3_uninit() is called. Keep this in mind if you're caching drmp3 + * objects because the operating system may restrict the number of file handles an application can have open at + * any given time. + */ +drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* filePath, const drmp3_config* pConfig); +#endif + +/* Uninitializes an MP3 decoder. */ +void drmp3_uninit(drmp3* pMP3); + +/* Reads PCM frames as interleaved 32-bit IEEE floating point PCM. + * + * Note that framesToRead specifies the number of PCM frames to read, _not_ the number of MP3 frames. + */ +drmp3_uint64 drmp3_read_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut); + +/* Seeks to a specific frame. + * + * Note that this is _not_ an MP3 frame, but rather a PCM frame. + */ +drmp3_bool32 drmp3_seek_to_frame(drmp3* pMP3, drmp3_uint64 frameIndex); + + +/* Opens an decodes an entire MP3 stream as a single operation. + * + * pConfig is both an input and output. On input it contains what you want. On output it contains what you got. + * + * Free the returned pointer with drmp3_free(). + */ +float* drmp3_open_and_decode_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount); +float* drmp3_open_and_decode_memory_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount); +#ifndef DR_MP3_NO_STDIO +float* drmp3_open_and_decode_file_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount); +#endif + +/* Frees any memory that was allocated by a public drmp3 API. */ +void drmp3_free(void* p); + +#ifdef __cplusplus +} +#endif +#endif /* dr_mp3_h */ + + +/* + * + * IMPLEMENTATION + * + */ +#ifdef DR_MP3_IMPLEMENTATION +#include +#include +#include +#include /* For INT_MAX */ + +#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */ +#define DRMP3_MAX_FRAME_SYNC_MATCHES 10 + +#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */ + +#define DRMP3_MAX_BITRESERVOIR_BYTES 511 +#define DRMP3_SHORT_BLOCK_TYPE 2 +#define DRMP3_STOP_BLOCK_TYPE 3 +#define DRMP3_MODE_MONO 3 +#define DRMP3_MODE_JOINT_STEREO 1 +#define DRMP3_HDR_SIZE 4 +#define DRMP3_HDR_IS_MONO(h) (((h[3]) & 0xC0) == 0xC0) +#define DRMP3_HDR_IS_MS_STEREO(h) (((h[3]) & 0xE0) == 0x60) +#define DRMP3_HDR_IS_FREE_FORMAT(h) (((h[2]) & 0xF0) == 0) +#define DRMP3_HDR_IS_CRC(h) (!((h[1]) & 1)) +#define DRMP3_HDR_TEST_PADDING(h) ((h[2]) & 0x2) +#define DRMP3_HDR_TEST_MPEG1(h) ((h[1]) & 0x8) +#define DRMP3_HDR_TEST_NOT_MPEG25(h) ((h[1]) & 0x10) +#define DRMP3_HDR_TEST_I_STEREO(h) ((h[3]) & 0x10) +#define DRMP3_HDR_TEST_MS_STEREO(h) ((h[3]) & 0x20) +#define DRMP3_HDR_GET_STEREO_MODE(h) (((h[3]) >> 6) & 3) +#define DRMP3_HDR_GET_STEREO_MODE_EXT(h) (((h[3]) >> 4) & 3) +#define DRMP3_HDR_GET_LAYER(h) (((h[1]) >> 1) & 3) +#define DRMP3_HDR_GET_BITRATE(h) ((h[2]) >> 4) +#define DRMP3_HDR_GET_SAMPLE_RATE(h) (((h[2]) >> 2) & 3) +#define DRMP3_HDR_GET_MY_SAMPLE_RATE(h) (DRMP3_HDR_GET_SAMPLE_RATE(h) + (((h[1] >> 3) & 1) + ((h[1] >> 4) & 1))*3) +#define DRMP3_HDR_IS_FRAME_576(h) ((h[1] & 14) == 2) +#define DRMP3_HDR_IS_LAYER_1(h) ((h[1] & 6) == 6) + +#define DRMP3_BITS_DEQUANTIZER_OUT -1 +#define DRMP3_MAX_SCF (255 + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210) +#define DRMP3_MAX_SCFI ((DRMP3_MAX_SCF + 3) & ~3) + +#define DRMP3_MIN(a, b) ((a) > (b) ? (b) : (a)) +#define DRMP3_MAX(a, b) ((a) < (b) ? (b) : (a)) + +#if !defined(DR_MP3_NO_SIMD) + +#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(_M_ARM64) || defined(__x86_64__) || defined(__aarch64__)) +/* x64 always have SSE2, arm64 always have neon, no need for generic code */ +#define DR_MP3_ONLY_SIMD +#endif + +#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || ((defined(__i386__) || defined(__x86_64__)) && defined(__SSE2__)) +#if defined(_MSC_VER) +#include +#endif +#include +#define DRMP3_HAVE_SSE 1 +#define DRMP3_HAVE_SIMD 1 +#define DRMP3_VSTORE _mm_storeu_ps +#define DRMP3_VLD _mm_loadu_ps +#define DRMP3_VSET _mm_set1_ps +#define DRMP3_VADD _mm_add_ps +#define DRMP3_VSUB _mm_sub_ps +#define DRMP3_VMUL _mm_mul_ps +#define DRMP3_VMAC(a, x, y) _mm_add_ps(a, _mm_mul_ps(x, y)) +#define DRMP3_VMSB(a, x, y) _mm_sub_ps(a, _mm_mul_ps(x, y)) +#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s)) +#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3)) +typedef __m128 drmp3_f4; +#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD) +#define drmp3_cpuid __cpuid +#else +static INLINE __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType) +{ +#if defined(__PIC__) + __asm__ __volatile__( +#if defined(__x86_64__) + "push %%rbx\n" + "cpuid\n" + "xchgl %%ebx, %1\n" + "pop %%rbx\n" +#else + "xchgl %%ebx, %1\n" + "cpuid\n" + "xchgl %%ebx, %1\n" +#endif + : "=a" (CPUInfo[0]), "=r" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) + : "a" (InfoType)); +#else + __asm__ __volatile__( + "cpuid" + : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) + : "a" (InfoType)); +#endif +} +#endif +static int drmp3_have_simd() +{ +#ifdef DR_MP3_ONLY_SIMD + return 1; +#else + static int g_have_simd; + int CPUInfo[4]; +#ifdef MINIMP3_TEST + static int g_counter; + if (g_counter++ > 100) + goto test_nosimd; +#endif + if (g_have_simd) + return g_have_simd - 1; + drmp3_cpuid(CPUInfo, 0); + if (CPUInfo[0] > 0) + { + drmp3_cpuid(CPUInfo, 1); + g_have_simd = (CPUInfo[3] & (1 << 26)) + 1; /* SSE2 */ + return g_have_simd - 1; + } +#ifdef MINIMP3_TEST +test_nosimd: +#endif + g_have_simd = 1; + return 0; +#endif +} +#elif defined(__ARM_NEON) || defined(__aarch64__) +#include +#define DRMP3_HAVE_SIMD 1 +#define DRMP3_VSTORE vst1q_f32 +#define DRMP3_VLD vld1q_f32 +#define DRMP3_VSET vmovq_n_f32 +#define DRMP3_VADD vaddq_f32 +#define DRMP3_VSUB vsubq_f32 +#define DRMP3_VMUL vmulq_f32 +#define DRMP3_VMAC(a, x, y) vmlaq_f32(a, x, y) +#define DRMP3_VMSB(a, x, y) vmlsq_f32(a, x, y) +#define DRMP3_VMUL_S(x, s) vmulq_f32(x, vmovq_n_f32(s)) +#define DRMP3_VREV(x) vcombine_f32(vget_high_f32(vrev64q_f32(x)), vget_low_f32(vrev64q_f32(x))) +typedef float32x4_t drmp3_f4; +static int drmp3_have_simd() +{ /* TODO: detect neon for !DR_MP3_ONLY_SIMD */ + return 1; +} +#else +#define DRMP3_HAVE_SIMD 0 +#ifdef DR_MP3_ONLY_SIMD +#error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled +#endif +#endif + +#else + +#define DRMP3_HAVE_SIMD 0 + +#endif + +typedef struct +{ + const drmp3_uint8 *buf; + int pos; + int limit; +} drmp3_bs; + +typedef struct +{ + drmp3_uint8 total_bands; + drmp3_uint8 stereo_bands; + drmp3_uint8 bitalloc[64]; + drmp3_uint8 scfcod[64]; + float scf[3*64]; +} drmp3_L12_scale_info; + +typedef struct +{ + drmp3_uint8 tab_offset; + drmp3_uint8 code_tab_width; + drmp3_uint8 band_count; +} drmp3_L12_subband_alloc; + +typedef struct +{ + const drmp3_uint8 *sfbtab; + drmp3_uint16 part_23_length; + drmp3_uint16 big_values; + drmp3_uint16 scalefac_compress; + drmp3_uint8 global_gain; + drmp3_uint8 block_type; + drmp3_uint8 mixed_block_flag; + drmp3_uint8 n_long_sfb; + drmp3_uint8 n_short_sfb; + drmp3_uint8 table_select[3]; + drmp3_uint8 region_count[3]; + drmp3_uint8 subblock_gain[3]; + drmp3_uint8 preflag; + drmp3_uint8 scalefac_scale; + drmp3_uint8 count1_table; + drmp3_uint8 scfsi; +} drmp3_L3_gr_info; + +typedef struct +{ + drmp3_bs bs; + drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES]; + drmp3_L3_gr_info gr_info[4]; + float grbuf[2][576]; + float scf[40]; + drmp3_uint8 ist_pos[2][39]; + float syn[18 + 15][2*32]; +} drmp3dec_scratch; + +static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes) +{ + bs->buf = data; + bs->pos = 0; + bs->limit = bytes*8; +} + +static drmp3_uint32 drmp3_bs_get_bits(drmp3_bs *bs, int n) +{ + drmp3_uint32 next, cache = 0, s = bs->pos & 7; + int shl = n + s; + const drmp3_uint8 *p = bs->buf + (bs->pos >> 3); + if ((bs->pos += n) > bs->limit) + return 0; + next = *p++ & (255 >> s); + while ((shl -= 8) > 0) + { + cache |= next << shl; + next = *p++; + } + return cache | (next >> -shl); +} + +static int drmp3_hdr_valid(const drmp3_uint8 *h) +{ + return h[0] == 0xff && + ((h[1] & 0xF0) == 0xf0 || (h[1] & 0xFE) == 0xe2) && + (DRMP3_HDR_GET_LAYER(h) != 0) && + (DRMP3_HDR_GET_BITRATE(h) != 15) && + (DRMP3_HDR_GET_SAMPLE_RATE(h) != 3); +} + +static int drmp3_hdr_compare(const drmp3_uint8 *h1, const drmp3_uint8 *h2) +{ + return drmp3_hdr_valid(h2) && + ((h1[1] ^ h2[1]) & 0xFE) == 0 && + ((h1[2] ^ h2[2]) & 0x0C) == 0 && + !(DRMP3_HDR_IS_FREE_FORMAT(h1) ^ DRMP3_HDR_IS_FREE_FORMAT(h2)); +} + +static unsigned drmp3_hdr_bitrate_kbps(const drmp3_uint8 *h) +{ + static const drmp3_uint8 halfrate[2][3][15] = { + { { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,16,24,28,32,40,48,56,64,72,80,88,96,112,128 } }, + { { 0,16,20,24,28,32,40,48,56,64,80,96,112,128,160 }, { 0,16,24,28,32,40,48,56,64,80,96,112,128,160,192 }, { 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224 } }, + }; + return 2*halfrate[!!DRMP3_HDR_TEST_MPEG1(h)][DRMP3_HDR_GET_LAYER(h) - 1][DRMP3_HDR_GET_BITRATE(h)]; +} + +static unsigned drmp3_hdr_sample_rate_hz(const drmp3_uint8 *h) +{ + static const unsigned g_hz[3] = { 44100, 48000, 32000 }; + return g_hz[DRMP3_HDR_GET_SAMPLE_RATE(h)] >> (int)!DRMP3_HDR_TEST_MPEG1(h) >> (int)!DRMP3_HDR_TEST_NOT_MPEG25(h); +} + +static unsigned drmp3_hdr_frame_samples(const drmp3_uint8 *h) +{ + return DRMP3_HDR_IS_LAYER_1(h) ? 384 : (1152 >> (int)DRMP3_HDR_IS_FRAME_576(h)); +} + +static int drmp3_hdr_frame_bytes(const drmp3_uint8 *h, int free_format_size) +{ + int frame_bytes = drmp3_hdr_frame_samples(h)*drmp3_hdr_bitrate_kbps(h)*125/drmp3_hdr_sample_rate_hz(h); + if (DRMP3_HDR_IS_LAYER_1(h)) + { + frame_bytes &= ~3; /* slot align */ + } + return frame_bytes ? frame_bytes : free_format_size; +} + +static int drmp3_hdr_padding(const drmp3_uint8 *h) +{ + return DRMP3_HDR_TEST_PADDING(h) ? (DRMP3_HDR_IS_LAYER_1(h) ? 4 : 1) : 0; +} + +#ifndef DR_MP3_ONLY_MP3 +static const drmp3_L12_subband_alloc *drmp3_L12_subband_alloc_table(const drmp3_uint8 *hdr, drmp3_L12_scale_info *sci) +{ + const drmp3_L12_subband_alloc *alloc; + int mode = DRMP3_HDR_GET_STEREO_MODE(hdr); + int nbands, stereo_bands = (mode == DRMP3_MODE_MONO) ? 0 : (mode == DRMP3_MODE_JOINT_STEREO) ? (DRMP3_HDR_GET_STEREO_MODE_EXT(hdr) << 2) + 4 : 32; + + if (DRMP3_HDR_IS_LAYER_1(hdr)) + { + static const drmp3_L12_subband_alloc g_alloc_L1[] = { { 76, 4, 32 } }; + alloc = g_alloc_L1; + nbands = 32; + } else if (!DRMP3_HDR_TEST_MPEG1(hdr)) + { + static const drmp3_L12_subband_alloc g_alloc_L2M2[] = { { 60, 4, 4 }, { 44, 3, 7 }, { 44, 2, 19 } }; + alloc = g_alloc_L2M2; + nbands = 30; + } else + { + static const drmp3_L12_subband_alloc g_alloc_L2M1[] = { { 0, 4, 3 }, { 16, 4, 8 }, { 32, 3, 12 }, { 40, 2, 7 } }; + int sample_rate_idx = DRMP3_HDR_GET_SAMPLE_RATE(hdr); + unsigned kbps = drmp3_hdr_bitrate_kbps(hdr) >> (int)(mode != DRMP3_MODE_MONO); + if (!kbps) /* free-format */ + { + kbps = 192; + } + + alloc = g_alloc_L2M1; + nbands = 27; + if (kbps < 56) + { + static const drmp3_L12_subband_alloc g_alloc_L2M1_lowrate[] = { { 44, 4, 2 }, { 44, 3, 10 } }; + alloc = g_alloc_L2M1_lowrate; + nbands = sample_rate_idx == 2 ? 12 : 8; + } else if (kbps >= 96 && sample_rate_idx != 1) + { + nbands = 30; + } + } + + sci->total_bands = (drmp3_uint8)nbands; + sci->stereo_bands = (drmp3_uint8)DRMP3_MIN(stereo_bands, nbands); + + return alloc; +} + +static void drmp3_L12_read_scalefactors(drmp3_bs *bs, drmp3_uint8 *pba, drmp3_uint8 *scfcod, int bands, float *scf) +{ + static const float g_deq_L12[18*3] = { +#define DRMP3_DQ(x) 9.53674316e-07f/x, 7.56931807e-07f/x, 6.00777173e-07f/x + DRMP3_DQ(3),DRMP3_DQ(7),DRMP3_DQ(15),DRMP3_DQ(31),DRMP3_DQ(63),DRMP3_DQ(127),DRMP3_DQ(255),DRMP3_DQ(511),DRMP3_DQ(1023),DRMP3_DQ(2047),DRMP3_DQ(4095),DRMP3_DQ(8191),DRMP3_DQ(16383),DRMP3_DQ(32767),DRMP3_DQ(65535),DRMP3_DQ(3),DRMP3_DQ(5),DRMP3_DQ(9) + }; + int i, m; + for (i = 0; i < bands; i++) + { + float s = 0; + int ba = *pba++; + int mask = ba ? 4 + ((19 >> scfcod[i]) & 3) : 0; + for (m = 4; m; m >>= 1) + { + if (mask & m) + { + int b = drmp3_bs_get_bits(bs, 6); + s = g_deq_L12[ba*3 - 6 + b % 3]*(1 << 21 >> b/3); + } + *scf++ = s; + } + } +} + +static void drmp3_L12_read_scale_info(const drmp3_uint8 *hdr, drmp3_bs *bs, drmp3_L12_scale_info *sci) +{ + static const drmp3_uint8 g_bitalloc_code_tab[] = { + 0,17, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16, + 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,16, + 0,17,18, 3,19,4,5,16, + 0,17,18,16, + 0,17,18,19, 4,5,6, 7,8, 9,10,11,12,13,14,15, + 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,14, + 0, 2, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16 + }; + const drmp3_L12_subband_alloc *subband_alloc = drmp3_L12_subband_alloc_table(hdr, sci); + + int i, k = 0, ba_bits = 0; + const drmp3_uint8 *ba_code_tab = g_bitalloc_code_tab; + + for (i = 0; i < sci->total_bands; i++) + { + drmp3_uint8 ba; + if (i == k) + { + k += subband_alloc->band_count; + ba_bits = subband_alloc->code_tab_width; + ba_code_tab = g_bitalloc_code_tab + subband_alloc->tab_offset; + subband_alloc++; + } + ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)]; + sci->bitalloc[2*i] = ba; + if (i < sci->stereo_bands) + { + ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)]; + } + sci->bitalloc[2*i + 1] = sci->stereo_bands ? ba : 0; + } + + for (i = 0; i < 2*sci->total_bands; i++) + { + sci->scfcod[i] = (drmp3_uint8)(sci->bitalloc[i] ? DRMP3_HDR_IS_LAYER_1(hdr) ? 2 : drmp3_bs_get_bits(bs, 2) : 6); + } + + drmp3_L12_read_scalefactors(bs, sci->bitalloc, sci->scfcod, sci->total_bands*2, sci->scf); + + for (i = sci->stereo_bands; i < sci->total_bands; i++) + { + sci->bitalloc[2*i + 1] = 0; + } +} + +static int drmp3_L12_dequantize_granule(float *grbuf, drmp3_bs *bs, drmp3_L12_scale_info *sci, int group_size) +{ + int i, j, k, choff = 576; + for (j = 0; j < 4; j++) + { + float *dst = grbuf + group_size*j; + for (i = 0; i < 2*sci->total_bands; i++) + { + int ba = sci->bitalloc[i]; + if (ba != 0) + { + if (ba < 17) + { + int half = (1 << (ba - 1)) - 1; + for (k = 0; k < group_size; k++) + { + dst[k] = (float)((int)drmp3_bs_get_bits(bs, ba) - half); + } + } else + { + unsigned mod = (2 << (ba - 17)) + 1; /* 3, 5, 9 */ + unsigned code = drmp3_bs_get_bits(bs, mod + 2 - (mod >> 3)); /* 5, 7, 10 */ + for (k = 0; k < group_size; k++, code /= mod) + { + dst[k] = (float)((int)(code % mod - mod/2)); + } + } + } + dst += choff; + choff = 18 - choff; + } + } + return group_size*4; +} + +static void drmp3_L12_apply_scf_384(drmp3_L12_scale_info *sci, const float *scf, float *dst) +{ + int i, k; + memcpy(dst + 576 + sci->stereo_bands*18, dst + sci->stereo_bands*18, (sci->total_bands - sci->stereo_bands)*18*sizeof(float)); + for (i = 0; i < sci->total_bands; i++, dst += 18, scf += 6) + { + for (k = 0; k < 12; k++) + { + dst[k + 0] *= scf[0]; + dst[k + 576] *= scf[3]; + } + } +} +#endif + +static int drmp3_L3_read_side_info(drmp3_bs *bs, drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr) +{ + static const drmp3_uint8 g_scf_long[9][23] = { + { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 }, + { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 }, + { 12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2,0 }, + { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 }, + { 6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36,0 }, + { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 }, + { 4,4,4,4,4,4,6,6,8,8,10,12,16,20,24,28,34,42,50,54,76,158,0 }, + { 4,4,4,4,4,4,6,6,6,8,10,12,16,18,22,28,34,40,46,54,54,192,0 }, + { 4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102,26,0 } + }; + static const drmp3_uint8 g_scf_short[9][40] = { + { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 8,8,8,8,8,8,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 }, + { 4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 }, + { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 }, + { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 }, + { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 }, + { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 } + }; + static const drmp3_uint8 g_scf_mixed[9][40] = { + { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 12,12,12,4,4,4,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 }, + { 6,6,6,6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 }, + { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 }, + { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 }, + { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 }, + { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 }, + { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 } + }; + + unsigned tables, scfsi = 0; + int main_data_begin, part_23_sum = 0; + int sr_idx = DRMP3_HDR_GET_MY_SAMPLE_RATE(hdr); + int gr_count = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2; + + if (DRMP3_HDR_TEST_MPEG1(hdr)) + { + gr_count *= 2; + main_data_begin = drmp3_bs_get_bits(bs, 9); + scfsi = drmp3_bs_get_bits(bs, 7 + gr_count); + } else + { + main_data_begin = drmp3_bs_get_bits(bs, 8 + gr_count) >> gr_count; + } + + do + { + if (DRMP3_HDR_IS_MONO(hdr)) + { + scfsi <<= 4; + } + gr->part_23_length = (drmp3_uint16)drmp3_bs_get_bits(bs, 12); + part_23_sum += gr->part_23_length; + gr->big_values = (drmp3_uint16)drmp3_bs_get_bits(bs, 9); + if (gr->big_values > 288) + { + return -1; + } + gr->global_gain = (drmp3_uint8)drmp3_bs_get_bits(bs, 8); + gr->scalefac_compress = (drmp3_uint16)drmp3_bs_get_bits(bs, DRMP3_HDR_TEST_MPEG1(hdr) ? 4 : 9); + gr->sfbtab = g_scf_long[sr_idx]; + gr->n_long_sfb = 22; + gr->n_short_sfb = 0; + if (drmp3_bs_get_bits(bs, 1)) + { + gr->block_type = (drmp3_uint8)drmp3_bs_get_bits(bs, 2); + if (!gr->block_type) + { + return -1; + } + gr->mixed_block_flag = (drmp3_uint8)drmp3_bs_get_bits(bs, 1); + gr->region_count[0] = 7; + gr->region_count[1] = 255; + if (gr->block_type == DRMP3_SHORT_BLOCK_TYPE) + { + scfsi &= 0x0F0F; + if (!gr->mixed_block_flag) + { + gr->region_count[0] = 8; + gr->sfbtab = g_scf_short[sr_idx]; + gr->n_long_sfb = 0; + gr->n_short_sfb = 39; + } else + { + gr->sfbtab = g_scf_mixed[sr_idx]; + gr->n_long_sfb = DRMP3_HDR_TEST_MPEG1(hdr) ? 8 : 6; + gr->n_short_sfb = 30; + } + } + tables = drmp3_bs_get_bits(bs, 10); + tables <<= 5; + gr->subblock_gain[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + gr->subblock_gain[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + gr->subblock_gain[2] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + } else + { + gr->block_type = 0; + gr->mixed_block_flag = 0; + tables = drmp3_bs_get_bits(bs, 15); + gr->region_count[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 4); + gr->region_count[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3); + gr->region_count[2] = 255; + } + gr->table_select[0] = (drmp3_uint8)(tables >> 10); + gr->table_select[1] = (drmp3_uint8)((tables >> 5) & 31); + gr->table_select[2] = (drmp3_uint8)((tables) & 31); + gr->preflag = (drmp3_uint8)(DRMP3_HDR_TEST_MPEG1(hdr) ? drmp3_bs_get_bits(bs, 1) : (gr->scalefac_compress >= 500)); + gr->scalefac_scale = (drmp3_uint8)drmp3_bs_get_bits(bs, 1); + gr->count1_table = (drmp3_uint8)drmp3_bs_get_bits(bs, 1); + gr->scfsi = (drmp3_uint8)((scfsi >> 12) & 15); + scfsi <<= 4; + gr++; + } while(--gr_count); + + if (part_23_sum + bs->pos > bs->limit + main_data_begin*8) + { + return -1; + } + + return main_data_begin; +} + +static void drmp3_L3_read_scalefactors(drmp3_uint8 *scf, drmp3_uint8 *ist_pos, const drmp3_uint8 *scf_size, const drmp3_uint8 *scf_count, drmp3_bs *bitbuf, int scfsi) +{ + int i, k; + for (i = 0; i < 4 && scf_count[i]; i++, scfsi *= 2) + { + int cnt = scf_count[i]; + if (scfsi & 8) + { + memcpy(scf, ist_pos, cnt); + } else + { + int bits = scf_size[i]; + if (!bits) + { + memset(scf, 0, cnt); + memset(ist_pos, 0, cnt); + } else + { + int max_scf = (scfsi < 0) ? (1 << bits) - 1 : -1; + for (k = 0; k < cnt; k++) + { + int s = drmp3_bs_get_bits(bitbuf, bits); + ist_pos[k] = (drmp3_uint8)(s == max_scf ? -1 : s); + scf[k] = (drmp3_uint8)s; + } + } + } + ist_pos += cnt; + scf += cnt; + } + scf[0] = scf[1] = scf[2] = 0; +} + +static float drmp3_L3_ldexp_q2(float y, int exp_q2) +{ + static const float g_expfrac[4] = { 9.31322575e-10f,7.83145814e-10f,6.58544508e-10f,5.53767716e-10f }; + int e; + do + { + e = DRMP3_MIN(30*4, exp_q2); + y *= g_expfrac[e & 3]*(1 << 30 >> (e >> 2)); + } while ((exp_q2 -= e) > 0); + return y; +} + +static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch) +{ + static const drmp3_uint8 g_scf_partitions[3][28] = { + { 6,5,5, 5,6,5,5,5,6,5, 7,3,11,10,0,0, 7, 7, 7,0, 6, 6,6,3, 8, 8,5,0 }, + { 8,9,6,12,6,9,9,9,6,9,12,6,15,18,0,0, 6,15,12,0, 6,12,9,6, 6,18,9,0 }, + { 9,9,6,12,9,9,9,9,9,9,12,6,18,18,0,0,12,12,12,0,12, 9,9,6,15,12,9,0 } + }; + const drmp3_uint8 *scf_partition = g_scf_partitions[!!gr->n_short_sfb + !gr->n_long_sfb]; + drmp3_uint8 scf_size[4], iscf[40]; + int i, scf_shift = gr->scalefac_scale + 1, gain_exp, scfsi = gr->scfsi; + float gain; + + if (DRMP3_HDR_TEST_MPEG1(hdr)) + { + static const drmp3_uint8 g_scfc_decode[16] = { 0,1,2,3, 12,5,6,7, 9,10,11,13, 14,15,18,19 }; + int part = g_scfc_decode[gr->scalefac_compress]; + scf_size[1] = scf_size[0] = (drmp3_uint8)(part >> 2); + scf_size[3] = scf_size[2] = (drmp3_uint8)(part & 3); + } else + { + static const drmp3_uint8 g_mod[6*4] = { 5,5,4,4,5,5,4,1,4,3,1,1,5,6,6,1,4,4,4,1,4,3,1,1 }; + int k, modprod, sfc, ist = DRMP3_HDR_TEST_I_STEREO(hdr) && ch; + sfc = gr->scalefac_compress >> ist; + for (k = ist*3*4; sfc >= 0; sfc -= modprod, k += 4) + { + for (modprod = 1, i = 3; i >= 0; i--) + { + scf_size[i] = (drmp3_uint8)(sfc / modprod % g_mod[k + i]); + modprod *= g_mod[k + i]; + } + } + scf_partition += k; + scfsi = -16; + } + drmp3_L3_read_scalefactors(iscf, ist_pos, scf_size, scf_partition, bs, scfsi); + + if (gr->n_short_sfb) + { + int sh = 3 - scf_shift; + for (i = 0; i < gr->n_short_sfb; i += 3) + { + iscf[gr->n_long_sfb + i + 0] += gr->subblock_gain[0] << sh; + iscf[gr->n_long_sfb + i + 1] += gr->subblock_gain[1] << sh; + iscf[gr->n_long_sfb + i + 2] += gr->subblock_gain[2] << sh; + } + } else if (gr->preflag) + { + static const drmp3_uint8 g_preamp[10] = { 1,1,1,1,2,2,3,3,3,2 }; + for (i = 0; i < 10; i++) + { + iscf[11 + i] += g_preamp[i]; + } + } + + gain_exp = gr->global_gain + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210 - (DRMP3_HDR_IS_MS_STEREO(hdr) ? 2 : 0); + gain = drmp3_L3_ldexp_q2(1 << (DRMP3_MAX_SCFI/4), DRMP3_MAX_SCFI - gain_exp); + for (i = 0; i < (int)(gr->n_long_sfb + gr->n_short_sfb); i++) + { + scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift); + } +} + +static float drmp3_L3_pow_43(int x) +{ + static const float g_pow43[129] = { + 0,1,2.519842f,4.326749f,6.349604f,8.549880f,10.902724f,13.390518f,16.000000f,18.720754f,21.544347f,24.463781f,27.473142f,30.567351f,33.741992f,36.993181f,40.317474f,43.711787f,47.173345f,50.699631f,54.288352f,57.937408f,61.644865f,65.408941f,69.227979f,73.100443f,77.024898f,81.000000f,85.024491f,89.097188f,93.216975f,97.382800f,101.593667f,105.848633f,110.146801f,114.487321f,118.869381f,123.292209f,127.755065f,132.257246f,136.798076f,141.376907f,145.993119f,150.646117f,155.335327f,160.060199f,164.820202f,169.614826f,174.443577f,179.305980f,184.201575f,189.129918f,194.090580f,199.083145f,204.107210f,209.162385f,214.248292f,219.364564f,224.510845f,229.686789f,234.892058f,240.126328f,245.389280f,250.680604f,256.000000f,261.347174f,266.721841f,272.123723f,277.552547f,283.008049f,288.489971f,293.998060f,299.532071f,305.091761f,310.676898f,316.287249f,321.922592f,327.582707f,333.267377f,338.976394f,344.709550f,350.466646f,356.247482f,362.051866f,367.879608f,373.730522f,379.604427f,385.501143f,391.420496f,397.362314f,403.326427f,409.312672f,415.320884f,421.350905f,427.402579f,433.475750f,439.570269f,445.685987f,451.822757f,457.980436f,464.158883f,470.357960f,476.577530f,482.817459f,489.077615f,495.357868f,501.658090f,507.978156f,514.317941f,520.677324f,527.056184f,533.454404f,539.871867f,546.308458f,552.764065f,559.238575f,565.731879f,572.243870f,578.774440f,585.323483f,591.890898f,598.476581f,605.080431f,611.702349f,618.342238f,625.000000f,631.675540f,638.368763f,645.079578f + }; + float frac; + int sign, mult = 256; + + if (x < 129) + { + return g_pow43[x]; + } + + if (x < 1024) + { + mult = 16; + x <<= 3; + } + + sign = 2*x & 64; + frac = (float)((x & 63) - sign) / ((x & ~63) + sign); + return g_pow43[(x + sign) >> 6]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult; +} + +static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit) +{ + static const float g_pow43_signed[32] = { 0,0,1,-1,2.519842f,-2.519842f,4.326749f,-4.326749f,6.349604f,-6.349604f,8.549880f,-8.549880f,10.902724f,-10.902724f,13.390518f,-13.390518f,16.000000f,-16.000000f,18.720754f,-18.720754f,21.544347f,-21.544347f,24.463781f,-24.463781f,27.473142f,-27.473142f,30.567351f,-30.567351f,33.741992f,-33.741992f,36.993181f,-36.993181f }; + static const drmp3_int16 tab0[32] = { 0, }; + static const drmp3_int16 tab1[] = { 785,785,785,785,784,784,784,784,513,513,513,513,513,513,513,513,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256 }; + static const drmp3_int16 tab2[] = { -255,1313,1298,1282,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,290,288 }; + static const drmp3_int16 tab3[] = { -255,1313,1298,1282,769,769,769,769,529,529,529,529,529,529,529,529,528,528,528,528,528,528,528,528,512,512,512,512,512,512,512,512,290,288 }; + static const drmp3_int16 tab5[] = { -253,-318,-351,-367,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,819,818,547,547,275,275,275,275,561,560,515,546,289,274,288,258 }; + static const drmp3_int16 tab6[] = { -254,-287,1329,1299,1314,1312,1057,1057,1042,1042,1026,1026,784,784,784,784,529,529,529,529,529,529,529,529,769,769,769,769,768,768,768,768,563,560,306,306,291,259 }; + static const drmp3_int16 tab7[] = { -252,-413,-477,-542,1298,-575,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-383,-399,1107,1092,1106,1061,849,849,789,789,1104,1091,773,773,1076,1075,341,340,325,309,834,804,577,577,532,532,516,516,832,818,803,816,561,561,531,531,515,546,289,289,288,258 }; + static const drmp3_int16 tab8[] = { -252,-429,-493,-559,1057,1057,1042,1042,529,529,529,529,529,529,529,529,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,-382,1077,-415,1106,1061,1104,849,849,789,789,1091,1076,1029,1075,834,834,597,581,340,340,339,324,804,833,532,532,832,772,818,803,817,787,816,771,290,290,290,290,288,258 }; + static const drmp3_int16 tab9[] = { -253,-349,-414,-447,-463,1329,1299,-479,1314,1312,1057,1057,1042,1042,1026,1026,785,785,785,785,784,784,784,784,769,769,769,769,768,768,768,768,-319,851,821,-335,836,850,805,849,341,340,325,336,533,533,579,579,564,564,773,832,578,548,563,516,321,276,306,291,304,259 }; + static const drmp3_int16 tab10[] = { -251,-572,-733,-830,-863,-879,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,1396,1351,1381,1366,1395,1335,1380,-559,1334,1138,1138,1063,1063,1350,1392,1031,1031,1062,1062,1364,1363,1120,1120,1333,1348,881,881,881,881,375,374,359,373,343,358,341,325,791,791,1123,1122,-703,1105,1045,-719,865,865,790,790,774,774,1104,1029,338,293,323,308,-799,-815,833,788,772,818,803,816,322,292,307,320,561,531,515,546,289,274,288,258 }; + static const drmp3_int16 tab11[] = { -251,-525,-605,-685,-765,-831,-846,1298,1057,1057,1312,1282,785,785,785,785,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,1399,1398,1383,1367,1382,1396,1351,-511,1381,1366,1139,1139,1079,1079,1124,1124,1364,1349,1363,1333,882,882,882,882,807,807,807,807,1094,1094,1136,1136,373,341,535,535,881,775,867,822,774,-591,324,338,-671,849,550,550,866,864,609,609,293,336,534,534,789,835,773,-751,834,804,308,307,833,788,832,772,562,562,547,547,305,275,560,515,290,290 }; + static const drmp3_int16 tab12[] = { -252,-397,-477,-557,-622,-653,-719,-735,-750,1329,1299,1314,1057,1057,1042,1042,1312,1282,1024,1024,785,785,785,785,784,784,784,784,769,769,769,769,-383,1127,1141,1111,1126,1140,1095,1110,869,869,883,883,1079,1109,882,882,375,374,807,868,838,881,791,-463,867,822,368,263,852,837,836,-543,610,610,550,550,352,336,534,534,865,774,851,821,850,805,593,533,579,564,773,832,578,578,548,548,577,577,307,276,306,291,516,560,259,259 }; + static const drmp3_int16 tab13[] = { -250,-2107,-2507,-2764,-2909,-2974,-3007,-3023,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-767,-1052,-1213,-1277,-1358,-1405,-1469,-1535,-1550,-1582,-1614,-1647,-1662,-1694,-1726,-1759,-1774,-1807,-1822,-1854,-1886,1565,-1919,-1935,-1951,-1967,1731,1730,1580,1717,-1983,1729,1564,-1999,1548,-2015,-2031,1715,1595,-2047,1714,-2063,1610,-2079,1609,-2095,1323,1323,1457,1457,1307,1307,1712,1547,1641,1700,1699,1594,1685,1625,1442,1442,1322,1322,-780,-973,-910,1279,1278,1277,1262,1276,1261,1275,1215,1260,1229,-959,974,974,989,989,-943,735,478,478,495,463,506,414,-1039,1003,958,1017,927,942,987,957,431,476,1272,1167,1228,-1183,1256,-1199,895,895,941,941,1242,1227,1212,1135,1014,1014,490,489,503,487,910,1013,985,925,863,894,970,955,1012,847,-1343,831,755,755,984,909,428,366,754,559,-1391,752,486,457,924,997,698,698,983,893,740,740,908,877,739,739,667,667,953,938,497,287,271,271,683,606,590,712,726,574,302,302,738,736,481,286,526,725,605,711,636,724,696,651,589,681,666,710,364,467,573,695,466,466,301,465,379,379,709,604,665,679,316,316,634,633,436,436,464,269,424,394,452,332,438,363,347,408,393,448,331,422,362,407,392,421,346,406,391,376,375,359,1441,1306,-2367,1290,-2383,1337,-2399,-2415,1426,1321,-2431,1411,1336,-2447,-2463,-2479,1169,1169,1049,1049,1424,1289,1412,1352,1319,-2495,1154,1154,1064,1064,1153,1153,416,390,360,404,403,389,344,374,373,343,358,372,327,357,342,311,356,326,1395,1394,1137,1137,1047,1047,1365,1392,1287,1379,1334,1364,1349,1378,1318,1363,792,792,792,792,1152,1152,1032,1032,1121,1121,1046,1046,1120,1120,1030,1030,-2895,1106,1061,1104,849,849,789,789,1091,1076,1029,1090,1060,1075,833,833,309,324,532,532,832,772,818,803,561,561,531,560,515,546,289,274,288,258 }; + static const drmp3_int16 tab15[] = { -250,-1179,-1579,-1836,-1996,-2124,-2253,-2333,-2413,-2477,-2542,-2574,-2607,-2622,-2655,1314,1313,1298,1312,1282,785,785,785,785,1040,1040,1025,1025,768,768,768,768,-766,-798,-830,-862,-895,-911,-927,-943,-959,-975,-991,-1007,-1023,-1039,-1055,-1070,1724,1647,-1103,-1119,1631,1767,1662,1738,1708,1723,-1135,1780,1615,1779,1599,1677,1646,1778,1583,-1151,1777,1567,1737,1692,1765,1722,1707,1630,1751,1661,1764,1614,1736,1676,1763,1750,1645,1598,1721,1691,1762,1706,1582,1761,1566,-1167,1749,1629,767,766,751,765,494,494,735,764,719,749,734,763,447,447,748,718,477,506,431,491,446,476,461,505,415,430,475,445,504,399,460,489,414,503,383,474,429,459,502,502,746,752,488,398,501,473,413,472,486,271,480,270,-1439,-1455,1357,-1471,-1487,-1503,1341,1325,-1519,1489,1463,1403,1309,-1535,1372,1448,1418,1476,1356,1462,1387,-1551,1475,1340,1447,1402,1386,-1567,1068,1068,1474,1461,455,380,468,440,395,425,410,454,364,467,466,464,453,269,409,448,268,432,1371,1473,1432,1417,1308,1460,1355,1446,1459,1431,1083,1083,1401,1416,1458,1445,1067,1067,1370,1457,1051,1051,1291,1430,1385,1444,1354,1415,1400,1443,1082,1082,1173,1113,1186,1066,1185,1050,-1967,1158,1128,1172,1097,1171,1081,-1983,1157,1112,416,266,375,400,1170,1142,1127,1065,793,793,1169,1033,1156,1096,1141,1111,1155,1080,1126,1140,898,898,808,808,897,897,792,792,1095,1152,1032,1125,1110,1139,1079,1124,882,807,838,881,853,791,-2319,867,368,263,822,852,837,866,806,865,-2399,851,352,262,534,534,821,836,594,594,549,549,593,593,533,533,848,773,579,579,564,578,548,563,276,276,577,576,306,291,516,560,305,305,275,259 }; + static const drmp3_int16 tab16[] = { -251,-892,-2058,-2620,-2828,-2957,-3023,-3039,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,-559,1530,-575,-591,1528,1527,1407,1526,1391,1023,1023,1023,1023,1525,1375,1268,1268,1103,1103,1087,1087,1039,1039,1523,-604,815,815,815,815,510,495,509,479,508,463,507,447,431,505,415,399,-734,-782,1262,-815,1259,1244,-831,1258,1228,-847,-863,1196,-879,1253,987,987,748,-767,493,493,462,477,414,414,686,669,478,446,461,445,474,429,487,458,412,471,1266,1264,1009,1009,799,799,-1019,-1276,-1452,-1581,-1677,-1757,-1821,-1886,-1933,-1997,1257,1257,1483,1468,1512,1422,1497,1406,1467,1496,1421,1510,1134,1134,1225,1225,1466,1451,1374,1405,1252,1252,1358,1480,1164,1164,1251,1251,1238,1238,1389,1465,-1407,1054,1101,-1423,1207,-1439,830,830,1248,1038,1237,1117,1223,1148,1236,1208,411,426,395,410,379,269,1193,1222,1132,1235,1221,1116,976,976,1192,1162,1177,1220,1131,1191,963,963,-1647,961,780,-1663,558,558,994,993,437,408,393,407,829,978,813,797,947,-1743,721,721,377,392,844,950,828,890,706,706,812,859,796,960,948,843,934,874,571,571,-1919,690,555,689,421,346,539,539,944,779,918,873,932,842,903,888,570,570,931,917,674,674,-2575,1562,-2591,1609,-2607,1654,1322,1322,1441,1441,1696,1546,1683,1593,1669,1624,1426,1426,1321,1321,1639,1680,1425,1425,1305,1305,1545,1668,1608,1623,1667,1592,1638,1666,1320,1320,1652,1607,1409,1409,1304,1304,1288,1288,1664,1637,1395,1395,1335,1335,1622,1636,1394,1394,1319,1319,1606,1621,1392,1392,1137,1137,1137,1137,345,390,360,375,404,373,1047,-2751,-2767,-2783,1062,1121,1046,-2799,1077,-2815,1106,1061,789,789,1105,1104,263,355,310,340,325,354,352,262,339,324,1091,1076,1029,1090,1060,1075,833,833,788,788,1088,1028,818,818,803,803,561,561,531,531,816,771,546,546,289,274,288,258 }; + static const drmp3_int16 tab24[] = { -253,-317,-381,-446,-478,-509,1279,1279,-811,-1179,-1451,-1756,-1900,-2028,-2189,-2253,-2333,-2414,-2445,-2511,-2526,1313,1298,-2559,1041,1041,1040,1040,1025,1025,1024,1024,1022,1007,1021,991,1020,975,1019,959,687,687,1018,1017,671,671,655,655,1016,1015,639,639,758,758,623,623,757,607,756,591,755,575,754,559,543,543,1009,783,-575,-621,-685,-749,496,-590,750,749,734,748,974,989,1003,958,988,973,1002,942,987,957,972,1001,926,986,941,971,956,1000,910,985,925,999,894,970,-1071,-1087,-1102,1390,-1135,1436,1509,1451,1374,-1151,1405,1358,1480,1420,-1167,1507,1494,1389,1342,1465,1435,1450,1326,1505,1310,1493,1373,1479,1404,1492,1464,1419,428,443,472,397,736,526,464,464,486,457,442,471,484,482,1357,1449,1434,1478,1388,1491,1341,1490,1325,1489,1463,1403,1309,1477,1372,1448,1418,1433,1476,1356,1462,1387,-1439,1475,1340,1447,1402,1474,1324,1461,1371,1473,269,448,1432,1417,1308,1460,-1711,1459,-1727,1441,1099,1099,1446,1386,1431,1401,-1743,1289,1083,1083,1160,1160,1458,1445,1067,1067,1370,1457,1307,1430,1129,1129,1098,1098,268,432,267,416,266,400,-1887,1144,1187,1082,1173,1113,1186,1066,1050,1158,1128,1143,1172,1097,1171,1081,420,391,1157,1112,1170,1142,1127,1065,1169,1049,1156,1096,1141,1111,1155,1080,1126,1154,1064,1153,1140,1095,1048,-2159,1125,1110,1137,-2175,823,823,1139,1138,807,807,384,264,368,263,868,838,853,791,867,822,852,837,866,806,865,790,-2319,851,821,836,352,262,850,805,849,-2399,533,533,835,820,336,261,578,548,563,577,532,532,832,772,562,562,547,547,305,275,560,515,290,290,288,258 }; + static const drmp3_uint8 tab32[] = { 130,162,193,209,44,28,76,140,9,9,9,9,9,9,9,9,190,254,222,238,126,94,157,157,109,61,173,205}; + static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 }; + static const drmp3_int16 * const tabindex[2*16] = { tab0,tab1,tab2,tab3,tab0,tab5,tab6,tab7,tab8,tab9,tab10,tab11,tab12,tab13,tab0,tab15,tab16,tab16,tab16,tab16,tab16,tab16,tab16,tab16,tab24,tab24,tab24,tab24,tab24,tab24,tab24,tab24 }; + static const drmp3_uint8 g_linbits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 }; + +#define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - n)) +#define DRMP3_FLUSH_BITS(n) { bs_cache <<= (n); bs_sh += (n); } +#define DRMP3_CHECK_BITS while (bs_sh >= 0) { bs_cache |= (drmp3_uint32)*bs_next_ptr++ << bs_sh; bs_sh -= 8; } +#define DRMP3_BSPOS ((bs_next_ptr - bs->buf)*8 - 24 + bs_sh) + + float one = 0.0f; + int ireg = 0, big_val_cnt = gr_info->big_values; + const drmp3_uint8 *sfb = gr_info->sfbtab; + const drmp3_uint8 *bs_next_ptr = bs->buf + bs->pos/8; + drmp3_uint32 bs_cache = (((bs_next_ptr[0]*256u + bs_next_ptr[1])*256u + bs_next_ptr[2])*256u + bs_next_ptr[3]) << (bs->pos & 7); + int pairs_to_decode, np, bs_sh = (bs->pos & 7) - 8; + bs_next_ptr += 4; + + while (big_val_cnt > 0) + { + int tab_num = gr_info->table_select[ireg]; + int sfb_cnt = gr_info->region_count[ireg++]; + const short *codebook = tabindex[tab_num]; + int linbits = g_linbits[tab_num]; + do + { + np = *sfb++ / 2; + pairs_to_decode = DRMP3_MIN(big_val_cnt, np); + one = *scf++; + do + { + int j, w = 5; + int leaf = codebook[DRMP3_PEEK_BITS(w)]; + while (leaf < 0) + { + DRMP3_FLUSH_BITS(w); + w = leaf & 7; + leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)]; + } + DRMP3_FLUSH_BITS(leaf >> 8); + + for (j = 0; j < 2; j++, dst++, leaf >>= 4) + { + int lsb = leaf & 0x0F; + if (lsb == 15 && linbits) + { + lsb += DRMP3_PEEK_BITS(linbits); + DRMP3_FLUSH_BITS(linbits); + DRMP3_CHECK_BITS; + *dst = one*drmp3_L3_pow_43(lsb)*((int32_t)bs_cache < 0 ? -1: 1); + } else + { + *dst = g_pow43_signed[lsb*2 + (bs_cache >> 31)]*one; + } + DRMP3_FLUSH_BITS(lsb ? 1 : 0); + } + DRMP3_CHECK_BITS; + } while (--pairs_to_decode); + } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0); + } + + for (np = 1 - big_val_cnt;; dst += 4) + { + const drmp3_uint8 *codebook_count1 = (gr_info->count1_table) ? tab33 : tab32; + int leaf = codebook_count1[DRMP3_PEEK_BITS(4)]; + if (!(leaf & 8)) + { + leaf = codebook_count1[(leaf >> 3) + (bs_cache << 4 >> (32 - (leaf & 3)))]; + } + DRMP3_FLUSH_BITS(leaf & 7); + if (DRMP3_BSPOS > layer3gr_limit) + { + break; + } +#define DRMP3_RELOAD_SCALEFACTOR if (!--np) { np = *sfb++/2; if (!np) break; one = *scf++; } +#define DRMP3_DEQ_COUNT1(s) if (leaf & (128 >> s)) { dst[s] = ((drmp3_int32)bs_cache < 0) ? -one : one; DRMP3_FLUSH_BITS(1) } + DRMP3_RELOAD_SCALEFACTOR; + DRMP3_DEQ_COUNT1(0); + DRMP3_DEQ_COUNT1(1); + DRMP3_RELOAD_SCALEFACTOR; + DRMP3_DEQ_COUNT1(2); + DRMP3_DEQ_COUNT1(3); + DRMP3_CHECK_BITS; + } + + bs->pos = layer3gr_limit; +} + +static void drmp3_L3_midside_stereo(float *left, int n) +{ + int i = 0; + float *right = left + 576; +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; i < n - 3; i += 4) + { + drmp3_f4 vl = DRMP3_VLD(left + i); + drmp3_f4 vr = DRMP3_VLD(right + i); + DRMP3_VSTORE(left + i, DRMP3_VADD(vl, vr)); + DRMP3_VSTORE(right + i, DRMP3_VSUB(vl, vr)); + } +#endif + for (; i < n; i++) + { + float a = left[i]; + float b = right[i]; + left[i] = a + b; + right[i] = a - b; + } +} + +static void drmp3_L3_intensity_stereo_band(float *left, int n, float kl, float kr) +{ + int i; + for (i = 0; i < n; i++) + { + left[i + 576] = left[i]*kr; + left[i] = left[i]*kl; + } +} + +static void drmp3_L3_stereo_top_band(const float *right, const drmp3_uint8 *sfb, int nbands, int max_band[3]) +{ + int i, k; + + max_band[0] = max_band[1] = max_band[2] = -1; + + for (i = 0; i < nbands; i++) + { + for (k = 0; k < sfb[i]; k += 2) + { + if (right[k] != 0 || right[k + 1] != 0) + { + max_band[i % 3] = i; + break; + } + } + right += sfb[i]; + } +} + +static void drmp3_L3_stereo_process(float *left, const drmp3_uint8 *ist_pos, const drmp3_uint8 *sfb, const drmp3_uint8 *hdr, int max_band[3], int mpeg2_sh) +{ + static const float g_pan[7*2] = { 0,1,0.21132487f,0.78867513f,0.36602540f,0.63397460f,0.5f,0.5f,0.63397460f,0.36602540f,0.78867513f,0.21132487f,1,0 }; + unsigned i, max_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 7 : 64; + + for (i = 0; sfb[i]; i++) + { + unsigned ipos = ist_pos[i]; + if ((int)i > max_band[i % 3] && ipos < max_pos) + { + float kl, kr, s = DRMP3_HDR_TEST_MS_STEREO(hdr) ? 1.41421356f : 1; + if (DRMP3_HDR_TEST_MPEG1(hdr)) + { + kl = g_pan[2*ipos]; + kr = g_pan[2*ipos + 1]; + } else + { + kl = 1; + kr = drmp3_L3_ldexp_q2(1, (ipos + 1) >> 1 << mpeg2_sh); + if (ipos & 1) + { + kl = kr; + kr = 1; + } + } + drmp3_L3_intensity_stereo_band(left, sfb[i], kl*s, kr*s); + } else if (DRMP3_HDR_TEST_MS_STEREO(hdr)) + { + drmp3_L3_midside_stereo(left, sfb[i]); + } + left += sfb[i]; + } +} + +static void drmp3_L3_intensity_stereo(float *left, drmp3_uint8 *ist_pos, const drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr) +{ + int max_band[3], n_sfb = gr->n_long_sfb + gr->n_short_sfb; + int i, max_blocks = gr->n_short_sfb ? 3 : 1; + + drmp3_L3_stereo_top_band(left + 576, gr->sfbtab, n_sfb, max_band); + if (gr->n_long_sfb) + { + max_band[0] = max_band[1] = max_band[2] = DRMP3_MAX(DRMP3_MAX(max_band[0], max_band[1]), max_band[2]); + } + for (i = 0; i < max_blocks; i++) + { + int default_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 3 : 0; + int itop = n_sfb - max_blocks + i; + int prev = itop - max_blocks; + ist_pos[itop] = (drmp3_uint8)(max_band[i] >= prev ? default_pos : ist_pos[prev]); + } + drmp3_L3_stereo_process(left, ist_pos, gr->sfbtab, hdr, max_band, gr[1].scalefac_compress&1); +} + +static void drmp3_L3_reorder(float *grbuf, float *scratch, const drmp3_uint8 *sfb) +{ + int i, len; + float *src = grbuf, *dst = scratch; + + for (;0 != (len = *sfb); sfb += 3, src += 2*len) + { + for (i = 0; i < len; i++, src++) + { + *dst++ = src[0*len]; + *dst++ = src[1*len]; + *dst++ = src[2*len]; + } + } + memcpy(grbuf, scratch, (dst - scratch)*sizeof(float)); +} + +static void drmp3_L3_antialias(float *grbuf, int nbands) +{ + static const float g_aa[2][8] = { + {0.85749293f,0.88174200f,0.94962865f,0.98331459f,0.99551782f,0.99916056f,0.99989920f,0.99999316f}, + {0.51449576f,0.47173197f,0.31337745f,0.18191320f,0.09457419f,0.04096558f,0.01419856f,0.00369997f} + }; + + for (; nbands > 0; nbands--, grbuf += 18) + { + int i = 0; +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; i < 8; i += 4) + { + drmp3_f4 vu = DRMP3_VLD(grbuf + 18 + i); + drmp3_f4 vd = DRMP3_VLD(grbuf + 14 - i); + drmp3_f4 vc0 = DRMP3_VLD(g_aa[0] + i); + drmp3_f4 vc1 = DRMP3_VLD(g_aa[1] + i); + vd = DRMP3_VREV(vd); + DRMP3_VSTORE(grbuf + 18 + i, DRMP3_VSUB(DRMP3_VMUL(vu, vc0), DRMP3_VMUL(vd, vc1))); + vd = DRMP3_VADD(DRMP3_VMUL(vu, vc1), DRMP3_VMUL(vd, vc0)); + DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vd)); + } +#endif +#ifndef DR_MP3_ONLY_SIMD + for(; i < 8; i++) + { + float u = grbuf[18 + i]; + float d = grbuf[17 - i]; + grbuf[18 + i] = u*g_aa[0][i] - d*g_aa[1][i]; + grbuf[17 - i] = u*g_aa[1][i] + d*g_aa[0][i]; + } +#endif + } +} + +static void drmp3_L3_dct3_9(float *y) +{ + float s0, s1, s2, s3, s4, s5, s6, s7, s8, t0, t2, t4; + + s0 = y[0]; s2 = y[2]; s4 = y[4]; s6 = y[6]; s8 = y[8]; + t0 = s0 + s6*0.5f; + s0 -= s6; + t4 = (s4 + s2)*0.93969262f; + t2 = (s8 + s2)*0.76604444f; + s6 = (s4 - s8)*0.17364818f; + s4 += s8 - s2; + + s2 = s0 - s4*0.5f; + y[4] = s4 + s0; + s8 = t0 - t2 + s6; + s0 = t0 - t4 + t2; + s4 = t0 + t4 - s6; + + s1 = y[1]; s3 = y[3]; s5 = y[5]; s7 = y[7]; + + s3 *= 0.86602540f; + t0 = (s5 + s1)*0.98480775f; + t4 = (s5 - s7)*0.34202014f; + t2 = (s1 + s7)*0.64278761f; + s1 = (s1 - s5 - s7)*0.86602540f; + + s5 = t0 - s3 - t2; + s7 = t4 - s3 - t0; + s3 = t4 + s3 - t2; + + y[0] = s4 - s7; + y[1] = s2 + s1; + y[2] = s0 - s3; + y[3] = s8 + s5; + y[5] = s8 - s5; + y[6] = s0 + s3; + y[7] = s2 - s1; + y[8] = s4 + s7; +} + +static void drmp3_L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands) +{ + int i, j; + static const float g_twid9[18] = { + 0.73727734f,0.79335334f,0.84339145f,0.88701083f,0.92387953f,0.95371695f,0.97629601f,0.99144486f,0.99904822f,0.67559021f,0.60876143f,0.53729961f,0.46174861f,0.38268343f,0.30070580f,0.21643961f,0.13052619f,0.04361938f + }; + + for (j = 0; j < nbands; j++, grbuf += 18, overlap += 9) + { + float co[9], si[9]; + co[0] = -grbuf[0]; + si[0] = grbuf[17]; + for (i = 0; i < 4; i++) + { + si[8 - 2*i] = grbuf[4*i + 1] - grbuf[4*i + 2]; + co[1 + 2*i] = grbuf[4*i + 1] + grbuf[4*i + 2]; + si[7 - 2*i] = grbuf[4*i + 4] - grbuf[4*i + 3]; + co[2 + 2*i] = -(grbuf[4*i + 3] + grbuf[4*i + 4]); + } + drmp3_L3_dct3_9(co); + drmp3_L3_dct3_9(si); + + si[1] = -si[1]; + si[3] = -si[3]; + si[5] = -si[5]; + si[7] = -si[7]; + + i = 0; + +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; i < 8; i += 4) + { + drmp3_f4 vovl = DRMP3_VLD(overlap + i); + drmp3_f4 vc = DRMP3_VLD(co + i); + drmp3_f4 vs = DRMP3_VLD(si + i); + drmp3_f4 vr0 = DRMP3_VLD(g_twid9 + i); + drmp3_f4 vr1 = DRMP3_VLD(g_twid9 + 9 + i); + drmp3_f4 vw0 = DRMP3_VLD(window + i); + drmp3_f4 vw1 = DRMP3_VLD(window + 9 + i); + drmp3_f4 vsum = DRMP3_VADD(DRMP3_VMUL(vc, vr1), DRMP3_VMUL(vs, vr0)); + DRMP3_VSTORE(overlap + i, DRMP3_VSUB(DRMP3_VMUL(vc, vr0), DRMP3_VMUL(vs, vr1))); + DRMP3_VSTORE(grbuf + i, DRMP3_VSUB(DRMP3_VMUL(vovl, vw0), DRMP3_VMUL(vsum, vw1))); + vsum = DRMP3_VADD(DRMP3_VMUL(vovl, vw1), DRMP3_VMUL(vsum, vw0)); + DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vsum)); + } +#endif + for (; i < 9; i++) + { + float ovl = overlap[i]; + float sum = co[i]*g_twid9[9 + i] + si[i]*g_twid9[0 + i]; + overlap[i] = co[i]*g_twid9[0 + i] - si[i]*g_twid9[9 + i]; + grbuf[i] = ovl*window[0 + i] - sum*window[9 + i]; + grbuf[17 - i] = ovl*window[9 + i] + sum*window[0 + i]; + } + } +} + +static void drmp3_L3_idct3(float x0, float x1, float x2, float *dst) +{ + float m1 = x1*0.86602540f; + float a1 = x0 - x2*0.5f; + dst[1] = x0 + x2; + dst[0] = a1 + m1; + dst[2] = a1 - m1; +} + +static void drmp3_L3_imdct12(float *x, float *dst, float *overlap) +{ + static const float g_twid3[6] = { 0.79335334f,0.92387953f,0.99144486f, 0.60876143f,0.38268343f,0.13052619f }; + float co[3], si[3]; + int i; + + drmp3_L3_idct3(-x[0], x[6] + x[3], x[12] + x[9], co); + drmp3_L3_idct3(x[15], x[12] - x[9], x[6] - x[3], si); + si[1] = -si[1]; + + for (i = 0; i < 3; i++) + { + float ovl = overlap[i]; + float sum = co[i]*g_twid3[3 + i] + si[i]*g_twid3[0 + i]; + overlap[i] = co[i]*g_twid3[0 + i] - si[i]*g_twid3[3 + i]; + dst[i] = ovl*g_twid3[2 - i] - sum*g_twid3[5 - i]; + dst[5 - i] = ovl*g_twid3[5 - i] + sum*g_twid3[2 - i]; + } +} + +static void drmp3_L3_imdct_short(float *grbuf, float *overlap, int nbands) +{ + for (;nbands > 0; nbands--, overlap += 9, grbuf += 18) + { + float tmp[18]; + memcpy(tmp, grbuf, sizeof(tmp)); + memcpy(grbuf, overlap, 6*sizeof(float)); + drmp3_L3_imdct12(tmp, grbuf + 6, overlap + 6); + drmp3_L3_imdct12(tmp + 1, grbuf + 12, overlap + 6); + drmp3_L3_imdct12(tmp + 2, overlap, overlap + 6); + } +} + +static void drmp3_L3_change_sign(float *grbuf) +{ + int b, i; + for (b = 0, grbuf += 18; b < 32; b += 2, grbuf += 36) + for (i = 1; i < 18; i += 2) + grbuf[i] = -grbuf[i]; +} + +static void drmp3_L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands) +{ + static const float g_mdct_window[2][18] = { + { 0.99904822f,0.99144486f,0.97629601f,0.95371695f,0.92387953f,0.88701083f,0.84339145f,0.79335334f,0.73727734f,0.04361938f,0.13052619f,0.21643961f,0.30070580f,0.38268343f,0.46174861f,0.53729961f,0.60876143f,0.67559021f }, + { 1,1,1,1,1,1,0.99144486f,0.92387953f,0.79335334f,0,0,0,0,0,0,0.13052619f,0.38268343f,0.60876143f } + }; + if (n_long_bands) + { + drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[0], n_long_bands); + grbuf += 18*n_long_bands; + overlap += 9*n_long_bands; + } + if (block_type == DRMP3_SHORT_BLOCK_TYPE) + drmp3_L3_imdct_short(grbuf, overlap, 32 - n_long_bands); + else + drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[block_type == DRMP3_STOP_BLOCK_TYPE], 32 - n_long_bands); +} + +static void drmp3_L3_save_reservoir(drmp3dec *h, drmp3dec_scratch *s) +{ + int pos = (s->bs.pos + 7)/8u; + int remains = s->bs.limit/8u - pos; + if (remains > DRMP3_MAX_BITRESERVOIR_BYTES) + { + pos += remains - DRMP3_MAX_BITRESERVOIR_BYTES; + remains = DRMP3_MAX_BITRESERVOIR_BYTES; + } + if (remains > 0) + { + memmove(h->reserv_buf, s->maindata + pos, remains); + } + h->reserv = remains; +} + +static int drmp3_L3_restore_reservoir(drmp3dec *h, drmp3_bs *bs, drmp3dec_scratch *s, int main_data_begin) +{ + int frame_bytes = (bs->limit - bs->pos)/8; + int bytes_have = DRMP3_MIN(h->reserv, main_data_begin); + memcpy(s->maindata, h->reserv_buf + DRMP3_MAX(0, h->reserv - main_data_begin), DRMP3_MIN(h->reserv, main_data_begin)); + memcpy(s->maindata + bytes_have, bs->buf + bs->pos/8, frame_bytes); + drmp3_bs_init(&s->bs, s->maindata, bytes_have + frame_bytes); + return h->reserv >= main_data_begin; +} + +static void drmp3_L3_decode(drmp3dec *h, drmp3dec_scratch *s, drmp3_L3_gr_info *gr_info, int nch) +{ + int ch; + + for (ch = 0; ch < nch; ch++) + { + int layer3gr_limit = s->bs.pos + gr_info[ch].part_23_length; + drmp3_L3_decode_scalefactors(h->header, s->ist_pos[ch], &s->bs, gr_info + ch, s->scf, ch); + drmp3_L3_huffman(s->grbuf[ch], &s->bs, gr_info + ch, s->scf, layer3gr_limit); + } + + if (DRMP3_HDR_TEST_I_STEREO(h->header)) + { + drmp3_L3_intensity_stereo(s->grbuf[0], s->ist_pos[1], gr_info, h->header); + } else if (DRMP3_HDR_IS_MS_STEREO(h->header)) + { + drmp3_L3_midside_stereo(s->grbuf[0], 576); + } + + for (ch = 0; ch < nch; ch++, gr_info++) + { + int aa_bands = 31; + int n_long_bands = (gr_info->mixed_block_flag ? 2 : 0) << (int)(DRMP3_HDR_GET_MY_SAMPLE_RATE(h->header) == 2); + + if (gr_info->n_short_sfb) + { + aa_bands = n_long_bands - 1; + drmp3_L3_reorder(s->grbuf[ch] + n_long_bands*18, s->syn[0], gr_info->sfbtab + gr_info->n_long_sfb); + } + + drmp3_L3_antialias(s->grbuf[ch], aa_bands); + drmp3_L3_imdct_gr(s->grbuf[ch], h->mdct_overlap[ch], gr_info->block_type, n_long_bands); + drmp3_L3_change_sign(s->grbuf[ch]); + } +} + +static void drmp3d_DCT_II(float *grbuf, int n) +{ + static const float g_sec[24] = { + 10.19000816f,0.50060302f,0.50241929f,3.40760851f,0.50547093f,0.52249861f,2.05778098f,0.51544732f,0.56694406f,1.48416460f,0.53104258f,0.64682180f,1.16943991f,0.55310392f,0.78815460f,0.97256821f,0.58293498f,1.06067765f,0.83934963f,0.62250412f,1.72244716f,0.74453628f,0.67480832f,5.10114861f + }; + int i, k = 0; +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (; k < n; k += 4) + { + drmp3_f4 t[4][8], *x; + float *y = grbuf + k; + + for (x = t[0], i = 0; i < 8; i++, x++) + { + drmp3_f4 x0 = DRMP3_VLD(&y[i*18]); + drmp3_f4 x1 = DRMP3_VLD(&y[(15 - i)*18]); + drmp3_f4 x2 = DRMP3_VLD(&y[(16 + i)*18]); + drmp3_f4 x3 = DRMP3_VLD(&y[(31 - i)*18]); + drmp3_f4 t0 = DRMP3_VADD(x0, x3); + drmp3_f4 t1 = DRMP3_VADD(x1, x2); + drmp3_f4 t2 = DRMP3_VMUL_S(DRMP3_VSUB(x1, x2), g_sec[3*i + 0]); + drmp3_f4 t3 = DRMP3_VMUL_S(DRMP3_VSUB(x0, x3), g_sec[3*i + 1]); + x[0] = DRMP3_VADD(t0, t1); + x[8] = DRMP3_VMUL_S(DRMP3_VSUB(t0, t1), g_sec[3*i + 2]); + x[16] = DRMP3_VADD(t3, t2); + x[24] = DRMP3_VMUL_S(DRMP3_VSUB(t3, t2), g_sec[3*i + 2]); + } + for (x = t[0], i = 0; i < 4; i++, x += 8) + { + drmp3_f4 x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt; + xt = DRMP3_VSUB(x0, x7); x0 = DRMP3_VADD(x0, x7); + x7 = DRMP3_VSUB(x1, x6); x1 = DRMP3_VADD(x1, x6); + x6 = DRMP3_VSUB(x2, x5); x2 = DRMP3_VADD(x2, x5); + x5 = DRMP3_VSUB(x3, x4); x3 = DRMP3_VADD(x3, x4); + x4 = DRMP3_VSUB(x0, x3); x0 = DRMP3_VADD(x0, x3); + x3 = DRMP3_VSUB(x1, x2); x1 = DRMP3_VADD(x1, x2); + x[0] = DRMP3_VADD(x0, x1); + x[4] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x1), 0.70710677f); + x5 = DRMP3_VADD(x5, x6); + x6 = DRMP3_VMUL_S(DRMP3_VADD(x6, x7), 0.70710677f); + x7 = DRMP3_VADD(x7, xt); + x3 = DRMP3_VMUL_S(DRMP3_VADD(x3, x4), 0.70710677f); + x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f)); /* rotate by PI/8 */ + x7 = DRMP3_VADD(x7, DRMP3_VMUL_S(x5, 0.382683432f)); + x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f)); + x0 = DRMP3_VSUB(xt, x6); xt = DRMP3_VADD(xt, x6); + x[1] = DRMP3_VMUL_S(DRMP3_VADD(xt, x7), 0.50979561f); + x[2] = DRMP3_VMUL_S(DRMP3_VADD(x4, x3), 0.54119611f); + x[3] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x5), 0.60134488f); + x[5] = DRMP3_VMUL_S(DRMP3_VADD(x0, x5), 0.89997619f); + x[6] = DRMP3_VMUL_S(DRMP3_VSUB(x4, x3), 1.30656302f); + x[7] = DRMP3_VMUL_S(DRMP3_VSUB(xt, x7), 2.56291556f); + } + + if (k > n - 3) + { +#if DRMP3_HAVE_SSE +#define DRMP3_VSAVE2(i, v) _mm_storel_pi((__m64 *)(void*)&y[i*18], v) +#else +#define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[i*18], vget_low_f32(v)) +#endif + for (i = 0; i < 7; i++, y += 4*18) + { + drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]); + DRMP3_VSAVE2(0, t[0][i]); + DRMP3_VSAVE2(1, DRMP3_VADD(t[2][i], s)); + DRMP3_VSAVE2(2, DRMP3_VADD(t[1][i], t[1][i + 1])); + DRMP3_VSAVE2(3, DRMP3_VADD(t[2][1 + i], s)); + } + DRMP3_VSAVE2(0, t[0][7]); + DRMP3_VSAVE2(1, DRMP3_VADD(t[2][7], t[3][7])); + DRMP3_VSAVE2(2, t[1][7]); + DRMP3_VSAVE2(3, t[3][7]); + } else + { +#define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[i*18], v) + for (i = 0; i < 7; i++, y += 4*18) + { + drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]); + DRMP3_VSAVE4(0, t[0][i]); + DRMP3_VSAVE4(1, DRMP3_VADD(t[2][i], s)); + DRMP3_VSAVE4(2, DRMP3_VADD(t[1][i], t[1][i + 1])); + DRMP3_VSAVE4(3, DRMP3_VADD(t[2][1 + i], s)); + } + DRMP3_VSAVE4(0, t[0][7]); + DRMP3_VSAVE4(1, DRMP3_VADD(t[2][7], t[3][7])); + DRMP3_VSAVE4(2, t[1][7]); + DRMP3_VSAVE4(3, t[3][7]); + } + } else +#endif +#ifdef DR_MP3_ONLY_SIMD + {} +#else + for (; k < n; k++) + { + float t[4][8], *x, *y = grbuf + k; + + for (x = t[0], i = 0; i < 8; i++, x++) + { + float x0 = y[i*18]; + float x1 = y[(15 - i)*18]; + float x2 = y[(16 + i)*18]; + float x3 = y[(31 - i)*18]; + float t0 = x0 + x3; + float t1 = x1 + x2; + float t2 = (x1 - x2)*g_sec[3*i + 0]; + float t3 = (x0 - x3)*g_sec[3*i + 1]; + x[0] = t0 + t1; + x[8] = (t0 - t1)*g_sec[3*i + 2]; + x[16] = t3 + t2; + x[24] = (t3 - t2)*g_sec[3*i + 2]; + } + for (x = t[0], i = 0; i < 4; i++, x += 8) + { + float x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt; + xt = x0 - x7; x0 += x7; + x7 = x1 - x6; x1 += x6; + x6 = x2 - x5; x2 += x5; + x5 = x3 - x4; x3 += x4; + x4 = x0 - x3; x0 += x3; + x3 = x1 - x2; x1 += x2; + x[0] = x0 + x1; + x[4] = (x0 - x1)*0.70710677f; + x5 = x5 + x6; + x6 = (x6 + x7)*0.70710677f; + x7 = x7 + xt; + x3 = (x3 + x4)*0.70710677f; + x5 -= x7*0.198912367f; /* rotate by PI/8 */ + x7 += x5*0.382683432f; + x5 -= x7*0.198912367f; + x0 = xt - x6; xt += x6; + x[1] = (xt + x7)*0.50979561f; + x[2] = (x4 + x3)*0.54119611f; + x[3] = (x0 - x5)*0.60134488f; + x[5] = (x0 + x5)*0.89997619f; + x[6] = (x4 - x3)*1.30656302f; + x[7] = (xt - x7)*2.56291556f; + + } + for (i = 0; i < 7; i++, y += 4*18) + { + y[0*18] = t[0][i]; + y[1*18] = t[2][i] + t[3][i] + t[3][i + 1]; + y[2*18] = t[1][i] + t[1][i + 1]; + y[3*18] = t[2][i + 1] + t[3][i] + t[3][i + 1]; + } + y[0*18] = t[0][7]; + y[1*18] = t[2][7] + t[3][7]; + y[2*18] = t[1][7]; + y[3*18] = t[3][7]; + } +#endif +} + +static short drmp3d_scale_pcm(float sample) +{ + int s; + if (sample > 32767.0) return (short) 32767; + if (sample < -32768.0) return (short)-32768; + s = (int)(sample + .5f); + s -= (s < 0); /* away from zero, to be compliant */ + if (s > 32767) return (short) 32767; + if (s < -32768) return (short)-32768; + return (short)s; +} + +static void drmp3d_synth_pair(short *pcm, int nch, const float *z) +{ + float a; + a = (z[14*64] - z[ 0]) * 29; + a += (z[ 1*64] + z[13*64]) * 213; + a += (z[12*64] - z[ 2*64]) * 459; + a += (z[ 3*64] + z[11*64]) * 2037; + a += (z[10*64] - z[ 4*64]) * 5153; + a += (z[ 5*64] + z[ 9*64]) * 6574; + a += (z[ 8*64] - z[ 6*64]) * 37489; + a += z[ 7*64] * 75038; + pcm[0] = drmp3d_scale_pcm(a); + + z += 2; + a = z[14*64] * 104; + a += z[12*64] * 1567; + a += z[10*64] * 9727; + a += z[ 8*64] * 64019; + a += z[ 6*64] * -9975; + a += z[ 4*64] * -45; + a += z[ 2*64] * 146; + a += z[ 0*64] * -5; + pcm[16*nch] = drmp3d_scale_pcm(a); +} + +static void drmp3d_synth(float *xl, short *dstl, int nch, float *lins) +{ + int i; + float *xr = xl + 576*(nch - 1); + short *dstr = dstl + (nch - 1); + + static const float g_win[] = { + -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992, + -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856, + -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630, + -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313, + -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908, + -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415, + -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835, + -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169, + -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420, + -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590, + -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679, + -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692, + -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629, + -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494, + -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290 + }; + float *zlin = lins + 15*64; + const float *w = g_win; + + zlin[4*15] = xl[18*16]; + zlin[4*15 + 1] = xr[18*16]; + zlin[4*15 + 2] = xl[0]; + zlin[4*15 + 3] = xr[0]; + + zlin[4*31] = xl[1 + 18*16]; + zlin[4*31 + 1] = xr[1 + 18*16]; + zlin[4*31 + 2] = xl[1]; + zlin[4*31 + 3] = xr[1]; + + drmp3d_synth_pair(dstr, nch, lins + 4*15 + 1); + drmp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1); + drmp3d_synth_pair(dstl, nch, lins + 4*15); + drmp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64); + +#if DRMP3_HAVE_SIMD + if (drmp3_have_simd()) for (i = 14; i >= 0; i--) + { +#define DRMP3_VLOAD(k) drmp3_f4 w0 = DRMP3_VSET(*w++); drmp3_f4 w1 = DRMP3_VSET(*w++); drmp3_f4 vz = DRMP3_VLD(&zlin[4*i - 64*k]); drmp3_f4 vy = DRMP3_VLD(&zlin[4*i - 64*(15 - k)]); +#define DRMP3_V0(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0)) ; a = DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1)); } +#define DRMP3_V1(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1))); } +#define DRMP3_V2(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vy, w1), DRMP3_VMUL(vz, w0))); } + drmp3_f4 a, b; + zlin[4*i] = xl[18*(31 - i)]; + zlin[4*i + 1] = xr[18*(31 - i)]; + zlin[4*i + 2] = xl[1 + 18*(31 - i)]; + zlin[4*i + 3] = xr[1 + 18*(31 - i)]; + zlin[4*i + 64] = xl[1 + 18*(1 + i)]; + zlin[4*i + 64 + 1] = xr[1 + 18*(1 + i)]; + zlin[4*i - 64 + 2] = xl[18*(1 + i)]; + zlin[4*i - 64 + 3] = xr[18*(1 + i)]; + + DRMP3_V0(0) DRMP3_V2(1) DRMP3_V1(2) DRMP3_V2(3) DRMP3_V1(4) DRMP3_V2(5) DRMP3_V1(6) DRMP3_V2(7) + + { +#if DRMP3_HAVE_SSE + static const drmp3_f4 g_max = { 32767.0f, 32767.0f, 32767.0f, 32767.0f }; + static const drmp3_f4 g_min = { -32768.0f, -32768.0f, -32768.0f, -32768.0f }; + __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, g_max), g_min)), + _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, g_max), g_min))); + dstr[(15 - i)*nch] = (short)_mm_extract_epi16(pcm8, 1); + dstr[(17 + i)*nch] = (short)_mm_extract_epi16(pcm8, 5); + dstl[(15 - i)*nch] = (short)_mm_extract_epi16(pcm8, 0); + dstl[(17 + i)*nch] = (short)_mm_extract_epi16(pcm8, 4); + dstr[(47 - i)*nch] = (short)_mm_extract_epi16(pcm8, 3); + dstr[(49 + i)*nch] = (short)_mm_extract_epi16(pcm8, 7); + dstl[(47 - i)*nch] = (short)_mm_extract_epi16(pcm8, 2); + dstl[(49 + i)*nch] = (short)_mm_extract_epi16(pcm8, 6); +#else + int16x4_t pcma, pcmb; + a = DRMP3_VADD(a, DRMP3_VSET(0.5f)); + b = DRMP3_VADD(b, DRMP3_VSET(0.5f)); + pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0))))); + pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0))))); + vst1_lane_s16(dstr + (15 - i)*nch, pcma, 1); + vst1_lane_s16(dstr + (17 + i)*nch, pcmb, 1); + vst1_lane_s16(dstl + (15 - i)*nch, pcma, 0); + vst1_lane_s16(dstl + (17 + i)*nch, pcmb, 0); + vst1_lane_s16(dstr + (47 - i)*nch, pcma, 3); + vst1_lane_s16(dstr + (49 + i)*nch, pcmb, 3); + vst1_lane_s16(dstl + (47 - i)*nch, pcma, 2); + vst1_lane_s16(dstl + (49 + i)*nch, pcmb, 2); +#endif + } + } else +#endif +#ifdef DR_MP3_ONLY_SIMD + {} +#else + for (i = 14; i >= 0; i--) + { +#define DRMP3_LOAD(k) float w0 = *w++; float w1 = *w++; float *vz = &zlin[4*i - k*64]; float *vy = &zlin[4*i - (15 - k)*64]; +#define DRMP3_S0(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] = vz[j]*w1 + vy[j]*w0, a[j] = vz[j]*w0 - vy[j]*w1; } +#define DRMP3_S1(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vz[j]*w0 - vy[j]*w1; } +#define DRMP3_S2(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vy[j]*w1 - vz[j]*w0; } + float a[4], b[4]; + + zlin[4*i] = xl[18*(31 - i)]; + zlin[4*i + 1] = xr[18*(31 - i)]; + zlin[4*i + 2] = xl[1 + 18*(31 - i)]; + zlin[4*i + 3] = xr[1 + 18*(31 - i)]; + zlin[4*(i + 16)] = xl[1 + 18*(1 + i)]; + zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)]; + zlin[4*(i - 16) + 2] = xl[18*(1 + i)]; + zlin[4*(i - 16) + 3] = xr[18*(1 + i)]; + + DRMP3_S0(0) DRMP3_S2(1) DRMP3_S1(2) DRMP3_S2(3) DRMP3_S1(4) DRMP3_S2(5) DRMP3_S1(6) DRMP3_S2(7) + + dstr[(15 - i)*nch] = drmp3d_scale_pcm(a[1]); + dstr[(17 + i)*nch] = drmp3d_scale_pcm(b[1]); + dstl[(15 - i)*nch] = drmp3d_scale_pcm(a[0]); + dstl[(17 + i)*nch] = drmp3d_scale_pcm(b[0]); + dstr[(47 - i)*nch] = drmp3d_scale_pcm(a[3]); + dstr[(49 + i)*nch] = drmp3d_scale_pcm(b[3]); + dstl[(47 - i)*nch] = drmp3d_scale_pcm(a[2]); + dstl[(49 + i)*nch] = drmp3d_scale_pcm(b[2]); + } +#endif +} + +static void drmp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, short *pcm, float *lins) +{ + int i; + for (i = 0; i < nch; i++) + { + drmp3d_DCT_II(grbuf + 576*i, nbands); + } + + memcpy(lins, qmf_state, sizeof(float)*15*64); + + for (i = 0; i < nbands; i += 2) + { + drmp3d_synth(grbuf + i, pcm + 32*nch*i, nch, lins + i*64); + } +#ifndef DR_MP3_NONSTANDARD_BUT_LOGICAL + if (nch == 1) + { + for (i = 0; i < 15*64; i += 2) + { + qmf_state[i] = lins[nbands*64 + i]; + } + } else +#endif + { + memcpy(qmf_state, lins + nbands*64, sizeof(float)*15*64); + } +} + +static int drmp3d_match_frame(const drmp3_uint8 *hdr, int mp3_bytes, int frame_bytes) +{ + int i, nmatch; + for (i = 0, nmatch = 0; nmatch < DRMP3_MAX_FRAME_SYNC_MATCHES; nmatch++) + { + i += drmp3_hdr_frame_bytes(hdr + i, frame_bytes) + drmp3_hdr_padding(hdr + i); + if (i + DRMP3_HDR_SIZE > mp3_bytes) + return nmatch > 0; + if (!drmp3_hdr_compare(hdr, hdr + i)) + return 0; + } + return 1; +} + +static int drmp3d_find_frame(const drmp3_uint8 *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes) +{ + int i, k; + for (i = 0; i < mp3_bytes - DRMP3_HDR_SIZE; i++, mp3++) + { + if (drmp3_hdr_valid(mp3)) + { + int frame_bytes = drmp3_hdr_frame_bytes(mp3, *free_format_bytes); + int frame_and_padding = frame_bytes + drmp3_hdr_padding(mp3); + + for (k = DRMP3_HDR_SIZE; !frame_bytes && k < DRMP3_MAX_FREE_FORMAT_FRAME_SIZE && i + 2*k < mp3_bytes - DRMP3_HDR_SIZE; k++) + { + if (drmp3_hdr_compare(mp3, mp3 + k)) + { + int fb = k - drmp3_hdr_padding(mp3); + int nextfb = fb + drmp3_hdr_padding(mp3 + k); + if (i + k + nextfb + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + k + nextfb)) + continue; + frame_and_padding = k; + frame_bytes = fb; + *free_format_bytes = fb; + } + } + + if ((frame_bytes && i + frame_and_padding <= mp3_bytes && + drmp3d_match_frame(mp3, mp3_bytes - i, frame_bytes)) || + (!i && frame_and_padding == mp3_bytes)) + { + *ptr_frame_bytes = frame_and_padding; + return i; + } + *free_format_bytes = 0; + } + } + *ptr_frame_bytes = 0; + return i; +} + +void drmp3dec_init(drmp3dec *dec) +{ + dec->header[0] = 0; +} + +int drmp3dec_decode_frame(drmp3dec *dec, const unsigned char *mp3, int mp3_bytes, short *pcm, drmp3dec_frame_info *info) +{ + int i = 0, igr, frame_size = 0, success = 1; + const drmp3_uint8 *hdr; + drmp3_bs bs_frame[1]; + drmp3dec_scratch scratch; + + if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3)) + { + frame_size = drmp3_hdr_frame_bytes(mp3, dec->free_format_bytes) + drmp3_hdr_padding(mp3); + if (frame_size != mp3_bytes && (frame_size + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + frame_size))) + { + frame_size = 0; + } + } + if (!frame_size) + { + memset(dec, 0, sizeof(drmp3dec)); + i = drmp3d_find_frame(mp3, mp3_bytes, &dec->free_format_bytes, &frame_size); + if (!frame_size || i + frame_size > mp3_bytes) + { + info->frame_bytes = i; + return 0; + } + } + + hdr = mp3 + i; + memcpy(dec->header, hdr, DRMP3_HDR_SIZE); + info->frame_bytes = i + frame_size; + info->channels = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2; + info->hz = drmp3_hdr_sample_rate_hz(hdr); + info->layer = 4 - DRMP3_HDR_GET_LAYER(hdr); + info->bitrate_kbps = drmp3_hdr_bitrate_kbps(hdr); + + drmp3_bs_init(bs_frame, hdr + DRMP3_HDR_SIZE, frame_size - DRMP3_HDR_SIZE); + if (DRMP3_HDR_IS_CRC(hdr)) + { + drmp3_bs_get_bits(bs_frame, 16); + } + + if (info->layer == 3) + { + int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr); + if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit) + { + drmp3dec_init(dec); + return 0; + } + success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin); + if (success) + { + for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm += 576*info->channels) + { + memset(scratch.grbuf[0], 0, 576*2*sizeof(float)); + drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels); + drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, pcm, scratch.syn[0]); + } + } + drmp3_L3_save_reservoir(dec, &scratch); + } else + { +#ifdef DR_MP3_ONLY_MP3 + return 0; +#else + drmp3_L12_scale_info sci[1]; + drmp3_L12_read_scale_info(hdr, bs_frame, sci); + + memset(scratch.grbuf[0], 0, 576*2*sizeof(float)); + for (i = 0, igr = 0; igr < 3; igr++) + { + if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1))) + { + i = 0; + drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]); + drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, pcm, scratch.syn[0]); + memset(scratch.grbuf[0], 0, 576*2*sizeof(float)); + pcm += 384*info->channels; + } + if (bs_frame->pos > bs_frame->limit) + { + drmp3dec_init(dec); + return 0; + } + } +#endif + } + return success*drmp3_hdr_frame_samples(dec->header); +} + + + + +/* + * + * Main Public API + * + */ + +/* Options. */ +#ifndef DR_MP3_DEFAULT_CHANNELS +#define DR_MP3_DEFAULT_CHANNELS 2 +#endif +#ifndef DR_MP3_DEFAULT_SAMPLE_RATE +#define DR_MP3_DEFAULT_SAMPLE_RATE 44100 +#endif + +/* Standard library stuff. */ +#ifndef DRMP3_ASSERT +#include +#define DRMP3_ASSERT(expression) assert(expression) +#endif +#ifndef DRMP3_COPY_MEMORY +#define DRMP3_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz)) +#endif +#ifndef DRMP3_ZERO_MEMORY +#define DRMP3_ZERO_MEMORY(p, sz) memset((p), 0, (sz)) +#endif +#define DRMP3_ZERO_OBJECT(p) DRMP3_ZERO_MEMORY((p), sizeof(*(p))) +#ifndef DRMP3_MALLOC +#define DRMP3_MALLOC(sz) malloc((sz)) +#endif +#ifndef DRMP3_REALLOC +#define DRMP3_REALLOC(p, sz) realloc((p), (sz)) +#endif +#ifndef DRMP3_FREE +#define DRMP3_FREE(p) free((p)) +#endif + +#define drmp3_assert DRMP3_ASSERT +#define drmp3_copy_memory DRMP3_COPY_MEMORY +#define drmp3_zero_memory DRMP3_ZERO_MEMORY +#define drmp3_zero_object DRMP3_ZERO_OBJECT +#define drmp3_malloc DRMP3_MALLOC +#define drmp3_realloc DRMP3_REALLOC + +#define drmp3_countof(x) (sizeof(x) / sizeof(x[0])) +#define drmp3_max(x, y) (((x) > (y)) ? (x) : (y)) +#define drmp3_min(x, y) (((x) < (y)) ? (x) : (y)) + +#define DRMP3_DATA_CHUNK_SIZE 16384 /* The size in bytes of each chunk of data to read from the MP3 stream. minimp3 recommends 16K. */ + +static INLINE float drmp3_mix_f32(float x, float y, float a) +{ + return x*(1-a) + y*a; +} + +static void drmp3_blend_f32(float* pOut, float* pInA, float* pInB, float factor, drmp3_uint32 channels) +{ + uint32_t i; + for (i = 0; i < channels; ++i) + pOut[i] = drmp3_mix_f32(pInA[i], pInB[i], factor); +} + +void drmp3_src_cache_init(drmp3_src* pSRC, drmp3_src_cache* pCache) +{ + drmp3_assert(pSRC != NULL); + drmp3_assert(pCache != NULL); + + pCache->pSRC = pSRC; + pCache->cachedFrameCount = 0; + pCache->iNextFrame = 0; +} + +drmp3_uint64 drmp3_src_cache_read_frames(drmp3_src_cache* pCache, drmp3_uint64 frameCount, float* pFramesOut) +{ + drmp3_uint32 channels; + drmp3_uint64 totalFramesRead = 0; + + drmp3_assert(pCache != NULL); + drmp3_assert(pCache->pSRC != NULL); + drmp3_assert(pCache->pSRC->onRead != NULL); + drmp3_assert(frameCount > 0); + drmp3_assert(pFramesOut != NULL); + + channels = pCache->pSRC->config.channels; + + while (frameCount > 0) + { + drmp3_uint32 framesToReadFromClient; + /* If there's anything in memory go ahead and copy that over first. */ + drmp3_uint64 framesRemainingInMemory = pCache->cachedFrameCount - pCache->iNextFrame; + drmp3_uint64 framesToReadFromMemory = frameCount; + if (framesToReadFromMemory > framesRemainingInMemory) + framesToReadFromMemory = framesRemainingInMemory; + + drmp3_copy_memory(pFramesOut, pCache->pCachedFrames + pCache->iNextFrame*channels, (drmp3_uint32)(framesToReadFromMemory * channels * sizeof(float))); + pCache->iNextFrame += (drmp3_uint32)framesToReadFromMemory; + + totalFramesRead += framesToReadFromMemory; + frameCount -= framesToReadFromMemory; + if (frameCount == 0) + break; + + + /* At this point there are still more frames to read from the client, so we'll need to reload the cache with fresh data. */ + drmp3_assert(frameCount > 0); + pFramesOut += framesToReadFromMemory * channels; + + pCache->iNextFrame = 0; + pCache->cachedFrameCount = 0; + + framesToReadFromClient = drmp3_countof(pCache->pCachedFrames) / pCache->pSRC->config.channels; + if (framesToReadFromClient > pCache->pSRC->config.cacheSizeInFrames) + framesToReadFromClient = pCache->pSRC->config.cacheSizeInFrames; + + pCache->cachedFrameCount = (drmp3_uint32)pCache->pSRC->onRead(pCache->pSRC, framesToReadFromClient, pCache->pCachedFrames, pCache->pSRC->pUserData); + + + /* Get out of this loop if nothing was able to be retrieved. */ + if (pCache->cachedFrameCount == 0) + break; + } + + return totalFramesRead; +} + + +drmp3_uint64 drmp3_src_read_frames_passthrough(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush); +drmp3_uint64 drmp3_src_read_frames_linear(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush); + +drmp3_bool32 drmp3_src_init(const drmp3_src_config* pConfig, drmp3_src_read_proc onRead, void* pUserData, drmp3_src* pSRC) +{ + if (pSRC == NULL) return DRMP3_FALSE; + drmp3_zero_object(pSRC); + + if (pConfig == NULL || onRead == NULL) return DRMP3_FALSE; + if (pConfig->channels == 0 || pConfig->channels > 2) return DRMP3_FALSE; + + pSRC->config = *pConfig; + pSRC->onRead = onRead; + pSRC->pUserData = pUserData; + + if (pSRC->config.cacheSizeInFrames > DRMP3_SRC_CACHE_SIZE_IN_FRAMES || pSRC->config.cacheSizeInFrames == 0) + pSRC->config.cacheSizeInFrames = DRMP3_SRC_CACHE_SIZE_IN_FRAMES; + + drmp3_src_cache_init(pSRC, &pSRC->cache); + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_src_set_input_sample_rate(drmp3_src* pSRC, drmp3_uint32 sampleRateIn) +{ + if (pSRC == NULL) return DRMP3_FALSE; + + /* Must have a sample rate of > 0. */ + if (sampleRateIn == 0) + return DRMP3_FALSE; + + pSRC->config.sampleRateIn = sampleRateIn; + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_src_set_output_sample_rate(drmp3_src* pSRC, drmp3_uint32 sampleRateOut) +{ + if (pSRC == NULL) return DRMP3_FALSE; + + /* Must have a sample rate of > 0. */ + if (sampleRateOut == 0) + return DRMP3_FALSE; + + pSRC->config.sampleRateOut = sampleRateOut; + return DRMP3_TRUE; +} + +drmp3_uint64 drmp3_src_read_frames_ex(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush) +{ + drmp3_src_algorithm algorithm; + if (pSRC == NULL || frameCount == 0 || pFramesOut == NULL) return 0; + + algorithm = pSRC->config.algorithm; + + /* Always use passthrough if the sample rates are the same. */ + if (pSRC->config.sampleRateIn == pSRC->config.sampleRateOut) + algorithm = drmp3_src_algorithm_none; + + /* Could just use a function pointer instead of a switch for this... */ + switch (algorithm) + { + case drmp3_src_algorithm_none: return drmp3_src_read_frames_passthrough(pSRC, frameCount, pFramesOut, flush); + case drmp3_src_algorithm_linear: return drmp3_src_read_frames_linear(pSRC, frameCount, pFramesOut, flush); + default: return 0; + } +} + +drmp3_uint64 drmp3_src_read_frames(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut) +{ + return drmp3_src_read_frames_ex(pSRC, frameCount, pFramesOut, DRMP3_FALSE); +} + +drmp3_uint64 drmp3_src_read_frames_passthrough(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush) +{ + drmp3_assert(pSRC != NULL); + drmp3_assert(frameCount > 0); + drmp3_assert(pFramesOut != NULL); + + (void)flush; /* Passthrough need not care about flushing. */ + return pSRC->onRead(pSRC, frameCount, pFramesOut, pSRC->pUserData); +} + +drmp3_uint64 drmp3_src_read_frames_linear(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, drmp3_bool32 flush) +{ + float factor; + drmp3_uint64 totalFramesRead = 0; + + drmp3_assert(pSRC != NULL); + drmp3_assert(frameCount > 0); + drmp3_assert(pFramesOut != NULL); + + /* For linear SRC, the bin is only 2 frames: 1 prior, 1 future. */ + + /* Load the bin if necessary. */ + if (!pSRC->algo.linear.isPrevFramesLoaded) + { + drmp3_uint64 framesRead = drmp3_src_cache_read_frames(&pSRC->cache, 1, pSRC->bin); + if (framesRead == 0) + return 0; + pSRC->algo.linear.isPrevFramesLoaded = DRMP3_TRUE; + } + if (!pSRC->algo.linear.isNextFramesLoaded) + { + drmp3_uint64 framesRead = drmp3_src_cache_read_frames(&pSRC->cache, 1, pSRC->bin + pSRC->config.channels); + if (framesRead == 0) + return 0; + pSRC->algo.linear.isNextFramesLoaded = DRMP3_TRUE; + } + + factor = (float)pSRC->config.sampleRateIn / pSRC->config.sampleRateOut; + + while (frameCount > 0) + { + drmp3_uint32 i; + drmp3_uint32 framesToReadFromClient; + /* The bin is where the previous and next frames are located. */ + float* pPrevFrame = pSRC->bin; + float* pNextFrame = pSRC->bin + pSRC->config.channels; + + drmp3_blend_f32((float*)pFramesOut, pPrevFrame, pNextFrame, pSRC->algo.linear.alpha, pSRC->config.channels); + + pSRC->algo.linear.alpha += factor; + + /* The new alpha value is how we determine whether or not we need to read fresh frames. */ + framesToReadFromClient = (drmp3_uint32)pSRC->algo.linear.alpha; + pSRC->algo.linear.alpha = pSRC->algo.linear.alpha - framesToReadFromClient; + + for (i = 0; i < framesToReadFromClient; ++i) + { + drmp3_uint32 j; + drmp3_uint64 framesRead; + for (j = 0; j < pSRC->config.channels; ++j) + pPrevFrame[j] = pNextFrame[j]; + + framesRead = drmp3_src_cache_read_frames(&pSRC->cache, 1, pNextFrame); + if (framesRead == 0) + { + drmp3_uint32 j; + for (j = 0; j < pSRC->config.channels; ++j) + pNextFrame[j] = 0; + + if (pSRC->algo.linear.isNextFramesLoaded) + pSRC->algo.linear.isNextFramesLoaded = DRMP3_FALSE; + else + { + if (flush) + pSRC->algo.linear.isPrevFramesLoaded = DRMP3_FALSE; + } + + break; + } + } + + pFramesOut = (drmp3_uint8*)pFramesOut + (1 * pSRC->config.channels * sizeof(float)); + frameCount -= 1; + totalFramesRead += 1; + + /* If there's no frames available we need to get out of this loop. */ + if (!pSRC->algo.linear.isNextFramesLoaded && (!flush || !pSRC->algo.linear.isPrevFramesLoaded)) + break; + } + + return totalFramesRead; +} + + + +static drmp3_bool32 drmp3_decode_next_frame(drmp3* pMP3) +{ + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->onRead != NULL); + + if (pMP3->atEnd) + return DRMP3_FALSE; + + do + { + drmp3dec_frame_info info; + drmp3_uint32 samplesRead; + + /* minimp3 recommends doing data submission in 16K chunks. If we don't have at least 16K bytes available, get more. */ + if (pMP3->dataSize < DRMP3_DATA_CHUNK_SIZE) + { + size_t bytesRead; + + if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) + { + drmp3_uint8* pNewData = NULL; + pMP3->dataCapacity = DRMP3_DATA_CHUNK_SIZE; + + pNewData = (drmp3_uint8*) + drmp3_realloc(pMP3->pData, pMP3->dataCapacity); + if (pNewData == NULL) + return DRMP3_FALSE; /* Out of memory. */ + + pMP3->pData = pNewData; + } + + bytesRead = pMP3->onRead(pMP3->pUserData, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); + if (bytesRead == 0) + { + pMP3->atEnd = DRMP3_TRUE; + return DRMP3_FALSE; /* No data. */ + } + + pMP3->dataSize += bytesRead; + } + + if (pMP3->dataSize > INT_MAX) + { + pMP3->atEnd = DRMP3_TRUE; + return DRMP3_FALSE; /* File too big. */ + } + + samplesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData, (int)pMP3->dataSize, pMP3->frames, &info); /* <-- Safe size_t -> int conversion thanks to the check above. */ + if (samplesRead != 0) + { + size_t i; + size_t leftoverDataSize = (pMP3->dataSize - (size_t)info.frame_bytes); + for (i = 0; i < leftoverDataSize; ++i) + pMP3->pData[i] = pMP3->pData[i + (size_t)info.frame_bytes]; + + pMP3->dataSize = leftoverDataSize; + pMP3->framesConsumed = 0; + pMP3->framesRemaining = samplesRead; + pMP3->frameChannels = info.channels; + pMP3->frameSampleRate = info.hz; + drmp3_src_set_input_sample_rate(&pMP3->src, pMP3->frameSampleRate); + break; + } + else + { + size_t bytesRead; + /* Need more data. minimp3 recommends doing data submission in 16K chunks. */ + if (pMP3->dataCapacity == pMP3->dataSize) + { + drmp3_uint8 *pNewData = NULL; + /* No room. Expand. */ + pMP3->dataCapacity += DRMP3_DATA_CHUNK_SIZE; + + pNewData = (drmp3_uint8*)drmp3_realloc(pMP3->pData, pMP3->dataCapacity); + if (pNewData == NULL) + return DRMP3_FALSE; /* Out of memory. */ + + pMP3->pData = pNewData; + } + + /* Fill in a chunk. */ + bytesRead = pMP3->onRead(pMP3->pUserData, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); + if (bytesRead == 0) + { + pMP3->atEnd = DRMP3_TRUE; + return DRMP3_FALSE; /* Error reading more data. */ + } + + pMP3->dataSize += bytesRead; + } + } while (DRMP3_TRUE); + + return DRMP3_TRUE; +} + +static drmp3_uint64 drmp3_read_src(drmp3_src* pSRC, drmp3_uint64 frameCount, void* pFramesOut, void* pUserData) +{ + float* pFramesOutF; + drmp3_uint32 totalFramesRead = 0; + drmp3* pMP3 = (drmp3*)pUserData; + + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->onRead != NULL); + + pFramesOutF = (float*)pFramesOut; + + while (frameCount > 0) + { + /* Read from the in-memory buffer first. */ + while (pMP3->framesRemaining > 0 && frameCount > 0) + { + if (pMP3->frameChannels == 1) + { + if (pMP3->channels == 1) + { + /* Mono -> Mono. */ + pFramesOutF[0] = pMP3->frames[pMP3->framesConsumed] / 32768.0f; + } else { + /* Mono -> Stereo. */ + pFramesOutF[0] = pMP3->frames[pMP3->framesConsumed] / 32768.0f; + pFramesOutF[1] = pMP3->frames[pMP3->framesConsumed] / 32768.0f; + } + } else { + if (pMP3->channels == 1) + { + /* Stereo -> Mono */ + float sample = 0; + sample += pMP3->frames[(pMP3->framesConsumed*pMP3->frameChannels)+0] / 32768.0f; + sample += pMP3->frames[(pMP3->framesConsumed*pMP3->frameChannels)+1] / 32768.0f; + pFramesOutF[0] = sample * 0.5f; + } else { + /* Stereo -> Stereo */ + pFramesOutF[0] = pMP3->frames[(pMP3->framesConsumed*pMP3->frameChannels)+0] / 32768.0f; + pFramesOutF[1] = pMP3->frames[(pMP3->framesConsumed*pMP3->frameChannels)+1] / 32768.0f; + } + } + + pMP3->framesConsumed += 1; + pMP3->framesRemaining -= 1; + frameCount -= 1; + totalFramesRead += 1; + pFramesOutF += pSRC->config.channels; + } + + if (frameCount == 0) + break; + + drmp3_assert(pMP3->framesRemaining == 0); + + /* At this point we have exhausted our in-memory buffer so we need to re-fill. Note that the sample rate may have changed + * at this point which means we'll also need to update our sample rate conversion pipeline. */ + if (!drmp3_decode_next_frame(pMP3)) + break; + } + + return totalFramesRead; +} + +drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_config* pConfig) +{ + drmp3_config config; + drmp3_src_config srcConfig; + + drmp3_assert(pMP3 != NULL); + drmp3_assert(onRead != NULL); + + /* This function assumes the output object has already been reset to 0. Do not do that here, otherwise things will break. */ + drmp3dec_init(&pMP3->decoder); + + /* The config can be null in which case we use defaults. */ + if (pConfig != NULL) + config = *pConfig; + else + drmp3_zero_object(&config); + + pMP3->channels = config.outputChannels; + if (pMP3->channels == 0) + pMP3->channels = DR_MP3_DEFAULT_CHANNELS; + + /* Cannot have more than 2 channels. */ + if (pMP3->channels > 2) + pMP3->channels = 2; + + pMP3->sampleRate = config.outputSampleRate; + if (pMP3->sampleRate == 0) + pMP3->sampleRate = DR_MP3_DEFAULT_SAMPLE_RATE; + + pMP3->onRead = onRead; + pMP3->onSeek = onSeek; + pMP3->pUserData = pUserData; + + /* We need a sample rate converter for converting the sample rate from the MP3 frames to the requested output sample rate. */ + drmp3_zero_object(&srcConfig); + srcConfig.sampleRateIn = DR_MP3_DEFAULT_SAMPLE_RATE; + srcConfig.sampleRateOut = pMP3->sampleRate; + srcConfig.channels = pMP3->channels; + srcConfig.algorithm = drmp3_src_algorithm_linear; + if (!drmp3_src_init(&srcConfig, drmp3_read_src, pMP3, &pMP3->src)) + return DRMP3_FALSE; + + /* Decode the first frame to confirm that it is indeed a valid MP3 stream. */ + if (!drmp3_decode_next_frame(pMP3)) + return DRMP3_FALSE; /* Not a valid MP3 stream. */ + + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_config* pConfig) +{ + if (pMP3 == NULL || onRead == NULL) + return DRMP3_FALSE; + + drmp3_zero_object(pMP3); + return drmp3_init_internal(pMP3, onRead, onSeek, pUserData, pConfig); +} + + +static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead) +{ + size_t bytesRemaining; + drmp3* pMP3 = (drmp3*)pUserData; + drmp3_assert(pMP3 != NULL); + drmp3_assert(pMP3->memory.dataSize >= pMP3->memory.currentReadPos); + + bytesRemaining = pMP3->memory.dataSize - pMP3->memory.currentReadPos; + if (bytesToRead > bytesRemaining) + bytesToRead = bytesRemaining; + + if (bytesToRead > 0) + { + drmp3_copy_memory(pBufferOut, pMP3->memory.pData + pMP3->memory.currentReadPos, bytesToRead); + pMP3->memory.currentReadPos += bytesToRead; + } + + return bytesToRead; +} + +static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin) +{ + drmp3* pMP3 = (drmp3*)pUserData; + drmp3_assert(pMP3 != NULL); + + if (origin == drmp3_seek_origin_current) + { + if (byteOffset > 0) + { + if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) + byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos); /* Trying to seek too far forward. */ + } + else + { + if (pMP3->memory.currentReadPos < (size_t)-byteOffset) + byteOffset = -(int)pMP3->memory.currentReadPos; /* Trying to seek too far backwards. */ + } + + /* This will never underflow thanks to the clamps above. */ + pMP3->memory.currentReadPos += byteOffset; + } else { + if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) + pMP3->memory.currentReadPos = byteOffset; + else + pMP3->memory.currentReadPos = pMP3->memory.dataSize; /* Trying to seek too far forward. */ + } + + return DRMP3_TRUE; +} + +drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_config* pConfig) +{ + if (pMP3 == NULL) + return DRMP3_FALSE; + + drmp3_zero_object(pMP3); + + if (pData == NULL || dataSize == 0) + return DRMP3_FALSE; + + pMP3->memory.pData = (const drmp3_uint8*)pData; + pMP3->memory.dataSize = dataSize; + pMP3->memory.currentReadPos = 0; + + return drmp3_init_internal(pMP3, drmp3__on_read_memory, drmp3__on_seek_memory, pMP3, pConfig); +} + + +#ifndef DR_MP3_NO_STDIO +#include + +static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead) +{ + return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData); +} + +static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin) +{ + return fseek((FILE*)pUserData, offset, (origin == drmp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0; +} + +drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* filePath, const drmp3_config* pConfig) +{ + FILE* pFile; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (fopen_s(&pFile, filePath, "rb") != 0) + return DRMP3_FALSE; +#else + pFile = fopen(filePath, "rb"); + if (pFile == NULL) + return DRMP3_FALSE; +#endif + + return drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pConfig); +} +#endif + +void drmp3_uninit(drmp3* pMP3) +{ + if (pMP3 == NULL) return; + +#ifndef DR_MP3_NO_STDIO + if (pMP3->onRead == drmp3__on_read_stdio) + fclose((FILE*)pMP3->pUserData); +#endif + + drmp3_free(pMP3->pData); +} + +drmp3_uint64 drmp3_read_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut) +{ + drmp3_uint64 totalFramesRead = 0; + if (pMP3 == NULL || pMP3->onRead == NULL) return 0; + + if (pBufferOut == NULL) + { + float temp[4096]; + while (framesToRead > 0) + { + drmp3_uint64 framesJustRead; + drmp3_uint64 framesToReadRightNow = sizeof(temp)/sizeof(temp[0]) / pMP3->channels; + if (framesToReadRightNow > framesToRead) + framesToReadRightNow = framesToRead; + + framesJustRead = drmp3_read_f32(pMP3, framesToReadRightNow, temp); + if (framesJustRead == 0) + break; + + framesToRead -= framesJustRead; + totalFramesRead += framesJustRead; + } + } else { + totalFramesRead = drmp3_src_read_frames_ex(&pMP3->src, framesToRead, pBufferOut, DRMP3_TRUE); + } + + return totalFramesRead; +} + +drmp3_bool32 drmp3_seek_to_frame(drmp3* pMP3, drmp3_uint64 frameIndex) +{ + drmp3_uint64 framesRead; + + if (pMP3 == NULL || pMP3->onSeek == NULL) return DRMP3_FALSE; + + /* Seek to the start of the stream to begin with. */ + if (!pMP3->onSeek(pMP3->pUserData, 0, drmp3_seek_origin_start)) + return DRMP3_FALSE; + + /* Clear any cached data. */ + pMP3->framesConsumed = 0; + pMP3->framesRemaining = 0; + pMP3->dataSize = 0; + pMP3->atEnd = DRMP3_FALSE; + + /* TODO: Optimize. + * + * This is inefficient. We simply read frames from the start of the stream. */ + framesRead = drmp3_read_f32(pMP3, frameIndex, NULL); + if (framesRead != frameIndex) + return DRMP3_FALSE; + + return DRMP3_TRUE; +} + + + +float* drmp3__full_decode_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3_uint64 totalFramesRead = 0; + drmp3_uint64 framesCapacity = 0; + float* pFrames = NULL; + + float temp[4096]; + + drmp3_assert(pMP3 != NULL); + + for (;;) + { + drmp3_uint64 framesToReadRightNow = drmp3_countof(temp) / pMP3->channels; + drmp3_uint64 framesJustRead = drmp3_read_f32(pMP3, framesToReadRightNow, temp); + if (framesJustRead == 0) + break; + + /* Reallocate the output buffer if there's not enough room. */ + if (framesCapacity < totalFramesRead + framesJustRead) + { + float* pNewFrames; + drmp3_uint64 newFramesBufferSize; + + framesCapacity *= 2; + if (framesCapacity < totalFramesRead + framesJustRead) + framesCapacity = totalFramesRead + framesJustRead; + + newFramesBufferSize = framesCapacity*pMP3->channels*sizeof(float); + if (newFramesBufferSize > SIZE_MAX) + break; + + pNewFrames = (float*)drmp3_realloc(pFrames, (size_t)newFramesBufferSize); + if (pNewFrames == NULL) + { + drmp3_free(pFrames); + break; + } + + pFrames = pNewFrames; + } + + drmp3_copy_memory(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(float))); + totalFramesRead += framesJustRead; + + /* If the number of frames we asked for is less that what we actually read it means we've reached the end. */ + if (framesJustRead != framesToReadRightNow) + break; + } + + if (pConfig != NULL) + { + pConfig->outputChannels = pMP3->channels; + pConfig->outputSampleRate = pMP3->sampleRate; + } + + drmp3_uninit(pMP3); + + if (pTotalFrameCount) *pTotalFrameCount = totalFramesRead; + return pFrames; +} + +float* drmp3_open_and_decode_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3 mp3; + if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pConfig)) + return NULL; + + return drmp3__full_decode_and_close_f32(&mp3, pConfig, pTotalFrameCount); +} + +float* drmp3_open_and_decode_memory_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3 mp3; + if (!drmp3_init_memory(&mp3, pData, dataSize, pConfig)) + return NULL; + + return drmp3__full_decode_and_close_f32(&mp3, pConfig, pTotalFrameCount); +} + +#ifndef DR_MP3_NO_STDIO +float* drmp3_open_and_decode_file_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount) +{ + drmp3 mp3; + if (!drmp3_init_file(&mp3, filePath, pConfig)) + return NULL; + + return drmp3__full_decode_and_close_f32(&mp3, pConfig, pTotalFrameCount); +} +#endif + +void drmp3_free(void* p) +{ + DRMP3_FREE(p); +} + +#endif /*DR_MP3_IMPLEMENTATION*/ + +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + +/* + https://github.com/lieff/minimp3 + To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. + This software is distributed without any warranty. + See . +*/ diff --git a/deps/libFLAC/bitmath.c b/deps/libFLAC/bitmath.c index b3d797d39b..b700b71e0c 100644 --- a/deps/libFLAC/bitmath.c +++ b/deps/libFLAC/bitmath.c @@ -34,7 +34,7 @@ # include #endif -#include "private/bitmath.h" +#include "include/private/bitmath.h" /* An example of what FLAC__bitmath_silog2() computes: * diff --git a/deps/libFLAC/bitreader.c b/deps/libFLAC/bitreader.c index 902c3a3327..5efde25e3f 100644 --- a/deps/libFLAC/bitreader.c +++ b/deps/libFLAC/bitreader.c @@ -38,13 +38,13 @@ #include #include -#include "private/bitmath.h" -#include "private/bitreader.h" -#include "private/crc.h" -#include "private/macros.h" -#include "FLAC/assert.h" -#include "share/compat.h" -#include "share/endswap.h" +#include "include/private/bitmath.h" +#include "include/private/bitreader.h" +#include "include/private/crc.h" +#include "include/private/macros.h" +#include "include/FLAC/assert.h" +#include "include/share/compat.h" +#include "include/share/endswap.h" /* Things should be fastest when this matches the machine word size */ /* WATCHOUT: if you change this you must also change the following #defines down to COUNT_ZERO_MSBS2 below to match */ diff --git a/deps/libFLAC/cpu.c b/deps/libFLAC/cpu.c index 3f0a2346db..da2b7e3955 100644 --- a/deps/libFLAC/cpu.c +++ b/deps/libFLAC/cpu.c @@ -34,11 +34,12 @@ # include #endif -#include "private/cpu.h" -#include "share/compat.h" #include #include +#include "include/private/cpu.h" +#include "include/share/compat.h" + #if defined(_MSC_VER) # include /* for __cpuid() and _xgetbv() */ #endif @@ -83,7 +84,7 @@ cpu_xgetbv_x86(void) return (uint32_t)_xgetbv(0); #elif defined __GNUC__ uint32_t lo, hi; - asm volatile (".byte 0x0f, 0x01, 0xd0" : "=a"(lo), "=d"(hi) : "c" (0)); + __asm__ volatile (".byte 0x0f, 0x01, 0xd0" : "=a"(lo), "=d"(hi) : "c" (0)); return lo; #else return 0; diff --git a/deps/libFLAC/crc.c b/deps/libFLAC/crc.c index 8123c3b69d..b1068cedad 100644 --- a/deps/libFLAC/crc.c +++ b/deps/libFLAC/crc.c @@ -34,7 +34,7 @@ # include #endif -#include "private/crc.h" +#include "include/private/crc.h" /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */ diff --git a/deps/libFLAC/fixed.c b/deps/libFLAC/fixed.c index b33f61f716..f444a1e2dc 100644 --- a/deps/libFLAC/fixed.c +++ b/deps/libFLAC/fixed.c @@ -38,11 +38,11 @@ #include #include -#include "share/compat.h" -#include "private/bitmath.h" -#include "private/fixed.h" -#include "private/macros.h" -#include "FLAC/assert.h" +#include "include/share/compat.h" +#include "include/private/bitmath.h" +#include "include/private/fixed.h" +#include "include/private/macros.h" +#include "include/FLAC/assert.h" #ifdef local_abs #undef local_abs diff --git a/deps/libFLAC/float.c b/deps/libFLAC/float.c index 25d1a78615..fdcfcb0a91 100644 --- a/deps/libFLAC/float.c +++ b/deps/libFLAC/float.c @@ -34,9 +34,9 @@ # include #endif -#include "FLAC/assert.h" -#include "share/compat.h" -#include "private/float.h" +#include "include/FLAC/assert.h" +#include "include/share/compat.h" +#include "include/private/float.h" #ifdef FLAC__INTEGER_ONLY_LIBRARY diff --git a/deps/libFLAC/format.c b/deps/libFLAC/format.c index f320807404..655a908eb9 100644 --- a/deps/libFLAC/format.c +++ b/deps/libFLAC/format.c @@ -40,12 +40,12 @@ #include -#include "FLAC/assert.h" -#include "FLAC/format.h" -#include "share/alloc.h" -#include "share/compat.h" -#include "private/format.h" -#include "private/macros.h" +#include "include/FLAC/assert.h" +#include "include/FLAC/format.h" +#include "include/share/alloc.h" +#include "include/share/compat.h" +#include "include/private/format.h" +#include "include/private/macros.h" /* FLAC_PACKAGE_VERSION should come from configure */ #if defined(__LIBRETRO__) || defined(RARCH_INTERNAL) diff --git a/deps/libFLAC/include/FLAC/format.h b/deps/libFLAC/include/FLAC/format.h index c087d4a70e..99ed7c5116 100644 --- a/deps/libFLAC/include/FLAC/format.h +++ b/deps/libFLAC/include/FLAC/format.h @@ -512,7 +512,7 @@ typedef enum { FLAC__METADATA_TYPE_UNDEFINED = 7, /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ - FLAC__MAX_METADATA_TYPE = FLAC__MAX_METADATA_TYPE_CODE, + FLAC__MAX_METADATA_TYPE = FLAC__MAX_METADATA_TYPE_CODE /**< No type will ever be greater than this. There is not enough room in the protocol block. */ } FLAC__MetadataType; diff --git a/deps/libFLAC/include/private/bitmath.h b/deps/libFLAC/include/private/bitmath.h index 2c8ecf53b9..24ba5e6003 100644 --- a/deps/libFLAC/include/private/bitmath.h +++ b/deps/libFLAC/include/private/bitmath.h @@ -35,10 +35,10 @@ #include -#include "FLAC/ordinals.h" -#include "FLAC/assert.h" +#include "../FLAC/ordinals.h" +#include "../FLAC/assert.h" -#include "share/compat.h" +#include "../share/compat.h" #if defined(_MSC_VER) #include /* for _BitScanReverse* */ diff --git a/deps/libFLAC/include/private/bitreader.h b/deps/libFLAC/include/private/bitreader.h index 7c7316556a..91230eee8c 100644 --- a/deps/libFLAC/include/private/bitreader.h +++ b/deps/libFLAC/include/private/bitreader.h @@ -34,7 +34,7 @@ #define FLAC__PRIVATE__BITREADER_H #include /* for FILE */ -#include "FLAC/ordinals.h" +#include "../FLAC/ordinals.h" #include "cpu.h" /* diff --git a/deps/libFLAC/include/private/cpu.h b/deps/libFLAC/include/private/cpu.h index 7c6518076b..1353817fe8 100644 --- a/deps/libFLAC/include/private/cpu.h +++ b/deps/libFLAC/include/private/cpu.h @@ -33,7 +33,7 @@ #ifndef FLAC__PRIVATE__CPU_H #define FLAC__PRIVATE__CPU_H -#include "FLAC/ordinals.h" +#include "../FLAC/ordinals.h" #ifdef HAVE_CONFIG_H #include diff --git a/deps/libFLAC/include/private/crc.h b/deps/libFLAC/include/private/crc.h index 294f60eaa2..6c63b3b272 100644 --- a/deps/libFLAC/include/private/crc.h +++ b/deps/libFLAC/include/private/crc.h @@ -33,7 +33,7 @@ #ifndef FLAC__PRIVATE__CRC_H #define FLAC__PRIVATE__CRC_H -#include "FLAC/ordinals.h" +#include "../FLAC/ordinals.h" /* 8 bit CRC generator, MSB shifted first ** polynomial = x^8 + x^2 + x^1 + x^0 diff --git a/deps/libFLAC/include/private/fixed.h b/deps/libFLAC/include/private/fixed.h index 68cdfceb37..b260d29697 100644 --- a/deps/libFLAC/include/private/fixed.h +++ b/deps/libFLAC/include/private/fixed.h @@ -37,9 +37,9 @@ #include #endif -#include "private/cpu.h" -#include "private/float.h" -#include "FLAC/format.h" +#include "../private/cpu.h" +#include "../private/float.h" +#include "../FLAC/format.h" /* * FLAC__fixed_compute_best_predictor() diff --git a/deps/libFLAC/include/private/float.h b/deps/libFLAC/include/private/float.h index 12ece60565..7d50f6103e 100644 --- a/deps/libFLAC/include/private/float.h +++ b/deps/libFLAC/include/private/float.h @@ -37,7 +37,7 @@ #include #endif -#include "FLAC/ordinals.h" +#include "../FLAC/ordinals.h" /* * All the code in libFLAC that uses float and double diff --git a/deps/libFLAC/include/private/format.h b/deps/libFLAC/include/private/format.h index 5b9cfbd0ed..e27f251f85 100644 --- a/deps/libFLAC/include/private/format.h +++ b/deps/libFLAC/include/private/format.h @@ -33,7 +33,7 @@ #ifndef FLAC__PRIVATE__FORMAT_H #define FLAC__PRIVATE__FORMAT_H -#include "FLAC/format.h" +#include "../FLAC/format.h" unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order); unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize); diff --git a/deps/libFLAC/include/private/lpc.h b/deps/libFLAC/include/private/lpc.h index 6eb02be63a..bf7b5d7f25 100644 --- a/deps/libFLAC/include/private/lpc.h +++ b/deps/libFLAC/include/private/lpc.h @@ -37,9 +37,9 @@ #include #endif -#include "private/cpu.h" -#include "private/float.h" -#include "FLAC/format.h" +#include "../private/cpu.h" +#include "../private/float.h" +#include "../FLAC/format.h" #ifndef FLAC__INTEGER_ONLY_LIBRARY diff --git a/deps/libFLAC/include/private/md5.h b/deps/libFLAC/include/private/md5.h index c665ab313f..3d4967c091 100644 --- a/deps/libFLAC/include/private/md5.h +++ b/deps/libFLAC/include/private/md5.h @@ -26,7 +26,7 @@ * Still in the public domain, with no warranty. */ -#include "FLAC/ordinals.h" +#include "../FLAC/ordinals.h" typedef union { FLAC__byte *p8; diff --git a/deps/libFLAC/include/private/memory.h b/deps/libFLAC/include/private/memory.h index f103c531ff..d9116e8bb6 100644 --- a/deps/libFLAC/include/private/memory.h +++ b/deps/libFLAC/include/private/memory.h @@ -39,8 +39,8 @@ #include /* for size_t */ -#include "private/float.h" -#include "FLAC/ordinals.h" /* for FLAC__bool */ +#include "../private/float.h" +#include "../FLAC/ordinals.h" /* for FLAC__bool */ /* Returns the unaligned address returned by malloc. * Use free() on this address to deallocate. diff --git a/deps/libFLAC/include/protected/stream_decoder.h b/deps/libFLAC/include/protected/stream_decoder.h index 5c31c1618d..bf08aa6081 100644 --- a/deps/libFLAC/include/protected/stream_decoder.h +++ b/deps/libFLAC/include/protected/stream_decoder.h @@ -33,9 +33,9 @@ #ifndef FLAC__PROTECTED__STREAM_DECODER_H #define FLAC__PROTECTED__STREAM_DECODER_H -#include "FLAC/stream_decoder.h" +#include "../FLAC/stream_decoder.h" #if FLAC__HAS_OGG -#include "private/ogg_decoder_aspect.h" +#include "../private/ogg_decoder_aspect.h" #endif typedef struct FLAC__StreamDecoderProtected { diff --git a/deps/libFLAC/include/share/alloc.h b/deps/libFLAC/include/share/alloc.h index 914de9ba6b..a66153eee9 100644 --- a/deps/libFLAC/include/share/alloc.h +++ b/deps/libFLAC/include/share/alloc.h @@ -33,6 +33,8 @@ #ifndef FLAC__SHARE__ALLOC_H #define FLAC__SHARE__ALLOC_H +#include + #ifdef HAVE_CONFIG_H # include #endif @@ -46,7 +48,7 @@ #include /* for SIZE_MAX in case limits.h didn't get it */ #endif #include /* for size_t, malloc(), etc */ -#include "share/compat.h" +#include "../share/compat.h" #ifndef SIZE_MAX # ifndef SIZE_T_MAX @@ -66,7 +68,7 @@ /* avoid malloc()ing 0 bytes, see: * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 */ -static inline void *safe_malloc_(size_t size) +static INLINE void *safe_malloc_(size_t size) { /* malloc(0) is undefined; FLAC src convention is to always allocate */ if(!size) @@ -74,7 +76,7 @@ static inline void *safe_malloc_(size_t size) return malloc(size); } -static inline void *safe_calloc_(size_t nmemb, size_t size) +static INLINE void *safe_calloc_(size_t nmemb, size_t size) { if(!nmemb || !size) return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ @@ -83,7 +85,7 @@ static inline void *safe_calloc_(size_t nmemb, size_t size) /*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */ -static inline void *safe_malloc_add_2op_(size_t size1, size_t size2) +static INLINE void *safe_malloc_add_2op_(size_t size1, size_t size2) { size2 += size1; if(size2 < size1) @@ -91,7 +93,7 @@ static inline void *safe_malloc_add_2op_(size_t size1, size_t size2) return safe_malloc_(size2); } -static inline void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3) +static INLINE void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3) { size2 += size1; if(size2 < size1) @@ -102,7 +104,7 @@ static inline void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size return safe_malloc_(size3); } -static inline void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4) +static INLINE void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4) { size2 += size1; if(size2 < size1) @@ -118,7 +120,7 @@ static inline void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size void *safe_malloc_mul_2op_(size_t size1, size_t size2) ; -static inline void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3) +static INLINE void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3) { if(!size1 || !size2 || !size3) return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ @@ -131,7 +133,7 @@ static inline void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size } /* size1*size2 + size3 */ -static inline void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) +static INLINE void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) { if(!size1 || !size2) return safe_malloc_(size3); @@ -141,7 +143,7 @@ static inline void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size } /* size1 * (size2 + size3) */ -static inline void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) +static INLINE void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) { if(!size1 || (!size2 && !size3)) return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ @@ -153,7 +155,7 @@ static inline void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size return malloc(size1*size2); } -static inline void *safe_realloc_(void *ptr, size_t size) +static INLINE void *safe_realloc_(void *ptr, size_t size) { void *oldptr = ptr; void *newptr = realloc(ptr, size); @@ -161,7 +163,7 @@ static inline void *safe_realloc_(void *ptr, size_t size) free(oldptr); return newptr; } -static inline void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) +static INLINE void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) { size2 += size1; if(size2 < size1) { @@ -171,7 +173,7 @@ static inline void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) return realloc(ptr, size2); } -static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) +static INLINE void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) { size2 += size1; if(size2 < size1) @@ -182,7 +184,7 @@ static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, return realloc(ptr, size3); } -static inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) +static INLINE void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) { size2 += size1; if(size2 < size1) @@ -196,7 +198,7 @@ static inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, return realloc(ptr, size4); } -static inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) +static INLINE void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) { if(!size1 || !size2) return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ @@ -206,7 +208,7 @@ static inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) } /* size1 * (size2 + size3) */ -static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) +static INLINE void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) { if(!size1 || (!size2 && !size3)) return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ diff --git a/deps/libFLAC/lpc.c b/deps/libFLAC/lpc.c index 531247b595..a6ae94446d 100644 --- a/deps/libFLAC/lpc.c +++ b/deps/libFLAC/lpc.c @@ -36,12 +36,12 @@ #include -#include "FLAC/assert.h" -#include "FLAC/format.h" -#include "share/compat.h" -#include "private/bitmath.h" -#include "private/lpc.h" -#include "private/macros.h" +#include "include/FLAC/assert.h" +#include "include/FLAC/format.h" +#include "include/share/compat.h" +#include "include/private/bitmath.h" +#include "include/private/lpc.h" +#include "include/private/macros.h" #if defined DEBUG || defined FLAC__OVERFLOW_DETECT || defined FLAC__OVERFLOW_DETECT_VERBOSE #include #endif diff --git a/deps/libFLAC/lpc_intrin_avx2.c b/deps/libFLAC/lpc_intrin_avx2.c index f9f5ccdb02..44e2169025 100644 --- a/deps/libFLAC/lpc_intrin_avx2.c +++ b/deps/libFLAC/lpc_intrin_avx2.c @@ -34,16 +34,16 @@ # include #endif -#include "private/cpu.h" +#include "include/private/cpu.h" #ifndef FLAC__INTEGER_ONLY_LIBRARY #ifndef FLAC__NO_ASM #if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN -#include "private/lpc.h" +#include "include/private/lpc.h" #ifdef FLAC__AVX2_SUPPORTED -#include "FLAC/assert.h" -#include "FLAC/format.h" +#include "include/FLAC/assert.h" +#include "include/FLAC/format.h" #include /* AVX2 */ diff --git a/deps/libFLAC/lpc_intrin_sse.c b/deps/libFLAC/lpc_intrin_sse.c index 430e73f08e..9c800f5831 100644 --- a/deps/libFLAC/lpc_intrin_sse.c +++ b/deps/libFLAC/lpc_intrin_sse.c @@ -34,15 +34,15 @@ # include #endif -#include "private/cpu.h" +#include "include/private/cpu.h" #ifndef FLAC__INTEGER_ONLY_LIBRARY #ifndef FLAC__NO_ASM #if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN -#include "private/lpc.h" +#include "include/private/lpc.h" #ifdef FLAC__SSE_SUPPORTED -#include "FLAC/assert.h" -#include "FLAC/format.h" +#include "include/FLAC/assert.h" +#include "include/FLAC/format.h" #include /* SSE */ diff --git a/deps/libFLAC/lpc_intrin_sse2.c b/deps/libFLAC/lpc_intrin_sse2.c index 138339483f..59b416253f 100644 --- a/deps/libFLAC/lpc_intrin_sse2.c +++ b/deps/libFLAC/lpc_intrin_sse2.c @@ -34,16 +34,16 @@ # include #endif -#include "private/cpu.h" +#include "include/private/cpu.h" #ifndef FLAC__INTEGER_ONLY_LIBRARY #ifndef FLAC__NO_ASM #if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN -#include "private/lpc.h" +#include "include/private/lpc.h" #ifdef FLAC__SSE2_SUPPORTED -#include "FLAC/assert.h" -#include "FLAC/format.h" +#include "include/FLAC/assert.h" +#include "include/FLAC/format.h" #include /* SSE2 */ diff --git a/deps/libFLAC/lpc_intrin_sse41.c b/deps/libFLAC/lpc_intrin_sse41.c index bef73f41f6..ea0e2bbc30 100644 --- a/deps/libFLAC/lpc_intrin_sse41.c +++ b/deps/libFLAC/lpc_intrin_sse41.c @@ -34,16 +34,16 @@ # include #endif -#include "private/cpu.h" +#include "include/private/cpu.h" #ifndef FLAC__INTEGER_ONLY_LIBRARY #ifndef FLAC__NO_ASM #if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN -#include "private/lpc.h" +#include "include/private/lpc.h" #ifdef FLAC__SSE4_1_SUPPORTED -#include "FLAC/assert.h" -#include "FLAC/format.h" +#include "include/FLAC/assert.h" +#include "include/FLAC/format.h" #include /* SSE4.1 */ diff --git a/deps/libFLAC/md5.c b/deps/libFLAC/md5.c index 9527f38deb..7ca816133e 100644 --- a/deps/libFLAC/md5.c +++ b/deps/libFLAC/md5.c @@ -5,9 +5,9 @@ #include /* for malloc() */ #include /* for memcpy() */ -#include "private/md5.h" -#include "share/alloc.h" -#include "share/endswap.h" +#include "include/private/md5.h" +#include "include/share/alloc.h" +#include "include/share/endswap.h" /* * This code implements the MD5 message-digest algorithm. diff --git a/deps/libFLAC/memory.c b/deps/libFLAC/memory.c index 41cc446034..a7a3f6a721 100644 --- a/deps/libFLAC/memory.c +++ b/deps/libFLAC/memory.c @@ -38,9 +38,9 @@ #include #endif -#include "private/memory.h" -#include "FLAC/assert.h" -#include "share/alloc.h" +#include "include/private/memory.h" +#include "include/FLAC/assert.h" +#include "include/share/alloc.h" void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) { diff --git a/deps/libFLAC/stream_decoder.c b/deps/libFLAC/stream_decoder.c index 8dab5caa18..ec34f75667 100644 --- a/deps/libFLAC/stream_decoder.c +++ b/deps/libFLAC/stream_decoder.c @@ -42,20 +42,20 @@ #include -#include "share/compat.h" -#include "FLAC/assert.h" -#include "share/alloc.h" -#include "protected/stream_decoder.h" -#include "private/bitreader.h" -#include "private/bitmath.h" -#include "private/cpu.h" -#include "private/crc.h" -#include "private/fixed.h" -#include "private/format.h" -#include "private/lpc.h" -#include "private/md5.h" -#include "private/memory.h" -#include "private/macros.h" +#include "include/share/compat.h" +#include "include/FLAC/assert.h" +#include "include/share/alloc.h" +#include "include/protected/stream_decoder.h" +#include "include/private/bitreader.h" +#include "include/private/bitmath.h" +#include "include/private/cpu.h" +#include "include/private/crc.h" +#include "include/private/fixed.h" +#include "include/private/format.h" +#include "include/private/lpc.h" +#include "include/private/md5.h" +#include "include/private/memory.h" +#include "include/private/macros.h" /* technically this should be in an "export.c" but this is convenient enough */ diff --git a/deps/libz/crc32.c b/deps/libz/libz-crc32.c similarity index 100% rename from deps/libz/crc32.c rename to deps/libz/libz-crc32.c diff --git a/deps/miniupnpc/minissdpc.c b/deps/miniupnpc/minissdpc.c index c2a00319ef..2a526d04e8 100644 --- a/deps/miniupnpc/minissdpc.c +++ b/deps/miniupnpc/minissdpc.c @@ -145,7 +145,7 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * err if(n<=0) break; \ bufferindex = 0; \ } \ - lcopy = MIN(l, (n - bufferindex)); \ + lcopy = (unsigned int)MIN(l, (n - bufferindex)); \ memcpy(p, buffer + bufferindex, lcopy); \ l -= lcopy; \ p += lcopy; \ @@ -584,7 +584,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], struct in_addr mc_if; memset(&mc_if, 0, sizeof(mc_if)); mc_if.s_addr = pIPAddrTable->table[i].dwAddr; - setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0; + setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)); ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; #ifndef DEBUG break; @@ -606,6 +606,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], { if(error) *error = MINISSDPC_SOCKET_ERROR; + closesocket(sudp); return NULL; } diff --git a/deps/stb/stb_rect_pack.h b/deps/stb/stb_rect_pack.h index 6c658de33e..ed1585ba19 100644 --- a/deps/stb/stb_rect_pack.h +++ b/deps/stb/stb_rect_pack.h @@ -528,12 +528,7 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n /* we use the 'was_packed' field internally to allow sorting/unsorting */ for (i=0; i < num_rects; ++i) - { rects[i].was_packed = i; - #ifndef STBRP_LARGE_RECTS - STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff); - #endif - } /* sort according to heuristic */ STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); diff --git a/deps/stb/stb_vorbis.h b/deps/stb/stb_vorbis.h index 6adaff4940..be97f0b655 100644 --- a/deps/stb/stb_vorbis.h +++ b/deps/stb/stb_vorbis.h @@ -3278,7 +3278,7 @@ static stb_vorbis * vorbis_alloc(stb_vorbis *f) unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) { - return f->stream - f->stream_start; + return (unsigned int)(f->stream - f->stream_start); } #ifndef STB_VORBIS_NO_PULLDATA_API diff --git a/dynamic.c b/dynamic.c index 3e89144f81..bed42e2370 100644 --- a/dynamic.c +++ b/dynamic.c @@ -66,9 +66,14 @@ #include "msg_hash.h" #include "verbosity.h" +#ifdef HAVE_RUNAHEAD +#include "runahead/secondary_core.h" +#include "runahead/run_ahead.h" +#endif + #ifdef HAVE_DYNAMIC #define SYMBOL(x) do { \ - function_t func = dylib_proc(lib_handle, #x); \ + function_t func = dylib_proc(lib_handle_local, #x); \ memcpy(¤t_core->x, &func, sizeof(func)); \ if (current_core->x == NULL) { RARCH_ERR("Failed to load symbol: \"%s\"\n", #x); retroarch_fail(1, "init_libretro_sym()"); } \ } while (0) @@ -383,14 +388,36 @@ bool libretro_get_system_info(const char *path, * Setup libretro callback symbols. Returns true on success, * or false if symbols could not be loaded. **/ -static bool load_symbols(enum rarch_core_type type, struct retro_core_t *current_core) +bool init_libretro_sym_custom(enum rarch_core_type type, struct retro_core_t *current_core, const char *lib_path, dylib_t *lib_handle_p) { + /* the library handle for use with the SYMBOL macro */ + dylib_t lib_handle_local; switch (type) { case CORE_TYPE_PLAIN: #ifdef HAVE_DYNAMIC - if (!load_dynamic_core()) - return false; +#ifdef HAVE_RUNAHEAD + if (!lib_path || !lib_handle_p) +#endif + { + if (!load_dynamic_core()) + return false; + lib_handle_local = lib_handle; + } +#ifdef HAVE_RUNAHEAD + else + { + /* for a secondary core, we already have a + * primary library loaded, so we can skip + * some checks and just load the library */ + retro_assert(lib_path != NULL && lib_handle_p != NULL); + lib_handle_local = dylib_load(lib_path); + + if (!lib_handle_local) + return false; + *lib_handle_p = lib_handle_local; + } +#endif #endif SYMBOL(retro_init); @@ -615,6 +642,11 @@ static bool load_symbols(enum rarch_core_type type, struct retro_core_t *current return true; } +static bool load_symbols(enum rarch_core_type type, struct retro_core_t *current_core) +{ + return init_libretro_sym_custom(type, current_core, NULL, NULL); +} + /** * init_libretro_sym: * @type : Type of core to be loaded. @@ -634,6 +666,11 @@ bool init_libretro_sym(enum rarch_core_type type, struct retro_core_t *current_c if (!load_symbols(type, current_core)) return false; +#ifdef HAVE_RUNAHEAD + /* remember last core type created, so creating a + * secondary core will know what core type to use. */ + set_last_core_type(type); +#endif return true; } @@ -885,23 +922,27 @@ static bool dynamic_request_hw_context(enum retro_hw_context_type type, break; #endif - case RETRO_HW_CONTEXT_DIRECT3D: - switch(major) - { +#if defined(HAVE_D3D9) || defined(HAVE_D3D11) + case RETRO_HW_CONTEXT_DIRECT3D: + switch (major) + { #ifdef HAVE_D3D9 - case 9: + case 9: + RARCH_LOG("Requesting D3D9 context.\n"); + break; #endif #ifdef HAVE_D3D11 - case 11: + case 11: + RARCH_LOG("Requesting D3D11 context.\n"); + break; +#endif + default: + RARCH_LOG("Requesting unknown context.\n"); + return false; + } + break; #endif - RARCH_LOG("Requesting D3D%i context.\n", major); - break; - default: - goto unknown; - } - break; -unknown: default: RARCH_LOG("Requesting unknown context.\n"); return false; @@ -1718,13 +1759,15 @@ bool rarch_environment_cb(unsigned cmd, void *data) { int result = 0; if (!audio_driver_is_suspended() && audio_driver_is_active()) - { result |= 2; - } if (video_driver_is_active() && !video_driver_is_stub_frame()) - { result |= 1; - } +#ifdef HAVE_RUNAHEAD + if (want_fast_savestate()) + result |= 4; + if (get_hard_disable_audio()) + result |= 8; +#endif if (data != NULL) { int* result_p = (int*)data; diff --git a/dynamic.h b/dynamic.h index 2432704e48..e930a2edc8 100644 --- a/dynamic.h +++ b/dynamic.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "core_type.h" @@ -132,6 +133,8 @@ bool libretro_get_shared_context(void); bool init_libretro_sym(enum rarch_core_type type, struct retro_core_t *core); +bool init_libretro_sym_custom(enum rarch_core_type type, struct retro_core_t *current_core, const char *lib_path, dylib_t *lib_handle_p); + /** * uninit_libretro_sym: * diff --git a/experimental-audio.diff b/experimental-audio.diff new file mode 100644 index 0000000000..7697070fb2 --- /dev/null +++ b/experimental-audio.diff @@ -0,0 +1,97 @@ +diff --git a/audio/audio_driver.c b/audio/audio_driver.c +index 3209354b19..caf10dbed2 100644 +--- a/audio/audio_driver.c ++++ b/audio/audio_driver.c +@@ -606,7 +606,6 @@ static void audio_driver_flush(const int16_t *data, size_t samples) + src_data.data_in = audio_driver_input_data; + src_data.input_frames = samples >> 1; + +- + if (audio_driver_dsp) + { + struct retro_dsp_data dsp_data; +@@ -722,6 +721,19 @@ void audio_driver_sample(int16_t left, int16_t right) + audio_driver_data_ptr = 0; + } + ++void audio_driver_menu_sample(void) ++{ ++ static unsigned count = 0; ++ audio_driver_output_samples_conv_buf[count++] = 0; ++ audio_driver_output_samples_conv_buf[count++] = 0; ++ ++ if (audio_driver_data_ptr < audio_driver_chunk_size) ++ return; ++ ++ audio_driver_flush(audio_driver_output_samples_conv_buf, ++ count); ++} ++ + /** + * audio_driver_sample_batch: + * @data : pointer to audio buffer. +diff --git a/audio/audio_driver.h b/audio/audio_driver.h +index 6dfacaa89f..e5c37a344c 100644 +--- a/audio/audio_driver.h ++++ b/audio/audio_driver.h +@@ -271,6 +271,8 @@ bool audio_driver_deinit(void); + + bool audio_driver_init(void); + ++void audio_driver_menu_sample(void); ++ + bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params); + + enum resampler_quality audio_driver_get_resampler_quality(void); +diff --git a/menu/menu_driver.c b/menu/menu_driver.c +index 45580c12f5..894cbf56bc 100644 +--- a/menu/menu_driver.c ++++ b/menu/menu_driver.c +@@ -1683,8 +1683,10 @@ static void menu_driver_toggle(bool on) + /* Stop all rumbling before entering the menu. */ + command_event(CMD_EVENT_RUMBLE_STOP, NULL); + ++#if 0 + if (pause_libretro) + command_event(CMD_EVENT_AUDIO_STOP, NULL); ++#endif + + /* Override keyboard callback to redirect to menu instead. + * We'll use this later for something ... */ +@@ -1702,8 +1704,10 @@ static void menu_driver_toggle(bool on) + if (!rarch_ctl(RARCH_CTL_IS_SHUTDOWN, NULL)) + driver_set_nonblock_state(); + ++#if 0 + if (pause_libretro) + command_event(CMD_EVENT_AUDIO_START, NULL); ++#endif + + /* Restore libretro keyboard callback. */ + if (key_event && frontend_key_event) +diff --git a/retroarch.c b/retroarch.c +index 537ed82f37..29df4434b0 100644 +--- a/retroarch.c ++++ b/retroarch.c +@@ -2608,6 +2608,7 @@ static enum runloop_state runloop_check_state( + + retro_ctx.poll_cb(); + ++ + { + enum menu_action action; + bool focused = false; +@@ -2627,10 +2628,13 @@ static enum runloop_state runloop_check_state( + rarch_menu_running_finished(); + + if (focused || !runloop_idle) ++ { + menu_driver_render(runloop_idle, rarch_is_inited, + (current_core_type == CORE_TYPE_DUMMY) + ) + ; ++ audio_driver_menu_sample(); ++ } + + old_input = current_input; + diff --git a/file_path_special.h b/file_path_special.h index b0eeee3bdc..16455f2486 100644 --- a/file_path_special.h +++ b/file_path_special.h @@ -86,6 +86,8 @@ enum file_path_enum FILE_PATH_ZIP_EXTENSION, FILE_PATH_7Z_EXTENSION, FILE_PATH_OGG_EXTENSION, + FILE_PATH_MP3_EXTENSION, + FILE_PATH_FLAC_EXTENSION, FILE_PATH_WAV_EXTENSION, FILE_PATH_MOD_EXTENSION, FILE_PATH_S3M_EXTENSION, diff --git a/file_path_str.c b/file_path_str.c index 219c719720..2d9d73481d 100644 --- a/file_path_str.c +++ b/file_path_str.c @@ -101,6 +101,12 @@ const char *file_path_str(enum file_path_enum enum_idx) case FILE_PATH_PNG_EXTENSION: str = ".png"; break; + case FILE_PATH_MP3_EXTENSION: + str = ".mp3"; + break; + case FILE_PATH_FLAC_EXTENSION: + str = ".flac"; + break; case FILE_PATH_OGG_EXTENSION: str = ".ogg"; break; diff --git a/frontend/drivers/platform_qnx.c b/frontend/drivers/platform_qnx.c index 0b3af7895b..ddd4829852 100644 --- a/frontend/drivers/platform_qnx.c +++ b/frontend/drivers/platform_qnx.c @@ -142,7 +142,9 @@ static void frontend_qnx_get_environment_settings(int *argc, char *argv[], file_path_str(FILE_PATH_MAIN_CONFIG), sizeof(g_defaults.path.config)); /* bundle copy */ - sprintf(data_assets_path, "%s/%s", data_path, "assets"); + snprintf(data_assets_path, + sizeof(data_assets_path), + "%s/%s", data_path, "assets"); if (!filestream_exists(data_assets_path)) { @@ -150,7 +152,9 @@ static void frontend_qnx_get_environment_settings(int *argc, char *argv[], RARCH_LOG( "Copying application assets to data directory...\n" ); - sprintf(copy_command, "cp -r %s/. %s", assets_path, data_path); + snprintf(copy_command, + sizeof(copy_command), + "cp -r %s/. %s", assets_path, data_path); if(system(copy_command) == -1) RARCH_LOG( "Asset copy failed: Shell could not be run.\n" ); diff --git a/frontend/drivers/platform_unix.c b/frontend/drivers/platform_unix.c index b750f43c66..11e6c2c8d8 100644 --- a/frontend/drivers/platform_unix.c +++ b/frontend/drivers/platform_unix.c @@ -54,9 +54,6 @@ #ifdef ANDROID #include -#ifdef __arm__ -#include -#endif #endif #include @@ -2372,8 +2369,15 @@ static bool frontend_unix_check_for_path_changes(path_change_data_t *change_data { unsigned j; - /* A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a file system to flush the buffers when the stream is closed. - * So we manually fsync() here to flush the data to disk, to make sure that the new data is immediately available when the file is re-read. + /* A successful close does not guarantee that the + * data has been successfully saved to disk, + * as the kernel defers writes. It is + * not common for a file system to flush + * the buffers when the stream is closed. + * + * So we manually fsync() here to flush the data + * to disk, to make sure that the new data is + * immediately available when the file is re-read. */ for (j = 0; j < inotify_data->wd_list->count; j++) { @@ -2381,7 +2385,7 @@ static bool frontend_unix_check_for_path_changes(path_change_data_t *change_data { /* found the right file, now sync it */ const char *path = inotify_data->path_list->elems[j].data; - FILE *fp = fopen_utf8(path, "rb"); + FILE *fp = (FILE*)fopen_utf8(path, "rb"); RARCH_LOG("file change detected: %s\n", path); diff --git a/frontend/drivers/platform_win32.c b/frontend/drivers/platform_win32.c index cce85bce6e..8308446f83 100644 --- a/frontend/drivers/platform_win32.c +++ b/frontend/drivers/platform_win32.c @@ -148,15 +148,15 @@ static void gfx_set_dwm(void) static void frontend_win32_get_os(char *s, size_t len, int *major, int *minor) { - char buildStr[11] = {0}; - bool server = false; - const char *arch = ""; - bool serverR2 = false; + char buildStr[11] = {0}; + bool server = false; + const char *arch = ""; + bool serverR2 = false; #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* Windows 2000 and later */ - SYSTEM_INFO si = {0}; - OSVERSIONINFOEX vi = {0}; + SYSTEM_INFO si = {{0}}; + OSVERSIONINFOEX vi = {0}; vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); GetSystemInfo(&si); @@ -359,7 +359,7 @@ enum frontend_architecture frontend_win32_get_architecture(void) { #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* Windows 2000 and later */ - SYSTEM_INFO si = {0}; + SYSTEM_INFO si = {{0}}; GetSystemInfo(&si); diff --git a/gfx/common/d3d10_common.c b/gfx/common/d3d10_common.c index 45d364d08f..1b145015f7 100644 --- a/gfx/common/d3d10_common.c +++ b/gfx/common/d3d10_common.c @@ -18,6 +18,7 @@ #include #include "d3d10_common.h" +#include "d3dcompiler_common.h" #ifdef HAVE_DYNAMIC #include @@ -67,43 +68,72 @@ HRESULT WINAPI D3D10CreateDeviceAndSwapChain( void d3d10_init_texture(D3D10Device device, d3d10_texture_t* texture) { - Release(texture->handle); - Release(texture->staging); - Release(texture->view); + bool is_render_target = texture->desc.BindFlags & D3D10_BIND_RENDER_TARGET; + UINT format_support = D3D10_FORMAT_SUPPORT_TEXTURE2D | D3D10_FORMAT_SUPPORT_SHADER_SAMPLE; - // .Usage = D3D10_USAGE_DYNAMIC, - // .CPUAccessFlags = D3D10_CPU_ACCESS_WRITE, + d3d10_release_texture(texture); texture->desc.MipLevels = 1; texture->desc.ArraySize = 1; texture->desc.SampleDesc.Count = 1; texture->desc.SampleDesc.Quality = 0; - texture->desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texture->desc.CPUAccessFlags = 0; - texture->desc.MiscFlags = 0; + texture->desc.BindFlags |= D3D10_BIND_SHADER_RESOURCE; + texture->desc.CPUAccessFlags = + texture->desc.Usage == D3D10_USAGE_DYNAMIC ? D3D10_CPU_ACCESS_WRITE : 0; + + if (texture->desc.MiscFlags & D3D10_RESOURCE_MISC_GENERATE_MIPS) + { + unsigned width, height; + + texture->desc.BindFlags |= D3D10_BIND_RENDER_TARGET; + width = texture->desc.Width >> 5; + height = texture->desc.Height >> 5; + + while (width && height) + { + width >>= 1; + height >>= 1; + texture->desc.MipLevels++; + } + } + + if (texture->desc.BindFlags & D3D10_BIND_RENDER_TARGET) + format_support |= D3D10_FORMAT_SUPPORT_RENDER_TARGET; + + texture->desc.Format = d3d10_get_closest_match(device, texture->desc.Format, format_support); + D3D10CreateTexture2D(device, &texture->desc, NULL, &texture->handle); { D3D10_SHADER_RESOURCE_VIEW_DESC view_desc = { DXGI_FORMAT_UNKNOWN }; - view_desc.Format = texture->desc.Format; - view_desc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; - view_desc.Texture2D.MostDetailedMip = 0; - view_desc.Texture2D.MipLevels = -1; - - D3D10CreateTexture2DShaderResourceView(device, - texture->handle, &view_desc, &texture->view); + view_desc.Format = texture->desc.Format; + view_desc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; + view_desc.Texture2D.MostDetailedMip = 0; + view_desc.Texture2D.MipLevels = -1; + D3D10CreateTexture2DShaderResourceView(device, texture->handle, &view_desc, &texture->view); } + if (is_render_target) + D3D10CreateTexture2DRenderTargetView(device, texture->handle, NULL, &texture->rt_view); + else { D3D10_TEXTURE2D_DESC desc = texture->desc; + desc.MipLevels = 1; desc.BindFlags = 0; + desc.MiscFlags = 0; desc.Usage = D3D10_USAGE_STAGING; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; D3D10CreateTexture2D(device, &desc, NULL, &texture->staging); } + + texture->size_data.x = texture->desc.Width; + texture->size_data.y = texture->desc.Height; + texture->size_data.z = 1.0f / texture->desc.Width; + texture->size_data.w = 1.0f / texture->desc.Height; } void d3d10_update_texture( + D3D10Device ctx, int width, int height, int pitch, @@ -112,8 +142,14 @@ void d3d10_update_texture( d3d10_texture_t* texture) { D3D10_MAPPED_TEXTURE2D mapped_texture; + D3D10_BOX frame_box = { 0, 0, 0, (UINT)width, + (UINT)height, 1 }; - D3D10MapTexture2D(texture->staging, 0, D3D10_MAP_WRITE, 0, + if (!texture || !texture->staging) + return; + + D3D10MapTexture2D(texture->staging, + 0, D3D10_MAP_WRITE, 0, &mapped_texture); #if 0 @@ -130,8 +166,11 @@ void d3d10_update_texture( D3D10UnmapTexture2D(texture->staging, 0); - if (texture->desc.Usage == D3D10_USAGE_DEFAULT) - texture->dirty = true; + D3D10CopyTexture2DSubresourceRegion( + ctx, texture->handle, 0, 0, 0, 0, texture->staging, 0, &frame_box); + + if (texture->desc.MiscFlags & D3D10_RESOURCE_MISC_GENERATE_MIPS) + D3D10GenerateMips(ctx, texture->view); } DXGI_FORMAT @@ -155,3 +194,65 @@ d3d10_get_closest_match(D3D10Device device, assert(*format); return *format; } + +bool d3d10_init_shader( + D3D10Device device, + const char* src, + size_t size, + const void* src_name, + LPCSTR vs_entry, + LPCSTR ps_entry, + LPCSTR gs_entry, + const D3D10_INPUT_ELEMENT_DESC* input_element_descs, + UINT num_elements, + d3d10_shader_t* out) +{ + D3DBlob vs_code = NULL; + D3DBlob ps_code = NULL; + D3DBlob gs_code = NULL; + + bool success = true; + + if (!src) /* LPCWSTR filename */ + { + if (vs_entry && !d3d_compile_from_file((LPCWSTR)src_name, vs_entry, "vs_4_0", &vs_code)) + success = false; + if (ps_entry && !d3d_compile_from_file((LPCWSTR)src_name, ps_entry, "ps_4_0", &ps_code)) + success = false; + if (gs_entry && !d3d_compile_from_file((LPCWSTR)src_name, gs_entry, "gs_4_0", &gs_code)) + success = false; + } + else /* char array */ + { + if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, "vs_4_0", &vs_code)) + success = false; + if (ps_entry && !d3d_compile(src, size, (LPCSTR)src_name, ps_entry, "ps_4_0", &ps_code)) + success = false; + if (gs_entry && !d3d_compile(src, size, (LPCSTR)src_name, gs_entry, "gs_4_0", &gs_code)) + success = false; + } + + if (vs_code) + D3D10CreateVertexShader( + device, D3DGetBufferPointer(vs_code), D3DGetBufferSize(vs_code), &out->vs); + + if (ps_code) + D3D10CreatePixelShader( + device, D3DGetBufferPointer(ps_code), D3DGetBufferSize(ps_code), &out->ps); + + if (gs_code) + D3D10CreateGeometryShader( + device, D3DGetBufferPointer(gs_code), D3DGetBufferSize(gs_code), &out->gs); + + if (vs_code && input_element_descs) + D3D10CreateInputLayout( + device, + (D3D10_INPUT_ELEMENT_DESC*)input_element_descs, num_elements, D3DGetBufferPointer(vs_code), + D3DGetBufferSize(vs_code), &out->layout); + + Release(vs_code); + Release(ps_code); + Release(gs_code); + + return success; +} diff --git a/gfx/common/d3d10_common.h b/gfx/common/d3d10_common.h index 500f898bd6..ee8373ca57 100644 --- a/gfx/common/d3d10_common.h +++ b/gfx/common/d3d10_common.h @@ -20,6 +20,10 @@ #include "dxgi_common.h" #include +#include "../drivers_shader/slang_process.h" + +typedef const ID3D10SamplerState* D3D10SamplerStateRef; + typedef ID3D10InputLayout* D3D10InputLayout; typedef ID3D10RasterizerState* D3D10RasterizerState; typedef ID3D10DepthStencilState* D3D10DepthStencilState; @@ -50,6 +54,7 @@ typedef ID3D10Debug* D3D10Debug; typedef ID3D10SwitchToRef* D3D10SwitchToRef; typedef ID3D10InfoQueue* D3D10InfoQueue; + #if !defined(__cplusplus) || defined(CINTERFACE) static INLINE void D3D10SetResourceEvictionPriority(D3D10Resource resource, UINT eviction_priority) { @@ -236,6 +241,7 @@ static INLINE void D3D10SetVShader(D3D10Device device, D3D10VertexShader vertex_ { device->lpVtbl->VSSetShader(device, vertex_shader); } + static INLINE void D3D10DrawIndexed( D3D10Device device, UINT index_count, UINT start_index_location, INT base_vertex_location) { @@ -265,6 +271,28 @@ static INLINE void D3D10SetVertexBuffers( device->lpVtbl->IASetVertexBuffers( device, start_slot, num_buffers, vertex_buffers, strides, offsets); } + +static INLINE void D3D10SetVertexBuffer( + D3D10Device device_context, + UINT slot, + D3D10Buffer const vertex_buffer, + UINT stride, + UINT offset) +{ + D3D10SetVertexBuffers(device_context, slot, 1, (D3D10Buffer* const)&vertex_buffer, &stride, &offset); +} +static INLINE void D3D10SetVShaderConstantBuffer( + D3D10Device device_context, UINT slot, D3D10Buffer const constant_buffer) +{ + D3D10SetVShaderConstantBuffers(device_context, slot, 1, (ID3D10Buffer ** const)&constant_buffer); +} + +static INLINE void D3D10SetPShaderConstantBuffer( + D3D10Device device_context, UINT slot, D3D10Buffer const constant_buffer) +{ + D3D10SetPShaderConstantBuffers(device_context, slot, 1, (ID3D10Buffer** const)&constant_buffer); +} + static INLINE void D3D10SetIndexBuffer(D3D10Device device, D3D10Buffer index_buffer, DXGI_FORMAT format, UINT offset) { @@ -1047,25 +1075,74 @@ typedef struct D3D10Texture2D handle; D3D10Texture2D staging; D3D10_TEXTURE2D_DESC desc; + D3D10RenderTargetView rt_view; D3D10ShaderResourceView view; - bool dirty; - bool ignore_alpha; + D3D10SamplerStateRef sampler; + float4_t size_data; } d3d10_texture_t; +typedef struct +{ + struct + { + float x, y, w, h; + } pos; + struct + { + float u, v, w, h; + } coords; + UINT32 colors[4]; + struct + { + float scaling; + float rotation; + } params; +} d3d10_sprite_t; + +#ifndef ALIGN +#ifdef _MSC_VER +#define ALIGN(x) __declspec(align(x)) +#else +#define ALIGN(x) __attribute__((aligned(x))) +#endif +#endif + +typedef struct ALIGN(16) +{ + math_matrix_4x4 mvp; + struct + { + float width; + float height; + } OutputSize; + float time; +} d3d10_uniform_t; + +static_assert( + (!(sizeof(d3d10_uniform_t) & 0xF)), "sizeof(d3d10_uniform_t) must be a multiple of 16"); + +typedef struct d3d10_shader_t +{ + D3D10VertexShader vs; + D3D10PixelShader ps; + D3D10GeometryShader gs; + D3D10InputLayout layout; +} d3d10_shader_t; + typedef struct { unsigned cur_mon_id; DXGISwapChain swapChain; D3D10Device device; + D3D10RasterizerState state; D3D10RenderTargetView renderTargetView; - D3D10InputLayout layout; D3D10Buffer ubo; - D3D10VertexShader vs; - D3D10PixelShader ps; - D3D10SamplerState sampler_nearest; - D3D10SamplerState sampler_linear; + d3d10_uniform_t ubo_values; + D3D10SamplerState samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX]; D3D10BlendState blend_enable; D3D10BlendState blend_disable; + D3D10BlendState blend_pipeline; + D3D10Buffer menu_pipeline_vbo; math_matrix_4x4 mvp, mvp_no_rot; struct video_viewport vp; D3D10_VIEWPORT viewport; @@ -1075,28 +1152,74 @@ typedef struct bool resize_chain; bool keep_aspect; bool resize_viewport; + bool resize_render_targets; + bool init_history; + d3d10_shader_t shaders[GFX_MAX_SHADERS]; + + struct + { + d3d10_shader_t shader; + d3d10_shader_t shader_font; + D3D10Buffer vbo; + int offset; + int capacity; + bool enabled; + } sprites; + +#ifdef HAVE_OVERLAY + struct + { + D3D10Buffer vbo; + d3d10_texture_t* textures; + bool enabled; + bool fullscreen; + int count; + } overlays; +#endif + struct { d3d10_texture_t texture; D3D10Buffer vbo; - D3D10SamplerState sampler; bool enabled; bool fullscreen; } menu; struct { - d3d10_texture_t texture; + d3d10_texture_t texture[GFX_MAX_FRAME_HISTORY + 1]; D3D10Buffer vbo; D3D10Buffer ubo; - D3D10SamplerState sampler; D3D10_VIEWPORT viewport; + float4_t output_size; int rotation; } frame; + + struct + { + d3d10_shader_t shader; + D3D10Buffer buffers[SLANG_CBUFFER_MAX]; + d3d10_texture_t rt; + d3d10_texture_t feedback; + D3D10_VIEWPORT viewport; + pass_semantics_t semantics; + uint32_t frame_count; + } pass[GFX_MAX_SHADERS]; + + struct video_shader* shader_preset; + d3d10_texture_t luts[GFX_MAX_TEXTURES]; } d3d10_video_t; void d3d10_init_texture(D3D10Device device, d3d10_texture_t* texture); +static INLINE void d3d10_release_texture(d3d10_texture_t* texture) +{ + Release(texture->handle); + Release(texture->staging); + Release(texture->view); + Release(texture->rt_view); +} void d3d10_update_texture( + D3D10Device ctx, int width, int height, int pitch, @@ -1107,6 +1230,26 @@ void d3d10_update_texture( DXGI_FORMAT d3d10_get_closest_match( D3D10Device device, DXGI_FORMAT desired_format, UINT desired_format_support); +bool d3d10_init_shader( + D3D10Device device, + const char* src, + size_t size, + const void* src_name, + LPCSTR vs_entry, + LPCSTR ps_entry, + LPCSTR gs_entry, + const D3D10_INPUT_ELEMENT_DESC* input_element_descs, + UINT num_elements, + d3d10_shader_t* out); + +static INLINE void d3d10_release_shader(d3d10_shader_t* shader) +{ + Release(shader->layout); + Release(shader->vs); + Release(shader->ps); + Release(shader->gs); +} + static INLINE DXGI_FORMAT d3d10_get_closest_match_texture2D(D3D10Device device, DXGI_FORMAT desired_format) { @@ -1114,3 +1257,20 @@ d3d10_get_closest_match_texture2D(D3D10Device device, DXGI_FORMAT desired_format device, desired_format, D3D10_FORMAT_SUPPORT_TEXTURE2D | D3D10_FORMAT_SUPPORT_SHADER_SAMPLE); } + +static INLINE void d3d10_set_shader(D3D10Device ctx, d3d10_shader_t* shader) +{ + D3D10SetInputLayout(ctx, shader->layout); + D3D10SetVShader(ctx, shader->vs); + D3D10SetPShader(ctx, shader->ps); + D3D10SetGShader(ctx, shader->gs); +} + +#if !defined(__cplusplus) || defined(CINTERFACE) +static INLINE void +d3d10_set_texture_and_sampler(D3D10Device ctx, UINT slot, d3d10_texture_t* texture) +{ + D3D10SetPShaderResources(ctx, slot, 1, &texture->view); + D3D10SetPShaderSamplers(ctx, slot, 1, (D3D10SamplerState*)&texture->sampler); +} +#endif diff --git a/gfx/common/d3d11_common.c b/gfx/common/d3d11_common.c index a815f04538..16b32151e1 100644 --- a/gfx/common/d3d11_common.c +++ b/gfx/common/d3d11_common.c @@ -137,11 +137,23 @@ void d3d11_update_texture( D3D11_MAPPED_SUBRESOURCE mapped_texture; D3D11_BOX frame_box = { 0, 0, 0, width, height, 1 }; - D3D11MapTexture2D(ctx, texture->staging, 0, D3D11_MAP_WRITE, 0, &mapped_texture); + if (!texture || !texture->staging) + return; + D3D11MapTexture2D(ctx, texture->staging, + 0, D3D11_MAP_WRITE, 0, &mapped_texture); + +#if 0 + PERF_START(); + conv_rgb565_argb8888(mapped_texture.pData, data, width, height, + mapped_texture.RowPitch, pitch); + PERF_STOP(); +#else dxgi_copy( - width, height, format, pitch, data, texture->desc.Format, mapped_texture.RowPitch, + width, height, format, pitch, data, + texture->desc.Format, mapped_texture.RowPitch, mapped_texture.pData); +#endif D3D11UnmapTexture2D(ctx, texture->staging, 0); @@ -193,20 +205,20 @@ bool d3d11_init_shader( if (!src) /* LPCWSTR filename */ { - if (vs_entry && !d3d_compile_from_file((LPCWSTR)src_name, vs_entry, "vs_5_0", &vs_code)) + if (vs_entry && !d3d_compile_from_file((LPCWSTR)src_name, vs_entry, "vs_4_0", &vs_code)) success = false; - if (ps_entry && !d3d_compile_from_file((LPCWSTR)src_name, ps_entry, "ps_5_0", &ps_code)) + if (ps_entry && !d3d_compile_from_file((LPCWSTR)src_name, ps_entry, "ps_4_0", &ps_code)) success = false; - if (gs_entry && !d3d_compile_from_file((LPCWSTR)src_name, gs_entry, "gs_5_0", &gs_code)) + if (gs_entry && !d3d_compile_from_file((LPCWSTR)src_name, gs_entry, "gs_4_0", &gs_code)) success = false; } else /* char array */ { - if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, "vs_5_0", &vs_code)) + if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, "vs_4_0", &vs_code)) success = false; - if (ps_entry && !d3d_compile(src, size, (LPCSTR)src_name, ps_entry, "ps_5_0", &ps_code)) + if (ps_entry && !d3d_compile(src, size, (LPCSTR)src_name, ps_entry, "ps_4_0", &ps_code)) success = false; - if (gs_entry && !d3d_compile(src, size, (LPCSTR)src_name, gs_entry, "gs_5_0", &gs_code)) + if (gs_entry && !d3d_compile(src, size, (LPCSTR)src_name, gs_entry, "gs_4_0", &gs_code)) success = false; } diff --git a/gfx/common/d3d11_common.h b/gfx/common/d3d11_common.h index 68333f1605..69128cd07a 100644 --- a/gfx/common/d3d11_common.h +++ b/gfx/common/d3d11_common.h @@ -237,6 +237,7 @@ static INLINE void D3D11SetPShaderSamplers( device_context->lpVtbl->PSSetSamplers( device_context, start_slot, num_samplers, samplers); } + static INLINE void D3D11SetVShader( D3D11DeviceContext device_context, D3D11VertexShader vertex_shader, diff --git a/gfx/common/d3d12_common.c b/gfx/common/d3d12_common.c index 0614c84439..1b8d9478c5 100644 --- a/gfx/common/d3d12_common.c +++ b/gfx/common/d3d12_common.c @@ -206,36 +206,39 @@ bool d3d12_init_queue(d3d12_video_t* d3d12) return true; } -bool d3d12_init_swapchain(d3d12_video_t* d3d12, int width, int height, HWND hwnd) +bool d3d12_init_swapchain(d3d12_video_t* d3d12, + int width, int height, HWND hwnd) { - { - DXGI_SWAP_CHAIN_DESC desc = { 0 }; - desc.BufferCount = countof(d3d12->chain.renderTargets); - desc.BufferDesc.Width = width; - desc.BufferDesc.Height = height; - desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; + unsigned i; + DXGI_SWAP_CHAIN_DESC desc; + + memset(&desc, 0, sizeof(DXGI_SWAP_CHAIN_DESC)); + + desc.BufferCount = countof(d3d12->chain.renderTargets); + desc.BufferDesc.Width = width; + desc.BufferDesc.Height = height; + desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; #if 0 - desc.BufferDesc.RefreshRate.Numerator = 60; - desc.BufferDesc.RefreshRate.Denominator = 1; - desc.SampleDesc.Quality = 0; + desc.BufferDesc.RefreshRate.Numerator = 60; + desc.BufferDesc.RefreshRate.Denominator = 1; + desc.SampleDesc.Quality = 0; #endif - desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - desc.OutputWindow = hwnd; - desc.Windowed = TRUE; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.OutputWindow = hwnd; + desc.Windowed = TRUE; #if 0 - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; #else - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; #endif - DXGICreateSwapChain(d3d12->factory, d3d12->queue.handle, &desc, &d3d12->chain.handle); - } + DXGICreateSwapChain(d3d12->factory, d3d12->queue.handle, &desc, &d3d12->chain.handle); DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER); d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle); - for (int i = 0; i < countof(d3d12->chain.renderTargets); i++) + for (i = 0; i < countof(d3d12->chain.renderTargets); i++) { DXGIGetSwapChainBuffer(d3d12->chain.handle, i, &d3d12->chain.renderTargets[i]); D3D12CreateRenderTargetView( @@ -270,7 +273,7 @@ static D3D12_CPU_DESCRIPTOR_HANDLE d3d12_descriptor_heap_slot_alloc(d3d12_descri int i; D3D12_CPU_DESCRIPTOR_HANDLE handle = { 0 }; - for (i = heap->start; i < heap->desc.NumDescriptors; i++) + for (i = heap->start; i < (int)heap->desc.NumDescriptors; i++) { if (!heap->map[i]) { @@ -372,18 +375,18 @@ bool d3d12_init_descriptors(d3d12_video_t* d3d12) cs_root_params[CS_ROOT_ID_TEXTURE_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; cs_root_params[CS_ROOT_ID_TEXTURE_T].DescriptorTable.NumDescriptorRanges = countof(srv_tbl); cs_root_params[CS_ROOT_ID_TEXTURE_T].DescriptorTable.pDescriptorRanges = srv_tbl; - cs_root_params[CS_ROOT_ID_TEXTURE_T].ShaderVisibility = 0; + cs_root_params[CS_ROOT_ID_TEXTURE_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; cs_root_params[CS_ROOT_ID_UAV_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; cs_root_params[CS_ROOT_ID_UAV_T].DescriptorTable.NumDescriptorRanges = countof(uav_tbl); cs_root_params[CS_ROOT_ID_UAV_T].DescriptorTable.pDescriptorRanges = uav_tbl; - cs_root_params[CS_ROOT_ID_UAV_T].ShaderVisibility = 0; + cs_root_params[CS_ROOT_ID_UAV_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; cs_root_params[CS_ROOT_ID_CONSTANTS].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.Num32BitValues = 3; cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.RegisterSpace = 0; cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.ShaderRegister = 0; - cs_root_params[CS_ROOT_ID_CONSTANTS].ShaderVisibility = 0; + cs_root_params[CS_ROOT_ID_CONSTANTS].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; static_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; static_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; @@ -733,6 +736,9 @@ void d3d12_update_texture( uint8_t* dst; D3D12_RANGE read_range = { 0, 0 }; + if (!texture || !texture->upload_buffer) + return; + D3D12Map(texture->upload_buffer, 0, &read_range, (void**)&dst); dxgi_copy( diff --git a/gfx/common/d3d8_common.c b/gfx/common/d3d8_common.c index 07fb3cf1a0..f05ab1a18a 100644 --- a/gfx/common/d3d8_common.c +++ b/gfx/common/d3d8_common.c @@ -13,6 +13,8 @@ * If not, see . */ +#define CINTERFACE + /* For Xbox we will just link statically * to Direct3D libraries instead. */ @@ -24,18 +26,11 @@ #include #endif -#include "../../configuration.h" #include "../../verbosity.h" -#include - #ifdef HAVE_D3DX -#ifdef _XBOX #include #include -#else -#include "../include/d3d8/d3dx8tex.h" -#endif #endif #include "d3d8_common.h" @@ -172,143 +167,32 @@ void d3d8_deinitialize_symbols(void) #endif } -bool d3d8_check_device_type(void *_d3d, - unsigned idx, - INT32 disp_format, - INT32 backbuffer_format, - bool windowed_mode) -{ - LPDIRECT3D8 d3d = (LPDIRECT3D8)_d3d; - if (!d3d) - return false; -#ifdef __cplusplus - if (FAILED(d3d->CheckDeviceType( - 0, - D3DDEVTYPE_HAL, - (D3DFORMAT)disp_format, - (D3DFORMAT)backbuffer_format, - windowed_mode))) - return false; -#else - if (FAILED(IDirect3D8_CheckDeviceType(d3d, - 0, - D3DDEVTYPE_HAL, - disp_format, - backbuffer_format, - windowed_mode))) - return false; -#endif - - return true; -} - -bool d3d8_get_adapter_display_mode( - void *_d3d, - unsigned idx, - void *display_mode) -{ - LPDIRECT3D8 d3d = (LPDIRECT3D8)_d3d; - if (!d3d) - return false; -#ifdef __cplusplus - if (FAILED(d3d->GetAdapterDisplayMode(idx, (D3DDISPLAYMODE*)display_mode))) - return false; -#else - if (FAILED(IDirect3D8_GetAdapterDisplayMode(d3d, idx, (D3DDISPLAYMODE*)display_mode))) - return false; -#endif - - return true; -} - -bool d3d8_swap(void *data, void *_dev) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; -#ifdef __cplusplus - if (dev->Present(NULL, NULL, NULL, NULL) != D3D_OK) - return false; -#else - if (IDirect3DDevice8_Present(dev, NULL, NULL, NULL, NULL) - == D3DERR_DEVICELOST) - return false; -#endif - return true; -} - -void d3d8_set_transform(void *_dev, - INT32 state, const void *_matrix) -{ - CONST D3DMATRIX *matrix = (CONST D3DMATRIX*)_matrix; - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; -#ifdef __cplusplus - dev->SetTransform((D3DTRANSFORMSTATETYPE)state, matrix); -#else - IDirect3DDevice8_SetTransform(dev, (D3DTRANSFORMSTATETYPE)state, matrix); -#endif -} - -bool d3d8_texture_get_level_desc(void *_tex, - unsigned idx, void *_ppsurface_level) -{ - LPDIRECT3DTEXTURE8 tex = (LPDIRECT3DTEXTURE8)_tex; -#ifdef __cplusplus - if (SUCCEEDED(tex->GetLevelDesc(idx, (D3DSURFACE_DESC*)_ppsurface_level))) - return true; -#else - if (SUCCEEDED(IDirect3DTexture8_GetLevelDesc(tex, idx, (D3DSURFACE_DESC*)_ppsurface_level))) - return true; -#endif - - return false; -} - -bool d3d8_texture_get_surface_level(void *_tex, - unsigned idx, void **_ppsurface_level) -{ - LPDIRECT3DTEXTURE8 tex = (LPDIRECT3DTEXTURE8)_tex; - if (!tex) - return false; -#ifdef __cplusplus - if (SUCCEEDED(tex->GetSurfaceLevel(idx, (IDirect3DSurface8**)_ppsurface_level))) - return true; -#else - if (SUCCEEDED(IDirect3DTexture8_GetSurfaceLevel(tex, idx, (IDirect3DSurface8**)_ppsurface_level))) - return true; -#endif - - return false; -} - #ifdef HAVE_D3DX static void *d3d8_texture_new_from_file( - void *dev, + LPDIRECT3DDEVICE8 dev, const char *path, unsigned width, unsigned height, unsigned miplevels, unsigned usage, D3DFORMAT format, - INT32 pool, unsigned filter, unsigned mipfilter, + D3DPOOL pool, unsigned filter, unsigned mipfilter, INT32 color_key, void *src_info_data, PALETTEENTRY *palette) { void *buf = NULL; - HRESULT hr = D3DCreateTextureFromFile((LPDIRECT3DDEVICE8)dev, + if (FAILED(D3DCreateTextureFromFile(dev, path, width, height, miplevels, usage, format, - (D3DPOOL)pool, filter, mipfilter, color_key, src_info_data, - palette, (struct IDirect3DTeture8**)&buf); - - if (FAILED(hr)) + pool, filter, mipfilter, color_key, src_info_data, + palette, (struct IDirect3DTeture8**)&buf))) return NULL; - return buf; } #endif -void *d3d8_texture_new(void *_dev, +void *d3d8_texture_new(LPDIRECT3DDEVICE8 dev, const char *path, unsigned width, unsigned height, unsigned miplevels, unsigned usage, INT32 format, INT32 pool, unsigned filter, unsigned mipfilter, INT32 color_key, void *src_info_data, PALETTEENTRY *palette, bool want_mipmap) { - HRESULT hr = S_OK; void *buf = NULL; if (path) @@ -324,528 +208,53 @@ void *d3d8_texture_new(void *_dev, #endif } - { - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; -#ifdef __cplusplus - hr = dev->CreateTexture( - width, height, miplevels, usage, - (D3DFORMAT)format, (D3DPOOL)pool, (IDirect3DTexture8**)&buf); -#else - hr = IDirect3DDevice8_CreateTexture(dev, - width, height, miplevels, usage, - (D3DFORMAT)format, (D3DPOOL)pool, (struct IDirect3DTexture8**)&buf); -#endif - } - - if (FAILED(hr)) + if (FAILED(IDirect3DDevice8_CreateTexture(dev, + width, height, miplevels, usage, + (D3DFORMAT)format, (D3DPOOL)pool, + (struct IDirect3DTexture8**)&buf))) return NULL; return buf; } -void d3d8_texture_free(void *_tex) -{ - LPDIRECT3DTEXTURE8 tex = (LPDIRECT3DTEXTURE8)_tex; - if (!tex) - return; -#ifdef __cplusplus - tex->Release(); -#else - IDirect3DTexture8_Release(tex); -#endif -} - -bool d3d8_surface_lock_rect(void *data, void *data2) -{ - LPDIRECT3DSURFACE8 surf = (LPDIRECT3DSURFACE8)data; - if (!surf) - return false; -#ifdef __cplusplus - if (FAILED(surf->LockRect((D3DLOCKED_RECT*)data2, NULL, D3DLOCK_READONLY))) - return false; -#else - if (FAILED(IDirect3DSurface8_LockRect(surf, (D3DLOCKED_RECT*)data2, NULL, D3DLOCK_READONLY))) - return false; -#endif - - return true; -} - -void d3d8_surface_unlock_rect(void *data) -{ - LPDIRECT3DSURFACE8 surf = (LPDIRECT3DSURFACE8)data; - if (!surf) - return; -#ifdef __cplusplus - surf->UnlockRect(); -#else - IDirect3DSurface8_UnlockRect(surf); -#endif -} - -void d3d8_surface_free(void *data) -{ - LPDIRECT3DSURFACE8 surf = (LPDIRECT3DSURFACE8)data; - if (!surf) - return; -#ifdef __cplusplus - surf->Release(); -#else - IDirect3DSurface8_Release(surf); -#endif -} - -void *d3d8_vertex_buffer_new(void *_dev, - unsigned length, unsigned usage, - unsigned fvf, INT32 pool, void *handle) -{ - void *buf = NULL; - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; -#ifdef __cplusplus - HRESULT hr = dev->CreateVertexBuffer( - length, usage, fvf, (D3DPOOL)pool, (IDirect3DVertexBuffer8**)&buf); -#else - HRESULT hr = IDirect3DDevice8_CreateVertexBuffer( - dev, length, usage, fvf, - (D3DPOOL)pool, - (struct IDirect3DVertexBuffer8**)&buf); -#endif - - if (FAILED(hr)) - return NULL; - - return buf; -} - -void d3d8_vertex_buffer_unlock(void *vertbuf_ptr) -{ - LPDIRECT3DVERTEXBUFFER8 vertbuf = (LPDIRECT3DVERTEXBUFFER8)vertbuf_ptr; - - if (!vertbuf) - return; -#ifdef __cplusplus - vertbuf->Unlock(); -#else - IDirect3DVertexBuffer8_Unlock(vertbuf); -#endif -} - -void *d3d8_vertex_buffer_lock(void *vertbuf_ptr) -{ - void *buf = NULL; - LPDIRECT3DVERTEXBUFFER8 vertbuf = (LPDIRECT3DVERTEXBUFFER8)vertbuf_ptr; - - if (!vertbuf) - return NULL; - -#ifdef __cplusplus - vertbuf->Lock(0, 0, (BYTE**)&buf, 0); -#else - IDirect3DVertexBuffer8_Lock(vertbuf, 0, 0, (BYTE**)&buf, 0); -#endif - - if (!buf) - return NULL; - - return buf; -} - -void d3d8_vertex_buffer_free(void *vertex_data, void *vertex_declaration) -{ - if (vertex_data) - { - LPDIRECT3DVERTEXBUFFER8 buf = (LPDIRECT3DVERTEXBUFFER8)vertex_data; -#ifdef __cplusplus - buf->Release(); -#else - IDirect3DVertexBuffer8_Release(buf); -#endif - buf = NULL; - } -} - -void d3d8_set_stream_source(void *_dev, unsigned stream_no, - void *stream_vertbuf_ptr, unsigned offset_bytes, - unsigned stride) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - LPDIRECT3DVERTEXBUFFER8 stream_vertbuf = (LPDIRECT3DVERTEXBUFFER8)stream_vertbuf_ptr; - if (!stream_vertbuf) - return; -#ifdef __cplusplus - dev->SetStreamSource(stream_no, stream_vertbuf, offset_bytes, stride); -#else - IDirect3DDevice8_SetStreamSource(dev, stream_no, stream_vertbuf, stride); -#endif -} - -static void d3d8_set_texture_stage_state(void *_dev, - unsigned sampler, unsigned type, unsigned value) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; -#ifdef __cplusplus - if (dev->SetTextureStageState(sampler, (D3DTEXTURESTAGESTATETYPE)type, value) != D3D_OK) - RARCH_ERR("SetTextureStageState call failed, sampler: %d, value: %d, type: %d\n", sampler, value, type); -#else - if (IDirect3DDevice8_SetTextureStageState(dev, sampler, (D3DTEXTURESTAGESTATETYPE)type, value) != D3D_OK) - RARCH_ERR("SetTextureStageState call failed, sampler: %d, value: %d, type: %d\n", sampler, value, type); -#endif -} - -void d3d8_set_sampler_address_u(void *_dev, - unsigned sampler, unsigned value) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - d3d8_set_texture_stage_state(dev, sampler, D3DTSS_ADDRESSU, value); -} - -void d3d8_set_sampler_address_v(void *_dev, - unsigned sampler, unsigned value) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - d3d8_set_texture_stage_state(dev, sampler, D3DTSS_ADDRESSV, value); -} - -void d3d8_set_sampler_minfilter(void *_dev, - unsigned sampler, unsigned value) -{ - d3d8_set_texture_stage_state(_dev, sampler, D3DTSS_MINFILTER, value); -} - -void d3d8_set_sampler_magfilter(void *_dev, - unsigned sampler, unsigned value) -{ - d3d8_set_texture_stage_state(_dev, sampler, D3DTSS_MAGFILTER, value); -} - -bool d3d8_begin_scene(void *_dev) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev) - return false; -#ifdef __cplusplus -#ifdef _XBOX - dev->BeginScene(); -#else - if (FAILED(dev->BeginScene())) - return false; -#endif -#else -#ifdef _XBOX - IDirect3DDevice8_BeginScene(dev); -#else - if (FAILED(IDirect3DDevice8_BeginScene(dev))) - return false; -#endif -#endif - - return true; -} - -void d3d8_end_scene(void *_dev) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev) - return; -#ifdef __cplusplus - dev->EndScene(); -#else - IDirect3DDevice8_EndScene(dev); -#endif -} - -static void d3d8_draw_primitive_internal(void *_dev, - D3DPRIMITIVETYPE type, unsigned start, unsigned count) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev) - return; -#ifdef __cplusplus - dev->DrawPrimitive(type, start, count); -#else - IDirect3DDevice8_DrawPrimitive(dev, type, start, count); -#endif -} - -void d3d8_draw_primitive(void *dev, - INT32 type, unsigned start, unsigned count) -{ - if (!d3d8_begin_scene(dev)) - return; - - d3d8_draw_primitive_internal(dev, (D3DPRIMITIVETYPE)type, start, count); - d3d8_end_scene(dev); -} - -void d3d8_clear(void *_dev, - unsigned count, const void *rects, unsigned flags, - INT32 color, float z, unsigned stencil) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev) - return; -#ifdef __cplusplus - dev->Clear(count, (const D3DRECT*)rects, flags, color, z, stencil); -#else - IDirect3DDevice8_Clear(dev, count, (const D3DRECT*)rects, flags, - color, z, stencil); -#endif -} - -bool d3d8_device_get_render_target(void *_dev, - unsigned idx, void **data) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev) - return false; -#ifdef __cplusplus - if (SUCCEEDED(dev->GetRenderTarget( - (LPDIRECT3DSURFACE8*)data))) - return true; -#else - if (SUCCEEDED(IDirect3DDevice8_GetRenderTarget(dev, - (LPDIRECT3DSURFACE8*)data))) - return true; -#endif - - return false; -} - - -bool d3d8_lock_rectangle(void *_tex, - unsigned level, void *_lr, RECT *rect, - unsigned rectangle_height, unsigned flags) -{ - D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; - LPDIRECT3DTEXTURE8 tex = (LPDIRECT3DTEXTURE8)_tex; - if (!tex) - return false; -#ifdef __cplusplus - if (FAILED(tex->LockRect(level, lr, rect, flags))) - return false; -#else - if (IDirect3DTexture8_LockRect(tex, level, lr, rect, flags) != D3D_OK) - return false; -#endif - - return true; -} - -void d3d8_unlock_rectangle(void *_tex) -{ - LPDIRECT3DTEXTURE8 tex = (LPDIRECT3DTEXTURE8)_tex; - if (!tex) - return; -#ifdef __cplusplus - tex->UnlockRect(0); -#else - IDirect3DTexture8_UnlockRect(tex, 0); -#endif -} - -void d3d8_lock_rectangle_clear(void *tex, - unsigned level, void *_lr, RECT *rect, - unsigned rectangle_height, unsigned flags) -{ - D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; -#if defined(_XBOX) - level = 0; -#endif - memset(lr->pBits, level, rectangle_height * lr->Pitch); - d3d8_unlock_rectangle(tex); -} - -void d3d8_set_viewports(void *_dev, void *_vp) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - D3DVIEWPORT8 *vp = (D3DVIEWPORT8*)_vp; - if (!dev) - return; -#ifdef __cplusplus - dev->SetViewport(vp); -#else - IDirect3DDevice8_SetViewport(dev, vp); -#endif -} - -void d3d8_set_texture(void *_dev, unsigned sampler, - void *tex_data) -{ - LPDIRECT3DTEXTURE8 tex = (LPDIRECT3DTEXTURE8)tex_data; - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev || !tex) - return; -#ifdef __cplusplus - dev->SetTexture(sampler, tex); -#else - IDirect3DDevice8_SetTexture(dev, sampler, - (IDirect3DBaseTexture8*)tex); -#endif -} - -bool d3d8_set_vertex_shader(void *_dev, unsigned index, - void *data) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; -#ifdef __cplusplus - LPDIRECT3DVERTEXSHADER8 shader = (LPDIRECT3DVERTEXSHADER8)data; - - if (dev->SetVertexShader(shader) != D3D_OK) - return false; -#else - if (IDirect3DDevice8_SetVertexShader(dev, index) != D3D_OK) - return false; -#endif - - return true; -} - -void d3d8_texture_blit(unsigned pixel_size, - void *tex, - void *_lr, const void *frame, - unsigned width, unsigned height, unsigned pitch) -{ - unsigned y; - D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; - - for (y = 0; y < height; y++) - { - const uint8_t *in = (const uint8_t*)frame + y * pitch; - uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; - memcpy(out, in, width * pixel_size); - } -} - -bool d3d8_get_render_state(void *data, INT32 state, DWORD *value) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)data; -#ifdef __cplusplus - if (dev && dev->GetRenderState((D3DRENDERSTATETYPE)state, value) == D3D_OK) - return true; -#else - if (dev && IDirect3DDevice8_GetRenderState(dev, (D3DRENDERSTATETYPE)state, value) == D3D_OK) - return true; -#endif - - return false; -} - -void d3d8_set_render_state(void *data, INT32 state, DWORD value) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)data; - if (!dev) - return; -#ifdef __cplusplus - dev->SetRenderState((D3DRENDERSTATETYPE)state, value); -#else - IDirect3DDevice8_SetRenderState(dev, (D3DRENDERSTATETYPE)state, value); -#endif -} - -void d3d8_enable_blend_func(void *data) -{ - if (!data) - return; - - d3d8_set_render_state(data, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - d3d8_set_render_state(data, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - d3d8_set_render_state(data, D3DRS_ALPHABLENDENABLE, true); -} - -void d3d8_device_set_render_target(void *_dev, unsigned idx, - void *data) -{ - LPDIRECT3DSURFACE8 surf = (LPDIRECT3DSURFACE8)data; - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev) - return; -#ifdef __cplusplus - dev->SetRenderTarget(idx, surf); -#else - IDirect3DDevice8_SetRenderTarget(dev, surf, NULL); -#endif -} - -void d3d8_enable_alpha_blend_texture_func(void *data) -{ - /* Also blend the texture with the set alpha value. */ - d3d8_set_texture_stage_state(data, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3d8_set_texture_stage_state(data, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); - d3d8_set_texture_stage_state(data, 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); -} - void d3d8_frame_postprocess(void *data) { #if defined(_XBOX) global_t *global = global_get_ptr(); -#ifdef __cplusplus - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)data; - if (!dev) - return; - - dev->SetFlickerFilter(global->console.screen.flicker_filter_index); - dev->SetSoftDisplayFilter(global->console.softfilter_enable); -#else D3DDevice_SetFlickerFilter(global->console.screen.flicker_filter_index); D3DDevice_SetSoftDisplayFilter(global->console.softfilter_enable); #endif -#endif } -void d3d8_disable_blend_func(void *data) -{ - d3d8_set_render_state(data, D3DRS_ALPHABLENDENABLE, false); -} - -static bool d3d8_reset_internal(void *data, +static bool d3d8_reset_internal(LPDIRECT3DDEVICE8 dev, D3DPRESENT_PARAMETERS *d3dpp ) { - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)data; - if (!dev) - return false; -#ifdef __cplusplus - if ((dev->Reset(d3dpp) == D3D_OK)) + if (dev && + IDirect3DDevice8_Reset(dev, d3dpp) == D3D_OK) return true; -#else - if (IDirect3DDevice8_Reset(dev, d3dpp) == D3D_OK) - return true; -#endif - return false; } -static HRESULT d3d8_test_cooperative_level(void *data) +static HRESULT d3d8_test_cooperative_level(LPDIRECT3DDEVICE8 dev) { -#ifdef _XBOX +#ifndef _XBOX + if (dev) + return IDirect3DDevice8_TestCooperativeLevel(dev); +#endif return E_FAIL; -#else - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)data; - if (!dev) - return E_FAIL; - -#ifdef __cplusplus - return dev->TestCooperativeLevel(); -#else - return IDirect3DDevice8_TestCooperativeLevel(dev); -#endif -#endif } static bool d3d8_create_device_internal( - void *data, + LPDIRECT3DDEVICE8 dev, D3DPRESENT_PARAMETERS *d3dpp, - void *_d3d, + LPDIRECT3D8 d3d, HWND focus_window, unsigned cur_mon_id, DWORD behavior_flags) { - LPDIRECT3D8 d3d = (LPDIRECT3D8)_d3d; - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)data; - if (!dev) - return false; -#ifdef __cplusplus - if (SUCCEEDED(d3d->CreateDevice( + if (dev && + SUCCEEDED(IDirect3D8_CreateDevice(d3d, cur_mon_id, D3DDEVTYPE_HAL, focus_window, @@ -853,23 +262,13 @@ static bool d3d8_create_device_internal( d3dpp, (IDirect3DDevice8**)dev))) return true; -#else - if (SUCCEEDED(IDirect3D8_CreateDevice(d3d, - cur_mon_id, - D3DDEVTYPE_HAL, - focus_window, - behavior_flags, - d3dpp, - (IDirect3DDevice8**)dev))) - return true; -#endif return false; } bool d3d8_create_device(void *dev, void *d3dpp, - void *d3d, + LPDIRECT3D8 d3d, HWND focus_window, unsigned cur_mon_id) { @@ -922,165 +321,47 @@ bool d3d8_reset(void *dev, void *d3dpp) return false; } -bool d3d8_device_get_backbuffer(void *_dev, - unsigned idx, unsigned swapchain_idx, - unsigned backbuffer_type, void **data) -{ - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (!dev) - return false; -#ifdef __cplusplus - if (SUCCEEDED(dev->GetBackBuffer(idx, - (D3DBACKBUFFER_TYPE)backbuffer_type, - (LPDIRECT3DSURFACE8*)data))) - return true; -#else - if (SUCCEEDED(IDirect3DDevice8_GetBackBuffer(dev, idx, - (D3DBACKBUFFER_TYPE)backbuffer_type, - (LPDIRECT3DSURFACE8*)data))) - return true; -#endif - - return false; -} - - -void d3d8_device_free(void *_dev, void *_pd3d) -{ - LPDIRECT3D8 pd3d = (LPDIRECT3D8)_pd3d; - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; - if (dev) - { -#ifdef __cplusplus - dev->Release(); -#else - IDirect3DDevice8_Release(dev); -#endif - } - - if (pd3d) - { -#if defined(__cplusplus) - pd3d->Release(); -#else - IDirect3D8_Release(pd3d); -#endif - } -} - -INT32 d3d8_translate_filter(unsigned type) -{ - switch (type) - { - case RARCH_FILTER_UNSPEC: - { - settings_t *settings = config_get_ptr(); - if (!settings->bools.video_smooth) - break; - } - /* fall-through */ - case RARCH_FILTER_LINEAR: - return D3DTEXF_LINEAR; - case RARCH_FILTER_NEAREST: - break; - } - - return D3DTEXF_POINT; -} - -bool d3d8x_create_font_indirect(void *_dev, +bool d3d8x_create_font_indirect(LPDIRECT3DDEVICE8 dev, void *desc, void **font_data) { #ifdef HAVE_D3DX - LPDIRECT3DDEVICE8 dev = (LPDIRECT3DDEVICE8)_dev; if (SUCCEEDED(D3DCreateFontIndirect( dev, (CONST LOGFONT*)desc, (struct ID3DXFont**)font_data))) return true; #endif - return false; } -void d3d8x_font_draw_text(void *data, void *sprite_data, void *string_data, - unsigned count, void *rect_data, unsigned format, unsigned color) +void d3d8x_font_draw_text(void *data, + void *sprite_data, void *string_data, + unsigned count, void *rect_data, + unsigned format, unsigned color) { #ifdef HAVE_D3DX -#if !defined(__cplusplus) || defined(CINTERFACE) ID3DXFont *font = (ID3DXFont*)data; - if (!font) - return; - font->lpVtbl->DrawText(font, (LPD3DXSPRITE)sprite_data, - (LPCTSTR)string_data, count, (LPRECT)rect_data, - (DWORD)format, (D3DCOLOR)color); -#else - LPD3DXFONT font = (LPD3DXFONT)data; - if (!font) - return; - font->DrawText((LPD3DXSPRITE)sprite_data, - (LPCTSTR)string_data, count, (LPRECT)rect_data, - (DWORD)format, (D3DCOLOR)color); -#endif + if (font) + font->lpVtbl->DrawText(font, (LPD3DXSPRITE)sprite_data, + (LPCTSTR)string_data, count, (LPRECT)rect_data, + (DWORD)format, (D3DCOLOR)color); #endif } void d3d8x_font_release(void *data) { #ifdef HAVE_D3DX -#if !defined(__cplusplus) || defined(CINTERFACE) ID3DXFont *font = (ID3DXFont*)data; - if (!font) - return; - font->lpVtbl->Release(font); -#else - LPD3DXFONT font = (LPD3DXFONT)data; - if (!font) - return; - font->Release(); -#endif + if (font) + font->lpVtbl->Release(font); #endif } void d3d8x_font_get_text_metrics(void *data, void *metrics) { #ifdef HAVE_D3DX -#if !defined(__cplusplus) || defined(CINTERFACE) ID3DXFont *font = (ID3DXFont*)data; - if (!font) - return; - font->lpVtbl->GetTextMetrics(font, (TEXTMETRICA*)metrics); -#else - LPD3DXFONT font = (LPD3DXFONT)data; - if (!font) - return; - font->GetTextMetricsA((TEXTMETRICA*)metrics); -#endif + if (font) + font->lpVtbl->GetTextMetrics(font, (TEXTMETRICA*)metrics); #endif } -INT32 d3d8_get_rgb565_format(void) -{ -#ifdef _XBOX - return D3DFMT_LIN_R5G6B5; -#else - return D3DFMT_R5G6B5; -#endif -} - -INT32 d3d8_get_argb8888_format(void) -{ -#ifdef _XBOX - return D3DFMT_LIN_A8R8G8B8; -#else - return D3DFMT_A8R8G8B8; -#endif -} - -INT32 d3d8_get_xrgb8888_format(void) -{ -#ifdef _XBOX - return D3DFMT_LIN_X8R8G8B8; -#else - return D3DFMT_X8R8G8B8; -#endif -} diff --git a/gfx/common/d3d8_common.h b/gfx/common/d3d8_common.h index 41260b7340..8bb9f8580f 100644 --- a/gfx/common/d3d8_common.h +++ b/gfx/common/d3d8_common.h @@ -18,166 +18,399 @@ #include #include +#include + +#include #include "../video_driver.h" +#include "../../verbosity.h" RETRO_BEGIN_DECLS -bool d3d8_swap(void *data, void *dev); +static INLINE bool d3d8_swap(void *data, LPDIRECT3DDEVICE8 dev) +{ + if (IDirect3DDevice8_Present(dev, NULL, NULL, NULL, NULL) + == D3DERR_DEVICELOST) + return false; + return true; +} -void *d3d8_vertex_buffer_new(void *dev, - unsigned length, unsigned usage, unsigned fvf, - INT32 pool, void *handle); +static INLINE void *d3d8_vertex_buffer_new( + LPDIRECT3DDEVICE8 dev, + unsigned length, unsigned usage, + unsigned fvf, D3DPOOL pool, void *handle) +{ + void *buf = NULL; + if (FAILED(IDirect3DDevice8_CreateVertexBuffer( + dev, length, usage, fvf, + pool, + (struct IDirect3DVertexBuffer8**)&buf))) + return NULL; + return buf; +} -void *d3d8_vertex_buffer_lock(void *data); -void d3d8_vertex_buffer_unlock(void *data); +static INLINE void * +d3d8_vertex_buffer_lock(LPDIRECT3DVERTEXBUFFER8 vertbuf) +{ + void *buf = NULL; -void d3d8_vertex_buffer_free(void *vertex_data, void *vertex_declaration); + if (!vertbuf) + return NULL; -bool d3d8_texture_get_level_desc(void *tex, - unsigned idx, void *_ppsurface_level); + IDirect3DVertexBuffer8_Lock(vertbuf, 0, 0, (BYTE**)&buf, 0); -bool d3d8_texture_get_surface_level(void *tex, - unsigned idx, void **_ppsurface_level); + if (!buf) + return NULL; -void *d3d8_texture_new(void *dev, + return buf; +} + +static INLINE void d3d8_vertex_buffer_unlock( + LPDIRECT3DVERTEXBUFFER8 vertbuf) +{ + if (vertbuf) + IDirect3DVertexBuffer8_Unlock(vertbuf); +} + +static INLINE void d3d8_vertex_buffer_free( + LPDIRECT3DVERTEXBUFFER8 buf, + void *vertex_declaration) +{ + if (buf) + { + IDirect3DVertexBuffer8_Release(buf); + buf = NULL; + } +} + +static INLINE bool d3d8_texture_get_level_desc( + LPDIRECT3DTEXTURE8 tex, + unsigned idx, void *_ppsurface_level) +{ + if (SUCCEEDED(IDirect3DTexture8_GetLevelDesc( + tex, idx, (D3DSURFACE_DESC*)_ppsurface_level))) + return true; + return false; +} + +static INLINE bool d3d8_texture_get_surface_level( + LPDIRECT3DTEXTURE8 tex, + unsigned idx, void **_ppsurface_level) +{ + if (tex && + SUCCEEDED( + IDirect3DTexture8_GetSurfaceLevel( + tex, idx, (IDirect3DSurface8**)_ppsurface_level))) + return true; + return false; +} + +void *d3d8_texture_new(LPDIRECT3DDEVICE8 dev, const char *path, unsigned width, unsigned height, unsigned miplevels, unsigned usage, INT32 format, INT32 pool, unsigned filter, unsigned mipfilter, - INT32 color_key, void *src_info, + INT32 color_key, void *src_info_data, PALETTEENTRY *palette, bool want_mipmap); -void d3d8_set_stream_source(void *dev, unsigned stream_no, - void *stream_vertbuf, unsigned offset_bytes, - unsigned stride); +static INLINE void d3d8_set_stream_source(LPDIRECT3DDEVICE8 dev, + unsigned stream_no, + LPDIRECT3DVERTEXBUFFER8 stream_vertbuf, + unsigned offset_bytes, + unsigned stride) +{ + if (stream_vertbuf) + IDirect3DDevice8_SetStreamSource(dev, + stream_no, stream_vertbuf, stride); +} -void d3d8_texture_free(void *tex); +static INLINE void d3d8_texture_free(LPDIRECT3DTEXTURE8 tex) +{ + if (tex) + IDirect3DTexture8_Release(tex); +} -void d3d8_set_transform(void *dev, - INT32 state, const void *_matrix); +static INLINE void d3d8_set_transform(LPDIRECT3DDEVICE8 dev, + D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) +{ + IDirect3DDevice8_SetTransform(dev, state, matrix); +} -void d3d8_set_sampler_address_u(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d8_set_texture_stage_state(LPDIRECT3DDEVICE8 dev, + unsigned sampler, D3DTEXTURESTAGESTATETYPE type, unsigned value) +{ + if (IDirect3DDevice8_SetTextureStageState(dev, sampler, + (D3DTEXTURESTAGESTATETYPE)type, value) != D3D_OK) + RARCH_ERR("SetTextureStageState call failed, sampler: %d, value: %d, type: %d\n", sampler, value, type); +} -void d3d8_set_sampler_address_v(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d8_set_sampler_address_u(LPDIRECT3DDEVICE8 dev, + unsigned sampler, unsigned value) +{ + d3d8_set_texture_stage_state(dev, sampler, D3DTSS_ADDRESSU, value); +} -void d3d8_set_sampler_minfilter(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d8_set_sampler_address_v(LPDIRECT3DDEVICE8 dev, + unsigned sampler, unsigned value) +{ + d3d8_set_texture_stage_state(dev, sampler, D3DTSS_ADDRESSV, value); +} -void d3d8_set_sampler_magfilter(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d8_set_sampler_minfilter(void *_dev, + unsigned sampler, unsigned value) +{ + d3d8_set_texture_stage_state(_dev, sampler, D3DTSS_MINFILTER, value); +} + +static INLINE void d3d8_set_sampler_magfilter(void *_dev, + unsigned sampler, unsigned value) +{ + d3d8_set_texture_stage_state(_dev, sampler, D3DTSS_MAGFILTER, value); +} void d3d8_set_sampler_mipfilter(void *dev, unsigned sampler, unsigned value); -bool d3d8_begin_scene(void *dev); +static INLINE bool d3d8_begin_scene(LPDIRECT3DDEVICE8 dev) +{ + if (!dev) + return false; +#ifdef _XBOX + IDirect3DDevice8_BeginScene(dev); +#else + if (FAILED(IDirect3DDevice8_BeginScene(dev))) + return false; +#endif -void d3d8_end_scene(void *dev); + return true; +} -void d3d8_draw_primitive(void *dev, - INT32 type, unsigned start, unsigned count); +static INLINE void d3d8_end_scene(LPDIRECT3DDEVICE8 dev) +{ + if (dev) + IDirect3DDevice8_EndScene(dev); +} -void d3d8_clear(void *dev, +static INLINE void d3d8_draw_primitive(LPDIRECT3DDEVICE8 dev, + D3DPRIMITIVETYPE type, unsigned start, unsigned count) +{ + if (!d3d8_begin_scene(dev)) + return; + + IDirect3DDevice8_DrawPrimitive(dev, type, start, count); + d3d8_end_scene(dev); +} + +static INLINE void d3d8_clear(LPDIRECT3DDEVICE8 dev, unsigned count, const void *rects, unsigned flags, - INT32 color, float z, unsigned stencil); + INT32 color, float z, unsigned stencil) +{ + if (dev) + IDirect3DDevice8_Clear(dev, count, (const D3DRECT*)rects, flags, + color, z, stencil); +} -bool d3d8_lock_rectangle(void *tex, - unsigned level, void *lock_rect, RECT *rect, - unsigned rectangle_height, unsigned flags); +static INLINE bool d3d8_lock_rectangle( + LPDIRECT3DTEXTURE8 tex, + unsigned level, D3DLOCKED_RECT *lr, RECT *rect, + unsigned rectangle_height, unsigned flags) +{ + if (tex && + IDirect3DTexture8_LockRect(tex, + level, lr, rect, flags) == D3D_OK) + return true; + return false; +} -void d3d8_lock_rectangle_clear(void *tex, - unsigned level, void *lock_rect, RECT *rect, - unsigned rectangle_height, unsigned flags); +static INLINE void d3d8_unlock_rectangle(LPDIRECT3DTEXTURE8 tex) +{ + if (tex) + IDirect3DTexture8_UnlockRect(tex, 0); +} -void d3d8_unlock_rectangle(void *tex); - -void d3d8_set_texture(void *dev, unsigned sampler, - void *tex_data); - -bool d3d8_create_vertex_shader(void *dev, - const DWORD *a, void **b); - -bool d3d8_create_pixel_shader(void *dev, - const DWORD *a, void **b); - -void d3d8_free_vertex_shader(void *dev, void *data); - -bool d3d8_set_vertex_shader(void *dev, unsigned index, - void *data); - -void d3d8_texture_blit(unsigned pixel_size, +static INLINE void d3d8_lock_rectangle_clear( void *tex, - void *lr, const void *frame, - unsigned width, unsigned height, unsigned pitch); + unsigned level, void *_lr, RECT *rect, + unsigned rectangle_height, unsigned flags) +{ + D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; +#if defined(_XBOX) + level = 0; +#endif + memset(lr->pBits, level, rectangle_height * lr->Pitch); + d3d8_unlock_rectangle(tex); +} -bool d3d8_vertex_declaration_new(void *dev, - const void *vertex_data, void **decl_data); +static INLINE void d3d8_set_texture( + LPDIRECT3DDEVICE8 dev, unsigned sampler, + LPDIRECT3DTEXTURE8 tex) +{ + if (dev && tex) + IDirect3DDevice8_SetTexture(dev, sampler, + (IDirect3DBaseTexture8*)tex); +} -void d3d8_vertex_declaration_free(void *data); +static INLINE bool d3d8_set_vertex_shader( + LPDIRECT3DDEVICE8 dev, + unsigned index, + void *data) +{ + if (IDirect3DDevice8_SetVertexShader(dev, index) != D3D_OK) + return false; + return true; +} -void d3d8_set_viewports(void *dev, void *vp); +static INLINE void d3d8_texture_blit( + unsigned pixel_size, + void *tex, + D3DLOCKED_RECT *lr, + const void *frame, + unsigned width, unsigned height, unsigned pitch) +{ + unsigned y; -void d3d8_enable_blend_func(void *data); + for (y = 0; y < height; y++) + { + const uint8_t *in = (const uint8_t*)frame + y * pitch; + uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; + memcpy(out, in, width * pixel_size); + } +} -void d3d8_disable_blend_func(void *data); +static INLINE void d3d8_set_viewports( + LPDIRECT3DDEVICE8 dev, + void *vp) +{ + if (dev) + IDirect3DDevice8_SetViewport(dev, (D3DVIEWPORT8*)vp); +} -void d3d8_set_vertex_declaration(void *data, void *vertex_data); +static INLINE void d3d8_set_render_state( + LPDIRECT3DDEVICE8 dev, + D3DRENDERSTATETYPE state, + DWORD value) +{ + if (dev) + IDirect3DDevice8_SetRenderState(dev, state, value); +} -void d3d8_enable_alpha_blend_texture_func(void *data); +static INLINE void d3d8_enable_blend_func(void *data) +{ + if (!data) + return; + + d3d8_set_render_state(data, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + d3d8_set_render_state(data, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + d3d8_set_render_state(data, D3DRS_ALPHABLENDENABLE, true); +} + +static INLINE void d3d8_disable_blend_func(void *data) +{ + d3d8_set_render_state(data, D3DRS_ALPHABLENDENABLE, false); +} + +static INLINE void d3d8_enable_alpha_blend_texture_func(void *data) +{ + /* Also blend the texture with the set alpha value. */ + d3d8_set_texture_stage_state(data, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + d3d8_set_texture_stage_state(data, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + d3d8_set_texture_stage_state(data, 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); +} void d3d8_frame_postprocess(void *data); -void d3d8_surface_free(void *data); +static INLINE void d3d8_surface_free(LPDIRECT3DSURFACE8 surf) +{ + if (surf) + IDirect3DSurface8_Release(surf); +} -bool d3d8_device_get_render_target_data(void *dev, - void *_src, void *_dst); +static INLINE bool d3d8_device_get_render_target( + LPDIRECT3DDEVICE8 dev, + unsigned idx, void **data) +{ + if (dev && + SUCCEEDED(IDirect3DDevice8_GetRenderTarget(dev, + (LPDIRECT3DSURFACE8*)data))) + return true; + return false; +} -bool d3d8_device_get_render_target(void *dev, - unsigned idx, void **data); +static INLINE void d3d8_device_set_render_target( + LPDIRECT3DDEVICE8 dev, unsigned idx, + LPDIRECT3DSURFACE8 surf) +{ + if (dev) + IDirect3DDevice8_SetRenderTarget(dev, surf, NULL); +} -void d3d8_device_set_render_target(void *dev, unsigned idx, - void *data); +static INLINE bool d3d8_get_render_state(LPDIRECT3DDEVICE8 dev, + D3DRENDERSTATETYPE state, DWORD *value) +{ + if (dev && + IDirect3DDevice8_GetRenderState(dev, state, value) == D3D_OK) + return true; + return false; +} -bool d3d8_get_render_state(void *data, - INT32 state, DWORD *value); +static INLINE bool d3d8_surface_lock_rect( + LPDIRECT3DSURFACE8 surf, void *data2) +{ + if (surf && + SUCCEEDED( + IDirect3DSurface8_LockRect( + surf, (D3DLOCKED_RECT*)data2, + NULL, D3DLOCK_READONLY))) + return true; + return false; +} -void d3d8_set_render_state(void *data, - INT32 state, DWORD value); +static INLINE void d3d8_surface_unlock_rect(LPDIRECT3DSURFACE8 surf) +{ + if (surf) + IDirect3DSurface8_UnlockRect(surf); +} -void d3d8_device_set_render_target(void *dev, unsigned idx, - void *data); - -bool d3d8_device_create_offscreen_plain_surface( - void *dev, - unsigned width, - unsigned height, - unsigned format, - unsigned pool, - void **surf_data, - void *data); - -bool d3d8_surface_lock_rect(void *data, void *data2); - -void d3d8_surface_unlock_rect(void *data); - -bool d3d8_get_adapter_display_mode(void *d3d, +static INLINE bool d3d8_get_adapter_display_mode( + LPDIRECT3D8 d3d, unsigned idx, - void *display_mode); + void *display_mode) +{ + if (d3d && + SUCCEEDED(IDirect3D8_GetAdapterDisplayMode( + d3d, idx, (D3DDISPLAYMODE*)display_mode))) + return true; + return false; +} bool d3d8_create_device(void *dev, void *d3dpp, - void *d3d, + LPDIRECT3D8 d3d, HWND focus_window, unsigned cur_mon_id); bool d3d8_reset(void *dev, void *d3dpp); -bool d3d8_device_get_backbuffer(void *dev, +static INLINE bool d3d8_device_get_backbuffer( + LPDIRECT3DDEVICE8 dev, unsigned idx, unsigned swapchain_idx, - unsigned backbuffer_type, void **data); + unsigned backbuffer_type, void **data) +{ + if (dev && + SUCCEEDED(IDirect3DDevice8_GetBackBuffer(dev, idx, + (D3DBACKBUFFER_TYPE)backbuffer_type, + (LPDIRECT3DSURFACE8*)data))) + return true; + return false; +} -void d3d8_device_free(void *dev, void *pd3d); +static INLINE void d3d8_device_free( + LPDIRECT3DDEVICE8 dev, LPDIRECT3D8 pd3d) +{ + if (dev) + IDirect3DDevice8_Release(dev); + if (pd3d) + IDirect3D8_Release(pd3d); +} void *d3d8_create(void); @@ -185,13 +418,25 @@ bool d3d8_initialize_symbols(enum gfx_ctx_api api); void d3d8_deinitialize_symbols(void); -bool d3d8_check_device_type(void *d3d, +static INLINE bool d3d8_check_device_type( + LPDIRECT3D8 d3d, unsigned idx, INT32 disp_format, INT32 backbuffer_format, - bool windowed_mode); + bool windowed_mode) +{ + if (d3d && + SUCCEEDED(IDirect3D8_CheckDeviceType(d3d, + 0, + D3DDEVTYPE_HAL, + disp_format, + backbuffer_format, + windowed_mode))) + return true; + return false; +} -bool d3d8x_create_font_indirect(void *dev, +bool d3d8x_create_font_indirect(LPDIRECT3DDEVICE8 dev, void *desc, void **font_data); void d3d8x_font_draw_text(void *data, void *sprite_data, void *string_data, @@ -201,11 +446,32 @@ void d3d8x_font_get_text_metrics(void *data, void *metrics); void d3d8x_font_release(void *data); -INT32 d3d8_translate_filter(unsigned type); +static INLINE INT32 d3d8_get_rgb565_format(void) +{ +#ifdef _XBOX + return D3DFMT_LIN_R5G6B5; +#else + return D3DFMT_R5G6B5; +#endif +} -INT32 d3d8_get_rgb565_format(void); -INT32 d3d8_get_argb8888_format(void); -INT32 d3d8_get_xrgb8888_format(void); +static INLINE INT32 d3d8_get_argb8888_format(void) +{ +#ifdef _XBOX + return D3DFMT_LIN_A8R8G8B8; +#else + return D3DFMT_A8R8G8B8; +#endif +} + +static INLINE INT32 d3d8_get_xrgb8888_format(void) +{ +#ifdef _XBOX + return D3DFMT_LIN_X8R8G8B8; +#else + return D3DFMT_X8R8G8B8; +#endif +} RETRO_END_DECLS diff --git a/gfx/common/d3d9_common.c b/gfx/common/d3d9_common.c index a6251e4b53..d71a4ceb18 100644 --- a/gfx/common/d3d9_common.c +++ b/gfx/common/d3d9_common.c @@ -13,6 +13,8 @@ * If not, see . */ +#define CINTERFACE + /* For Xbox we will just link statically * to Direct3D libraries instead. */ @@ -24,23 +26,15 @@ #include #endif -#include "../../configuration.h" #include "../../verbosity.h" -#include +#include "d3d9_common.h" #ifdef HAVE_D3DX -#ifdef _XBOX #include #include -#else -#include "../include/d3d9/d3dx9tex.h" #endif -#endif - -#include "d3d9_common.h" - #ifdef _XBOX #include #endif @@ -240,131 +234,6 @@ void d3d9_deinitialize_symbols(void) #endif } -bool d3d9_check_device_type(void *_d3d, - unsigned idx, - INT32 disp_format, - INT32 backbuffer_format, - bool windowed_mode) -{ - LPDIRECT3D9 d3d = (LPDIRECT3D9)_d3d; - if (!d3d) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (FAILED(d3d->CheckDeviceType( - 0, - D3DDEVTYPE_HAL, - (D3DFORMAT)disp_format, - (D3DFORMAT)backbuffer_format, - windowed_mode))) - return false; -#else - if (FAILED(IDirect3D9_CheckDeviceType(d3d, - 0, - D3DDEVTYPE_HAL, - (D3DFORMAT)disp_format, - (D3DFORMAT)backbuffer_format, - windowed_mode))) - return false; -#endif - - return true; -} - -bool d3d9_get_adapter_display_mode( - void *_d3d, - unsigned idx, - void *display_mode) -{ - LPDIRECT3D9 d3d = (LPDIRECT3D9)_d3d; - if (!d3d) - return false; -#ifdef _XBOX - return true; -#elif defined(__cplusplus) && !defined(CINTERFACE) - if (FAILED(d3d->GetAdapterDisplayMode(idx, (D3DDISPLAYMODE*)display_mode))) - return false; -#else - if (FAILED(IDirect3D9_GetAdapterDisplayMode(d3d, idx, (D3DDISPLAYMODE*)display_mode))) - return false; -#endif - - return true; -} - -bool d3d9_swap(void *data, void *_dev) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#if defined(__cplusplus) && !defined(CINTERFACE) -#ifdef _XBOX - dev->Present(NULL, NULL, NULL, NULL); -#else - if (dev->Present(NULL, NULL, NULL, NULL) != D3D_OK) - return false; -#endif -#else -#ifdef _XBOX - IDirect3DDevice9_Present(dev, NULL, NULL, NULL, NULL); -#else - if (IDirect3DDevice9_Present(dev, NULL, NULL, NULL, NULL) - == D3DERR_DEVICELOST) - return false; -#endif -#endif - return true; -} - -void d3d9_set_transform(void *_dev, - INT32 state, const void *_matrix) -{ -#ifndef _XBOX - CONST D3DMATRIX *matrix = (CONST D3DMATRIX*)_matrix; - /* XBox 360 D3D9 does not support fixed-function pipeline. */ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetTransform((D3DTRANSFORMSTATETYPE)state, matrix); -#else - IDirect3DDevice9_SetTransform(dev, (D3DTRANSFORMSTATETYPE)state, matrix); -#endif -#endif -} - -bool d3d9_texture_get_level_desc(void *_tex, - unsigned idx, void *_ppsurface_level) -{ - LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)_tex; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(tex->GetLevelDesc(idx, (D3DSURFACE_DESC*)_ppsurface_level))) - return true; -#else -#if defined(_XBOX) - D3DTexture_GetLevelDesc(tex, idx, (D3DSURFACE_DESC*)_ppsurface_level); - return true; -#else - if (SUCCEEDED(IDirect3DTexture9_GetLevelDesc(tex, idx, (D3DSURFACE_DESC*)_ppsurface_level))) - return true; -#endif -#endif - - return false; -} - -bool d3d9_texture_get_surface_level(void *_tex, - unsigned idx, void **_ppsurface_level) -{ - LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)_tex; - if (!tex) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(tex->GetSurfaceLevel(idx, (IDirect3DSurface9**)_ppsurface_level))) - return true; -#else - if (SUCCEEDED(IDirect3DTexture9_GetSurfaceLevel(tex, idx, (IDirect3DSurface9**)_ppsurface_level))) - return true; -#endif - - return false; -} - #ifdef HAVE_D3DX static void *d3d9_texture_new_from_file( void *dev, @@ -375,15 +244,12 @@ static void *d3d9_texture_new_from_file( PALETTEENTRY *palette) { void *buf = NULL; - HRESULT hr = D3D9CreateTextureFromFile((LPDIRECT3DDEVICE9)dev, - path, width, height, miplevels, usage, format, - (D3DPOOL)pool, filter, mipfilter, color_key, - (D3DXIMAGE_INFO*)src_info_data, - palette, (struct IDirect3DTexture9**)&buf); - - if (FAILED(hr)) + if (FAILED(D3D9CreateTextureFromFile((LPDIRECT3DDEVICE9)dev, + path, width, height, miplevels, usage, format, + (D3DPOOL)pool, filter, mipfilter, color_key, + (D3DXIMAGE_INFO*)src_info_data, + palette, (struct IDirect3DTexture9**)&buf))) return NULL; - return buf; } #endif @@ -395,7 +261,7 @@ void *d3d9_texture_new(void *_dev, INT32 color_key, void *src_info_data, PALETTEENTRY *palette, bool want_mipmap) { - HRESULT hr = S_OK; + LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; void *buf = NULL; if (path) @@ -411,189 +277,37 @@ void *d3d9_texture_new(void *_dev, #endif } - { - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; #ifndef _XBOX - if (want_mipmap) - usage |= D3DUSAGE_AUTOGENMIPMAP; + if (want_mipmap) + usage |= D3DUSAGE_AUTOGENMIPMAP; #endif -#if defined(__cplusplus) && !defined(CINTERFACE) - hr = dev->CreateTexture( - width, height, miplevels, usage, - (D3DFORMAT)format, - (D3DPOOL)pool, - (struct IDirect3DTexture9**)&buf, NULL); -#else - hr = IDirect3DDevice9_CreateTexture(dev, - width, height, miplevels, usage, - (D3DFORMAT)format, - (D3DPOOL)pool, - (struct IDirect3DTexture9**)&buf, NULL); -#endif - } - if (FAILED(hr)) + if (FAILED(IDirect3DDevice9_CreateTexture(dev, + width, height, miplevels, usage, + (D3DFORMAT)format, + (D3DPOOL)pool, + (struct IDirect3DTexture9**)&buf, NULL))) return NULL; - return buf; } -void d3d9_texture_free(void *_tex) -{ - LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)_tex; - if (!tex) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - tex->Release(); -#else - IDirect3DTexture9_Release(tex); -#endif -} - -bool d3d9_surface_lock_rect(void *data, void *data2) -{ - LPDIRECT3DSURFACE9 surf = (LPDIRECT3DSURFACE9)data; - if (!surf) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (FAILED(surf->LockRect((D3DLOCKED_RECT*)data2, NULL, D3DLOCK_READONLY))) - return false; -#else -#if defined(_XBOX) - IDirect3DSurface9_LockRect(surf, (D3DLOCKED_RECT*)data2, NULL, D3DLOCK_READONLY); -#else - if (FAILED(IDirect3DSurface9_LockRect(surf, (D3DLOCKED_RECT*)data2, NULL, D3DLOCK_READONLY))) - return false; -#endif -#endif - - return true; -} - -void d3d9_surface_unlock_rect(void *data) -{ - LPDIRECT3DSURFACE9 surf = (LPDIRECT3DSURFACE9)data; - if (!surf) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - surf->UnlockRect(); -#else - IDirect3DSurface9_UnlockRect(surf); -#endif -} - -void d3d9_surface_free(void *data) -{ - LPDIRECT3DSURFACE9 surf = (LPDIRECT3DSURFACE9)data; - if (!surf) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - surf->Release(); -#else - IDirect3DSurface9_Release(surf); -#endif -} - -void d3d9_vertex_declaration_free(void *data) -{ - if (!data) - return; - -#if defined(__cplusplus) && !defined(CINTERFACE) - { - LPDIRECT3DVERTEXDECLARATION9 vertex_decl = - (LPDIRECT3DVERTEXDECLARATION9)data; - if (vertex_decl) - vertex_decl->Release(); - } -#else - IDirect3DVertexDeclaration9_Release((LPDIRECT3DVERTEXDECLARATION9)data); -#endif -} - -bool d3d9_vertex_declaration_new(void *_dev, - const void *vertex_data, void **decl_data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - const D3DVERTEXELEMENT9 *vertex_elements = (const D3DVERTEXELEMENT9*)vertex_data; - LPDIRECT3DVERTEXDECLARATION9 **vertex_decl = (LPDIRECT3DVERTEXDECLARATION9**)decl_data; - -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(dev->CreateVertexDeclaration(vertex_elements, - (IDirect3DVertexDeclaration9**)vertex_decl))) - return true; -#else - if (SUCCEEDED(IDirect3DDevice9_CreateVertexDeclaration(dev, - vertex_elements, (IDirect3DVertexDeclaration9**)vertex_decl))) - return true; -#endif - - return false; -} - void *d3d9_vertex_buffer_new(void *_dev, unsigned length, unsigned usage, unsigned fvf, INT32 pool, void *handle) { - HRESULT hr = S_OK; void *buf = NULL; LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (usage == 0) - { #ifndef _XBOX -#if defined(__cplusplus) && !defined(CINTERFACE) - if (dev->GetSoftwareVertexProcessing()) - usage = D3DUSAGE_SOFTWAREPROCESSING; -#else + if (usage == 0) if (IDirect3DDevice9_GetSoftwareVertexProcessing(dev)) usage = D3DUSAGE_SOFTWAREPROCESSING; -#endif #endif - } -#if defined(__cplusplus) && !defined(CINTERFACE) - hr = dev->CreateVertexBuffer(length, usage, fvf, - (D3DPOOL)pool, - (LPDIRECT3DVERTEXBUFFER9*)&buf, NULL); -#else - hr = IDirect3DDevice9_CreateVertexBuffer(dev, length, usage, fvf, - (D3DPOOL)pool, - (LPDIRECT3DVERTEXBUFFER9*)&buf, NULL); -#endif - - if (FAILED(hr)) - return NULL; - - return buf; -} - -void d3d9_vertex_buffer_unlock(void *vertbuf_ptr) -{ - LPDIRECT3DVERTEXBUFFER9 vertbuf = (LPDIRECT3DVERTEXBUFFER9)vertbuf_ptr; - - if (!vertbuf) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - vertbuf->Unlock(); -#else - IDirect3DVertexBuffer9_Unlock(vertbuf); -#endif -} - -void *d3d9_vertex_buffer_lock(void *vertbuf_ptr) -{ - void *buf = NULL; - LPDIRECT3DVERTEXBUFFER9 vertbuf = (LPDIRECT3DVERTEXBUFFER9)vertbuf_ptr; - if (!vertbuf) - return NULL; -#if defined(__cplusplus) && !defined(CINTERFACE) - vertbuf->Lock(0, 0, &buf, 0); -#else - IDirect3DVertexBuffer9_Lock(vertbuf, 0, 0, &buf, 0); -#endif - - if (!buf) + if (FAILED(IDirect3DDevice9_CreateVertexBuffer( + dev, length, usage, fvf, + (D3DPOOL)pool, + (LPDIRECT3DVERTEXBUFFER9*)&buf, NULL))) return NULL; return buf; @@ -603,595 +317,41 @@ void d3d9_vertex_buffer_free(void *vertex_data, void *vertex_declaration) { if (vertex_data) { - LPDIRECT3DVERTEXBUFFER9 buf = (LPDIRECT3DVERTEXBUFFER9)vertex_data; -#if defined(__cplusplus) && !defined(CINTERFACE) - buf->Release(); -#else + LPDIRECT3DVERTEXBUFFER9 buf = + (LPDIRECT3DVERTEXBUFFER9)vertex_data; IDirect3DVertexBuffer9_Release(buf); -#endif buf = NULL; } if (vertex_declaration) { - LPDIRECT3DVERTEXDECLARATION9 vertex_decl = (LPDIRECT3DVERTEXDECLARATION9)vertex_declaration; + LPDIRECT3DVERTEXDECLARATION9 vertex_decl = + (LPDIRECT3DVERTEXDECLARATION9)vertex_declaration; d3d9_vertex_declaration_free(vertex_decl); vertex_decl = NULL; } } -void d3d9_set_stream_source(void *_dev, unsigned stream_no, - void *stream_vertbuf_ptr, unsigned offset_bytes, - unsigned stride) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - LPDIRECT3DVERTEXBUFFER9 stream_vertbuf = (LPDIRECT3DVERTEXBUFFER9)stream_vertbuf_ptr; - if (!stream_vertbuf) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetStreamSource(stream_no, stream_vertbuf, offset_bytes, stride); -#else - IDirect3DDevice9_SetStreamSource(dev, stream_no, stream_vertbuf, - offset_bytes, - stride); -#endif -} - -bool d3d9_device_create_offscreen_plain_surface( - void *_dev, - unsigned width, - unsigned height, - unsigned format, - unsigned pool, - void **surf_data, - void *data) -{ -#ifndef _XBOX - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(dev->CreateOffscreenPlainSurface(width, height, - (D3DFORMAT)format, (D3DPOOL)pool, - (LPDIRECT3DSURFACE9*)surf_data, - (HANDLE*)data))) - return true; -#else - if (SUCCEEDED(IDirect3DDevice9_CreateOffscreenPlainSurface(dev, - width, height, - (D3DFORMAT)format, (D3DPOOL)pool, - (LPDIRECT3DSURFACE9*)surf_data, - (HANDLE*)data))) - return true; -#endif -#endif - - return false; -} - -static void d3d9_set_texture_stage_state(void *_dev, - unsigned sampler, unsigned type, unsigned value) -{ -#ifndef _XBOX - /* XBox 360 has no fixed-function pipeline. */ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (dev->SetTextureStageState(sampler, (D3DTEXTURESTAGESTATETYPE)type, value) != D3D_OK) - RARCH_ERR("SetTextureStageState call failed, sampler: %d, value: %d, type: %d\n", sampler, value, type); -#else - if (IDirect3DDevice9_SetTextureStageState(dev, sampler, (D3DTEXTURESTAGESTATETYPE)type, value) != D3D_OK) - RARCH_ERR("SetTextureStageState call failed, sampler: %d, value: %d, type: %d\n", sampler, value, type); -#endif -#endif -} - -void d3d9_set_sampler_address_u(void *_dev, - unsigned sampler, unsigned value) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetSamplerState(sampler, D3DSAMP_ADDRESSU, value); -#else - IDirect3DDevice9_SetSamplerState(dev, sampler, D3DSAMP_ADDRESSU, value); -#endif -} - -void d3d9_set_sampler_address_v(void *_dev, - unsigned sampler, unsigned value) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetSamplerState(sampler, D3DSAMP_ADDRESSV, value); -#else - IDirect3DDevice9_SetSamplerState(dev, sampler, D3DSAMP_ADDRESSV, value); -#endif -} - -void d3d9_set_sampler_minfilter(void *_dev, - unsigned sampler, unsigned value) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetSamplerState(sampler, D3DSAMP_MINFILTER, value); -#else - IDirect3DDevice9_SetSamplerState(dev, sampler, D3DSAMP_MINFILTER, value); -#endif -} - -void d3d9_set_sampler_magfilter(void *_dev, - unsigned sampler, unsigned value) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetSamplerState(sampler, D3DSAMP_MAGFILTER, value); -#else - IDirect3DDevice9_SetSamplerState(dev, sampler, D3DSAMP_MAGFILTER, value); -#endif -} - -void d3d9_set_sampler_mipfilter(void *_dev, - unsigned sampler, unsigned value) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return; - IDirect3DDevice9_SetSamplerState(dev, sampler, - D3DSAMP_MIPFILTER, value); -} - -bool d3d9_begin_scene(void *_dev) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (FAILED(dev->BeginScene())) - return false; -#else -#if defined(_XBOX) - IDirect3DDevice9_BeginScene(dev); -#else - if (FAILED(IDirect3DDevice9_BeginScene(dev))) - return false; -#endif -#endif - - return true; -} - -void d3d9_end_scene(void *_dev) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->EndScene(); -#else - IDirect3DDevice9_EndScene(dev); -#endif -} - -static void d3d9_draw_primitive_internal(void *_dev, - D3DPRIMITIVETYPE type, unsigned start, unsigned count) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->DrawPrimitive(type, start, count); -#else - IDirect3DDevice9_DrawPrimitive(dev, type, start, count); -#endif -} - -void d3d9_draw_primitive(void *dev, - INT32 type, unsigned start, unsigned count) -{ - if (!d3d9_begin_scene(dev)) - return; - - d3d9_draw_primitive_internal(dev, (D3DPRIMITIVETYPE)type, start, count); - d3d9_end_scene(dev); -} - -void d3d9_clear(void *_dev, - unsigned count, const void *rects, unsigned flags, - INT32 color, float z, unsigned stencil) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->Clear(count, (const D3DRECT*)rects, flags, color, z, stencil); -#else - IDirect3DDevice9_Clear(dev, count, (const D3DRECT*)rects, flags, - color, z, stencil); -#endif -} - -bool d3d9_device_get_render_target_data(void *_dev, - void *_src, void *_dst) -{ -#ifndef _XBOX - LPDIRECT3DSURFACE9 src = (LPDIRECT3DSURFACE9)_src; - LPDIRECT3DSURFACE9 dst = (LPDIRECT3DSURFACE9)_dst; - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(dev->GetRenderTargetData(src, dst))) - return true; -#else - if (SUCCEEDED(IDirect3DDevice9_GetRenderTargetData( - dev, src, dst))) - return true; -#endif -#endif - - return false; -} - -bool d3d9_device_get_render_target(void *_dev, - unsigned idx, void **data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(dev->GetRenderTarget(idx, - (LPDIRECT3DSURFACE9*)data))) - return true; -#else - if (SUCCEEDED(IDirect3DDevice9_GetRenderTarget(dev, - idx, (LPDIRECT3DSURFACE9*)data))) - return true; -#endif - - return false; -} - - -bool d3d9_lock_rectangle(void *_tex, - unsigned level, void *_lr, RECT *rect, - unsigned rectangle_height, unsigned flags) -{ - D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; - LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)_tex; - if (!tex) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (FAILED(tex->LockRect(level, lr, rect, flags))) - return false; -#else -#ifdef _XBOX - IDirect3DTexture9_LockRect(tex, level, lr, (const RECT*)rect, flags); -#else - if (IDirect3DTexture9_LockRect(tex, level, lr, (const RECT*)rect, flags) != D3D_OK) - return false; -#endif -#endif - - return true; -} - -void d3d9_unlock_rectangle(void *_tex) -{ - LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)_tex; - if (!tex) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - tex->UnlockRect(0); -#else - IDirect3DTexture9_UnlockRect(tex, 0); -#endif -} - -void d3d9_lock_rectangle_clear(void *tex, - unsigned level, void *_lr, RECT *rect, - unsigned rectangle_height, unsigned flags) -{ - D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; -#if defined(_XBOX) - level = 0; -#endif - memset(lr->pBits, level, rectangle_height * lr->Pitch); - d3d9_unlock_rectangle(tex); -} - -void d3d9_set_viewports(void *_dev, void *_vp) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - D3DVIEWPORT9 *vp = (D3DVIEWPORT9*)_vp; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetViewport(vp); -#else - IDirect3DDevice9_SetViewport(dev, vp); -#endif -} - -void d3d9_set_texture(void *_dev, unsigned sampler, - void *tex_data) -{ - LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)tex_data; - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev || !tex) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetTexture(sampler, tex); -#else - IDirect3DDevice9_SetTexture(dev, sampler, - (IDirect3DBaseTexture9*)tex); -#endif -} - -void d3d9_free_vertex_shader(void *_dev, void *data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - IDirect3DVertexShader9 *vs = (IDirect3DVertexShader9*)data; - if (!dev || !vs) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - vs->Release(); -#else - IDirect3DVertexShader9_Release(vs); -#endif -} - -void d3d9_free_pixel_shader(void *_dev, void *data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - IDirect3DPixelShader9 *ps = (IDirect3DPixelShader9*)data; - if (!dev || !ps) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - ps->Release(); -#else - IDirect3DPixelShader9_Release(ps); -#endif -} - -bool d3d9_create_vertex_shader(void *_dev, const DWORD *a, void **b) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return false; - -#if defined(__cplusplus) && !defined(CINTERFACE) - if (dev->CreateVertexShader(a, (IDirect3DVertexShader9**)b) == D3D_OK) - return true; -#else - if (IDirect3DDevice9_CreateVertexShader(dev, a, - (LPDIRECT3DVERTEXSHADER9*)b) == D3D_OK) - return true; -#endif - - return false; -} - -bool d3d9_create_pixel_shader(void *_dev, const DWORD *a, void **b) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return false; - -#if defined(__cplusplus) && !defined(CINTERFACE) - if (dev->CreatePixelShader(a, (IDirect3DPixelShader9**)b) == D3D_OK) - return true; -#else - if (IDirect3DDevice9_CreatePixelShader(dev, a, - (LPDIRECT3DPIXELSHADER9*)b) == D3D_OK) - return true; -#endif - - return false; -} - -bool d3d9_set_pixel_shader(void *_dev, void *data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - LPDIRECT3DPIXELSHADER9 d3dps = (LPDIRECT3DPIXELSHADER9)data; - if (!dev || !d3dps) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (dev->SetPixelShader(d3dps) == D3D_OK) - return true; -#else -#ifdef _XBOX - /* Returns void on Xbox */ - IDirect3DDevice9_SetPixelShader(dev, d3dps); - return true; -#else - if (IDirect3DDevice9_SetPixelShader(dev, d3dps) == D3D_OK) - return true; -#endif -#endif - - return false; -} - -bool d3d9_set_vertex_shader(void *_dev, unsigned index, - void *data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - LPDIRECT3DVERTEXSHADER9 shader = (LPDIRECT3DVERTEXSHADER9)data; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (dev->SetVertexShader(shader) != D3D_OK) - return false; -#else -#ifdef _XBOX - IDirect3DDevice9_SetVertexShader(dev, shader); -#else - if (IDirect3DDevice9_SetVertexShader(dev, shader) != D3D_OK) - return false; -#endif -#endif - - return true; -} - -bool d3d9_set_vertex_shader_constantf(void *_dev, - UINT start_register,const float* constant_data, - unsigned vector4f_count) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#if defined(__cplusplus) && !defined(CINTERFACE) -#ifdef _XBOX - dev->SetVertexShaderConstantF( - start_register, constant_data, vector4f_count); -#else - if (dev->SetVertexShaderConstantF( - start_register, constant_data, vector4f_count) == D3D_OK) - return true; -#endif -#else -#ifdef _XBOX - IDirect3DDevice9_SetVertexShaderConstantF(dev, - start_register, constant_data, vector4f_count); - return true; -#else - if (IDirect3DDevice9_SetVertexShaderConstantF(dev, - start_register, constant_data, vector4f_count) == D3D_OK) - return true; -#endif -#endif - - return false; -} - -void d3d9_texture_blit(unsigned pixel_size, - void *tex, - void *_lr, const void *frame, - unsigned width, unsigned height, unsigned pitch) -{ - unsigned y; - D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; - - for (y = 0; y < height; y++) - { - const uint8_t *in = (const uint8_t*)frame + y * pitch; - uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; - memcpy(out, in, width * pixel_size); - } -} - -bool d3d9_get_render_state(void *data, INT32 state, DWORD *value) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; - if (!dev) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (dev->GetRenderState((D3DRENDERSTATETYPE)state, value) == D3D_OK) - return true; -#else -#ifdef _XBOX - IDirect3DDevice9_GetRenderState(dev, (D3DRENDERSTATETYPE)state, value); - return true; -#else - if (IDirect3DDevice9_GetRenderState(dev, (D3DRENDERSTATETYPE)state, value) == D3D_OK) - return true; -#endif -#endif - - return false; -} - -void d3d9_set_render_state(void *data, INT32 state, DWORD value) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetRenderState((D3DRENDERSTATETYPE)state, value); -#else - IDirect3DDevice9_SetRenderState(dev, (D3DRENDERSTATETYPE)state, value); -#endif -} - -void d3d9_enable_blend_func(void *data) -{ - if (!data) - return; - - d3d9_set_render_state(data, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - d3d9_set_render_state(data, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - d3d9_set_render_state(data, D3DRS_ALPHABLENDENABLE, true); -} - -void d3d9_device_set_render_target(void *_dev, unsigned idx, - void *data) -{ - LPDIRECT3DSURFACE9 surf = (LPDIRECT3DSURFACE9)data; - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetRenderTarget(idx, surf); -#else - IDirect3DDevice9_SetRenderTarget(dev, idx, surf); -#endif -} - -void d3d9_enable_alpha_blend_texture_func(void *data) -{ - /* Also blend the texture with the set alpha value. */ - d3d9_set_texture_stage_state(data, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3d9_set_texture_stage_state(data, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); - d3d9_set_texture_stage_state(data, 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); -} - -void d3d9_disable_blend_func(void *data) -{ - d3d9_set_render_state(data, D3DRS_ALPHABLENDENABLE, false); -} - -void d3d9_set_vertex_declaration(void *data, void *vertex_data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; - if (!dev) - return; -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->SetVertexDeclaration((LPDIRECT3DVERTEXDECLARATION9)vertex_data); -#else - IDirect3DDevice9_SetVertexDeclaration(dev, (LPDIRECT3DVERTEXDECLARATION9)vertex_data); -#endif -} - static bool d3d9_reset_internal(void *data, D3DPRESENT_PARAMETERS *d3dpp ) { LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; - if (!dev) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if ((dev->Reset(d3dpp) == D3D_OK)) + if (dev && + IDirect3DDevice9_Reset(dev, d3dpp) == D3D_OK) return true; -#else - if (IDirect3DDevice9_Reset(dev, d3dpp) == D3D_OK) - return true; -#endif return false; } static HRESULT d3d9_test_cooperative_level(void *data) { -#ifdef _XBOX - return E_FAIL; -#else +#ifndef _XBOX LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; - if (!dev) - return E_FAIL; -#if defined(__cplusplus) && !defined(CINTERFACE) - return dev->TestCooperativeLevel(); -#else - return IDirect3DDevice9_TestCooperativeLevel(dev); -#endif + if (dev) + return IDirect3DDevice9_TestCooperativeLevel(dev); #endif + return E_FAIL; } static bool d3d9_create_device_internal( @@ -1204,10 +364,8 @@ static bool d3d9_create_device_internal( { LPDIRECT3D9 d3d = (LPDIRECT3D9)_d3d; LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; - if (!dev) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(d3d->CreateDevice( + if (dev && + SUCCEEDED(IDirect3D9_CreateDevice(d3d, cur_mon_id, D3DDEVTYPE_HAL, focus_window, @@ -1215,16 +373,6 @@ static bool d3d9_create_device_internal( d3dpp, (IDirect3DDevice9**)dev))) return true; -#else - if (SUCCEEDED(IDirect3D9_CreateDevice(d3d, - cur_mon_id, - D3DDEVTYPE_HAL, - focus_window, - behavior_flags, - d3dpp, - (IDirect3DDevice9**)dev))) - return true; -#endif return false; } @@ -1284,112 +432,29 @@ bool d3d9_reset(void *dev, void *d3dpp) return false; } -bool d3d9_device_get_backbuffer(void *_dev, - unsigned idx, unsigned swapchain_idx, - unsigned backbuffer_type, void **data) -{ - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (!dev) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (SUCCEEDED(dev->GetBackBuffer( - swapchain_idx, idx, - (D3DBACKBUFFER_TYPE)backbuffer_type, - (LPDIRECT3DSURFACE9*)data))) - return true; -#else - if (SUCCEEDED(IDirect3DDevice9_GetBackBuffer(dev, - swapchain_idx, idx, - (D3DBACKBUFFER_TYPE)backbuffer_type, - (LPDIRECT3DSURFACE9*)data))) - return true; -#endif - - return false; -} - - -void d3d9_device_free(void *_dev, void *_pd3d) -{ - LPDIRECT3D9 pd3d = (LPDIRECT3D9)_pd3d; - LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; - if (dev) - { -#if defined(__cplusplus) && !defined(CINTERFACE) - dev->Release(); -#else - IDirect3DDevice9_Release(dev); -#endif - } - - if (pd3d) - { -#if defined(__cplusplus) && !defined(CINTERFACE) - pd3d->Release(); -#else - IDirect3D9_Release(pd3d); -#endif - } -} - -INT32 d3d9_translate_filter(unsigned type) -{ - switch (type) - { - case RARCH_FILTER_UNSPEC: - { - settings_t *settings = config_get_ptr(); - if (!settings->bools.video_smooth) - break; - } - /* fall-through */ - case RARCH_FILTER_LINEAR: - return D3DTEXF_LINEAR; - case RARCH_FILTER_NEAREST: - break; - } - - return D3DTEXF_POINT; -} - bool d3d9x_create_font_indirect(void *_dev, void *desc, void **font_data) { #ifdef HAVE_D3DX LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; -#ifdef __cplusplus if (SUCCEEDED(D3D9CreateFontIndirect( dev, (D3DXFONT_DESC*)desc, (struct ID3DXFont**)font_data))) return true; -#else - if (SUCCEEDED(D3D9CreateFontIndirect( - dev, (D3DXFONT_DESC*)desc, - (struct ID3DXFont**)font_data))) - return true; -#endif #endif return false; } -void d3dxbuffer_release(void *data) +void d3d9x_buffer_release(void *data) { #ifdef HAVE_D3DX -#ifdef __cplusplus - ID3DXBuffer *p = (ID3DXBuffer*)data; -#else LPD3DXBUFFER p = (LPD3DXBUFFER)data; -#endif if (!p) return; -#if defined(__cplusplus) && !defined(CINTERFACE) - p->Release(); -#else p->lpVtbl->Release(p); #endif -#endif } bool d3d9x_compile_shader( @@ -1426,55 +491,29 @@ void d3d9x_font_draw_text(void *data, void *sprite_data, void *string_data, unsigned count, void *rect_data, unsigned format, unsigned color) { #ifdef HAVE_D3DX -#if !defined(__cplusplus) || defined(CINTERFACE) ID3DXFont *font = (ID3DXFont*)data; - if (!font) - return; - font->lpVtbl->DrawText(font, (LPD3DXSPRITE)sprite_data, - (LPCTSTR)string_data, count, (LPRECT)rect_data, - (DWORD)format, (D3DCOLOR)color); -#else - LPD3DXFONT font = (LPD3DXFONT)data; - if (!font) - return; - font->DrawText((LPD3DXSPRITE)sprite_data, - (LPCTSTR)string_data, count, (LPRECT)rect_data, - (DWORD)format, (D3DCOLOR)color); -#endif + if (font) + font->lpVtbl->DrawText(font, (LPD3DXSPRITE)sprite_data, + (LPCTSTR)string_data, count, (LPRECT)rect_data, + (DWORD)format, (D3DCOLOR)color); #endif } void d3d9x_font_release(void *data) { #ifdef HAVE_D3DX -#if !defined(__cplusplus) || defined(CINTERFACE) ID3DXFont *font = (ID3DXFont*)data; - if (!font) - return; - font->lpVtbl->Release(font); -#else - LPD3DXFONT font = (LPD3DXFONT)data; - if (!font) - return; - font->Release(); -#endif + if (font) + font->lpVtbl->Release(font); #endif } void d3d9x_font_get_text_metrics(void *data, void *metrics) { #ifdef HAVE_D3DX -#if !defined(__cplusplus) || defined(CINTERFACE) ID3DXFont *font = (ID3DXFont*)data; - if (!font) - return; - font->lpVtbl->GetTextMetrics(font, (TEXTMETRICA*)metrics); -#else - LPD3DXFONT font = (LPD3DXFONT)data; - if (!font) - return; - font->GetTextMetricsA((TEXTMETRICA*)metrics); -#endif + if (font) + font->lpVtbl->GetTextMetrics(font, (TEXTMETRICA*)metrics); #endif } @@ -1506,66 +545,77 @@ bool d3d9x_compile_shader_from_file( return false; } -INT32 d3d9_get_rgb565_format(void) -{ -#ifdef _XBOX - return D3DFMT_LIN_R5G6B5; -#else - return D3DFMT_R5G6B5; -#endif -} - -INT32 d3d9_get_argb8888_format(void) -{ -#ifdef _XBOX - return D3DFMT_LIN_A8R8G8B8; -#else - return D3DFMT_A8R8G8B8; -#endif -} - -INT32 d3d9_get_xrgb8888_format(void) -{ -#ifdef _XBOX - return D3DFMT_LIN_X8R8G8B8; -#else - return D3DFMT_X8R8G8B8; -#endif -} - const void *d3d9x_get_buffer_ptr(void *data) { #if defined(HAVE_D3DX) ID3DXBuffer *listing = (ID3DXBuffer*)data; - if (!listing) - return NULL; -#if defined(__cplusplus) && !defined(CINTERFACE) - return listing->GetBufferPointer(); -#else - return listing->lpVtbl->GetBufferPointer(listing); + if (listing) + return listing->lpVtbl->GetBufferPointer(listing); #endif -#else return NULL; +} + +void *d3d9x_constant_table_get_constant_by_name(void *_tbl, + void *_handle, void *_name) +{ +#if defined(HAVE_D3DX) + D3DXHANDLE handle = (D3DXHANDLE)_handle; + LPD3DXCONSTANTTABLE consttbl = (LPD3DXCONSTANTTABLE)_tbl; + LPCSTR name = (LPCSTR)_name; + if (consttbl && handle && name) + return (void*)consttbl->lpVtbl->GetConstantByName(consttbl, + handle, name); +#endif + return NULL; +} + +void d3d9x_constant_table_set_float_array(LPDIRECT3DDEVICE9 dev, + void *p, void *_handle, const void *_pf, unsigned count) +{ +#if defined(HAVE_D3DX) + LPD3DXCONSTANTTABLE consttbl = (LPD3DXCONSTANTTABLE)p; + D3DXHANDLE handle = (D3DXHANDLE)_handle; + CONST FLOAT *pf = (CONST FLOAT*)_pf; + if (consttbl && dev) + consttbl->lpVtbl->SetFloatArray(consttbl, dev, handle, pf, + (UINT)count); +#endif +} + +void d3d9x_constant_table_set_defaults(LPDIRECT3DDEVICE9 dev, + void *p) +{ +#if defined(HAVE_D3DX) + LPD3DXCONSTANTTABLE consttbl = (LPD3DXCONSTANTTABLE)p; + if (consttbl && dev) + consttbl->lpVtbl->SetDefaults(consttbl, dev); +#endif +} + +void d3d9x_constant_table_set_matrix(LPDIRECT3DDEVICE9 dev, + void *p, + void *data, const void *_matrix) +{ +#if defined(HAVE_D3DX) + LPD3DXCONSTANTTABLE consttbl = (LPD3DXCONSTANTTABLE)p; + D3DXHANDLE handle = (D3DXHANDLE)data; + const D3DXMATRIX *matrix = (const D3DXMATRIX*)matrix; + if (consttbl && dev && handle) + consttbl->lpVtbl->SetMatrix(consttbl, dev, handle, matrix); #endif } const bool d3d9x_constant_table_set_float(void *p, - void *a, - const void *b, float val) + void *a, void *b, float val) { #if defined(HAVE_D3DX) LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)a; D3DXHANDLE handle = (D3DXHANDLE)b; LPD3DXCONSTANTTABLE consttbl = (LPD3DXCONSTANTTABLE)p; - if (!consttbl || !dev || !handle) - return false; -#if defined(__cplusplus) && !defined(CINTERFACE) - if (consttbl->SetFloat(dev, handle, val) == D3D_OK) + if (consttbl && dev && handle && + consttbl->lpVtbl->SetFloat( + consttbl, dev, handle, val) == D3D_OK) return true; -#else - if (consttbl->lpVtbl->SetFloat(consttbl, dev, handle, val) == D3D_OK) - return true; -#endif #endif return false; } diff --git a/gfx/common/d3d9_common.h b/gfx/common/d3d9_common.h index 008ae8cde3..17c2b05fec 100644 --- a/gfx/common/d3d9_common.h +++ b/gfx/common/d3d9_common.h @@ -18,27 +18,76 @@ #include #include +#include + +#include #include "../video_driver.h" +#include "../../verbosity.h" RETRO_BEGIN_DECLS -bool d3d9_swap(void *data, void *dev); +static INLINE bool d3d9_swap(void *data, LPDIRECT3DDEVICE9 dev) +{ +#ifdef _XBOX + IDirect3DDevice9_Present(dev, NULL, NULL, NULL, NULL); +#else + if (IDirect3DDevice9_Present(dev, NULL, NULL, NULL, NULL) + == D3DERR_DEVICELOST) + return false; +#endif + return true; +} void *d3d9_vertex_buffer_new(void *dev, unsigned length, unsigned usage, unsigned fvf, INT32 pool, void *handle); -void *d3d9_vertex_buffer_lock(void *data); -void d3d9_vertex_buffer_unlock(void *data); +static INLINE void *d3d9_vertex_buffer_lock(LPDIRECT3DVERTEXBUFFER9 vertbuf) +{ + void *buf = NULL; + if (!vertbuf) + return NULL; + IDirect3DVertexBuffer9_Lock(vertbuf, 0, 0, &buf, 0); + + if (!buf) + return NULL; + + return buf; +} + +static INLINE void d3d9_vertex_buffer_unlock(LPDIRECT3DVERTEXBUFFER9 vertbuf) +{ + if (vertbuf) + IDirect3DVertexBuffer9_Unlock(vertbuf); +} void d3d9_vertex_buffer_free(void *vertex_data, void *vertex_declaration); -bool d3d9_texture_get_level_desc(void *tex, - unsigned idx, void *_ppsurface_level); +static INLINE bool d3d9_texture_get_level_desc( + LPDIRECT3DTEXTURE9 tex, + unsigned idx, + D3DSURFACE_DESC *_ppsurface_level) +{ +#if defined(_XBOX) + D3DTexture_GetLevelDesc(tex, idx, _ppsurface_level); +#else + if (FAILED(IDirect3DTexture9_GetLevelDesc(tex, idx, _ppsurface_level))) + return false; +#endif + return true; +} -bool d3d9_texture_get_surface_level(void *tex, - unsigned idx, void **_ppsurface_level); +static INLINE bool d3d9_texture_get_surface_level( + LPDIRECT3DTEXTURE9 tex, + unsigned idx, void **_ppsurface_level) +{ + if (tex && + SUCCEEDED(IDirect3DTexture9_GetSurfaceLevel( + tex, idx, (IDirect3DSurface9**)_ppsurface_level))) + return true; + return false; +} void *d3d9_texture_new(void *dev, const char *path, unsigned width, unsigned height, @@ -47,130 +96,474 @@ void *d3d9_texture_new(void *dev, INT32 color_key, void *src_info, PALETTEENTRY *palette, bool want_mipmap); -void d3d9_set_stream_source(void *dev, unsigned stream_no, - void *stream_vertbuf, unsigned offset_bytes, - unsigned stride); +static INLINE void d3d9_set_stream_source( + LPDIRECT3DDEVICE9 dev, + unsigned stream_no, + LPDIRECT3DVERTEXBUFFER9 stream_vertbuf, + unsigned offset_bytes, + unsigned stride) +{ + if (stream_vertbuf) + IDirect3DDevice9_SetStreamSource(dev, stream_no, stream_vertbuf, + offset_bytes, + stride); +} -void d3d9_texture_free(void *tex); +static INLINE void d3d9_texture_free(LPDIRECT3DTEXTURE9 tex) +{ + if (tex) + IDirect3DTexture9_Release(tex); +} -void d3d9_set_transform(void *dev, - INT32 state, const void *_matrix); +static INLINE void d3d9_set_transform( + LPDIRECT3DDEVICE9 dev, + D3DTRANSFORMSTATETYPE state, + const void *_matrix) +{ +#ifndef _XBOX + CONST D3DMATRIX *matrix = (CONST D3DMATRIX*)_matrix; + /* XBox 360 D3D9 does not support fixed-function pipeline. */ + IDirect3DDevice9_SetTransform(dev, state, matrix); +#endif +} -void d3d9_set_sampler_address_u(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d9_set_sampler_address_u( + LPDIRECT3DDEVICE9 dev, + unsigned sampler, unsigned value) +{ + IDirect3DDevice9_SetSamplerState(dev, + sampler, D3DSAMP_ADDRESSU, value); +} -void d3d9_set_sampler_address_v(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d9_set_sampler_address_v( + LPDIRECT3DDEVICE9 dev, + unsigned sampler, unsigned value) +{ + IDirect3DDevice9_SetSamplerState(dev, + sampler, D3DSAMP_ADDRESSV, value); +} -void d3d9_set_sampler_minfilter(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d9_set_sampler_minfilter( + LPDIRECT3DDEVICE9 dev, + unsigned sampler, unsigned value) +{ + if (dev) + IDirect3DDevice9_SetSamplerState(dev, + sampler, D3DSAMP_MINFILTER, value); +} -void d3d9_set_sampler_magfilter(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d9_set_sampler_magfilter( + LPDIRECT3DDEVICE9 dev, + unsigned sampler, unsigned value) +{ + if (dev) + IDirect3DDevice9_SetSamplerState(dev, + sampler, D3DSAMP_MAGFILTER, value); +} -void d3d9_set_sampler_mipfilter(void *dev, - unsigned sampler, unsigned value); +static INLINE void d3d9_set_sampler_mipfilter( + LPDIRECT3DDEVICE9 dev, + unsigned sampler, unsigned value) +{ + if (dev) + IDirect3DDevice9_SetSamplerState(dev, sampler, + D3DSAMP_MIPFILTER, value); +} -bool d3d9_begin_scene(void *dev); +static INLINE bool d3d9_begin_scene(LPDIRECT3DDEVICE9 dev) +{ + if (!dev) + return false; +#if defined(_XBOX) + IDirect3DDevice9_BeginScene(dev); +#else + if (FAILED(IDirect3DDevice9_BeginScene(dev))) + return false; +#endif -void d3d9_end_scene(void *dev); + return true; +} -void d3d9_draw_primitive(void *dev, - INT32 type, unsigned start, unsigned count); +static INLINE void d3d9_end_scene(LPDIRECT3DDEVICE9 dev) +{ + if (dev) + IDirect3DDevice9_EndScene(dev); +} -void d3d9_clear(void *dev, - unsigned count, const void *rects, unsigned flags, - INT32 color, float z, unsigned stencil); +static INLINE void d3d9_draw_primitive( + LPDIRECT3DDEVICE9 dev, + D3DPRIMITIVETYPE type, + unsigned start, unsigned count) +{ + if (!dev || !d3d9_begin_scene(dev)) + return; + IDirect3DDevice9_DrawPrimitive(dev, type, start, count); + d3d9_end_scene(dev); +} -bool d3d9_lock_rectangle(void *tex, - unsigned level, void *lock_rect, RECT *rect, - unsigned rectangle_height, unsigned flags); +static INLINE void d3d9_clear( + LPDIRECT3DDEVICE9 dev, + unsigned count, const D3DRECT *rects, unsigned flags, + INT32 color, float z, unsigned stencil) +{ + if (dev) + IDirect3DDevice9_Clear(dev, count, rects, flags, + color, z, stencil); +} -void d3d9_lock_rectangle_clear(void *tex, - unsigned level, void *lock_rect, RECT *rect, - unsigned rectangle_height, unsigned flags); +static INLINE bool d3d9_lock_rectangle( + LPDIRECT3DTEXTURE9 tex, + unsigned level, + D3DLOCKED_RECT *lr, + const RECT *rect, + unsigned rectangle_height, unsigned flags) +{ + if (!tex) + return false; +#ifdef _XBOX + IDirect3DTexture9_LockRect(tex, level, lr, rect, flags); +#else + if (IDirect3DTexture9_LockRect(tex, level, lr, rect, flags) != D3D_OK) + return false; +#endif -void d3d9_unlock_rectangle(void *tex); + return true; +} -void d3d9_set_texture(void *dev, unsigned sampler, - void *tex_data); +static INLINE void d3d9_unlock_rectangle(LPDIRECT3DTEXTURE9 tex) +{ + if (tex) + IDirect3DTexture9_UnlockRect(tex, 0); +} -bool d3d9_create_vertex_shader(void *dev, - const DWORD *a, void **b); +static INLINE void d3d9_lock_rectangle_clear(void *tex, + unsigned level, void *_lr, RECT *rect, + unsigned rectangle_height, unsigned flags) +{ + D3DLOCKED_RECT *lr = (D3DLOCKED_RECT*)_lr; +#if defined(_XBOX) + level = 0; +#endif + memset(lr->pBits, level, rectangle_height * lr->Pitch); + d3d9_unlock_rectangle((LPDIRECT3DTEXTURE9)tex); +} -bool d3d9_create_pixel_shader(void *dev, - const DWORD *a, void **b); +static INLINE void d3d9_set_texture( + LPDIRECT3DDEVICE9 dev, + unsigned sampler, + LPDIRECT3DTEXTURE9 tex) +{ + if (dev && tex) + IDirect3DDevice9_SetTexture(dev, sampler, + (IDirect3DBaseTexture9*)tex); +} -void d3d9_free_pixel_shader(void *dev, void *data); +static INLINE bool d3d9_create_vertex_shader( + LPDIRECT3DDEVICE9 dev, const DWORD *a, void **b) +{ + if (dev && IDirect3DDevice9_CreateVertexShader(dev, a, + (LPDIRECT3DVERTEXSHADER9*)b) == D3D_OK) + return true; + return false; +} -void d3d9_free_vertex_shader(void *dev, void *data); +static INLINE bool d3d9_create_pixel_shader( + LPDIRECT3DDEVICE9 dev, const DWORD *a, void **b) +{ + if (dev && + IDirect3DDevice9_CreatePixelShader(dev, a, + (LPDIRECT3DPIXELSHADER9*)b) == D3D_OK) + return true; + return false; +} -bool d3d9_set_pixel_shader(void *dev, void *data); +static INLINE void d3d9_free_vertex_shader( + LPDIRECT3DDEVICE9 dev, IDirect3DVertexShader9 *vs) +{ + if (dev && vs) + IDirect3DVertexShader9_Release(vs); +} -bool d3d9_set_vertex_shader(void *dev, unsigned index, - void *data); +static INLINE void d3d9_free_pixel_shader(LPDIRECT3DDEVICE9 dev, + IDirect3DPixelShader9 *ps) +{ + if (dev && ps) + IDirect3DPixelShader9_Release(ps); +} -bool d3d9_set_vertex_shader_constantf(void *dev, - UINT start_register,const float* constant_data, unsigned vector4f_count); +static INLINE bool d3d9_set_pixel_shader( + LPDIRECT3DDEVICE9 dev, + LPDIRECT3DPIXELSHADER9 d3dps) +{ + if (!dev || !d3dps) + return false; -void d3d9_texture_blit(unsigned pixel_size, +#ifdef _XBOX + /* Returns void on Xbox */ + IDirect3DDevice9_SetPixelShader(dev, d3dps); +#else + if (IDirect3DDevice9_SetPixelShader(dev, d3dps) != D3D_OK) + return false; +#endif + return true; +} + +static INLINE bool d3d9_set_vertex_shader( + LPDIRECT3DDEVICE9 dev, unsigned index, + LPDIRECT3DVERTEXSHADER9 shader) +{ +#ifdef _XBOX + IDirect3DDevice9_SetVertexShader(dev, shader); +#else + if (IDirect3DDevice9_SetVertexShader(dev, shader) != D3D_OK) + return false; +#endif + + return true; +} + +static INLINE bool d3d9_set_vertex_shader_constantf( + LPDIRECT3DDEVICE9 dev, + UINT start_register, + const float* constant_data, + unsigned vector4f_count) +{ +#ifdef _XBOX + IDirect3DDevice9_SetVertexShaderConstantF(dev, + start_register, constant_data, vector4f_count); +#else + if (IDirect3DDevice9_SetVertexShaderConstantF(dev, + start_register, constant_data, vector4f_count) != D3D_OK) + return false; +#endif + + return true; +} + +static INLINE void d3d9_texture_blit( + unsigned pixel_size, void *tex, - void *lr, const void *frame, - unsigned width, unsigned height, unsigned pitch); + D3DLOCKED_RECT *lr, const void *frame, + unsigned width, unsigned height, unsigned pitch) +{ + unsigned y; -bool d3d9_vertex_declaration_new(void *dev, - const void *vertex_data, void **decl_data); + for (y = 0; y < height; y++) + { + const uint8_t *in = (const uint8_t*)frame + y * pitch; + uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; + memcpy(out, in, width * pixel_size); + } +} -void d3d9_vertex_declaration_free(void *data); +static INLINE bool d3d9_vertex_declaration_new( + LPDIRECT3DDEVICE9 dev, + const void *vertex_data, void **decl_data) +{ + const D3DVERTEXELEMENT9 *vertex_elements = (const D3DVERTEXELEMENT9*)vertex_data; + LPDIRECT3DVERTEXDECLARATION9 **vertex_decl = (LPDIRECT3DVERTEXDECLARATION9**)decl_data; -void d3d9_set_viewports(void *dev, void *vp); + if (SUCCEEDED(IDirect3DDevice9_CreateVertexDeclaration(dev, + vertex_elements, (IDirect3DVertexDeclaration9**)vertex_decl))) + return true; -void d3d9_enable_blend_func(void *data); + return false; +} -void d3d9_disable_blend_func(void *data); +static INLINE void d3d9_vertex_declaration_free( + LPDIRECT3DVERTEXDECLARATION9 decl) +{ + if (decl) + IDirect3DVertexDeclaration9_Release(decl); +} -void d3d9_set_vertex_declaration(void *data, void *vertex_data); +static INLINE void d3d9_set_viewports(LPDIRECT3DDEVICE9 dev, + void *vp) +{ + if (dev) + IDirect3DDevice9_SetViewport(dev, (D3DVIEWPORT9*)vp); +} -void d3d9_enable_alpha_blend_texture_func(void *data); +static INLINE void d3d9_set_render_state( + LPDIRECT3DDEVICE9 dev, D3DRENDERSTATETYPE state, DWORD value) +{ + IDirect3DDevice9_SetRenderState(dev, state, value); +} + +static INLINE void d3d9_enable_blend_func(LPDIRECT3DDEVICE9 dev) +{ + if (!dev) + return; + + d3d9_set_render_state(dev, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + d3d9_set_render_state(dev, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + d3d9_set_render_state(dev, D3DRS_ALPHABLENDENABLE, true); +} + +static INLINE void d3d9_disable_blend_func(LPDIRECT3DDEVICE9 dev) +{ + if (dev) + d3d9_set_render_state(dev, D3DRS_ALPHABLENDENABLE, false); +} + +static INLINE void +d3d9_set_vertex_declaration(LPDIRECT3DDEVICE9 dev, + LPDIRECT3DVERTEXDECLARATION9 vertex_data) +{ + if (dev) + IDirect3DDevice9_SetVertexDeclaration(dev, vertex_data); +} + +static INLINE void d3d9_set_texture_stage_state( + LPDIRECT3DDEVICE9 dev, + unsigned sampler, + D3DTEXTURESTAGESTATETYPE type, + unsigned value) +{ +#ifndef _XBOX + /* XBox 360 has no fixed-function pipeline. */ + if (IDirect3DDevice9_SetTextureStageState(dev, sampler, + type, value) != D3D_OK) + RARCH_ERR("SetTextureStageState call failed, sampler" + ": %d, value: %d, type: %d\n", sampler, value, type); +#endif +} + +static INLINE void d3d9_enable_alpha_blend_texture_func(LPDIRECT3DDEVICE9 dev) +{ + if (!dev) + return; + + /* Also blend the texture with the set alpha value. */ + d3d9_set_texture_stage_state(dev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + d3d9_set_texture_stage_state(dev, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + d3d9_set_texture_stage_state(dev, 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); +} void d3d9_frame_postprocess(void *data); -void d3d9_surface_free(void *data); +static INLINE void d3d9_surface_free(LPDIRECT3DSURFACE9 surf) +{ + if (surf) + IDirect3DSurface9_Release(surf); +} -bool d3d9_device_get_render_target_data(void *dev, - void *_src, void *_dst); +static INLINE bool d3d9_device_get_render_target_data( + void *_dev, + void *_src, void *_dst) +{ +#ifndef _XBOX + LPDIRECT3DSURFACE9 src = (LPDIRECT3DSURFACE9)_src; + LPDIRECT3DSURFACE9 dst = (LPDIRECT3DSURFACE9)_dst; + LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; + if (dev && + SUCCEEDED(IDirect3DDevice9_GetRenderTargetData( + dev, src, dst))) + return true; +#endif -bool d3d9_device_get_render_target(void *dev, - unsigned idx, void **data); + return false; +} -void d3d9_device_set_render_target(void *dev, unsigned idx, - void *data); +static INLINE bool d3d9_device_get_render_target( + LPDIRECT3DDEVICE9 dev, + unsigned idx, void **data) +{ + if (dev && + SUCCEEDED(IDirect3DDevice9_GetRenderTarget(dev, + idx, (LPDIRECT3DSURFACE9*)data))) + return true; + return false; +} -bool d3d9_get_render_state(void *data, - INT32 state, DWORD *value); +static INLINE void d3d9_device_set_render_target( + void *_dev, unsigned idx, + void *data) +{ + LPDIRECT3DSURFACE9 surf = (LPDIRECT3DSURFACE9)data; + LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; + if (dev) + IDirect3DDevice9_SetRenderTarget(dev, idx, surf); +} -void d3d9_set_render_state(void *data, - INT32 state, DWORD value); +static INLINE bool d3d9_get_render_state( + void *data, INT32 state, DWORD *value) +{ + LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; + if (!dev) + return false; -void d3d9_device_set_render_target(void *dev, unsigned idx, - void *data); +#ifdef _XBOX + IDirect3DDevice9_GetRenderState(dev, + (D3DRENDERSTATETYPE)state, value); +#else + if (IDirect3DDevice9_GetRenderState(dev, + (D3DRENDERSTATETYPE)state, value) != D3D_OK) + return false; +#endif + return true; +} -bool d3d9_device_create_offscreen_plain_surface( - void *dev, +static INLINE bool d3d9_device_create_offscreen_plain_surface( + void *_dev, unsigned width, unsigned height, unsigned format, unsigned pool, void **surf_data, - void *data); + void *data) +{ +#ifndef _XBOX + LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; + if (SUCCEEDED(IDirect3DDevice9_CreateOffscreenPlainSurface(dev, + width, height, + (D3DFORMAT)format, (D3DPOOL)pool, + (LPDIRECT3DSURFACE9*)surf_data, + (HANDLE*)data))) + return true; +#endif + return false; +} -bool d3d9_surface_lock_rect(void *data, void *data2); +static INLINE bool d3d9_surface_lock_rect(LPDIRECT3DSURFACE9 surf, + D3DLOCKED_RECT *data2) +{ + if (!surf) + return false; +#if defined(_XBOX) + IDirect3DSurface9_LockRect(surf, + data2, NULL, D3DLOCK_READONLY); +#else + if (FAILED(IDirect3DSurface9_LockRect(surf, + data2, NULL, D3DLOCK_READONLY))) + return false; +#endif -void d3d9_surface_unlock_rect(void *data); + return true; +} -bool d3d9_get_adapter_display_mode(void *d3d, +static INLINE void d3d9_surface_unlock_rect(LPDIRECT3DSURFACE9 surf) +{ + if (surf) + IDirect3DSurface9_UnlockRect(surf); +} + +static INLINE bool d3d9_get_adapter_display_mode( + LPDIRECT3D9 d3d, unsigned idx, - void *display_mode); + void *display_mode) +{ + if (!d3d) + return false; +#ifndef _XBOX + if (FAILED( + IDirect3D9_GetAdapterDisplayMode( + d3d, idx, (D3DDISPLAYMODE*)display_mode))) + return false; +#endif + + return true; +} bool d3d9_create_device(void *dev, void *d3dpp, @@ -180,11 +573,29 @@ bool d3d9_create_device(void *dev, bool d3d9_reset(void *dev, void *d3dpp); -bool d3d9_device_get_backbuffer(void *dev, +static INLINE bool d3d9_device_get_backbuffer( + LPDIRECT3DDEVICE9 dev, unsigned idx, unsigned swapchain_idx, - unsigned backbuffer_type, void **data); + unsigned backbuffer_type, void **data) +{ + if (dev && + SUCCEEDED(IDirect3DDevice9_GetBackBuffer(dev, + swapchain_idx, idx, + (D3DBACKBUFFER_TYPE)backbuffer_type, + (LPDIRECT3DSURFACE9*)data))) + return true; + return false; +} -void d3d9_device_free(void *dev, void *pd3d); +static INLINE void d3d9_device_free(void *_dev, void *_pd3d) +{ + LPDIRECT3D9 pd3d = (LPDIRECT3D9)_pd3d; + LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; + if (dev) + IDirect3DDevice9_Release(dev); + if (pd3d) + IDirect3D9_Release(pd3d); +} void *d3d9_create(void); @@ -192,11 +603,23 @@ bool d3d9_initialize_symbols(enum gfx_ctx_api api); void d3d9_deinitialize_symbols(void); -bool d3d9_check_device_type(void *d3d, +static INLINE bool d3d9_check_device_type( + LPDIRECT3D9 d3d, unsigned idx, INT32 disp_format, INT32 backbuffer_format, - bool windowed_mode); + bool windowed_mode) +{ + if (d3d && + SUCCEEDED(IDirect3D9_CheckDeviceType(d3d, + 0, + D3DDEVTYPE_HAL, + (D3DFORMAT)disp_format, + (D3DFORMAT)backbuffer_format, + windowed_mode))) + return true; + return false; +} bool d3d9x_create_font_indirect(void *dev, void *desc, void **font_data); @@ -206,12 +629,10 @@ void d3d9x_font_draw_text(void *data, void *sprite_data, void *string_data, void d3d9x_font_get_text_metrics(void *data, void *metrics); -void d3dxbuffer_release(void *data); +void d3d9x_buffer_release(void *data); void d3d9x_font_release(void *data); -INT32 d3d9_translate_filter(unsigned type); - bool d3d9x_compile_shader( const char *src, unsigned src_data_len, @@ -235,14 +656,49 @@ bool d3d9x_compile_shader_from_file( void *pperrormsgs, void *ppconstanttable); +void d3d9x_constant_table_set_float_array(LPDIRECT3DDEVICE9 dev, + void *p, void *_handle, const void *_pf, unsigned count); + +void d3d9x_constant_table_set_defaults(LPDIRECT3DDEVICE9 dev, + void *p); + +void d3d9x_constant_table_set_matrix(LPDIRECT3DDEVICE9 dev, + void *p, void *data, const void *matrix); + const void *d3d9x_get_buffer_ptr(void *data); const bool d3d9x_constant_table_set_float(void *p, - void *a, const void *b, float val); + void *a, void *b, float val); -INT32 d3d9_get_rgb565_format(void); -INT32 d3d9_get_argb8888_format(void); -INT32 d3d9_get_xrgb8888_format(void); +void *d3d9x_constant_table_get_constant_by_name(void *_tbl, + void *_handle, void *_name); + +static INLINE INT32 d3d9_get_rgb565_format(void) +{ +#ifdef _XBOX + return D3DFMT_LIN_R5G6B5; +#else + return D3DFMT_R5G6B5; +#endif +} + +static INLINE INT32 d3d9_get_argb8888_format(void) +{ +#ifdef _XBOX + return D3DFMT_LIN_A8R8G8B8; +#else + return D3DFMT_A8R8G8B8; +#endif +} + +static INLINE INT32 d3d9_get_xrgb8888_format(void) +{ +#ifdef _XBOX + return D3DFMT_LIN_X8R8G8B8; +#else + return D3DFMT_X8R8G8B8; +#endif +} RETRO_END_DECLS diff --git a/gfx/common/d3d_common.c b/gfx/common/d3d_common.c index 1908181945..020f20d681 100644 --- a/gfx/common/d3d_common.c +++ b/gfx/common/d3d_common.c @@ -86,7 +86,8 @@ void *d3d_matrix_identity(void *_pout) return pout; } -void *d3d_matrix_ortho_off_center_lh(void *_pout, float l, float r, float b, float t, float zn, float zf) +void *d3d_matrix_ortho_off_center_lh(void *_pout, + float l, float r, float b, float t, float zn, float zf) { D3DMATRIX *pout = (D3DMATRIX*)_pout; @@ -101,7 +102,8 @@ void *d3d_matrix_ortho_off_center_lh(void *_pout, float l, float r, float b, flo return pout; } -void *d3d_matrix_multiply(void *_pout, const void *_pm1, const void *_pm2) +void *d3d_matrix_multiply(void *_pout, + const void *_pm1, const void *_pm2) { unsigned i,j; D3DMATRIX *pout = (D3DMATRIX*)_pout; @@ -127,3 +129,23 @@ void *d3d_matrix_rotation_z(void *_pout, float angle) pout->m[1][0] = -sin(angle); return pout; } + +int32_t d3d_translate_filter(unsigned type) +{ + switch (type) + { + case RARCH_FILTER_UNSPEC: + { + settings_t *settings = config_get_ptr(); + if (!settings->bools.video_smooth) + break; + } + /* fall-through */ + case RARCH_FILTER_LINEAR: + return (int32_t)D3DTEXF_LINEAR; + case RARCH_FILTER_NEAREST: + break; + } + + return (int32_t)D3DTEXF_POINT; +} diff --git a/gfx/common/d3d_common.h b/gfx/common/d3d_common.h index 083cfd7fa1..b951881ae2 100644 --- a/gfx/common/d3d_common.h +++ b/gfx/common/d3d_common.h @@ -33,248 +33,26 @@ typedef struct d3d_texture #define BYTE_CLAMP(i) (int) ((((i) > 255) ? 255 : (((i) < 0) ? 0 : (i)))) #endif -#ifndef D3DCOLOR_ARGB -#define D3DCOLOR_ARGB(_a, _r, _g, _b) ( (DWORD)( ( ( (_a)&0xff)<<24)|( ( (_r)&0xff)<<16)|( ( (_g)&0xff)<<8)|( (_b)&0xff) ) ) -#endif - #define D3DTADDRESS_COMM_CLAMP 3 #define D3DTEXF_COMM_LINEAR 2 #define D3DPT_COMM_TRIANGLESTRIP 5 -#define D3D_COMM_CLEAR_TARGET 0x00000001l /* Clear target surface */ - -bool d3d_swap(void *data, void *dev); - -void *d3d_vertex_buffer_new(void *dev, - unsigned length, unsigned usage, unsigned fvf, - INT32 pool, void *handle); - -void *d3d_vertex_buffer_lock(void *data); -void d3d_vertex_buffer_unlock(void *data); - -void d3d_vertex_buffer_free(void *vertex_data, void *vertex_declaration); - -bool d3d_texture_get_level_desc(void *tex, - unsigned idx, void *_ppsurface_level); - -bool d3d_texture_get_surface_level(void *tex, - unsigned idx, void **_ppsurface_level); - -void *d3d_texture_new(void *dev, - const char *path, unsigned width, unsigned height, - unsigned miplevels, unsigned usage, INT32 format, - INT32 pool, unsigned filter, unsigned mipfilter, - INT32 color_key, void *src_info, - PALETTEENTRY *palette, bool want_mipmap); - -void d3d_set_stream_source(void *dev, unsigned stream_no, - void *stream_vertbuf, unsigned offset_bytes, - unsigned stride); - -void d3d_texture_free(void *tex); - -void d3d_set_transform(void *dev, - INT32 state, const void *_matrix); - -void d3d_set_sampler_address_u(void *dev, - unsigned sampler, unsigned value); - -void d3d_set_sampler_address_v(void *dev, - unsigned sampler, unsigned value); - -void d3d_set_sampler_minfilter(void *dev, - unsigned sampler, unsigned value); - -void d3d_set_sampler_magfilter(void *dev, - unsigned sampler, unsigned value); - -void d3d_set_sampler_mipfilter(void *dev, - unsigned sampler, unsigned value); - -bool d3d_begin_scene(void *dev); - -void d3d_end_scene(void *dev); - -void d3d_draw_primitive(void *dev, - INT32 type, unsigned start, unsigned count); - -void d3d_clear(void *dev, - unsigned count, const void *rects, unsigned flags, - INT32 color, float z, unsigned stencil); - -bool d3d_lock_rectangle(void *tex, - unsigned level, void *lock_rect, RECT *rect, - unsigned rectangle_height, unsigned flags); - -void d3d_lock_rectangle_clear(void *tex, - unsigned level, void *lock_rect, RECT *rect, - unsigned rectangle_height, unsigned flags); - -void d3d_unlock_rectangle(void *tex); - -void d3d_set_texture(void *dev, unsigned sampler, - void *tex_data); - -bool d3d_create_vertex_shader(void *dev, - const DWORD *a, void **b); - -bool d3d_create_pixel_shader(void *dev, - const DWORD *a, void **b); - -void d3d_free_pixel_shader(void *dev, void *data); - -void d3d_free_vertex_shader(void *dev, void *data); - -bool d3d_set_pixel_shader(void *dev, void *data); - -bool d3d_set_vertex_shader(void *dev, unsigned index, - void *data); - -bool d3d_set_vertex_shader_constantf(void *dev, - UINT start_register,const float* constant_data, unsigned vector4f_count); - -void d3d_texture_blit(unsigned pixel_size, - void *tex, - void *lr, const void *frame, - unsigned width, unsigned height, unsigned pitch); - -bool d3d_vertex_declaration_new(void *dev, - const void *vertex_data, void **decl_data); - -void d3d_vertex_declaration_free(void *data); - -void d3d_set_viewports(void *dev, void *vp); - -void d3d_enable_blend_func(void *data); - -void d3d_disable_blend_func(void *data); - -void d3d_set_vertex_declaration(void *data, void *vertex_data); - -void d3d_enable_alpha_blend_texture_func(void *data); - -void d3d_frame_postprocess(void *data); - -void d3d_surface_free(void *data); - -bool d3d_device_get_render_target_data(void *dev, - void *_src, void *_dst); - -bool d3d_device_get_render_target(void *dev, - unsigned idx, void **data); - -void d3d_device_set_render_target(void *dev, unsigned idx, - void *data); - -bool d3d_get_render_state(void *data, - INT32 state, DWORD *value); - -void d3d_set_render_state(void *data, - INT32 state, DWORD value); - -void d3d_device_set_render_target(void *dev, unsigned idx, - void *data); - -bool d3d_device_create_offscreen_plain_surface( - void *dev, - unsigned width, - unsigned height, - unsigned format, - unsigned pool, - void **surf_data, - void *data); - -bool d3d_surface_lock_rect(void *data, void *data2); - -void d3d_surface_unlock_rect(void *data); +/* Clear target surface */ +#define D3D_COMM_CLEAR_TARGET 0x00000001l void *d3d_matrix_transpose(void *_pout, const void *_pm); -void *d3d_matrix_multiply(void *_pout, - const void *_pm1, const void *_pm2); +void *d3d_matrix_identity(void *_pout); void *d3d_matrix_ortho_off_center_lh(void *_pout, float l, float r, float b, float t, float zn, float zf); -void * d3d_matrix_identity(void *_pout); +void *d3d_matrix_multiply(void *_pout, + const void *_pm1, const void *_pm2); void *d3d_matrix_rotation_z(void *_pout, float angle); -bool d3d_get_adapter_display_mode(void *d3d, - unsigned idx, - void *display_mode); - -bool d3d_create_device(void *dev, - void *d3dpp, - void *d3d, - HWND focus_window, - unsigned cur_mon_id); - -bool d3d_reset(void *dev, void *d3dpp); - -bool d3d_device_get_backbuffer(void *dev, - unsigned idx, unsigned swapchain_idx, - unsigned backbuffer_type, void **data); - -void d3d_device_free(void *dev, void *pd3d); - -void *d3d_create(void); - -bool d3d_initialize_symbols(enum gfx_ctx_api api); - -void d3d_deinitialize_symbols(void); - -bool d3d_check_device_type(void *d3d, - unsigned idx, - INT32 disp_format, - INT32 backbuffer_format, - bool windowed_mode); - -bool d3dx_create_font_indirect(void *dev, - void *desc, void **font_data); - -void d3dx_font_draw_text(void *data, void *sprite_data, void *string_data, - unsigned count, void *rect_data, unsigned format, unsigned color); - -void d3dx_font_get_text_metrics(void *data, void *metrics); - -void d3dxbuffer_release(void *data); - -void d3dx_font_release(void *data); - -INT32 d3d_translate_filter(unsigned type); - -bool d3dx_compile_shader( - const char *src, - unsigned src_data_len, - const void *pdefines, - void *pinclude, - const char *pfunctionname, - const char *pprofile, - unsigned flags, - void *ppshader, - void *pperrormsgs, - void *ppconstanttable); - -bool d3dx_compile_shader_from_file( - const char *src, - const void *pdefines, - void *pinclude, - const char *pfunctionname, - const char *pprofile, - unsigned flags, - void *ppshader, - void *pperrormsgs, - void *ppconstanttable); - -const void *d3dx_get_buffer_ptr(void *data); - -const bool d3dx_constant_table_set_float(void *p, - void *a, const void *b, float val); - -INT32 d3d_get_rgb565_format(void); -INT32 d3d_get_argb8888_format(void); -INT32 d3d_get_xrgb8888_format(void); +int32_t d3d_translate_filter(unsigned type); RETRO_END_DECLS diff --git a/gfx/common/drm_common.c b/gfx/common/drm_common.c index 33052c83e1..577d2f09a5 100644 --- a/gfx/common/drm_common.c +++ b/gfx/common/drm_common.c @@ -168,6 +168,18 @@ void drm_setup(int fd) RARCH_WARN("[DRM]: Cannot find original CRTC.\n"); } +float drm_get_refresh_rate(void *data) +{ + float refresh_rate = 0.0f; + + if (g_drm_mode) + { + refresh_rate = g_drm_mode->clock * 1000.0f / g_drm_mode->htotal / g_drm_mode->vtotal; + } + + return refresh_rate; +} + void drm_free(void) { if (g_drm_encoder) diff --git a/gfx/common/drm_common.h b/gfx/common/drm_common.h index 87458dac9a..e8cb3ac411 100644 --- a/gfx/common/drm_common.h +++ b/gfx/common/drm_common.h @@ -55,6 +55,8 @@ void drm_free(void); bool drm_get_connector(int fd, video_frame_info_t *video_info); +float drm_get_refresh_rate(void *data); + static INLINE bool drm_wait_flip(int timeout) { g_drm_fds.revents = 0; diff --git a/gfx/common/dxgi_common.h b/gfx/common/dxgi_common.h index a35090dfb5..32af9b89b2 100644 --- a/gfx/common/dxgi_common.h +++ b/gfx/common/dxgi_common.h @@ -767,7 +767,7 @@ static INLINE HRESULT DXGICreateFactory(DXGIFactory* factory) #define DXGI_COLOR_RGBA(r, g, b, a) (((UINT32)(a) << 24) | ((UINT32)(b) << 16) | ((UINT32)(g) << 8) | ((UINT32)(r) << 0)) typedef enum { - DXGI_FORMAT_EX_A4R4G4B4_UNORM = 1000, + DXGI_FORMAT_EX_A4R4G4B4_UNORM = 1000 } DXGI_FORMAT_EX; typedef struct diff --git a/gfx/common/gx2_common.h b/gfx/common/gx2_common.h index 3ab9d9eefe..3b424f4b44 100644 --- a/gfx/common/gx2_common.h +++ b/gfx/common/gx2_common.h @@ -2,11 +2,13 @@ #include -#include "gfx/drivers/gx2_shaders/frame.h" -#include "gfx/drivers/gx2_shaders/tex.h" -#include "gfx/drivers/gx2_shaders/sprite.h" -#include "gfx/drivers/gx2_shaders/menu_shaders.h" -#include "gfx/video_shader_parse.h" +#include "../video_defines.h" +#include "../video_shader_parse.h" + +#include "../drivers/gx2_shaders/frame.h" +#include "../drivers/gx2_shaders/tex.h" +#include "../drivers/gx2_shaders/sprite.h" +#include "../drivers/gx2_shaders/menu_shaders.h" #undef _X #undef _B @@ -23,7 +25,6 @@ #define _1 0x05 #define GX2_COMP_SEL(c0, c1, c2, c3) (((c0) << 24) | ((c1) << 16) | ((c2) << 8) | (c3)) -#define COLOR_ABGR(r, g, b, a) (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(g) << 8) | ((u32)(r) << 0)) #define COLOR_ARGB(r, g, b, a) (((u32)(a) << 24) | ((u32)(r) << 16) | ((u32)(g) << 8) | ((u32)(b) << 0)) #define COLOR_RGBA(r, g, b, a) (((u32)(r) << 24) | ((u32)(g) << 16) | ((u32)(b) << 8) | ((u32)(a) << 0)) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 3f789fa8e7..c1231e780b 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -31,10 +31,10 @@ #include "../../libretro-common/include/retro_timers.h" #include "../../configuration.h" -static dylib_t vulkan_library; -static VkInstance cached_instance; -static VkDevice cached_device; -static retro_vulkan_destroy_device_t cached_destroy_device; +static dylib_t vulkan_library; +static VkInstance cached_instance_vk; +static VkDevice cached_device_vk; +static retro_vulkan_destroy_device_t cached_destroy_device_vk; #ifdef VULKAN_DEBUG static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_cb( @@ -962,6 +962,34 @@ void vulkan_image_layout_transition( 1, &barrier); } +void vulkan_image_layout_transition_levels( + VkCommandBuffer cmd, VkImage image, uint32_t levels, + VkImageLayout old_layout, VkImageLayout new_layout, + VkAccessFlags src_access, VkAccessFlags dst_access, + VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages) +{ + VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + + barrier.srcAccessMask = src_access; + barrier.dstAccessMask = dst_access; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.levelCount = levels; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + + vkCmdPipelineBarrier(cmd, + src_stages, + dst_stages, + false, + 0, NULL, + 0, NULL, + 1, &barrier); +} + struct vk_buffer vulkan_create_buffer( const struct vulkan_context *context, size_t size, VkBufferUsageFlags usage) @@ -1437,7 +1465,7 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) iface = NULL; } - if (!cached_device && iface && iface->create_device) + if (!cached_device_vk && iface && iface->create_device) { struct retro_vulkan_context context = { 0 }; const VkPhysicalDeviceFeatures features = { 0 }; @@ -1478,10 +1506,10 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) } } - if (cached_device && cached_destroy_device) + if (cached_device_vk && cached_destroy_device_vk) { - vk->context.destroy_device = cached_destroy_device; - cached_destroy_device = NULL; + vk->context.destroy_device = cached_destroy_device_vk; + cached_destroy_device_vk = NULL; } if (!vulkan_context_init_gpu(vk)) @@ -1565,10 +1593,10 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) device_info.ppEnabledLayerNames = device_layers; #endif - if (cached_device) + if (cached_device_vk) { - vk->context.device = cached_device; - cached_device = NULL; + vk->context.device = cached_device_vk; + cached_device_vk = NULL; video_driver_set_video_cache_context_ack(); RARCH_LOG("[Vulkan]: Using cached Vulkan context.\n"); @@ -1736,10 +1764,10 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, } } - if (cached_instance) + if (cached_instance_vk) { - vk->context.instance = cached_instance; - cached_instance = NULL; + vk->context.instance = cached_instance_vk; + cached_instance_vk = NULL; res = VK_SUCCESS; } else @@ -2239,9 +2267,9 @@ void vulkan_context_destroy(gfx_ctx_vulkan_data_t *vk, if (video_driver_is_video_cache_context()) { - cached_device = vk->context.device; - cached_instance = vk->context.instance; - cached_destroy_device = vk->context.destroy_device; + cached_device_vk = vk->context.device; + cached_instance_vk = vk->context.instance; + cached_destroy_device_vk = vk->context.destroy_device; } else { @@ -2253,6 +2281,7 @@ void vulkan_context_destroy(gfx_ctx_vulkan_data_t *vk, vk->context.destroy_device(); vkDestroyInstance(vk->context.instance, NULL); + if (vulkan_library) { dylib_close(vulkan_library); diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index e4714142ef..d154d77ac7 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -446,6 +446,12 @@ void vulkan_image_layout_transition(vk_t *vk, VkAccessFlags srcAccess, VkAccessFlags dstAccess, VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages); +void vulkan_image_layout_transition_levels( + VkCommandBuffer cmd, VkImage image, uint32_t levels, + VkImageLayout old_layout, VkImageLayout new_layout, + VkAccessFlags src_access, VkAccessFlags dst_access, + VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages); + static INLINE unsigned vulkan_format_to_bpp(VkFormat format) { switch (format) diff --git a/gfx/common/win32_common.c b/gfx/common/win32_common.c index 6a1af71c1f..b29359a8ce 100644 --- a/gfx/common/win32_common.c +++ b/gfx/common/win32_common.c @@ -13,6 +13,22 @@ * If not, see . */ +#if !defined(_XBOX) + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0601 /* Windows 7 */ +#endif + +#if !defined(_MSC_VER) || _WIN32_WINNT >= 0x0601 +#undef WINVER +#define WINVER 0x0601 +#endif + +#define IDI_ICON 1 + +#include +#endif /* !defined(_XBOX) */ + #include #include @@ -33,13 +49,6 @@ #if !defined(_XBOX) -#define IDI_ICON 1 - -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 /* _WIN32_WINNT_WIN2K */ -#endif - -#include #include #include #include "../../retroarch.h" @@ -83,18 +92,22 @@ extern void *dinput_wgl; extern void *dinput; #endif -unsigned g_resize_width = 0; -unsigned g_resize_height = 0; static bool g_resized = false; bool g_restore_desktop = false; static bool doubleclick_on_titlebar = false; +static bool g_taskbar_is_created = false; bool g_inited = false; static bool g_quit = false; + static int g_pos_x = CW_USEDEFAULT; static int g_pos_y = CW_USEDEFAULT; -static void *curD3D = NULL; -static bool g_taskbar_is_created = false; + +unsigned g_resize_width = 0; +unsigned g_resize_height = 0; static unsigned g_taskbar_message = 0; +static unsigned win32_monitor_count = 0; + +static void *curD3D = NULL; ui_window_win32_t main_window; @@ -147,7 +160,6 @@ typedef REASON_CONTEXT POWER_REQUEST_CONTEXT, *PPOWER_REQUEST_CONTEXT, *LPPOWER_ static HMONITOR win32_monitor_last; static HMONITOR win32_monitor_all[MAX_MONITORS]; -static unsigned win32_monitor_count = 0; bool win32_taskbar_is_created(void) { @@ -256,6 +268,19 @@ void win32_monitor_from_window(void) #endif } +int win32_change_display_settings(const char *str, void *devmode_data, + unsigned flags) +{ +#if _WIN32_WINDOWS >= 0x0410 || _WIN32_WINNT >= 0x0410 + /* Windows 98 and later codepath */ + return ChangeDisplaySettingsEx(str, (DEVMODE*)devmode_data, + NULL, flags, NULL); +#else + /* Windows 95 / NT codepath */ + return ChangeDisplaySettings((DEVMODE*)devmode_data, flags); +#endif +} + void win32_monitor_get_info(void) { MONITORINFOEX current_mon; @@ -265,13 +290,7 @@ void win32_monitor_get_info(void) GetMonitorInfo(win32_monitor_last, (LPMONITORINFO)¤t_mon); -#if _WIN32_WINDOWS >= 0x0410 || _WIN32_WINNT >= 0x0410 - /* Windows 98 and later codepath */ - ChangeDisplaySettingsEx(current_mon.szDevice, NULL, NULL, 0, NULL); -#else - /* Windows 95 / NT codepath */ - ChangeDisplaySettings(NULL, 0); -#endif + win32_change_display_settings(current_mon.szDevice, NULL, 0); } void win32_monitor_info(void *data, void *hm_data, unsigned *mon_id) @@ -373,10 +392,10 @@ static int win32_drag_query_file(HWND hwnd, WPARAM wparam) { const core_info_t *info = (const core_info_t*)&core_info[i]; - if(!string_is_equal(info->systemname, current_core->systemname)) + if (!string_is_equal(info->systemname, current_core->systemname)) break; - if(string_is_equal(path_get(RARCH_PATH_CORE), info->path)) + if (string_is_equal(path_get(RARCH_PATH_CORE), info->path)) { /* Our previous core supports the current rom */ content_ctx_info_t content_info = {0}; @@ -391,29 +410,22 @@ static int win32_drag_query_file(HWND hwnd, WPARAM wparam) } /* Poll for cores for current rom since none exist. */ - if(list_size ==1) + if (list_size ==1) { /*pick core that only exists and is bound to work. Ish. */ const core_info_t *info = (const core_info_t*)&core_info[0]; if (info) task_push_load_content_with_new_core_from_companion_ui( - info->path, NULL, - &content_info, - NULL, NULL); + info->path, NULL, &content_info, NULL, NULL); } else { /* Pick one core that could be compatible, ew */ - if(DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_PICKCORE), + if (DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_PICKCORE), hwnd,PickCoreProc,(LPARAM)NULL)==IDOK) - { task_push_load_content_with_current_core_from_companion_ui( - NULL, - &content_info, - CORE_TYPE_PLAIN, - NULL, NULL); - } + NULL, &content_info, CORE_TYPE_PLAIN, NULL, NULL); } } @@ -424,9 +436,7 @@ static int win32_drag_query_file(HWND hwnd, WPARAM wparam) static LRESULT win32_handle_keyboard_event(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - unsigned keycode; - uint16_t mod = 0; - bool keydown = true; + uint16_t mod = 0; if (GetKeyState(VK_SHIFT) & 0x80) mod |= RETROKMOD_SHIFT; @@ -447,7 +457,7 @@ static LRESULT win32_handle_keyboard_event(HWND hwnd, UINT message, * WM_CHAR and WM_KEYDOWN properly. */ case WM_CHAR: - input_keyboard_event(keydown, RETROK_UNKNOWN, wparam, mod, + input_keyboard_event(true, RETROK_UNKNOWN, wparam, mod, RETRO_DEVICE_KEYBOARD); return TRUE; @@ -455,34 +465,35 @@ static LRESULT win32_handle_keyboard_event(HWND hwnd, UINT message, case WM_SYSKEYUP: case WM_KEYDOWN: case WM_SYSKEYDOWN: - /* Key released? */ - if (message == WM_KEYUP || message == WM_SYSKEYUP) - keydown = false; - -#if _WIN32_WINNT >= 0x0501 /* XP */ - if (string_is_equal(config_get_ptr()->arrays.input_driver, "raw")) - keycode = input_keymaps_translate_keysym_to_rk((unsigned)(wparam)); - else -#endif - keycode = input_keymaps_translate_keysym_to_rk((lparam >> 16) & 0xff); - - input_keyboard_event(keydown, keycode, 0, mod, RETRO_DEVICE_KEYBOARD); - - if (message == WM_SYSKEYDOWN) { - switch (wparam) - { - case VK_F10: - case VK_MENU: - case VK_RSHIFT: - return 0; - default: - break; - } - } - else - return 0; + unsigned keycode = 0; + bool keydown = true; + unsigned keysym = (lparam >> 16) & 0xff; +#if _WIN32_WINNT >= 0x0501 /* XP */ + settings_t *settings = config_get_ptr(); + if (settings && string_is_equal(settings->arrays.input_driver, "raw")) + keysym = (unsigned)wparam; +#endif + /* Key released? */ + if (message == WM_KEYUP || message == WM_SYSKEYUP) + keydown = false; + + keycode = input_keymaps_translate_keysym_to_rk(keysym); + + input_keyboard_event(keydown, keycode, + 0, mod, RETRO_DEVICE_KEYBOARD); + + if (message != WM_SYSKEYDOWN) + return 0; + + if ( + wparam == VK_F10 || + wparam == VK_MENU || + wparam == VK_RSHIFT + ) + return 0; + } break; } @@ -542,7 +553,8 @@ static LRESULT CALLBACK WndProcCommon(bool *quit, HWND hwnd, UINT message, break; case WM_SIZE: /* Do not send resize message if we minimize. */ - if (wparam != SIZE_MAXHIDE && wparam != SIZE_MINIMIZED) + if ( wparam != SIZE_MAXHIDE && + wparam != SIZE_MINIMIZED) { g_resize_width = LOWORD(lparam); g_resize_height = HIWORD(lparam); @@ -838,9 +850,7 @@ bool win32_window_create(void *data, unsigned style, bool win32_get_metrics(void *data, enum display_metric_types type, float *value) { -#ifdef _XBOX - return false; -#else +#ifndef _XBOX HDC monitor = GetDC(NULL); int pixels_x = GetDeviceCaps(monitor, HORZRES); int pixels_y = GetDeviceCaps(monitor, VERTRES); @@ -853,22 +863,22 @@ bool win32_get_metrics(void *data, { case DISPLAY_METRIC_MM_WIDTH: *value = physical_width; - break; + return true; case DISPLAY_METRIC_MM_HEIGHT: *value = physical_height; - break; + return true; case DISPLAY_METRIC_DPI: /* 25.4 mm in an inch. */ *value = 254 * pixels_x / physical_width / 10; - break; + return true; case DISPLAY_METRIC_NONE: default: *value = 0; - return false; + break; } - - return true; #endif + + return false; } void win32_monitor_init(void) @@ -900,14 +910,8 @@ static bool win32_monitor_set_fullscreen( RARCH_LOG("Setting fullscreen to %ux%u @ %uHz on device %s.\n", width, height, refresh, dev_name); -#if _WIN32_WINDOWS >= 0x0410 || _WIN32_WINNT >= 0x0410 - /* Windows 98 and later codepath */ - return ChangeDisplaySettingsEx(dev_name, &devmode, - NULL, CDS_FULLSCREEN, NULL) == DISP_CHANGE_SUCCESSFUL; -#else - /* Windows 95 / NT codepath */ - return ChangeDisplaySettings(&devmode, CDS_FULLSCREEN); -#endif + return win32_change_display_settings(dev_name, &devmode, + CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL; #endif } @@ -944,10 +948,11 @@ void win32_check_window(bool *quit, bool *resize, bool win32_suppress_screensaver(void *data, bool enable) { #ifndef _XBOX - if(enable) + if (enable) { - int major, minor; char tmp[PATH_MAX_LENGTH]; + int major = 0; + int minor = 0; const frontend_ctx_driver_t *frontend = frontend_get_ptr(); if (!frontend) @@ -969,16 +974,20 @@ bool win32_suppress_screensaver(void *data, bool enable) PowerSetRequestPtr powerSetRequest = (PowerSetRequestPtr)GetProcAddress(kernel32, "PowerSetRequest"); - if(powerCreateRequest && powerSetRequest) + if (powerCreateRequest && powerSetRequest) { POWER_REQUEST_CONTEXT RequestContext; HANDLE Request; - RequestContext.Version = POWER_REQUEST_CONTEXT_VERSION; - RequestContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING; - RequestContext.Reason.SimpleReasonString = (LPWSTR)L"RetroArch running"; + RequestContext.Version = + POWER_REQUEST_CONTEXT_VERSION; + RequestContext.Flags = + POWER_REQUEST_CONTEXT_SIMPLE_STRING; + RequestContext.Reason.SimpleReasonString = (LPWSTR) + L"RetroArch running"; - Request = powerCreateRequest(&RequestContext); + Request = + powerCreateRequest(&RequestContext); powerSetRequest( Request, PowerRequestDisplayRequired); return true; @@ -1032,8 +1041,7 @@ void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use, *style = WS_POPUP | WS_VISIBLE; if (!win32_monitor_set_fullscreen(*width, *height, - refresh, current_mon->szDevice)) - {} + refresh, current_mon->szDevice)) { } /* Display settings might have changed, get new coordinates. */ GetMonitorInfo(*hm_to_use, (LPMONITORINFO)current_mon); @@ -1141,11 +1149,9 @@ bool win32_set_video_mode(void *data, RARCH_ERR("GetMessage error code %d\n", GetLastError()); break; } - else - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + + TranslateMessage(&msg); + DispatchMessage(&msg); } if (g_quit) @@ -1237,7 +1243,7 @@ void win32_get_video_output_prev( EnumDisplaySettings(NULL, i, &dm) != 0; i++) { - if ( dm.dmPelsWidth == curr_width + if ( dm.dmPelsWidth == curr_width && dm.dmPelsHeight == curr_height) { if ( prev_width != curr_width @@ -1259,6 +1265,57 @@ void win32_get_video_output_prev( } } +float win32_get_refresh_rate(void *data) +{ + float refresh_rate = 0.0f; +#if _WIN32_WINNT >= 0x0601 || _WIN32_WINDOWS >= 0x0601 /* Win 7 */ + OSVERSIONINFO version_info; + DISPLAYCONFIG_TOPOLOGY_ID TopologyID; + unsigned int NumPathArrayElements = 0; + unsigned int NumModeInfoArrayElements = 0; + DISPLAYCONFIG_PATH_INFO *PathInfoArray = NULL; + DISPLAYCONFIG_MODE_INFO *ModeInfoArray = NULL; + int result = 0; + + version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx(&version_info)) + return refresh_rate; + + if (version_info.dwMajorVersion < 6 || + (version_info.dwMajorVersion == 6 && version_info.dwMinorVersion < 1)) + return refresh_rate; + + result = GetDisplayConfigBufferSizes(QDC_DATABASE_CURRENT, + &NumPathArrayElements, + &NumModeInfoArrayElements); + + if (result != ERROR_SUCCESS) + return refresh_rate; + + PathInfoArray = (DISPLAYCONFIG_PATH_INFO *) + malloc(sizeof(DISPLAYCONFIG_PATH_INFO) * NumPathArrayElements); + ModeInfoArray = (DISPLAYCONFIG_MODE_INFO *) + malloc(sizeof(DISPLAYCONFIG_MODE_INFO) * NumModeInfoArrayElements); + + result = QueryDisplayConfig(QDC_DATABASE_CURRENT, + &NumPathArrayElements, + PathInfoArray, + &NumModeInfoArrayElements, + ModeInfoArray, + &TopologyID); + if (result == ERROR_SUCCESS && NumPathArrayElements >= 1) + { + refresh_rate = (float) PathInfoArray[0].targetInfo.refreshRate.Numerator / + PathInfoArray[0].targetInfo.refreshRate.Denominator; + } + + free(ModeInfoArray); + free(PathInfoArray); + +#endif + return refresh_rate; +} + void win32_get_video_output_next( unsigned *width, unsigned *height) { @@ -1284,7 +1341,7 @@ void win32_get_video_output_next( break; } - if ( dm.dmPelsWidth == curr_width + if ( dm.dmPelsWidth == curr_width && dm.dmPelsHeight == curr_height) found = true; } @@ -1294,7 +1351,7 @@ void win32_get_video_output_size(unsigned *width, unsigned *height) { DEVMODE dm; memset(&dm, 0, sizeof(dm)); - dm.dmSize = sizeof(dm); + dm.dmSize = sizeof(dm); if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm) != 0) { diff --git a/gfx/common/win32_common.h b/gfx/common/win32_common.h index 963db7f2cf..40fa4d3b39 100644 --- a/gfx/common/win32_common.h +++ b/gfx/common/win32_common.h @@ -56,14 +56,15 @@ void win32_monitor_get_info(void); void win32_monitor_info(void *data, void *hm_data, unsigned *mon_id); +int win32_change_display_settings(const char *str, void *devmode_data, + unsigned flags); + void create_graphics_context(HWND hwnd, bool *quit); void create_gdi_context(HWND hwnd, bool *quit); bool gdi_has_menu_frame(void); -bool win32_shader_dlg_init(void); -void shader_dlg_show(HWND parent_hwnd); void shader_dlg_params_reload(void); #endif @@ -127,6 +128,8 @@ bool win32_taskbar_is_created(void); void win32_set_taskbar_created(bool created); +float win32_get_refresh_rate(void *data); + #if defined(HAVE_D3D8) || defined(HAVE_D3D9) || defined (HAVE_D3D10) || defined (HAVE_D3D11) || defined (HAVE_D3D12) LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); diff --git a/gfx/common/x11_common.c b/gfx/common/x11_common.c index fd2832536b..d8d3a353dd 100644 --- a/gfx/common/x11_common.c +++ b/gfx/common/x11_common.c @@ -66,7 +66,7 @@ Display *g_x11_dpy = NULL; unsigned g_x11_screen = 0; Colormap g_x11_cmap; -Window g_x11_win; +Window g_x11_win = None; static Atom XA_NET_WM_STATE; static Atom XA_NET_WM_STATE_FULLSCREEN; @@ -107,7 +107,7 @@ void x11_show_mouse(Display *dpy, Window win, bool state) x11_hide_mouse(dpy, win); } -void x11_windowed_fullscreen(Display *dpy, Window win) +void x11_set_net_wm_fullscreen(Display *dpy, Window win) { XEvent xev = {0}; @@ -234,6 +234,28 @@ void x11_suspend_screensaver(Window wnd, bool enable) x11_suspend_screensaver_xdg_screensaver(wnd, enable); } +float x11_get_refresh_rate(void *data) +{ + XWindowAttributes attr; + XF86VidModeModeLine modeline; + Screen *screen; + int screenid; + int dotclock; + + if (!g_x11_dpy || g_x11_win == None) + return 0.0f; + + if (!XGetWindowAttributes(g_x11_dpy, g_x11_win, &attr)) + return 0.0f; + + screen = attr.screen; + screenid = XScreenNumberOfScreen(screen); + + XF86VidModeGetModeLine(g_x11_dpy, screenid, &dotclock, &modeline); + + return (float) dotclock * 1000.0f / modeline.htotal / modeline.vtotal; +} + static bool get_video_mode(video_frame_info_t *video_info, Display *dpy, unsigned width, unsigned height, XF86VidModeModeInfo *mode, XF86VidModeModeInfo *desktop_mode) @@ -408,7 +430,8 @@ static void x11_handle_key_event(XEvent *event, XIC ic, bool filter) status = 0; /* XwcLookupString doesn't seem to work. */ - num = Xutf8LookupString(ic, &event->xkey, keybuf, ARRAY_SIZE(keybuf), &keysym, &status); + num = Xutf8LookupString(ic, &event->xkey, keybuf, + ARRAY_SIZE(keybuf), &keysym, &status); /* libc functions need UTF-8 locale to work properly, * which makes mbrtowc a bit impractical. @@ -417,7 +440,8 @@ static void x11_handle_key_event(XEvent *event, XIC ic, bool filter) num = utf8_conv_utf32(chars, ARRAY_SIZE(chars), keybuf, num); #else (void)ic; - num = XLookupString(&event->xkey, keybuf, sizeof(keybuf), &keysym, NULL); /* ASCII only. */ + num = XLookupString(&event->xkey, keybuf, + sizeof(keybuf), &keysym, NULL); /* ASCII only. */ for (i = 0; i < num; i++) chars[i] = keybuf[i] & 0x7f; #endif @@ -685,3 +709,104 @@ void x11_event_queue_check(XEvent *event) XIfEvent(g_x11_dpy, event, x11_wait_notify, NULL); } +static bool x11_check_atom_supported(Display *dpy, Atom atom) +{ + Atom XA_NET_SUPPORTED = XInternAtom(dpy, "_NET_SUPPORTED", True); + Atom type; + int format; + unsigned long nitems; + unsigned long bytes_after; + Atom *prop; + int i; + + if (XA_NET_SUPPORTED == None) + return false; + + XGetWindowProperty(dpy, DefaultRootWindow(dpy), XA_NET_SUPPORTED, + 0, UINT_MAX, False, XA_ATOM, &type, &format,&nitems, + &bytes_after, (unsigned char **) &prop); + + if (!prop || type != XA_ATOM) + return false; + + for (i = 0; i < nitems; i++) + { + if (prop[i] == atom) + { + XFree(prop); + return true; + } + } + + XFree(prop); + + return false; +} + +bool x11_has_net_wm_fullscreen(Display *dpy) +{ + XA_NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + + return x11_check_atom_supported(dpy, XA_NET_WM_STATE_FULLSCREEN); +} + +char *x11_get_wm_name(Display *dpy) +{ + Atom XA_NET_SUPPORTING_WM_CHECK = XInternAtom(g_x11_dpy, "_NET_SUPPORTING_WM_CHECK", False); + Atom XA_NET_WM_NAME = XInternAtom(g_x11_dpy, "_NET_WM_NAME", False); + Atom XA_UTF8_STRING = XInternAtom(g_x11_dpy, "UTF8_STRING", False); + int status; + Atom type; + int format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *propdata; + char *title; + Window window; + + if (!XA_NET_SUPPORTING_WM_CHECK || !XA_NET_WM_NAME) + return NULL; + + status = XGetWindowProperty(dpy, + DefaultRootWindow(dpy), + XA_NET_SUPPORTING_WM_CHECK, + 0, + 1, + False, + XA_WINDOW, + &type, + &format, + &nitems, + &bytes_after, + &propdata); + + if (status == Success && propdata) + window = ((Window *) propdata)[0]; + else + return NULL; + + XFree(propdata); + + status = XGetWindowProperty(dpy, + window, + XA_NET_WM_NAME, + 0, + 8192, + False, + XA_UTF8_STRING, + &type, + &format, + &nitems, + &bytes_after, + &propdata); + + if (status == Success && propdata) + title = strdup((char *) propdata); + else + return NULL; + + XFree(propdata); + + return title; +} + diff --git a/gfx/common/x11_common.h b/gfx/common/x11_common.h index 23fc4898bc..3aa8117075 100644 --- a/gfx/common/x11_common.h +++ b/gfx/common/x11_common.h @@ -29,7 +29,7 @@ extern Colormap g_x11_cmap; extern unsigned g_x11_screen; void x11_show_mouse(Display *dpy, Window win, bool state); -void x11_windowed_fullscreen(Display *dpy, Window win); +void x11_set_net_wm_fullscreen(Display *dpy, Window win); void x11_suspend_screensaver(Window win, bool enable); bool x11_enter_fullscreen(video_frame_info_t *video_info, Display *dpy, unsigned width, @@ -48,6 +48,8 @@ void x11_destroy_input_context(XIM *xim, XIC *xic); bool x11_get_metrics(void *data, enum display_metric_types type, float *value); +float x11_get_refresh_rate(void *data); + void x11_check_window(void *data, bool *quit, bool *resize, unsigned *width, unsigned *height, bool is_shutdown); @@ -75,5 +77,9 @@ void x11_install_quit_atom(void); void x11_event_queue_check(XEvent *event); +char *x11_get_wm_name(Display *dpy); + +bool x11_has_net_wm_fullscreen(Display *dpy); + #endif diff --git a/gfx/display_servers/dispserv_null.c b/gfx/display_servers/dispserv_null.c index aa02bcc9c4..8de3b98710 100644 --- a/gfx/display_servers/dispserv_null.c +++ b/gfx/display_servers/dispserv_null.c @@ -49,6 +49,8 @@ const video_display_server_t dispserv_null = { null_set_window_opacity, null_set_window_progress, NULL, + NULL, + NULL, "null" }; diff --git a/gfx/display_servers/dispserv_win32.c b/gfx/display_servers/dispserv_win32.c index ce72e247f9..d4514a9f90 100644 --- a/gfx/display_servers/dispserv_win32.c +++ b/gfx/display_servers/dispserv_win32.c @@ -67,8 +67,8 @@ be received by your application before it calls any ITaskbarList3 method. static void* win32_display_server_init(void) { - dispserv_win32_t *dispserv = (dispserv_win32_t*)calloc(1, sizeof(*dispserv)); HRESULT hr; + dispserv_win32_t *dispserv = (dispserv_win32_t*)calloc(1, sizeof(*dispserv)); (void)hr; @@ -77,11 +77,13 @@ static void* win32_display_server_init(void) #ifdef HAS_TASKBAR_EXT #ifdef __cplusplus - /* when compiling in C++ mode, GUIDs are references instead of pointers */ - hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&g_taskbarList); + /* When compiling in C++ mode, GUIDs are references instead of pointers */ + hr = CoCreateInstance(CLSID_TaskbarList, NULL, + CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&g_taskbarList); #else - /* mingw GUIDs are pointers instead of references since we're in C mode */ - hr = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskbarList3, (void**)&g_taskbarList); + /* Mingw GUIDs are pointers instead of references since we're in C mode */ + hr = CoCreateInstance(&CLSID_TaskbarList, NULL, + CLSCTX_INPROC_SERVER, &IID_ITaskbarList3, (void**)&g_taskbarList); #endif if (!SUCCEEDED(hr)) @@ -115,7 +117,8 @@ static bool win32_set_window_opacity(void *data, unsigned opacity) HWND hwnd = win32_get_window(); dispserv_win32_t *serv = (dispserv_win32_t*)data; - serv->opacity = opacity; + if (serv) + serv->opacity = opacity; #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* Set window transparency on Windows 2000 and above */ @@ -126,24 +129,23 @@ static bool win32_set_window_opacity(void *data, unsigned opacity) GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); return SetLayeredWindowAttributes(hwnd, 0, (255 * opacity) / 100, LWA_ALPHA); } - else - { - SetWindowLongPtr(hwnd, - GWL_EXSTYLE, - GetWindowLongPtr(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); - return true; - } -#endif + + SetWindowLongPtr(hwnd, + GWL_EXSTYLE, + GetWindowLongPtr(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); + return true; +#else return false; +#endif } static bool win32_set_window_progress(void *data, int progress, bool finished) { HWND hwnd = win32_get_window(); dispserv_win32_t *serv = (dispserv_win32_t*)data; - bool ret = false; - serv->progress = progress; + if (serv) + serv->progress = progress; #ifdef HAS_TASKBAR_EXT if (!g_taskbarList || !win32_taskbar_is_created()) @@ -151,53 +153,140 @@ static bool win32_set_window_progress(void *data, int progress, bool finished) if (progress == -1) { - if (ITaskbarList3_SetProgressState(g_taskbarList, hwnd, TBPF_INDETERMINATE) == S_OK) - ret = true; - - if (!ret) + if (ITaskbarList3_SetProgressState( + g_taskbarList, hwnd, TBPF_INDETERMINATE) != S_OK) return false; } else if (finished) { - if (ITaskbarList3_SetProgressState(g_taskbarList, hwnd, TBPF_NOPROGRESS) == S_OK) - ret = true; - - if (!ret) + if (ITaskbarList3_SetProgressState( + g_taskbarList, hwnd, TBPF_NOPROGRESS) != S_OK) return false; } else if (progress >= 0) { - if (ITaskbarList3_SetProgressState(g_taskbarList, hwnd, TBPF_NORMAL) == S_OK) - ret = true; - - if (!ret) + if (ITaskbarList3_SetProgressState( + g_taskbarList, hwnd, TBPF_NORMAL) != S_OK) return false; - if (ITaskbarList3_SetProgressValue(g_taskbarList, hwnd, progress, 100) == S_OK) - ret = true; + if (ITaskbarList3_SetProgressValue( + g_taskbarList, hwnd, progress, 100) != S_OK) + return false; } #endif - return ret; + return true; } static bool win32_set_window_decorations(void *data, bool on) { dispserv_win32_t *serv = (dispserv_win32_t*)data; - serv->decorations = on; + if (serv) + serv->decorations = on; - /* menu_setting performs a reinit instead to properly apply decoration changes */ + /* menu_setting performs a reinit instead to properly + * apply decoration changes */ return true; } +static bool win32_display_server_set_resolution(void *data, + unsigned width, unsigned height, int f_restore, int hz) +{ + LONG res; + DEVMODE curDevmode; + DEVMODE devmode; + + int iModeNum; + int freq = 0; + DWORD flags = 0; + int depth = 0; + dispserv_win32_t *serv = (dispserv_win32_t*)data; + + if (!serv) + return false; + + if (f_restore == 0) + freq = hz; + + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &curDevmode); + + /* Used to stop super resolution bug */ + if (width == curDevmode.dmPelsWidth) + width = 0; + if (width == 0) + width = curDevmode.dmPelsWidth; + if (height == 0) + height = curDevmode.dmPelsHeight; + if (depth == 0) + depth = curDevmode.dmBitsPerPel; + if (freq == 0) + freq = curDevmode.dmDisplayFrequency; + + for (iModeNum = 0; ; iModeNum++) + { + if (!EnumDisplaySettings(NULL, iModeNum, &devmode)) + break; + + if (devmode.dmPelsWidth != width) + continue; + + if (devmode.dmPelsHeight != height) + continue; + + if (devmode.dmBitsPerPel != depth) + continue; + + if (devmode.dmDisplayFrequency != freq) + continue; + + devmode.dmFields |= + DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; + res = + win32_change_display_settings(NULL, &devmode, CDS_TEST); + + switch (res) + { + case DISP_CHANGE_SUCCESSFUL: + res = win32_change_display_settings(NULL, &devmode, flags); + switch (res) + { + case DISP_CHANGE_SUCCESSFUL: + return true; + case DISP_CHANGE_NOTUPDATED: + return true; + default: + break; + } + break; + case DISP_CHANGE_RESTART: + break; + default: + break; + } + } + + return true; +} + +void win32_display_server_get_current_resolution( + unsigned *width, unsigned *height) +{ + if (width) + *width = GetSystemMetrics(SM_CYSCREEN); + if (height) + *height = GetSystemMetrics(SM_CXSCREEN); +} + const video_display_server_t dispserv_win32 = { win32_display_server_init, win32_display_server_destroy, win32_set_window_opacity, win32_set_window_progress, win32_set_window_decorations, + win32_display_server_get_current_resolution, + win32_display_server_set_resolution, "win32" }; diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 0d20343315..ee19ec0478 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -78,6 +78,8 @@ const video_display_server_t dispserv_x11 = { x11_set_window_opacity, NULL, x11_set_window_decorations, + NULL, /* get_current_resolution */ + NULL, /* set_resolution */ "x11" }; diff --git a/gfx/drivers/caca_gfx.c b/gfx/drivers/caca_gfx.c index ae50a65937..a9405a6be1 100644 --- a/gfx/drivers/caca_gfx.c +++ b/gfx/drivers/caca_gfx.c @@ -305,6 +305,7 @@ static void caca_set_osd_msg(void *data, } static const video_poke_interface_t caca_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, @@ -318,6 +319,7 @@ static const video_poke_interface_t caca_poke_interface = { NULL, NULL, NULL, + NULL, caca_set_texture_frame, NULL, caca_set_osd_msg, diff --git a/gfx/drivers/ctr_gfx.c b/gfx/drivers/ctr_gfx.c index bdb3a69596..74a5c074d2 100644 --- a/gfx/drivers/ctr_gfx.c +++ b/gfx/drivers/ctr_gfx.c @@ -1133,11 +1133,13 @@ static void ctr_set_osd_msg(void *data, } static const video_poke_interface_t ctr_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ ctr_load_texture, ctr_unload_texture, NULL, + NULL, ctr_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/d3d10.c b/gfx/drivers/d3d10.c index c0f41e9f2d..ea557a2084 100644 --- a/gfx/drivers/d3d10.c +++ b/gfx/drivers/d3d10.c @@ -1,4 +1,4 @@ -/* RetroArch - A frontend for libretro. +/* RetroArch - A frontend for libretro. * Copyright (C) 2014-2018 - Ali Bouhlel * * RetroArch is free software: you can redistribute it and/or modify it under the terms @@ -16,44 +16,215 @@ #define CINTERFACE #include + #include +#include #include "../../driver.h" #include "../../verbosity.h" #include "../../configuration.h" #include "../video_driver.h" +#include "../font_driver.h" #include "../common/win32_common.h" #include "../common/d3d10_common.h" #include "../common/dxgi_common.h" #include "../common/d3dcompiler_common.h" +#ifdef HAVE_MENU +#include "../../menu/menu_driver.h" +#endif -static void d3d10_set_filtering(void* data, unsigned index, bool smooth) +#ifdef HAVE_OVERLAY +static void d3d10_free_overlays(d3d10_video_t* d3d10) +{ + unsigned i; + for (i = 0; i < (unsigned)d3d10->overlays.count; i++) + d3d10_release_texture(&d3d10->overlays.textures[i]); + + Release(d3d10->overlays.vbo); +} + +static void +d3d10_overlay_vertex_geom(void* data, unsigned index, float x, float y, float w, float h) +{ + d3d10_sprite_t* sprites = NULL; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return; + + D3D10MapBuffer(d3d10->overlays.vbo, + D3D10_MAP_WRITE_NO_OVERWRITE, 0, (void**)&sprites); + sprites[index].pos.x = x; + sprites[index].pos.y = y; + sprites[index].pos.w = w; + sprites[index].pos.h = h; + D3D10UnmapBuffer(d3d10->overlays.vbo); +} + +static void d3d10_overlay_tex_geom(void* data, unsigned index, float u, float v, float w, float h) +{ + d3d10_sprite_t* sprites = NULL; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return; + + D3D10MapBuffer( + d3d10->overlays.vbo, + D3D10_MAP_WRITE_NO_OVERWRITE, 0, (void**)&sprites); + sprites[index].coords.u = u; + sprites[index].coords.v = v; + sprites[index].coords.w = w; + sprites[index].coords.h = h; + D3D10UnmapBuffer(d3d10->overlays.vbo); +} + +static void d3d10_overlay_set_alpha(void* data, unsigned index, float mod) +{ + d3d10_sprite_t* sprites = NULL; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return; + + D3D10MapBuffer( + d3d10->overlays.vbo, + D3D10_MAP_WRITE_NO_OVERWRITE, 0, (void**)&sprites); + sprites[index].colors[0] = DXGI_COLOR_RGBA(0xFF, 0xFF, 0xFF, mod * 0xFF); + sprites[index].colors[1] = sprites[index].colors[0]; + sprites[index].colors[2] = sprites[index].colors[0]; + sprites[index].colors[3] = sprites[index].colors[0]; + D3D10UnmapBuffer(d3d10->overlays.vbo); +} + +static bool d3d10_overlay_load(void* data, const void* image_data, unsigned num_images) +{ + D3D10_BUFFER_DESC desc; + unsigned i; + d3d10_sprite_t* sprites; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + const struct texture_image* images = (const struct texture_image*)image_data; + + if (!d3d10) + return false; + + d3d10_free_overlays(d3d10); + d3d10->overlays.count = num_images; + d3d10->overlays.textures = (d3d10_texture_t*)calloc( + num_images, sizeof(d3d10_texture_t)); + + desc.ByteWidth = sizeof(d3d10_sprite_t) * num_images; + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; +#if 0 + desc.StructureByteStride = 0; +#endif + D3D10CreateBuffer(d3d10->device, &desc, NULL, &d3d10->overlays.vbo); + + D3D10MapBuffer(d3d10->overlays.vbo, + D3D10_MAP_WRITE_DISCARD, 0, (void**)&sprites); + + for (i = 0; i < (unsigned)num_images; i++) + { + + d3d10->overlays.textures[i].desc.Width = images[i].width; + d3d10->overlays.textures[i].desc.Height = images[i].height; + d3d10->overlays.textures[i].desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + + d3d10_init_texture(d3d10->device, &d3d10->overlays.textures[i]); + + d3d10_update_texture( + d3d10->device, + images[i].width, + images[i].height, 0, DXGI_FORMAT_B8G8R8A8_UNORM, + images[i].pixels, &d3d10->overlays.textures[i]); + + sprites[i].pos.x = 0.0f; + sprites[i].pos.y = 0.0f; + sprites[i].pos.w = 1.0f; + sprites[i].pos.h = 1.0f; + + sprites[i].coords.u = 0.0f; + sprites[i].coords.v = 0.0f; + sprites[i].coords.w = 1.0f; + sprites[i].coords.h = 1.0f; + + sprites[i].params.scaling = 1; + sprites[i].params.rotation = 0; + + sprites[i].colors[0] = 0xFFFFFFFF; + sprites[i].colors[1] = sprites[i].colors[0]; + sprites[i].colors[2] = sprites[i].colors[0]; + sprites[i].colors[3] = sprites[i].colors[0]; + } + D3D10UnmapBuffer(d3d10->overlays.vbo); + + return true; +} + +static void d3d10_overlay_enable(void* data, bool state) { d3d10_video_t* d3d10 = (d3d10_video_t*)data; - if (smooth) - d3d10->frame.sampler = d3d10->sampler_linear; - else - d3d10->frame.sampler = d3d10->sampler_nearest; + if (!d3d10) + return; + + d3d10->overlays.enabled = state; + win32_show_cursor(state); } +static void d3d10_overlay_full_screen(void* data, bool enable) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return; + + d3d10->overlays.fullscreen = enable; +} + +static void d3d10_get_overlay_interface(void* data, const video_overlay_interface_t** iface) +{ + static const video_overlay_interface_t overlay_interface = { + d3d10_overlay_enable, d3d10_overlay_load, d3d10_overlay_tex_geom, + d3d10_overlay_vertex_geom, d3d10_overlay_full_screen, d3d10_overlay_set_alpha, + }; + + *iface = &overlay_interface; +} +#endif + +static void d3d10_set_filtering(void* data, unsigned index, bool smooth) +{ + unsigned i; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + for (i = 0; i < RARCH_WRAP_MAX; i++) + { + if (smooth) + d3d10->samplers[RARCH_FILTER_UNSPEC][i] = d3d10->samplers[RARCH_FILTER_LINEAR][i]; + else + d3d10->samplers[RARCH_FILTER_UNSPEC][i] = d3d10->samplers[RARCH_FILTER_NEAREST][i]; + } +} + + static void d3d10_gfx_set_rotation(void* data, unsigned rotation) { - math_matrix_4x4 rot; - math_matrix_4x4* mvp; - d3d10_video_t* d3d10 = (d3d10_video_t*)data; + math_matrix_4x4 rot; + void* mapped_ubo = NULL; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; - if(!d3d10) + if (!d3d10) return; - d3d10->frame.rotation = rotation; + matrix_4x4_rotate_z(rot, rotation * (M_PI / 2.0f)); + matrix_4x4_multiply(d3d10->mvp, rot, d3d10->ubo_values.mvp); - - matrix_4x4_rotate_z(rot, d3d10->frame.rotation * (M_PI / 2.0f)); - matrix_4x4_multiply(d3d10->mvp, rot, d3d10->mvp_no_rot); - - D3D10MapBuffer(d3d10->frame.ubo, D3D10_MAP_WRITE_DISCARD, 0, (void**)&mvp); - *mvp = d3d10->mvp; + D3D10MapBuffer(d3d10->frame.ubo, D3D10_MAP_WRITE_DISCARD, 0, &mapped_ubo); + *(math_matrix_4x4*)mapped_ubo = d3d10->mvp; D3D10UnmapBuffer(d3d10->frame.ubo); } @@ -63,22 +234,342 @@ static void d3d10_update_viewport(void* data, bool force_full) video_driver_update_viewport(&d3d10->vp, force_full, d3d10->keep_aspect); - d3d10->frame.viewport.TopLeftX = (float)d3d10->vp.x; - d3d10->frame.viewport.TopLeftY = (float)d3d10->vp.y; - d3d10->frame.viewport.Width = (float)d3d10->vp.width; - d3d10->frame.viewport.Height = (float)d3d10->vp.height; + d3d10->frame.viewport.TopLeftX = d3d10->vp.x; + d3d10->frame.viewport.TopLeftY = d3d10->vp.y; + d3d10->frame.viewport.Width = d3d10->vp.width; + d3d10->frame.viewport.Height = d3d10->vp.height; d3d10->frame.viewport.MaxDepth = 0.0f; d3d10->frame.viewport.MaxDepth = 1.0f; + if (d3d10->shader_preset && (d3d10->frame.output_size.x != d3d10->vp.width || + d3d10->frame.output_size.y != d3d10->vp.height)) + d3d10->resize_render_targets = true; + + d3d10->frame.output_size.x = d3d10->vp.width; + d3d10->frame.output_size.y = d3d10->vp.height; + d3d10->frame.output_size.z = 1.0f / d3d10->vp.width; + d3d10->frame.output_size.w = 1.0f / d3d10->vp.height; + d3d10->resize_viewport = false; } - static void* -d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) +static void d3d10_free_shader_preset(d3d10_video_t* d3d10) { - WNDCLASSEX wndclass = { 0 }; + unsigned i; + if (!d3d10->shader_preset) + return; + + for (i = 0; i < d3d10->shader_preset->passes; i++) + { + unsigned j; + + free(d3d10->shader_preset->pass[i].source.string.vertex); + free(d3d10->shader_preset->pass[i].source.string.fragment); + free(d3d10->pass[i].semantics.textures); + d3d10_release_shader(&d3d10->pass[i].shader); + d3d10_release_texture(&d3d10->pass[i].rt); + d3d10_release_texture(&d3d10->pass[i].feedback); + + for (j = 0; j < SLANG_CBUFFER_MAX; j++) + { + free(d3d10->pass[i].semantics.cbuffers[j].uniforms); + Release(d3d10->pass[i].buffers[j]); + } + } + + memset(d3d10->pass, 0, sizeof(d3d10->pass)); + + /* only free the history textures here */ + for (i = 1; i <= (unsigned)d3d10->shader_preset->history_size; i++) + d3d10_release_texture(&d3d10->frame.texture[i]); + + memset( + &d3d10->frame.texture[1], 0, + sizeof(d3d10->frame.texture[1]) * d3d10->shader_preset->history_size); + + for (i = 0; i < d3d10->shader_preset->luts; i++) + d3d10_release_texture(&d3d10->luts[i]); + + memset(d3d10->luts, 0, sizeof(d3d10->luts)); + + free(d3d10->shader_preset); + d3d10->shader_preset = NULL; + d3d10->init_history = false; + d3d10->resize_render_targets = false; +} + +static bool d3d10_gfx_set_shader(void* data, + enum rarch_shader_type type, const char* path) +{ +#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) + unsigned i; + config_file_t* conf = NULL; + d3d10_texture_t* source = NULL; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return false; + + D3D10Flush(d3d10->device); + d3d10_free_shader_preset(d3d10); + + if (!path) + return true; + + if (type != RARCH_SHADER_SLANG) + { + RARCH_WARN("Only .slang or .slangp shaders are supported. Falling back to stock.\n"); + return false; + } + + conf = config_file_new(path); + + if (!conf) + return false; + + d3d10->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d10->shader_preset)); + + if (!video_shader_read_conf_cgp(conf, d3d10->shader_preset)) + goto error; + + video_shader_resolve_relative(d3d10->shader_preset, path); + + source = &d3d10->frame.texture[0]; + for (i = 0; i < d3d10->shader_preset->passes; source = &d3d10->pass[i++].rt) + { + unsigned j; + /* clang-format off */ + semantics_map_t semantics_map = { + { + /* Original */ + { &d3d10->frame.texture[0].view, 0, + &d3d10->frame.texture[0].size_data, 0}, + + /* Source */ + { &source->view, 0, + &source->size_data, 0}, + + /* OriginalHistory */ + { &d3d10->frame.texture[0].view, sizeof(*d3d10->frame.texture), + &d3d10->frame.texture[0].size_data, sizeof(*d3d10->frame.texture)}, + + /* PassOutput */ + { &d3d10->pass[0].rt.view, sizeof(*d3d10->pass), + &d3d10->pass[0].rt.size_data, sizeof(*d3d10->pass)}, + + /* PassFeedback */ + { &d3d10->pass[0].feedback.view, sizeof(*d3d10->pass), + &d3d10->pass[0].feedback.size_data, sizeof(*d3d10->pass)}, + + /* User */ + { &d3d10->luts[0].view, sizeof(*d3d10->luts), + &d3d10->luts[0].size_data, sizeof(*d3d10->luts)}, + }, + { + &d3d10->mvp, /* MVP */ + &d3d10->pass[i].rt.size_data, /* OutputSize */ + &d3d10->frame.output_size, /* FinalViewportSize */ + &d3d10->pass[i].frame_count, /* FrameCount */ + } + }; + /* clang-format on */ + + if (!slang_process( + d3d10->shader_preset, i, RARCH_SHADER_HLSL, 40, &semantics_map, + &d3d10->pass[i].semantics)) + goto error; + + { + static const D3D10_INPUT_ELEMENT_DESC desc[] = { + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, position), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, texcoord), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + }; +#ifdef DEBUG + bool save_hlsl = true; +#else + bool save_hlsl = false; +#endif + static const char vs_ext[] = ".vs.hlsl"; + static const char ps_ext[] = ".ps.hlsl"; + char vs_path[PATH_MAX_LENGTH]; + char ps_path[PATH_MAX_LENGTH]; + const char* slang_path = d3d10->shader_preset->pass[i].source.path; + const char* vs_src = d3d10->shader_preset->pass[i].source.string.vertex; + const char* ps_src = d3d10->shader_preset->pass[i].source.string.fragment; + int base_len = strlen(slang_path) - strlen(".slang"); + + if (base_len <= 0) + base_len = strlen(slang_path); + + strncpy(vs_path, slang_path, base_len); + strncpy(ps_path, slang_path, base_len); + strncpy(vs_path + base_len, vs_ext, sizeof(vs_ext)); + strncpy(ps_path + base_len, ps_ext, sizeof(ps_ext)); + + if (!d3d10_init_shader( + d3d10->device, vs_src, 0, vs_path, "main", NULL, NULL, desc, countof(desc), + &d3d10->pass[i].shader)) + save_hlsl = true; + + if (!d3d10_init_shader( + d3d10->device, ps_src, 0, ps_path, NULL, "main", NULL, NULL, 0, + &d3d10->pass[i].shader)) + save_hlsl = true; + + if (save_hlsl) + { + FILE* fp = fopen(vs_path, "w"); + fwrite(vs_src, 1, strlen(vs_src), fp); + fclose(fp); + + fp = fopen(ps_path, "w"); + fwrite(ps_src, 1, strlen(ps_src), fp); + fclose(fp); + } + + free(d3d10->shader_preset->pass[i].source.string.vertex); + free(d3d10->shader_preset->pass[i].source.string.fragment); + + d3d10->shader_preset->pass[i].source.string.vertex = NULL; + d3d10->shader_preset->pass[i].source.string.fragment = NULL; + + if (!d3d10->pass[i].shader.vs || !d3d10->pass[i].shader.ps) + goto error; + } + + for (j = 0; j < SLANG_CBUFFER_MAX; j++) + { + D3D10_BUFFER_DESC desc; + desc.ByteWidth = d3d10->pass[i].semantics.cbuffers[j].size; + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (!desc.ByteWidth) + continue; + + D3D10CreateBuffer(d3d10->device, &desc, + NULL, &d3d10->pass[i].buffers[j]); + } + } + + for (i = 0; i < d3d10->shader_preset->luts; i++) + { + struct texture_image image = { 0 }; + image.supports_rgba = true; + + if (!image_texture_load(&image, d3d10->shader_preset->lut[i].path)) + goto error; + + d3d10->luts[i].desc.Width = image.width; + d3d10->luts[i].desc.Height = image.height; + d3d10->luts[i].desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + + if (d3d10->shader_preset->lut[i].mipmap) + d3d10->luts[i].desc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS; + + d3d10_init_texture(d3d10->device, &d3d10->luts[i]); + + d3d10_update_texture( + d3d10->device, + image.width, image.height, 0, + DXGI_FORMAT_R8G8B8A8_UNORM, image.pixels, + &d3d10->luts[i]); + + image_texture_free(&image); + } + + video_shader_resolve_current_parameters(conf, d3d10->shader_preset); + config_file_free(conf); + + d3d10->resize_render_targets = true; + d3d10->init_history = true; + + return true; + +error: + d3d10_free_shader_preset(d3d10); +#endif + + return false; +} + +static void d3d10_gfx_free(void* data) +{ + unsigned i; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return; + +#ifdef HAVE_OVERLAY + d3d10_free_overlays(d3d10); +#endif + + d3d10_free_shader_preset(d3d10); + + d3d10_release_texture(&d3d10->frame.texture[0]); + Release(d3d10->frame.ubo); + Release(d3d10->frame.vbo); + + d3d10_release_texture(&d3d10->menu.texture); + Release(d3d10->menu.vbo); + + d3d10_release_shader(&d3d10->sprites.shader); + d3d10_release_shader(&d3d10->sprites.shader_font); + Release(d3d10->sprites.vbo); + + for (i = 0; i < GFX_MAX_SHADERS; i++) + d3d10_release_shader(&d3d10->shaders[i]); + + Release(d3d10->menu_pipeline_vbo); + Release(d3d10->blend_pipeline); + + Release(d3d10->ubo); + + Release(d3d10->blend_enable); + Release(d3d10->blend_disable); + + for (i = 0; i < RARCH_WRAP_MAX; i++) + { + Release(d3d10->samplers[RARCH_FILTER_LINEAR][i]); + Release(d3d10->samplers[RARCH_FILTER_NEAREST][i]); + } + + Release(d3d10->state); + Release(d3d10->renderTargetView); + Release(d3d10->swapChain); + + font_driver_free_osd(); + +#if 0 + if (video_driver_is_video_cache_context()) + { + cached_device_d3d10 = d3d10->device; + cached_context = d3d10->context; + } + else +#endif + { + Release(d3d10->device); + } + + win32_monitor_from_window(); + win32_destroy_window(); + free(d3d10); +} + + static void* +d3d10_gfx_init(const video_info_t* video, + const input_driver_t** input, void** input_data) +{ + unsigned i; MONITORINFOEX current_mon; HMONITOR hm_to_use; + WNDCLASSEX wndclass = { 0 }; settings_t* settings = config_get_ptr(); d3d10_video_t* d3d10 = (d3d10_video_t*)calloc(1, sizeof(*d3d10)); @@ -96,38 +587,38 @@ d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** i d3d10->vp.full_height = video->height; if (!d3d10->vp.full_width) - d3d10->vp.full_width = current_mon.rcMonitor.right - current_mon.rcMonitor.left; + d3d10->vp.full_width = + current_mon.rcMonitor.right - current_mon.rcMonitor.left; if (!d3d10->vp.full_height) - d3d10->vp.full_height = current_mon.rcMonitor.bottom - current_mon.rcMonitor.top; + d3d10->vp.full_height = + current_mon.rcMonitor.bottom - current_mon.rcMonitor.top; - if (!win32_set_video_mode(d3d10, video->width, video->height, video->fullscreen)) + if (!win32_set_video_mode(d3d10, + d3d10->vp.full_width, d3d10->vp.full_height, video->fullscreen)) { RARCH_ERR("[D3D10]: win32_set_video_mode failed.\n"); goto error; } - dxgi_input_driver(settings->arrays.input_joypad_driver, input, input_data); { UINT flags = 0; DXGI_SWAP_CHAIN_DESC desc = {0}; - desc.BufferCount = 2; - desc.BufferDesc.Width = video->width; - desc.BufferDesc.Height = video->height; + desc.BufferCount = 1; + desc.BufferDesc.Width = d3d10->vp.full_width; + desc.BufferDesc.Height = d3d10->vp.full_height; desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; -#if 0 desc.BufferDesc.RefreshRate.Numerator = 60; desc.BufferDesc.RefreshRate.Denominator = 1; -#endif desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.OutputWindow = main_window.hwnd; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Windowed = TRUE; - desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; #if 0 - desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; + desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; #endif @@ -136,9 +627,11 @@ d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** i flags |= D3D10_CREATE_DEVICE_DEBUG; #endif - D3D10CreateDeviceAndSwapChain( - NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D10_SDK_VERSION, &desc, - (IDXGISwapChain**)&d3d10->swapChain, &d3d10->device); + if (FAILED(D3D10CreateDeviceAndSwapChain( + NULL, D3D10_DRIVER_TYPE_HARDWARE, + NULL, flags, D3D10_SDK_VERSION, &desc, + (IDXGISwapChain**)&d3d10->swapChain, &d3d10->device))) + goto error; } { @@ -149,164 +642,426 @@ d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** i Release(backBuffer); } - D3D10SetRenderTargets(d3d10->device, 1, &d3d10->renderTargetView, NULL); - d3d10->viewport.Width = video->width; - d3d10->viewport.Height = video->height; - d3d10->resize_viewport = true; - d3d10->keep_aspect = video->force_aspect; - d3d10->vsync = video->vsync; - d3d10->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; + D3D10SetRenderTargets(d3d10->device, 1, &d3d10->renderTargetView, NULL); - d3d10->frame.texture.desc.Format = - d3d10_get_closest_match_texture2D(d3d10->device, d3d10->format); - d3d10->frame.texture.desc.Usage = D3D10_USAGE_DEFAULT; + video_driver_set_size(&d3d10->vp.full_width, &d3d10->vp.full_height); + d3d10->viewport.Width = d3d10->vp.full_width; + d3d10->viewport.Height = d3d10->vp.full_height; + d3d10->resize_viewport = true; + d3d10->vsync = video->vsync; + d3d10->format = video->rgb32 ? + DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; + + d3d10->frame.texture[0].desc.Format = d3d10->format; + d3d10->frame.texture[0].desc.Usage = D3D10_USAGE_DEFAULT; + d3d10->frame.texture[0].desc.Width = 4; + d3d10->frame.texture[0].desc.Height = 4; + + d3d10_init_texture(d3d10->device, &d3d10->frame.texture[0]); d3d10->menu.texture.desc.Usage = D3D10_USAGE_DEFAULT; - matrix_4x4_ortho(d3d10->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + matrix_4x4_ortho(d3d10->ubo_values.mvp, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + + d3d10->ubo_values.OutputSize.width = d3d10->viewport.Width; + d3d10->ubo_values.OutputSize.height = d3d10->viewport.Height; { - D3D10_BUFFER_DESC desc; D3D10_SUBRESOURCE_DATA ubo_data; + D3D10_BUFFER_DESC desc; - desc.ByteWidth = sizeof(math_matrix_4x4); + desc.ByteWidth = sizeof(d3d10->ubo_values); desc.Usage = D3D10_USAGE_DYNAMIC; desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - ubo_data.pSysMem = &d3d10->mvp_no_rot; + ubo_data.pSysMem = &d3d10->ubo_values.mvp; ubo_data.SysMemPitch = 0; ubo_data.SysMemSlicePitch = 0; D3D10CreateBuffer(d3d10->device, &desc, &ubo_data, &d3d10->ubo); D3D10CreateBuffer(d3d10->device, &desc, NULL, &d3d10->frame.ubo); } + d3d10_gfx_set_rotation(d3d10, 0); { - unsigned k; - D3D10_SAMPLER_DESC desc; + D3D10_SAMPLER_DESC desc = { D3D10_FILTER_MIN_MAG_MIP_POINT }; + desc.MaxAnisotropy = 1; + desc.ComparisonFunc = D3D10_COMPARISON_NEVER; + desc.MinLOD = -D3D10_FLOAT32_MAX; + desc.MaxLOD = D3D10_FLOAT32_MAX; - desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT; - desc.AddressU = D3D10_TEXTURE_ADDRESS_BORDER; - desc.AddressV = D3D10_TEXTURE_ADDRESS_BORDER; - desc.AddressW = D3D10_TEXTURE_ADDRESS_BORDER; - desc.MipLODBias = 0.0f; - desc.MaxAnisotropy = 1; - desc.ComparisonFunc = D3D10_COMPARISON_NEVER; - desc.MinLOD = -D3D10_FLOAT32_MAX; - desc.MaxLOD = D3D10_FLOAT32_MAX; + /* Initialize samplers */ + for (i = 0; i < RARCH_WRAP_MAX; i++) + { + switch (i) + { + case RARCH_WRAP_BORDER: + desc.AddressU = D3D10_TEXTURE_ADDRESS_BORDER; + break; - for (k = 0; k < 4; k++) - desc.BorderColor[k] = 0.0f; + case RARCH_WRAP_EDGE: + desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP; + break; - D3D10CreateSamplerState(d3d10->device, &desc, &d3d10->sampler_nearest); + case RARCH_WRAP_REPEAT: + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + break; - desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - D3D10CreateSamplerState(d3d10->device, &desc, &d3d10->sampler_linear); + case RARCH_WRAP_MIRRORED_REPEAT: + desc.AddressU = D3D10_TEXTURE_ADDRESS_MIRROR; + break; + } + desc.AddressV = desc.AddressU; + desc.AddressW = desc.AddressU; + + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + D3D10CreateSamplerState(d3d10->device, &desc, + &d3d10->samplers[RARCH_FILTER_LINEAR][i]); + + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT; + D3D10CreateSamplerState(d3d10->device, &desc, + &d3d10->samplers[RARCH_FILTER_NEAREST][i]); + } } d3d10_set_filtering(d3d10, 0, video->smooth); { + D3D10_BUFFER_DESC desc; d3d10_vertex_t vertices[] = { { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 0.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, }; + D3D10_SUBRESOURCE_DATA + vertexData = { vertices }; - { - D3D10_SUBRESOURCE_DATA vertexData; - D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(vertices); + desc.Usage = D3D10_USAGE_IMMUTABLE; + desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; - desc.ByteWidth = sizeof(vertices); - desc.Usage = D3D10_USAGE_DYNAMIC; - desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; - desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; + D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->frame.vbo); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->menu.vbo); - vertexData.pSysMem = vertices; - vertexData.SysMemPitch = 0; - vertexData.SysMemSlicePitch = 0; - - D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->frame.vbo); - desc.Usage = D3D10_USAGE_IMMUTABLE; - desc.CPUAccessFlags = 0; - D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->menu.vbo); - } - D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + d3d10->sprites.capacity = 4096; + desc.ByteWidth = sizeof(d3d10_sprite_t) * d3d10->sprites.capacity; + D3D10CreateBuffer(d3d10->device, &desc, NULL, &d3d10->sprites.vbo); } { - D3DBlob vs_code; - D3DBlob ps_code; - - static const char stock[] = -#include "d3d_shaders/opaque_sm5.hlsl.h" - ; - D3D10_INPUT_ELEMENT_DESC desc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, position), - D3D10_INPUT_PER_VERTEX_DATA, 0 }, + D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, texcoord), - D3D10_INPUT_PER_VERTEX_DATA, 0 }, + D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d10_vertex_t, color), - D3D10_INPUT_PER_VERTEX_DATA, 0 }, + D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - d3d_compile(stock, sizeof(stock), NULL, "VSMain", "vs_4_0", &vs_code); - d3d_compile(stock, sizeof(stock), NULL, "PSMain", "ps_4_0", &ps_code); + static const char shader[] = +#include "d3d_shaders/opaque_sm5.hlsl.h" + ; - D3D10CreateVertexShader( - d3d10->device, D3DGetBufferPointer(vs_code), D3DGetBufferSize(vs_code), &d3d10->vs); - D3D10CreatePixelShader( - d3d10->device, D3DGetBufferPointer(ps_code), D3DGetBufferSize(ps_code), &d3d10->ps); - D3D10CreateInputLayout( - d3d10->device, desc, countof(desc), D3DGetBufferPointer(vs_code), - D3DGetBufferSize(vs_code), &d3d10->layout); - - Release(vs_code); - Release(ps_code); + if (!d3d10_init_shader( + d3d10->device, shader, sizeof(shader), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d10->shaders[VIDEO_SHADER_STOCK_BLEND])) + goto error; } - D3D10SetInputLayout(d3d10->device, d3d10->layout); - D3D10SetVShader(d3d10->device, d3d10->vs); - D3D10SetPShader(d3d10->device, d3d10->ps); - { - unsigned k; - D3D10_BLEND_DESC blend_desc; + D3D10_INPUT_ELEMENT_DESC desc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d10_sprite_t, pos), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d10_sprite_t, coords), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d10_sprite_t, colors[0]), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d10_sprite_t, colors[1]), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 2, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d10_sprite_t, colors[2]), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 3, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d10_sprite_t, colors[3]), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "PARAMS", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_sprite_t, params), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + }; + static const char shader[] = +#include "d3d_shaders/sprite_sm4.hlsl.h" + ; + if (!d3d10_init_shader( + d3d10->device, shader, sizeof(shader), NULL, "VSMain", "PSMain", "GSMain", desc, + countof(desc), &d3d10->sprites.shader)) + goto error; + if (!d3d10_init_shader( + d3d10->device, shader, sizeof(shader), NULL, "VSMain", "PSMainA8", "GSMain", desc, + countof(desc), &d3d10->sprites.shader_font)) + goto error; + } - for (k = 0; k < 8; k++) + if (string_is_equal(settings->arrays.menu_driver, "xmb")) + { { - blend_desc.BlendEnable[k] = TRUE; - blend_desc.RenderTargetWriteMask[k] = D3D10_COLOR_WRITE_ENABLE_ALL; + D3D10_INPUT_ELEMENT_DESC desc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, + }; + + static const char ribbon[] = +#include "d3d_shaders/ribbon_sm4.hlsl.h" + ; + static const char ribbon_simple[] = +#include "d3d_shaders/ribbon_simple_sm4.hlsl.h" + ; + + if (!d3d10_init_shader( + d3d10->device, ribbon, sizeof(ribbon), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d10->shaders[VIDEO_SHADER_MENU])) + goto error; + + if (!d3d10_init_shader( + d3d10->device, ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "PSMain", NULL, + desc, countof(desc), &d3d10->shaders[VIDEO_SHADER_MENU_2])) + goto error; } - blend_desc.AlphaToCoverageEnable = FALSE; - blend_desc.SrcBlend = D3D10_BLEND_SRC_ALPHA; - blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; - blend_desc.BlendOp = D3D10_BLEND_OP_ADD; - blend_desc.SrcBlendAlpha = D3D10_BLEND_SRC_ALPHA; - blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; - blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; + { + D3D10_INPUT_ELEMENT_DESC desc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, position), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, texcoord), + D3D10_INPUT_PER_VERTEX_DATA, 0 }, + }; + static const char simple_snow[] = +#include "d3d_shaders/simple_snow_sm4.hlsl.h" + ; + static const char snow[] = +#include "d3d_shaders/snow_sm4.hlsl.h" + ; + static const char bokeh[] = +#include "d3d_shaders/bokeh_sm4.hlsl.h" + ; + static const char snowflake[] = +#include "d3d_shaders/snowflake_sm4.hlsl.h" + ; + + if (!d3d10_init_shader( + d3d10->device, simple_snow, sizeof(simple_snow), NULL, "VSMain", "PSMain", NULL, + desc, countof(desc), &d3d10->shaders[VIDEO_SHADER_MENU_3])) + goto error; + if (!d3d10_init_shader( + d3d10->device, snow, sizeof(snow), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d10->shaders[VIDEO_SHADER_MENU_4])) + goto error; + + if (!d3d10_init_shader( + d3d10->device, bokeh, sizeof(bokeh), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d10->shaders[VIDEO_SHADER_MENU_5])) + goto error; + + if (!d3d10_init_shader( + d3d10->device, snowflake, sizeof(snowflake), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d10->shaders[VIDEO_SHADER_MENU_6])) + goto error; + } + } + + { + D3D10_BLEND_DESC blend_desc = { 0 }; + + blend_desc.AlphaToCoverageEnable = FALSE; + blend_desc.BlendEnable[0] = TRUE; + blend_desc.SrcBlend = D3D10_BLEND_SRC_ALPHA; + blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; + blend_desc.BlendOp = D3D10_BLEND_OP_ADD; + blend_desc.SrcBlendAlpha = D3D10_BLEND_SRC_ALPHA; + blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; + blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; + blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; D3D10CreateBlendState(d3d10->device, &blend_desc, &d3d10->blend_enable); + + blend_desc.SrcBlend = D3D10_BLEND_ONE; + blend_desc.DestBlend = D3D10_BLEND_ONE; + D3D10CreateBlendState(d3d10->device, &blend_desc, &d3d10->blend_pipeline); + blend_desc.BlendEnable[0] = FALSE; D3D10CreateBlendState(d3d10->device, &blend_desc, &d3d10->blend_disable); + } + + { + D3D10_RASTERIZER_DESC desc = { (D3D10_FILL_MODE)0 }; + + desc.FillMode = D3D10_FILL_SOLID; + desc.CullMode = D3D10_CULL_NONE; + + D3D10CreateRasterizerState(d3d10->device, &desc, &d3d10->state); } + D3D10SetState(d3d10->device, d3d10->state); + + font_driver_init_osd(d3d10, false, video->is_threaded, FONT_DRIVER_RENDER_D3D10_API); + + if (settings->bools.video_shader_enable) + { + const char* ext = path_get_extension(settings->paths.path_shader); + + if (ext && !strncmp(ext, "slang", 5)) + d3d10_gfx_set_shader(d3d10, RARCH_SHADER_SLANG, settings->paths.path_shader); + } + +#if 0 + if (video_driver_get_hw_context()->context_type == RETRO_HW_CONTEXT_DIRECT3D && + video_driver_get_hw_context()->version_major == 11) + { + d3d10->hw.enable = true; + d3d10->hw.iface.interface_type = RETRO_HW_RENDER_INTERFACE_D3D10; + d3d10->hw.iface.interface_version = RETRO_HW_RENDER_INTERFACE_D3D10_VERSION; + d3d10->hw.iface.handle = d3d10; + d3d10->hw.iface.device = d3d10->device; + d3d10->hw.iface.context = d3d10->context; + d3d10->hw.iface.featureLevel = d3d10->supportedFeatureLevel; + d3d10->hw.iface.D3DCompile = D3DCompile; + } +#endif + return d3d10; error: - free(d3d10); + d3d10_gfx_free(d3d10); return NULL; } +static void d3d10_init_history(d3d10_video_t* d3d10, unsigned width, unsigned height) +{ + unsigned i; + + /* todo: should we init history to max_width/max_height instead ? + * to prevent out of memory errors happening several frames later + * and to reduce memory fragmentation */ + + assert(d3d10->shader_preset); + for (i = 0; i < (unsigned)d3d10->shader_preset->history_size + 1; i++) + { + d3d10->frame.texture[i].desc.Width = width; + d3d10->frame.texture[i].desc.Height = height; + d3d10->frame.texture[i].desc.Format = d3d10->frame.texture[0].desc.Format; + d3d10->frame.texture[i].desc.Usage = d3d10->frame.texture[0].desc.Usage; + d3d10_init_texture(d3d10->device, &d3d10->frame.texture[i]); + /* todo: clear texture ? */ + } + d3d10->init_history = false; +} + +static void d3d10_init_render_targets(d3d10_video_t* d3d10, + unsigned width, unsigned height) +{ + unsigned i; + + assert(d3d10->shader_preset); + + for (i = 0; i < d3d10->shader_preset->passes; i++) + { + struct video_shader_pass* pass = &d3d10->shader_preset->pass[i]; + + if (pass->fbo.valid) + { + + switch (pass->fbo.type_x) + { + case RARCH_SCALE_INPUT: + width *= pass->fbo.scale_x; + break; + + case RARCH_SCALE_VIEWPORT: + width = d3d10->vp.width * pass->fbo.scale_x; + break; + + case RARCH_SCALE_ABSOLUTE: + width = pass->fbo.abs_x; + break; + + default: + break; + } + + if (!width) + width = d3d10->vp.width; + + switch (pass->fbo.type_y) + { + case RARCH_SCALE_INPUT: + height *= pass->fbo.scale_y; + break; + + case RARCH_SCALE_VIEWPORT: + height = d3d10->vp.height * pass->fbo.scale_y; + break; + + case RARCH_SCALE_ABSOLUTE: + height = pass->fbo.abs_y; + break; + + default: + break; + } + + if (!height) + height = d3d10->vp.height; + } + else if (i == (d3d10->shader_preset->passes - 1)) + { + width = d3d10->vp.width; + height = d3d10->vp.height; + } + + RARCH_LOG("[D3D10]: Updating framebuffer size %u x %u.\n", width, height); + + if ((i != (d3d10->shader_preset->passes - 1)) || (width != d3d10->vp.width) || + (height != d3d10->vp.height)) + { + d3d10->pass[i].viewport.Width = width; + d3d10->pass[i].viewport.Height = height; + d3d10->pass[i].viewport.MaxDepth = 1.0; + d3d10->pass[i].rt.desc.Width = width; + d3d10->pass[i].rt.desc.Height = height; + d3d10->pass[i].rt.desc.BindFlags = D3D10_BIND_RENDER_TARGET; + d3d10->pass[i].rt.desc.Format = glslang_format_to_dxgi(d3d10->pass[i].semantics.format); + d3d10_init_texture(d3d10->device, &d3d10->pass[i].rt); + + if (pass->feedback) + { + d3d10->pass[i].feedback.desc = d3d10->pass[i].rt.desc; + d3d10_init_texture(d3d10->device, &d3d10->pass[i].feedback); + /* todo: do we need to clear it to black here ? */ + } + } + else + { + d3d10->pass[i].rt.size_data.x = width; + d3d10->pass[i].rt.size_data.y = height; + d3d10->pass[i].rt.size_data.z = 1.0f / width; + d3d10->pass[i].rt.size_data.w = 1.0f / height; + } + } + + d3d10->resize_render_targets = false; + +#if 0 +error: + d3d10_free_shader_preset(d3d10); + return false; +#endif +} + static bool d3d10_gfx_frame( void* data, const void* frame, @@ -317,9 +1072,10 @@ static bool d3d10_gfx_frame( const char* msg, video_frame_info_t* video_info) { - (void)msg; - - d3d10_video_t* d3d10 = (d3d10_video_t*)data; + unsigned i; + d3d10_texture_t* texture = NULL; + d3d10_video_t * d3d10 = (d3d10_video_t*)data; + D3D10Device context = d3d10->device; if (d3d10->resize_chain) { @@ -337,71 +1093,291 @@ static bool d3d10_gfx_frame( d3d10->viewport.Width = video_info->width; d3d10->viewport.Height = video_info->height; + d3d10->ubo_values.OutputSize.width = d3d10->viewport.Width; + d3d10->ubo_values.OutputSize.height = d3d10->viewport.Height; + d3d10->resize_chain = false; d3d10->resize_viewport = true; + + video_driver_set_size(&video_info->width, &video_info->height); } PERF_START(); - D3D10ClearRenderTargetView(d3d10->device, d3d10->renderTargetView, d3d10->clearcolor); + +#if 0 /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ + if (d3d10->resize_viewport) +#endif + d3d10_update_viewport(d3d10, false); + + D3D10SetPrimitiveTopology(context, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + +#if 0 + if (d3d10->hw.enable) + { + D3D10SetRenderTargets(context, 1, &d3d10->renderTargetView, NULL); + D3D10SetState(context, d3d10->state); + } +#endif if (frame && width && height) { - D3D10_BOX frame_box = { 0, 0, 0, width, height, 1 }; - - if (d3d10->frame.texture.desc.Width != width || d3d10->frame.texture.desc.Height != height) + if (d3d10->shader_preset) { - d3d10->frame.texture.desc.Width = width; - d3d10->frame.texture.desc.Height = height; - d3d10_init_texture(d3d10->device, &d3d10->frame.texture); + if (d3d10->frame.texture[0].desc.Width != width || + d3d10->frame.texture[0].desc.Height != height) + d3d10->resize_render_targets = true; + + if (d3d10->resize_render_targets) + { + unsigned i; + + /* release all render targets first to avoid memory fragmentation */ + for (i = 0; i < d3d10->shader_preset->passes; i++) + { + d3d10_release_texture(&d3d10->pass[i].rt); + d3d10_release_texture(&d3d10->pass[i].feedback); + memset(&d3d10->pass[i].rt, 0, sizeof(d3d10->pass[i].rt)); + memset(&d3d10->pass[i].feedback, 0, sizeof(d3d10->pass[i].feedback)); + } + } + + if (d3d10->shader_preset->history_size) + { + if (d3d10->init_history) + d3d10_init_history(d3d10, width, height); + else + { + int k; + /* todo: what about frame-duping ? + * maybe clone d3d10_texture_t with AddRef */ + d3d10_texture_t tmp = d3d10->frame.texture[d3d10->shader_preset->history_size]; + for (k = d3d10->shader_preset->history_size; k > 0; k--) + d3d10->frame.texture[k] = d3d10->frame.texture[k - 1]; + d3d10->frame.texture[0] = tmp; + } + } } - d3d10_update_texture(width, height, pitch, d3d10->format, frame, &d3d10->frame.texture); - D3D10CopyTexture2DSubresourceRegion( - d3d10->device, d3d10->frame.texture.handle, 0, 0, 0, 0, d3d10->frame.texture.staging, 0, - &frame_box); + /* either no history, or we moved a texture of a different size in the front slot */ + if (d3d10->frame.texture[0].desc.Width != width || + d3d10->frame.texture[0].desc.Height != height) + { + d3d10->frame.texture[0].desc.Width = width; + d3d10->frame.texture[0].desc.Height = height; + d3d10_init_texture(d3d10->device, &d3d10->frame.texture[0]); + } + + if (d3d10->resize_render_targets) + d3d10_init_render_targets(d3d10, width, height); + + if (frame != RETRO_HW_FRAME_BUFFER_VALID) + d3d10_update_texture( + d3d10->device, + width, height, pitch, d3d10->format, frame, &d3d10->frame.texture[0]); } + D3D10SetVertexBuffer(context, 0, d3d10->frame.vbo, sizeof(d3d10_vertex_t), 0); + D3D10SetBlendState(context, d3d10->blend_disable, NULL, D3D10_DEFAULT_SAMPLE_MASK); + + texture = d3d10->frame.texture; + + if (d3d10->shader_preset) { - UINT stride = sizeof(d3d10_vertex_t); - UINT offset = 0; -#if 0 /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ - if (d3d10->resize_viewport) -#endif - d3d10_update_viewport(d3d10, false); + unsigned i; - D3D10SetViewports(d3d10->device, 1, &d3d10->frame.viewport); - D3D10SetVertexBuffers(d3d10->device, 0, 1, &d3d10->frame.vbo, &stride, &offset); - D3D10SetVShaderConstantBuffers(d3d10->device, 0, 1, &d3d10->frame.ubo); - D3D10SetPShaderResources(d3d10->device, 0, 1, &d3d10->frame.texture.view); - D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->frame.sampler); - - D3D10SetBlendState(d3d10->device, d3d10->blend_disable, NULL, D3D10_DEFAULT_SAMPLE_MASK); - D3D10Draw(d3d10->device, 4, 0); - D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); - - if (d3d10->menu.enabled && d3d10->menu.texture.handle) + for (i = 0; i < d3d10->shader_preset->passes; i++) { - if (d3d10->menu.texture.dirty) - D3D10CopyTexture2DSubresourceRegion( - d3d10->device, d3d10->menu.texture.handle, 0, 0, 0, 0, - d3d10->menu.texture.staging, 0, NULL); + if (d3d10->shader_preset->pass[i].feedback) + { + d3d10_texture_t tmp = d3d10->pass[i].feedback; + d3d10->pass[i].feedback = d3d10->pass[i].rt; + d3d10->pass[i].rt = tmp; + } + } - if (d3d10->menu.fullscreen) - D3D10SetViewports(d3d10->device, 1, &d3d10->viewport); - D3D10SetVertexBuffers(d3d10->device, 0, 1, &d3d10->menu.vbo, &stride, &offset); - D3D10SetVShaderConstantBuffers(d3d10->device, 0, 1, &d3d10->ubo); - D3D10SetPShaderResources(d3d10->device, 0, 1, &d3d10->menu.texture.view); - D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->menu.sampler); + for (i = 0; i < d3d10->shader_preset->passes; i++) + { + unsigned j; - D3D10Draw(d3d10->device, 4, 0); + d3d10_set_shader(context, &d3d10->pass[i].shader); + + if (d3d10->shader_preset->pass[i].frame_count_mod) + d3d10->pass[i].frame_count = + frame_count % d3d10->shader_preset->pass[i].frame_count_mod; + else + d3d10->pass[i].frame_count = frame_count; + + for (j = 0; j < SLANG_CBUFFER_MAX; j++) + { + D3D10Buffer buffer = d3d10->pass[i].buffers[j]; + cbuffer_sem_t* buffer_sem = &d3d10->pass[i].semantics.cbuffers[j]; + + if (buffer_sem->stage_mask && buffer_sem->uniforms) + { + void* data; + uniform_sem_t* uniform = buffer_sem->uniforms; + + D3D10MapBuffer(buffer, D3D10_MAP_WRITE_DISCARD, 0, (void**)&data); + while (uniform->size) + { + if (uniform->data) + memcpy((uint8_t*)data + uniform->offset, uniform->data, uniform->size); + uniform++; + } + D3D10UnmapBuffer(buffer); + + if (buffer_sem->stage_mask & SLANG_STAGE_VERTEX_MASK) + D3D10SetVShaderConstantBuffers(context, buffer_sem->binding, 1, &buffer); + + if (buffer_sem->stage_mask & SLANG_STAGE_FRAGMENT_MASK) + D3D10SetPShaderConstantBuffers(context, buffer_sem->binding, 1, &buffer); + } + } + + { + D3D10RenderTargetView null_rt = NULL; + D3D10SetRenderTargets(context, 1, &null_rt, NULL); + } + + { + D3D10ShaderResourceView textures[SLANG_NUM_BINDINGS] = { NULL }; + D3D10SamplerState samplers[SLANG_NUM_BINDINGS] = { NULL }; + + texture_sem_t* texture_sem = d3d10->pass[i].semantics.textures; + while (texture_sem->stage_mask) + { + int binding = texture_sem->binding; + textures[binding] = *(D3D10ShaderResourceView*)texture_sem->texture_data; + samplers[binding] = d3d10->samplers[texture_sem->filter][texture_sem->wrap]; + texture_sem++; + } + +#if 0 + if (d3d10->hw.enable && (i == 0)) + D3D10SetPShaderResources(context, 1, SLANG_NUM_BINDINGS - 1, textures + 1); + else +#endif + D3D10SetPShaderResources(context, 0, SLANG_NUM_BINDINGS, textures); + + D3D10SetPShaderSamplers(context, 0, SLANG_NUM_BINDINGS, samplers); + } + + if (d3d10->pass[i].rt.handle) + { + D3D10SetRenderTargets(context, 1, &d3d10->pass[i].rt.rt_view, NULL); +#if 0 + D3D10ClearRenderTargetView(context, d3d10->pass[i].rt.rt_view, d3d10->clearcolor); +#endif + D3D10SetViewports(context, 1, &d3d10->pass[i].viewport); + + D3D10Draw(context, 4, 0); + texture = &d3d10->pass[i].rt; + } + else + { + texture = NULL; + break; + } + } + D3D10SetRenderTargets(context, 1, &d3d10->renderTargetView, NULL); + } + + if (texture) + { + d3d10_set_shader(context, &d3d10->shaders[VIDEO_SHADER_STOCK_BLEND]); +#if 0 + /* TODO/FIXME */ + if (!d3d10->hw.enable || d3d10->shader_preset) +#endif + D3D10SetPShaderResources(context, 0, 1, &texture->view); + D3D10SetPShaderSamplers( + context, 0, 1, &d3d10->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); + D3D10SetVShaderConstantBuffers(context, 0, 1, &d3d10->frame.ubo); + } + + D3D10ClearRenderTargetView(context, d3d10->renderTargetView, d3d10->clearcolor); + D3D10SetViewports(context, 1, &d3d10->frame.viewport); + + D3D10Draw(context, 4, 0); + + D3D10SetBlendState(context, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); + + if (d3d10->menu.enabled && d3d10->menu.texture.handle) + { + if (d3d10->menu.fullscreen) + D3D10SetViewports(context, 1, &d3d10->viewport); + + d3d10_set_shader(context, &d3d10->shaders[VIDEO_SHADER_STOCK_BLEND]); + D3D10SetVertexBuffer(context, 0, d3d10->menu.vbo, sizeof(d3d10_vertex_t), 0); + D3D10SetVShaderConstantBuffers(context, 0, 1, &d3d10->ubo); + d3d10_set_texture_and_sampler(context, 0, &d3d10->menu.texture); + D3D10Draw(context, 4, 0); + } + + d3d10_set_shader(context, &d3d10->sprites.shader); + D3D10SetPrimitiveTopology(context, D3D10_PRIMITIVE_TOPOLOGY_POINTLIST); + D3D10SetVShaderConstantBuffer(context, 0, d3d10->ubo); + D3D10SetPShaderConstantBuffer(context, 0, d3d10->ubo); + + d3d10->sprites.enabled = true; + +#ifdef HAVE_MENU + if (d3d10->menu.enabled) + { + D3D10SetViewports(context, 1, &d3d10->viewport); + D3D10SetVertexBuffer(context, 0, d3d10->sprites.vbo, sizeof(d3d10_sprite_t), 0); + menu_driver_frame(video_info); + } + else +#endif + if (video_info->statistics_show) + { + struct font_params* osd_params = (struct font_params*)&video_info->osd_stat_params; + + if (osd_params) + { + D3D10SetViewports(context, 1, &d3d10->viewport); + D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); + D3D10SetVertexBuffer(context, 0, d3d10->sprites.vbo, sizeof(d3d10_sprite_t), 0); + font_driver_render_msg( + video_info, NULL, video_info->stat_text, + (const struct font_params*)&video_info->osd_stat_params); } } - DXGIPresent(d3d10->swapChain, !!d3d10->vsync, 0); - PERF_STOP(); +#ifdef HAVE_OVERLAY + if (d3d10->overlays.enabled) + { + if (d3d10->overlays.fullscreen) + D3D10SetViewports(context, 1, &d3d10->viewport); + else + D3D10SetViewports(context, 1, &d3d10->frame.viewport); + + D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); + D3D10SetVertexBuffer(context, 0, d3d10->overlays.vbo, sizeof(d3d10_sprite_t), 0); + D3D10SetPShaderSamplers( + context, 0, 1, &d3d10->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); + + for (i = 0; i < (unsigned)d3d10->overlays.count; i++) + { + D3D10SetPShaderResources(context, 0, 1, &d3d10->overlays.textures[i].view); + D3D10Draw(d3d10->device, 1, i); + } + } +#endif if (msg && *msg) + { + D3D10SetViewports(d3d10->device, 1, &d3d10->viewport); + D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); + D3D10SetVertexBuffer(d3d10->device, 0, d3d10->sprites.vbo, sizeof(d3d10_sprite_t), 0); + font_driver_render_msg(video_info, NULL, msg, NULL); dxgi_update_title(video_info); + } + d3d10->sprites.enabled = false; + + PERF_STOP(); + DXGIPresent(d3d10->swapChain, !!d3d10->vsync, 0); return true; } @@ -409,6 +1385,10 @@ static bool d3d10_gfx_frame( static void d3d10_gfx_set_nonblock_state(void* data, bool toggle) { d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return; + d3d10->vsync = !toggle; } @@ -440,45 +1420,14 @@ static bool d3d10_gfx_has_windowed(void* data) return true; } -static void d3d10_gfx_free(void* data) +static struct video_shader* d3d10_gfx_get_current_shader(void* data) { d3d10_video_t* d3d10 = (d3d10_video_t*)data; - Release(d3d10->frame.ubo); - Release(d3d10->frame.vbo); - Release(d3d10->frame.texture.view); - Release(d3d10->frame.texture.handle); - Release(d3d10->frame.texture.staging); + if (!d3d10) + return NULL; - Release(d3d10->menu.texture.handle); - Release(d3d10->menu.texture.staging); - Release(d3d10->menu.texture.view); - Release(d3d10->menu.vbo); - - Release(d3d10->ubo); - Release(d3d10->blend_enable); - Release(d3d10->blend_disable); - Release(d3d10->sampler_nearest); - Release(d3d10->sampler_linear); - Release(d3d10->ps); - Release(d3d10->vs); - Release(d3d10->layout); - Release(d3d10->renderTargetView); - Release(d3d10->swapChain); - Release(d3d10->device); - - win32_monitor_from_window(); - win32_destroy_window(); - free(d3d10); -} - -static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path) -{ - (void)data; - (void)type; - (void)path; - - return false; + return d3d10->shader_preset; } static void d3d10_gfx_viewport_info(void* data, struct video_viewport* vp) @@ -499,26 +1448,35 @@ static bool d3d10_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle) static void d3d10_set_menu_texture_frame( void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha) { - d3d10_video_t* d3d10 = (d3d10_video_t*)data; - int pitch = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t)); - DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + settings_t* settings = config_get_ptr(); + DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : + (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM; - if (d3d10->menu.texture.desc.Width != width || d3d10->menu.texture.desc.Height != height) + if ( + d3d10->menu.texture.desc.Width != width || + d3d10->menu.texture.desc.Height != height) { - d3d10->menu.texture.desc.Format = d3d10_get_closest_match_texture2D(d3d10->device, format); + d3d10->menu.texture.desc.Format = format; d3d10->menu.texture.desc.Width = width; d3d10->menu.texture.desc.Height = height; d3d10_init_texture(d3d10->device, &d3d10->menu.texture); } - d3d10_update_texture(width, height, pitch, format, frame, &d3d10->menu.texture); - d3d10->menu.sampler = config_get_ptr()->bools.menu_linear_filter ? d3d10->sampler_linear - : d3d10->sampler_nearest; + d3d10_update_texture(d3d10->device, width, height, 0, + format, frame, &d3d10->menu.texture); + d3d10->menu.texture.sampler = d3d10->samplers + [settings->bools.menu_linear_filter + ? RARCH_FILTER_LINEAR + : RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT]; } static void d3d10_set_menu_texture_enable(void* data, bool state, bool full_screen) { d3d10_video_t* d3d10 = (d3d10_video_t*)data; + if (!d3d10) + return; + d3d10->menu.enabled = state; d3d10->menu.fullscreen = full_screen; } @@ -538,18 +1496,110 @@ static void d3d10_gfx_apply_state_changes(void* data) { d3d10_video_t* d3d10 = (d3d10_video_t*)data; -#if 0 if (d3d10) d3d10->resize_viewport = true; +} + +static void d3d10_gfx_set_osd_msg( + void* data, video_frame_info_t* video_info, const char* msg, const void* params, void* font) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (d3d10) + { + if (d3d10->sprites.enabled) + font_driver_render_msg(video_info, font, msg, (const struct font_params*)params); + else + printf("OSD msg: %s\n", msg); + } +} + +static void d3d10_gfx_show_mouse(void* data, bool state) { win32_show_cursor(state); } + +static uintptr_t d3d10_gfx_load_texture( + void* video_data, void* data, bool threaded, enum texture_filter_type filter_type) +{ + d3d10_texture_t* texture = NULL; + d3d10_video_t* d3d10 = (d3d10_video_t*)video_data; + struct texture_image* image = (struct texture_image*)data; + + if (!d3d10) + return 0; + + texture = (d3d10_texture_t*)calloc(1, sizeof(*texture)); + + if (!texture) + return 0; + + switch (filter_type) + { + case TEXTURE_FILTER_MIPMAP_LINEAR: + texture->desc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS; + /* fallthrough */ + case TEXTURE_FILTER_LINEAR: + texture->sampler = d3d10->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_EDGE]; + break; + case TEXTURE_FILTER_MIPMAP_NEAREST: + texture->desc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS; + /* fallthrough */ + case TEXTURE_FILTER_NEAREST: + texture->sampler = d3d10->samplers[RARCH_FILTER_NEAREST][RARCH_WRAP_EDGE]; + break; + } + + texture->desc.Width = image->width; + texture->desc.Height = image->height; + texture->desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + + d3d10_init_texture(d3d10->device, texture); + + d3d10_update_texture( + d3d10->device, + image->width, image->height, 0, DXGI_FORMAT_B8G8R8A8_UNORM, image->pixels, + texture); + + return (uintptr_t)texture; +} +static void d3d10_gfx_unload_texture(void* data, uintptr_t handle) +{ + d3d10_texture_t* texture = (d3d10_texture_t*)handle; + + if (!texture) + return; + + Release(texture->view); + Release(texture->staging); + Release(texture->handle); + free(texture); +} + +#if 0 +static bool +d3d10_get_hw_render_interface(void* data, const struct retro_hw_render_interface** iface) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + *iface = (const struct retro_hw_render_interface*)&d3d10->hw.iface; + return d3d10->hw.enable; +} #endif + +static uint32_t d3d10_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + + return flags; } static const video_poke_interface_t d3d10_poke_interface = { + d3d10_get_flags, NULL, /* set_coords */ NULL, /* set_mvp */ - NULL, /* load_texture */ - NULL, /* unload_texture */ + d3d10_gfx_load_texture, + d3d10_gfx_unload_texture, NULL, /* set_video_mode */ + win32_get_refresh_rate, d3d10_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ @@ -560,12 +1610,16 @@ static const video_poke_interface_t d3d10_poke_interface = { d3d10_gfx_apply_state_changes, d3d10_set_menu_texture_frame, d3d10_set_menu_texture_enable, - NULL, /* set_osd_msg */ - NULL, /* show_mouse */ + d3d10_gfx_set_osd_msg, + d3d10_gfx_show_mouse, NULL, /* grab_mouse_toggle */ - NULL, /* get_current_shader */ + d3d10_gfx_get_current_shader, NULL, /* get_current_software_framebuffer */ +#if 0 + d3d10_get_hw_render_interface, +#else NULL, /* get_hw_render_interface */ +#endif }; static void d3d10_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface) @@ -591,7 +1645,7 @@ video_driver_t video_d3d10 = { NULL, /* read_frame_raw */ #ifdef HAVE_OVERLAY - NULL, /* overlay_interface */ + d3d10_get_overlay_interface, #endif d3d10_gfx_get_poke_interface, }; diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index a33fa75ad1..e9fc4b71f1 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -1,4 +1,4 @@ -/* RetroArch - A frontend for libretro. +/* RetroArch - A frontend for libretro. * Copyright (C) 2014-2018 - Ali Bouhlel * * RetroArch is free software: you can redistribute it and/or modify it under the terms @@ -19,6 +19,7 @@ #include #include +#include #include #include "../../driver.h" @@ -39,11 +40,16 @@ #include "../drivers_shader/slang_process.h" #endif +static D3D11Device cached_device_d3d11; +static D3D_FEATURE_LEVEL cached_supportedFeatureLevel; +static D3D11DeviceContext cached_context; + + #ifdef HAVE_OVERLAY static void d3d11_free_overlays(d3d11_video_t* d3d11) { unsigned i; - for (i = 0; i < d3d11->overlays.count; i++) + for (i = 0; i < (unsigned)d3d11->overlays.count; i++) d3d11_release_texture(&d3d11->overlays.textures[i]); Release(d3d11->overlays.vbo); @@ -112,9 +118,10 @@ static void d3d11_overlay_set_alpha(void* data, unsigned index, float mod) static bool d3d11_overlay_load(void* data, const void* image_data, unsigned num_images) { - int i; - d3d11_sprite_t* sprites; + D3D11_BUFFER_DESC desc; D3D11_MAPPED_SUBRESOURCE mapped_vbo; + unsigned i; + d3d11_sprite_t* sprites; d3d11_video_t* d3d11 = (d3d11_video_t*)data; const struct texture_image* images = (const struct texture_image*)image_data; @@ -123,19 +130,19 @@ static bool d3d11_overlay_load(void* data, const void* image_data, unsigned num_ d3d11_free_overlays(d3d11); d3d11->overlays.count = num_images; - d3d11->overlays.textures = (d3d11_texture_t*)calloc(num_images, sizeof(d3d11_texture_t)); + d3d11->overlays.textures = (d3d11_texture_t*)calloc( + num_images, sizeof(d3d11_texture_t)); - { - D3D11_BUFFER_DESC desc = { sizeof(d3d11_sprite_t) * num_images }; - desc.Usage = D3D11_USAGE_DYNAMIC; - - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->overlays.vbo); - } + desc.ByteWidth = sizeof(d3d11_sprite_t) * num_images; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + desc.StructureByteStride = 0; + D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->overlays.vbo); D3D11MapBuffer(d3d11->context, d3d11->overlays.vbo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_vbo); - sprites = (d3d11_sprite_t*)mapped_vbo.pData; + sprites = (d3d11_sprite_t*)mapped_vbo.pData; for (i = 0; i < num_images; i++) { @@ -147,26 +154,27 @@ static bool d3d11_overlay_load(void* data, const void* image_data, unsigned num_ d3d11_init_texture(d3d11->device, &d3d11->overlays.textures[i]); d3d11_update_texture( - d3d11->context, images[i].width, images[i].height, 0, DXGI_FORMAT_B8G8R8A8_UNORM, + d3d11->context, images[i].width, + images[i].height, 0, DXGI_FORMAT_B8G8R8A8_UNORM, images[i].pixels, &d3d11->overlays.textures[i]); - sprites[i].pos.x = 0.0f; - sprites[i].pos.y = 0.0f; - sprites[i].pos.w = 1.0f; - sprites[i].pos.h = 1.0f; + sprites[i].pos.x = 0.0f; + sprites[i].pos.y = 0.0f; + sprites[i].pos.w = 1.0f; + sprites[i].pos.h = 1.0f; - sprites[i].coords.u = 0.0f; - sprites[i].coords.v = 0.0f; - sprites[i].coords.w = 1.0f; - sprites[i].coords.h = 1.0f; + sprites[i].coords.u = 0.0f; + sprites[i].coords.v = 0.0f; + sprites[i].coords.w = 1.0f; + sprites[i].coords.h = 1.0f; sprites[i].params.scaling = 1; sprites[i].params.rotation = 0; - sprites[i].colors[0] = 0xFFFFFFFF; - sprites[i].colors[1] = sprites[i].colors[0]; - sprites[i].colors[2] = sprites[i].colors[0]; - sprites[i].colors[3] = sprites[i].colors[0]; + sprites[i].colors[0] = 0xFFFFFFFF; + sprites[i].colors[1] = sprites[i].colors[0]; + sprites[i].colors[2] = sprites[i].colors[0]; + sprites[i].colors[3] = sprites[i].colors[0]; } D3D11UnmapBuffer(d3d11->context, d3d11->overlays.vbo, 0); @@ -288,7 +296,7 @@ static void d3d11_free_shader_preset(d3d11_video_t* d3d11) memset(d3d11->pass, 0, sizeof(d3d11->pass)); /* only free the history textures here */ - for (i = 1; i <= d3d11->shader_preset->history_size; i++) + for (i = 1; i <= (unsigned)d3d11->shader_preset->history_size; i++) d3d11_release_texture(&d3d11->frame.texture[i]); memset( @@ -381,7 +389,7 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const /* clang-format on */ if (!slang_process( - d3d11->shader_preset, i, RARCH_SHADER_HLSL, 50, &semantics_map, + d3d11->shader_preset, i, RARCH_SHADER_HLSL, 40, &semantics_map, &d3d11->pass[i].semantics)) goto error; @@ -548,8 +556,17 @@ static void d3d11_gfx_free(void* data) font_driver_free_osd(); - Release(d3d11->context); - Release(d3d11->device); + if (video_driver_is_video_cache_context()) + { + cached_device_d3d11 = d3d11->device; + cached_context = d3d11->context; + cached_supportedFeatureLevel = d3d11->supportedFeatureLevel; + } + else + { + Release(d3d11->context); + Release(d3d11->device); + } win32_monitor_from_window(); win32_destroy_window(); @@ -560,9 +577,9 @@ static void* d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) { unsigned i; - WNDCLASSEX wndclass = { 0 }; MONITORINFOEX current_mon; HMONITOR hm_to_use; + WNDCLASSEX wndclass = { 0 }; settings_t* settings = config_get_ptr(); d3d11_video_t* d3d11 = (d3d11_video_t*)calloc(1, sizeof(*d3d11)); @@ -593,9 +610,16 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i dxgi_input_driver(settings->arrays.input_joypad_driver, input, input_data); { - UINT flags = 0; - D3D_FEATURE_LEVEL requested_feature_level = D3D_FEATURE_LEVEL_11_0; - DXGI_SWAP_CHAIN_DESC desc = { 0 }; + UINT flags = 0; + D3D_FEATURE_LEVEL + requested_feature_levels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0 + }; + DXGI_SWAP_CHAIN_DESC desc = { 0 }; + UINT number_feature_levels = ARRAY_SIZE(requested_feature_levels); desc.BufferCount = 1; desc.BufferDesc.Width = d3d11->vp.full_width; @@ -618,11 +642,39 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i #ifdef DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif + if(cached_device_d3d11 && cached_context) + { + IDXGIFactory* dxgiFactory = NULL; + IDXGIDevice* dxgiDevice = NULL; + IDXGIAdapter* adapter = NULL; - D3D11CreateDeviceAndSwapChain( - NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, &requested_feature_level, 1, - D3D11_SDK_VERSION, &desc, (IDXGISwapChain**)&d3d11->swapChain, &d3d11->device, - &d3d11->supportedFeatureLevel, &d3d11->context); + d3d11->device = cached_device_d3d11; + d3d11->context = cached_context; + d3d11->supportedFeatureLevel = cached_supportedFeatureLevel; + + d3d11->device->lpVtbl->QueryInterface( + d3d11->device, uuidof(IDXGIDevice), (void**)&dxgiDevice); + dxgiDevice->lpVtbl->GetAdapter(dxgiDevice, &adapter); + adapter->lpVtbl->GetParent( + adapter, uuidof(IDXGIFactory1), (void**)&dxgiFactory); + dxgiFactory->lpVtbl->CreateSwapChain( + dxgiFactory, (IUnknown*)d3d11->device, + &desc, (IDXGISwapChain**)&d3d11->swapChain); + + dxgiFactory->lpVtbl->Release(dxgiFactory); + adapter->lpVtbl->Release(adapter); + dxgiDevice->lpVtbl->Release(dxgiDevice); + } + else + { + if (FAILED(D3D11CreateDeviceAndSwapChain( + NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, + requested_feature_levels, number_feature_levels, + D3D11_SDK_VERSION, &desc, + (IDXGISwapChain**)&d3d11->swapChain, &d3d11->device, + &d3d11->supportedFeatureLevel, &d3d11->context))) + goto error; + } } { @@ -640,12 +692,14 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i d3d11->viewport.Height = d3d11->vp.full_height; d3d11->resize_viewport = true; d3d11->vsync = video->vsync; - d3d11->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; + d3d11->format = video->rgb32 ? + DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; d3d11->frame.texture[0].desc.Format = d3d11->format; d3d11->frame.texture[0].desc.Usage = D3D11_USAGE_DEFAULT; d3d11->frame.texture[0].desc.Width = 4; d3d11->frame.texture[0].desc.Height = 4; + d3d11_init_texture(d3d11->device, &d3d11->frame.texture[0]); d3d11->menu.texture.desc.Usage = D3D11_USAGE_DEFAULT; @@ -717,29 +771,31 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i d3d11_set_filtering(d3d11, 0, video->smooth); { + D3D11_BUFFER_DESC desc; d3d11_vertex_t vertices[] = { { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 0.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, }; + D3D11_SUBRESOURCE_DATA + vertexData = { vertices }; - { - D3D11_BUFFER_DESC desc = { 0 }; - desc.Usage = D3D11_USAGE_IMMUTABLE; - desc.ByteWidth = sizeof(vertices); - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.ByteWidth = sizeof(vertices); + desc.Usage = D3D11_USAGE_IMMUTABLE; + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + desc.StructureByteStride = 0; - D3D11_SUBRESOURCE_DATA vertexData = { vertices }; - D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->frame.vbo); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->menu.vbo); + D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->frame.vbo); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->menu.vbo); - d3d11->sprites.capacity = 4096; - desc.ByteWidth = sizeof(d3d11_sprite_t) * d3d11->sprites.capacity; - D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->sprites.vbo); - } + d3d11->sprites.capacity = 4096; + desc.ByteWidth = sizeof(d3d11_sprite_t) * d3d11->sprites.capacity; + D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->sprites.vbo); } { @@ -794,68 +850,71 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i goto error; } + if (string_is_equal(settings->arrays.menu_driver, "xmb")) { - D3D11_INPUT_ELEMENT_DESC desc[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; + { + D3D11_INPUT_ELEMENT_DESC desc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; - static const char ribbon[] = + static const char ribbon[] = #include "d3d_shaders/ribbon_sm4.hlsl.h" ; - static const char ribbon_simple[] = + static const char ribbon_simple[] = #include "d3d_shaders/ribbon_simple_sm4.hlsl.h" ; - if (!d3d11_init_shader( - d3d11->device, ribbon, sizeof(ribbon), NULL, "VSMain", "PSMain", NULL, desc, - countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU])) - goto error; + if (!d3d11_init_shader( + d3d11->device, ribbon, sizeof(ribbon), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU])) + goto error; - if (!d3d11_init_shader( - d3d11->device, ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "PSMain", NULL, - desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_2])) - goto error; - } + if (!d3d11_init_shader( + d3d11->device, ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "PSMain", NULL, + desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_2])) + goto error; + } - { - D3D11_INPUT_ELEMENT_DESC desc[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, position), - D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, texcoord), - D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; + { + D3D11_INPUT_ELEMENT_DESC desc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, position), + D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, texcoord), + D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; - static const char simple_snow[] = + static const char simple_snow[] = #include "d3d_shaders/simple_snow_sm4.hlsl.h" ; - static const char snow[] = + static const char snow[] = #include "d3d_shaders/snow_sm4.hlsl.h" ; - static const char bokeh[] = + static const char bokeh[] = #include "d3d_shaders/bokeh_sm4.hlsl.h" ; - static const char snowflake[] = + static const char snowflake[] = #include "d3d_shaders/snowflake_sm4.hlsl.h" ; - if (!d3d11_init_shader( - d3d11->device, simple_snow, sizeof(simple_snow), NULL, "VSMain", "PSMain", NULL, - desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_3])) - goto error; - if (!d3d11_init_shader( - d3d11->device, snow, sizeof(snow), NULL, "VSMain", "PSMain", NULL, desc, - countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_4])) - goto error; + if (!d3d11_init_shader( + d3d11->device, simple_snow, sizeof(simple_snow), NULL, "VSMain", "PSMain", NULL, + desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_3])) + goto error; + if (!d3d11_init_shader( + d3d11->device, snow, sizeof(snow), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_4])) + goto error; - if (!d3d11_init_shader( - d3d11->device, bokeh, sizeof(bokeh), NULL, "VSMain", "PSMain", NULL, desc, - countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_5])) - goto error; + if (!d3d11_init_shader( + d3d11->device, bokeh, sizeof(bokeh), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_5])) + goto error; - if (!d3d11_init_shader( - d3d11->device, snowflake, sizeof(snowflake), NULL, "VSMain", "PSMain", NULL, desc, - countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_6])) - goto error; + if (!d3d11_init_shader( + d3d11->device, snowflake, sizeof(snowflake), NULL, "VSMain", "PSMain", NULL, desc, + countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_6])) + goto error; + } } { @@ -929,7 +988,7 @@ static void d3d11_init_history(d3d11_video_t* d3d11, unsigned width, unsigned he * and to reduce memory fragmentation */ assert(d3d11->shader_preset); - for (i = 0; i < d3d11->shader_preset->history_size + 1; i++) + for (i = 0; i < (unsigned)d3d11->shader_preset->history_size + 1; i++) { d3d11->frame.texture[i].desc.Width = width; d3d11->frame.texture[i].desc.Height = height; @@ -940,6 +999,7 @@ static void d3d11_init_history(d3d11_video_t* d3d11, unsigned width, unsigned he } d3d11->init_history = false; } + static void d3d11_init_render_targets(d3d11_video_t* d3d11, unsigned width, unsigned height) { unsigned i; @@ -1321,7 +1381,7 @@ static bool d3d11_gfx_frame( D3D11SetPShaderSamplers( context, 0, 1, &d3d11->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); - for (i = 0; i < d3d11->overlays.count; i++) + for (i = 0; i < (unsigned)d3d11->overlays.count; i++) { D3D11SetPShaderResources(context, 0, 1, &d3d11->overlays.textures[i].view); D3D11Draw(d3d11->context, 1, i); @@ -1411,11 +1471,14 @@ static bool d3d11_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle) static void d3d11_set_menu_texture_frame( void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha) { - d3d11_video_t* d3d11 = (d3d11_video_t*)data; - DXGI_FORMAT format = - rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM; + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + settings_t* settings = config_get_ptr(); + DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : + (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM; - if (d3d11->menu.texture.desc.Width != width || d3d11->menu.texture.desc.Height != height) + if ( + d3d11->menu.texture.desc.Width != width || + d3d11->menu.texture.desc.Height != height) { d3d11->menu.texture.desc.Format = format; d3d11->menu.texture.desc.Width = width; @@ -1423,11 +1486,12 @@ static void d3d11_set_menu_texture_frame( d3d11_init_texture(d3d11->device, &d3d11->menu.texture); } - d3d11_update_texture(d3d11->context, width, height, 0, format, frame, &d3d11->menu.texture); + d3d11_update_texture(d3d11->context, width, height, 0, + format, frame, &d3d11->menu.texture); d3d11->menu.texture.sampler = d3d11->samplers - [config_get_ptr()->bools.menu_linear_filter - ? RARCH_FILTER_LINEAR - : RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT]; + [settings->bools.menu_linear_filter + ? RARCH_FILTER_LINEAR + : RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT]; } static void d3d11_set_menu_texture_enable(void* data, bool state, bool full_screen) @@ -1540,12 +1604,23 @@ d3d11_get_hw_render_interface(void* data, const struct retro_hw_render_interface return d3d11->hw.enable; } +static uint32_t d3d11_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + + return flags; +} + static const video_poke_interface_t d3d11_poke_interface = { + d3d11_get_flags, NULL, /* set_coords */ NULL, /* set_mvp */ d3d11_gfx_load_texture, d3d11_gfx_unload_texture, NULL, /* set_video_mode */ + win32_get_refresh_rate, d3d11_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 2b942fc868..4f7e884c0c 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -48,7 +48,7 @@ static void d3d12_gfx_sync(d3d12_video_t* d3d12) static void d3d12_free_overlays(d3d12_video_t* d3d12) { unsigned i; - for (i = 0; i < d3d12->overlays.count; i++) + for (i = 0; i < (unsigned)d3d12->overlays.count; i++) d3d12_release_texture(&d3d12->overlays.textures[i]); Release(d3d12->overlays.vbo); @@ -120,7 +120,7 @@ static void d3d12_overlay_set_alpha(void* data, unsigned index, float mod) static bool d3d12_overlay_load(void* data, const void* image_data, unsigned num_images) { - int i; + unsigned i; d3d12_sprite_t* sprites = NULL; D3D12_RANGE range = { 0, 0 }; d3d12_video_t* d3d12 = (d3d12_video_t*)data; @@ -304,7 +304,7 @@ static void d3d12_free_shader_preset(d3d12_video_t* d3d12) memset(d3d12->pass, 0, sizeof(d3d12->pass)); /* only free the history textures here */ - for (i = 1; i <= d3d12->shader_preset->history_size; i++) + for (i = 1; i <= (unsigned)d3d12->shader_preset->history_size; i++) d3d12_release_texture(&d3d12->frame.texture[i]); memset( @@ -544,6 +544,7 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) D3DBlob ps_code = NULL; D3DBlob gs_code = NULL; D3DBlob cs_code = NULL; + settings_t * settings = config_get_ptr(); D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { d3d12->desc.rootSignature }; desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc; @@ -643,134 +644,137 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) gs_code = NULL; } + if (string_is_equal(settings->arrays.menu_driver, "xmb")) { - static const char simple_snow[] = -#include "d3d_shaders/simple_snow_sm4.hlsl.h" - ; - static const char snow[] = -#include "d3d_shaders/snow_sm4.hlsl.h" - ; - static const char bokeh[] = -#include "d3d_shaders/bokeh_sm4.hlsl.h" - ; - static const char snowflake[] = -#include "d3d_shaders/snowflake_sm4.hlsl.h" - ; - - D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position), - D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord), - D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - }; - - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - desc.InputLayout.pInputElementDescs = inputElementDesc; - desc.InputLayout.NumElements = countof(inputElementDesc); - - if (!d3d_compile(simple_snow, sizeof(simple_snow), NULL, "VSMain", "vs_5_0", &vs_code)) - goto error; - if (!d3d_compile(simple_snow, sizeof(simple_snow), NULL, "PSMain", "ps_5_0", &ps_code)) - goto error; - - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_3])) - goto error; - - Release(vs_code); - Release(ps_code); - vs_code = NULL; - ps_code = NULL; - - if (!d3d_compile(snow, sizeof(snow), NULL, "VSMain", "vs_5_0", &vs_code)) - goto error; - if (!d3d_compile(snow, sizeof(snow), NULL, "PSMain", "ps_5_0", &ps_code)) - goto error; - - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_4])) - goto error; - - Release(vs_code); - Release(ps_code); - vs_code = NULL; - ps_code = NULL; - - if (!d3d_compile(bokeh, sizeof(bokeh), NULL, "VSMain", "vs_5_0", &vs_code)) - goto error; - if (!d3d_compile(bokeh, sizeof(bokeh), NULL, "PSMain", "ps_5_0", &ps_code)) - goto error; - - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_5])) - goto error; - - Release(vs_code); - Release(ps_code); - vs_code = NULL; - ps_code = NULL; - - if (!d3d_compile(snowflake, sizeof(snowflake), NULL, "VSMain", "vs_5_0", &vs_code)) - goto error; - if (!d3d_compile(snowflake, sizeof(snowflake), NULL, "PSMain", "ps_5_0", &ps_code)) - goto error; - - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_6])) - goto error; - - Release(vs_code); - Release(ps_code); - vs_code = NULL; - ps_code = NULL; - } - - { - static const char ribbon[] = + { + static const char ribbon[] = #include "d3d_shaders/ribbon_sm4.hlsl.h" ; - static const char ribbon_simple[] = + static const char ribbon_simple[] = #include "d3d_shaders/ribbon_simple_sm4.hlsl.h" ; - D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, - D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - }; + D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, + D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; - desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ONE; - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - desc.InputLayout.pInputElementDescs = inputElementDesc; - desc.InputLayout.NumElements = countof(inputElementDesc); + desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; + desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ONE; + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + desc.InputLayout.pInputElementDescs = inputElementDesc; + desc.InputLayout.NumElements = countof(inputElementDesc); - if (!d3d_compile(ribbon, sizeof(ribbon), NULL, "VSMain", "vs_5_0", &vs_code)) - goto error; - if (!d3d_compile(ribbon, sizeof(ribbon), NULL, "PSMain", "ps_5_0", &ps_code)) - goto error; + if (!d3d_compile(ribbon, sizeof(ribbon), NULL, "VSMain", "vs_5_0", &vs_code)) + goto error; + if (!d3d_compile(ribbon, sizeof(ribbon), NULL, "PSMain", "ps_5_0", &ps_code)) + goto error; - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU])) - goto error; + if (!d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU])) + goto error; - Release(vs_code); - Release(ps_code); - vs_code = NULL; - ps_code = NULL; + Release(vs_code); + Release(ps_code); + vs_code = NULL; + ps_code = NULL; - if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "vs_5_0", &vs_code)) - goto error; - if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "PSMain", "ps_5_0", &ps_code)) - goto error; + if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "vs_5_0", &vs_code)) + goto error; + if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "PSMain", "ps_5_0", &ps_code)) + goto error; - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_2])) - goto error; + if (!d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_2])) + goto error; - Release(vs_code); - Release(ps_code); - vs_code = NULL; - ps_code = NULL; + Release(vs_code); + Release(ps_code); + vs_code = NULL; + ps_code = NULL; + } + + { + static const char simple_snow[] = +#include "d3d_shaders/simple_snow_sm4.hlsl.h" + ; + static const char snow[] = +#include "d3d_shaders/snow_sm4.hlsl.h" + ; + static const char bokeh[] = +#include "d3d_shaders/bokeh_sm4.hlsl.h" + ; + static const char snowflake[] = +#include "d3d_shaders/snowflake_sm4.hlsl.h" + ; + + D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position), + D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord), + D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + desc.InputLayout.pInputElementDescs = inputElementDesc; + desc.InputLayout.NumElements = countof(inputElementDesc); + + if (!d3d_compile(simple_snow, sizeof(simple_snow), NULL, "VSMain", "vs_5_0", &vs_code)) + goto error; + if (!d3d_compile(simple_snow, sizeof(simple_snow), NULL, "PSMain", "ps_5_0", &ps_code)) + goto error; + + if (!d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_3])) + goto error; + + Release(vs_code); + Release(ps_code); + vs_code = NULL; + ps_code = NULL; + + if (!d3d_compile(snow, sizeof(snow), NULL, "VSMain", "vs_5_0", &vs_code)) + goto error; + if (!d3d_compile(snow, sizeof(snow), NULL, "PSMain", "ps_5_0", &ps_code)) + goto error; + + if (!d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_4])) + goto error; + + Release(vs_code); + Release(ps_code); + vs_code = NULL; + ps_code = NULL; + + if (!d3d_compile(bokeh, sizeof(bokeh), NULL, "VSMain", "vs_5_0", &vs_code)) + goto error; + if (!d3d_compile(bokeh, sizeof(bokeh), NULL, "PSMain", "ps_5_0", &ps_code)) + goto error; + + if (!d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_5])) + goto error; + + Release(vs_code); + Release(ps_code); + vs_code = NULL; + ps_code = NULL; + + if (!d3d_compile(snowflake, sizeof(snowflake), NULL, "VSMain", "vs_5_0", &vs_code)) + goto error; + if (!d3d_compile(snowflake, sizeof(snowflake), NULL, "PSMain", "ps_5_0", &ps_code)) + goto error; + + if (!d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_6])) + goto error; + + Release(vs_code); + Release(ps_code); + vs_code = NULL; + ps_code = NULL; + } } { @@ -871,9 +875,9 @@ static void d3d12_gfx_free(void* data) static void* d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) { - WNDCLASSEX wndclass = { 0 }; MONITORINFOEX current_mon; HMONITOR hm_to_use; + WNDCLASSEX wndclass = { 0 }; settings_t* settings = config_get_ptr(); d3d12_video_t* d3d12 = (d3d12_video_t*)calloc(1, sizeof(*d3d12)); @@ -993,7 +997,7 @@ static void d3d12_init_history(d3d12_video_t* d3d12, unsigned width, unsigned he * and to reduce memory fragmentation */ assert(d3d12->shader_preset); - for (i = 0; i < d3d12->shader_preset->history_size + 1; i++) + for (i = 0; i < (unsigned)d3d12->shader_preset->history_size + 1; i++) { d3d12->frame.texture[i].desc.Width = width; d3d12->frame.texture[i].desc.Height = height; @@ -1298,19 +1302,20 @@ static bool d3d12_gfx_frame( while (texture_sem->stage_mask) { { - D3D12_CPU_DESCRIPTOR_HANDLE handle = { + D3D12_CPU_DESCRIPTOR_HANDLE handle = { d3d12->pass[i].textures.ptr - d3d12->desc.srv_heap.gpu.ptr + - d3d12->desc.srv_heap.cpu.ptr + - texture_sem->binding * d3d12->desc.srv_heap.stride + d3d12->desc.srv_heap.cpu.ptr + + texture_sem->binding * d3d12->desc.srv_heap.stride }; - d3d12_texture_t* tex = texture_sem->texture_data; + d3d12_texture_t* tex = (d3d12_texture_t*)texture_sem->texture_data; D3D12_SHADER_RESOURCE_VIEW_DESC desc = { tex->desc.Format }; - desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - desc.Texture2D.MipLevels = tex->desc.MipLevels; + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipLevels = tex->desc.MipLevels; - D3D12CreateShaderResourceView(d3d12->device, tex->handle, &desc, handle); + D3D12CreateShaderResourceView(d3d12->device, + tex->handle, &desc, handle); } { @@ -1491,7 +1496,7 @@ static bool d3d12_gfx_frame( d3d12->queue.cmd, ROOT_ID_SAMPLER_T, d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); - for (i = 0; i < d3d12->overlays.count; i++) + for (i = 0; i < (unsigned)d3d12->overlays.count; i++) { if (d3d12->overlays.textures[i].dirty) d3d12_upload_texture(d3d12->queue.cmd, @@ -1596,14 +1601,19 @@ static bool d3d12_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle) } static void d3d12_set_menu_texture_frame( - void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha) + void* data, const void* frame, bool rgb32, + unsigned width, unsigned height, float alpha) { - d3d12_video_t* d3d12 = (d3d12_video_t*)data; - int pitch = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t)); - DXGI_FORMAT format = - rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + settings_t* settings = config_get_ptr(); + int pitch = width * + (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t)); + DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM + : (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM; - if (d3d12->menu.texture.desc.Width != width || d3d12->menu.texture.desc.Height != height) + if ( + d3d12->menu.texture.desc.Width != width || + d3d12->menu.texture.desc.Height != height) { d3d12->menu.texture.desc.Width = width; d3d12->menu.texture.desc.Height = height; @@ -1612,13 +1622,14 @@ static void d3d12_set_menu_texture_frame( d3d12_init_texture(d3d12->device, &d3d12->menu.texture); } - d3d12_update_texture(width, height, pitch, format, frame, &d3d12->menu.texture); + d3d12_update_texture(width, height, pitch, + format, frame, &d3d12->menu.texture); d3d12->menu.alpha = alpha; { D3D12_RANGE read_range = { 0, 0 }; - d3d12_vertex_t* v; + d3d12_vertex_t* v = NULL; D3D12Map(d3d12->menu.vbo, 0, &read_range, (void**)&v); v[0].color[3] = alpha; @@ -1628,19 +1639,27 @@ static void d3d12_set_menu_texture_frame( D3D12Unmap(d3d12->menu.vbo, 0, NULL); } - d3d12->menu.texture.sampler = config_get_ptr()->bools.menu_linear_filter - ? d3d12->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_DEFAULT] - : d3d12->samplers[RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT]; + d3d12->menu.texture.sampler = settings->bools.menu_linear_filter + ? d3d12->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_DEFAULT] + : d3d12->samplers[RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT]; } -static void d3d12_set_menu_texture_enable(void* data, bool state, bool full_screen) + +static void d3d12_set_menu_texture_enable(void* data, + bool state, bool full_screen) { - d3d12_video_t* d3d12 = (d3d12_video_t*)data; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + if (!d3d12) + return; d3d12->menu.enabled = state; d3d12->menu.fullscreen = full_screen; } -static void d3d12_gfx_show_mouse(void* data, bool state) { win32_show_cursor(state); } +static void d3d12_gfx_show_mouse(void* data, bool state) +{ + win32_show_cursor(state); +} static void d3d12_gfx_set_aspect_ratio(void* data, unsigned aspect_ratio_idx) { @@ -1662,21 +1681,21 @@ static void d3d12_gfx_apply_state_changes(void* data) } static void d3d12_gfx_set_osd_msg( - void* data, video_frame_info_t* video_info, const char* msg, const void* params, void* font) + void* data, video_frame_info_t* video_info, + const char* msg, const void* params, void* font) { d3d12_video_t* d3d12 = (d3d12_video_t*)data; - if (d3d12) - { - if (d3d12->sprites.enabled) - font_driver_render_msg(video_info, font, msg, params); - else - printf("OSD msg: %s\n", msg); - } + if (!d3d12 || !d3d12->sprites.enabled) + return; + + font_driver_render_msg(video_info, font, msg, + (const struct font_params*)params); } static uintptr_t d3d12_gfx_load_texture( - void* video_data, void* data, bool threaded, enum texture_filter_type filter_type) + void* video_data, void* data, bool threaded, + enum texture_filter_type filter_type) { d3d12_texture_t* texture = NULL; d3d12_video_t* d3d12 = (d3d12_video_t*)video_data; @@ -1695,12 +1714,14 @@ static uintptr_t d3d12_gfx_load_texture( case TEXTURE_FILTER_MIPMAP_LINEAR: texture->desc.MipLevels = UINT16_MAX; case TEXTURE_FILTER_LINEAR: - texture->sampler = d3d12->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_EDGE]; + texture->sampler = d3d12->samplers[ + RARCH_FILTER_LINEAR][RARCH_WRAP_EDGE]; break; case TEXTURE_FILTER_MIPMAP_NEAREST: texture->desc.MipLevels = UINT16_MAX; case TEXTURE_FILTER_NEAREST: - texture->sampler = d3d12->samplers[RARCH_FILTER_NEAREST][RARCH_WRAP_EDGE]; + texture->sampler = d3d12->samplers[ + RARCH_FILTER_NEAREST][RARCH_WRAP_EDGE]; break; } @@ -1712,7 +1733,8 @@ static uintptr_t d3d12_gfx_load_texture( d3d12_init_texture(d3d12->device, texture); d3d12_update_texture( - image->width, image->height, 0, DXGI_FORMAT_B8G8R8A8_UNORM, image->pixels, texture); + image->width, image->height, 0, + DXGI_FORMAT_B8G8R8A8_UNORM, image->pixels, texture); return (uintptr_t)texture; } @@ -1728,12 +1750,23 @@ static void d3d12_gfx_unload_texture(void* data, uintptr_t handle) free(texture); } +static uint32_t d3d12_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + + return flags; +} + static const video_poke_interface_t d3d12_poke_interface = { + d3d12_get_flags, NULL, /* set_coords */ NULL, /* set_mvp */ d3d12_gfx_load_texture, d3d12_gfx_unload_texture, NULL, /* set_video_mode */ + win32_get_refresh_rate, d3d12_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index dcb0f51676..11d19f9c9f 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -15,6 +15,8 @@ * If not, see . */ +#define CINTERFACE + #ifdef _XBOX #include #include @@ -437,14 +439,14 @@ static void d3d8_set_mvp(void *data, static void d3d8_overlay_render(d3d_video_t *d3d, video_frame_info_t *video_info, - overlay_t *overlay) + overlay_t *overlay, bool force_linear) { D3DVIEWPORT8 vp_full; + D3DTEXTUREFILTERTYPE filter_type; struct video_viewport vp; void *verts; unsigned i; Vertex vert[4]; - unsigned width = video_info->width; unsigned height = video_info->height; @@ -512,12 +514,19 @@ static void d3d8_overlay_render(d3d_video_t *d3d, d3d8_set_viewports(d3d->dev, &vp_full); } + if (!force_linear) + { + settings_t *settings = config_get_ptr(); + if (!settings->bools.menu_linear_filter) + filter_type = D3DTEXF_POINT; + } + /* Render overlay. */ d3d8_set_texture(d3d->dev, 0, overlay->tex); d3d8_set_sampler_address_u(d3d->dev, 0, D3DTADDRESS_BORDER); d3d8_set_sampler_address_v(d3d->dev, 0, D3DTADDRESS_BORDER); - d3d8_set_sampler_minfilter(d3d->dev, 0, D3DTEXF_LINEAR); - d3d8_set_sampler_magfilter(d3d->dev, 0, D3DTEXF_LINEAR); + d3d8_set_sampler_minfilter(d3d->dev, 0, filter_type); + d3d8_set_sampler_magfilter(d3d->dev, 0, filter_type); d3d8_draw_primitive(d3d->dev, D3DPT_TRIANGLESTRIP, 0, 2); /* Restore previous state. */ @@ -1005,7 +1014,7 @@ static void d3d8_set_nonblock_state(void *data, bool state) #ifdef _XBOX d3d8_set_render_state(d3d->dev, D3D8_PRESENTATIONINTERVAL, interval ? - D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE ); #else d3d->needs_restore = true; @@ -1511,9 +1520,7 @@ static void d3d8_get_overlay_interface(void *data, static void d3d8_update_title(video_frame_info_t *video_info) { -#ifdef _XBOX - const ui_window_t *window = NULL; -#else +#ifndef _XBOX const ui_window_t *window = ui_companion_driver_get_window_ptr(); #endif @@ -1616,7 +1623,7 @@ static bool d3d8_frame(void *data, const void *frame, if (d3d->menu && d3d->menu->enabled) { d3d8_set_mvp(d3d, NULL, &d3d->mvp); - d3d8_overlay_render(d3d, video_info, d3d->menu); + d3d8_overlay_render(d3d, video_info, d3d->menu, false); d3d->menu_display.offset = 0; d3d8_set_stream_source(d3d->dev, 0, d3d->menu_display.buffer, 0, sizeof(Vertex)); @@ -1642,7 +1649,7 @@ static bool d3d8_frame(void *data, const void *frame, { d3d8_set_mvp(d3d, NULL, &d3d->mvp); for (i = 0; i < d3d->overlays_size; i++) - d3d8_overlay_render(d3d, video_info, &d3d->overlays[i]); + d3d8_overlay_render(d3d, video_info, &d3d->overlays[i], true); } #endif @@ -1860,12 +1867,28 @@ static void d3d8_set_video_mode(void *data, #endif } +static uint32_t d3d8_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + + return flags; +} + static const video_poke_interface_t d3d_poke_interface = { - NULL, /* set_coords */ + d3d8_get_flags, + NULL, /* set_coords */ d3d8_set_mvp, d3d8_load_texture, d3d8_unload_texture, d3d8_set_video_mode, +#ifdef _XBOX + NULL, +#else + win32_get_refresh_rate, +#endif NULL, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9.c index 24b54dcf77..61b610ed4a 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9.c @@ -15,6 +15,8 @@ * If not, see . */ +#define CINTERFACE + #ifdef _XBOX #include #include @@ -136,7 +138,6 @@ static bool d3d9_init_imports(d3d_video_t *d3d) extern d3d_renderchain_driver_t cg_d3d9_renderchain; extern d3d_renderchain_driver_t hlsl_d3d9_renderchain; -extern d3d_renderchain_driver_t null_d3d_renderchain; static bool renderchain_d3d_init_first( enum gfx_ctx_api api, @@ -155,7 +156,6 @@ static bool renderchain_d3d_init_first( #if defined(_WIN32) && defined(HAVE_HLSL) &hlsl_d3d9_renderchain, #endif - &null_d3d_renderchain, NULL }; unsigned i; @@ -413,8 +413,9 @@ static void d3d9_set_mvp(void *data, static void d3d9_overlay_render(d3d_video_t *d3d, video_frame_info_t *video_info, - overlay_t *overlay) + overlay_t *overlay, bool force_linear) { + D3DTEXTUREFILTERTYPE filter_type; LPDIRECT3DVERTEXDECLARATION9 vertex_decl; struct video_viewport vp; void *verts; @@ -503,12 +504,21 @@ static void d3d9_overlay_render(d3d_video_t *d3d, d3d9_set_viewports(d3d->dev, &vp_full); } + filter_type = D3DTEXF_LINEAR; + + if (!force_linear) + { + settings_t *settings = config_get_ptr(); + if (!settings->bools.menu_linear_filter) + filter_type = D3DTEXF_POINT; + } + /* Render overlay. */ d3d9_set_texture(d3d->dev, 0, overlay->tex); d3d9_set_sampler_address_u(d3d->dev, 0, D3DTADDRESS_BORDER); d3d9_set_sampler_address_v(d3d->dev, 0, D3DTADDRESS_BORDER); - d3d9_set_sampler_minfilter(d3d->dev, 0, D3DTEXF_LINEAR); - d3d9_set_sampler_magfilter(d3d->dev, 0, D3DTEXF_LINEAR); + d3d9_set_sampler_minfilter(d3d->dev, 0, filter_type); + d3d9_set_sampler_magfilter(d3d->dev, 0, filter_type); d3d9_draw_primitive(d3d->dev, D3DPT_TRIANGLESTRIP, 0, 2); /* Restore previous state. */ @@ -1592,7 +1602,7 @@ static bool d3d9_frame(void *data, const void *frame, if (d3d->menu && d3d->menu->enabled) { d3d9_set_mvp(d3d, NULL, &d3d->mvp); - d3d9_overlay_render(d3d, video_info, d3d->menu); + d3d9_overlay_render(d3d, video_info, d3d->menu, false); d3d->menu_display.offset = 0; d3d9_set_vertex_declaration(d3d->dev, d3d->menu_display.decl); @@ -1622,7 +1632,7 @@ static bool d3d9_frame(void *data, const void *frame, { d3d9_set_mvp(d3d, NULL, &d3d->mvp); for (i = 0; i < d3d->overlays_size; i++) - d3d9_overlay_render(d3d, video_info, &d3d->overlays[i]); + d3d9_overlay_render(d3d, video_info, &d3d->overlays[i], true); } #endif @@ -1884,12 +1894,27 @@ static void d3d9_set_video_mode(void *data, #endif } +static uint32_t d3d9_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + + return flags; +} + static const video_poke_interface_t d3d9_poke_interface = { + d3d9_get_flags, NULL, /* set_coords */ d3d9_set_mvp, d3d9_load_texture, d3d9_unload_texture, d3d9_set_video_mode, +#ifdef _XBOX +#else + win32_get_refresh_rate, +#endif NULL, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/dispmanx_gfx.c b/gfx/drivers/dispmanx_gfx.c index 13c925ce79..386d2bcc38 100644 --- a/gfx/drivers/dispmanx_gfx.c +++ b/gfx/drivers/dispmanx_gfx.c @@ -631,11 +631,13 @@ static void dispmanx_set_aspect_ratio (void *data, unsigned aspect_ratio_idx) } static const video_poke_interface_t dispmanx_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, /* set_video_mode */ + NULL, /* get_refresh_rate */ NULL, /* set_filtering */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/drm_gfx.c b/gfx/drivers/drm_gfx.c index 6dda0b192c..cd43998614 100644 --- a/gfx/drivers/drm_gfx.c +++ b/gfx/drivers/drm_gfx.c @@ -39,6 +39,7 @@ #include "../font_driver.h" #include "../../retroarch.h" #include "../../verbosity.h" +#include "../common/drm_common.h" #include "drm_pixformats.h" @@ -683,6 +684,7 @@ static bool init_drm(void) * on exit in case we change it. */ drm.orig_crtc = drmModeGetCrtc(drm.fd, drm.encoder->crtc_id); drm.current_mode = &(drm.orig_crtc->mode); + g_drm_mode = drm.current_mode; /* Set mode physical video mode. Not really needed, but clears TTY console. */ struct modeset_buf buf; @@ -964,11 +966,13 @@ static void drm_set_aspect_ratio (void *data, unsigned aspect_ratio_idx) } static const video_poke_interface_t drm_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, /* set_video_mode */ + drm_get_refresh_rate, NULL, /* set_filtering */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ @@ -1011,6 +1015,8 @@ static void drm_gfx_free(void *data) slock_free(_drmvars->vsync_cond_mutex); scond_free(_drmvars->vsync_condition); + g_drm_mode = NULL; + free(_drmvars); } diff --git a/gfx/drivers/exynos_gfx.c b/gfx/drivers/exynos_gfx.c index 91984819b8..2ce72de395 100644 --- a/gfx/drivers/exynos_gfx.c +++ b/gfx/drivers/exynos_gfx.c @@ -663,6 +663,7 @@ static void exynos_deinit(struct exynos_data *pdata) { drm_restore_crtc(); + g_drm_mode = NULL; pdata->width = 0; pdata->height = 0; pdata->num_pages = 0; @@ -1489,11 +1490,13 @@ static void exynos_show_mouse(void *data, bool state) } static const video_poke_interface_t exynos_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, /* set_video_mode */ + drm_get_refresh_rate, NULL, /* set_filtering */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c index 6ac92b19c4..dae5a1b091 100644 --- a/gfx/drivers/gdi_gfx.c +++ b/gfx/drivers/gdi_gfx.c @@ -533,11 +533,13 @@ static void gdi_set_video_mode(void *data, unsigned width, unsigned height, } static const video_poke_interface_t gdi_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, gdi_set_video_mode, + win32_get_refresh_rate, NULL, gdi_get_video_output_size, gdi_get_video_output_prev, diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index 720a4b238b..34b781fad3 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -747,7 +747,7 @@ static void gl_render_osd_background( float *verts = (float*)malloc(2 * vertices_total * sizeof(float)); settings_t *settings = config_get_ptr(); int msg_width = - font_driver_get_message_width(NULL, msg, strlen(msg), 1.0f); + font_driver_get_message_width(NULL, msg, (unsigned)strlen(msg), 1.0f); /* shader driver expects vertex coords as 0..1 */ float x = video_info->font_msg_pos_x; @@ -1687,13 +1687,10 @@ static void gl_begin_debug(gl_t *gl) extern gl_renderchain_driver_t gl2_renderchain; static const gl_renderchain_driver_t *renderchain_gl_drivers[] = { -#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) &gl2_renderchain, -#endif NULL }; - static bool renderchain_gl_init_first( const gl_renderchain_driver_t **renderchain_driver, void **renderchain_handle) @@ -1715,7 +1712,8 @@ static bool renderchain_gl_init_first( return false; } -static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) +static void *gl_init(const video_info_t *video, + const input_driver_t **input, void **input_data) { gfx_ctx_mode_t mode; gfx_ctx_input_t inp; @@ -2586,6 +2584,14 @@ static void gl_set_coords(void *handle_data, void *shader_data, shader_data, coords); } +static float gl_get_refresh_rate(void *data) +{ + float refresh_rate = 0.0f; + if (video_context_driver_get_refresh_rate(&refresh_rate)) + return refresh_rate; + return 0.0f; +} + static void gl_set_mvp(void *data, void *shader_data, const void *mat_data) { @@ -2595,12 +2601,25 @@ static void gl_set_mvp(void *data, void *shader_data, shader_data, mat_data); } +static uint32_t gl_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_HARD_SYNC); + BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + + return flags; +} + static const video_poke_interface_t gl_poke_interface = { + gl_get_flags, gl_set_coords, gl_set_mvp, gl_load_texture, gl_unload_texture, gl_set_video_mode, + gl_get_refresh_rate, NULL, gl_get_video_output_size, gl_get_video_output_prev, diff --git a/gfx/drivers/gx2_gfx.c b/gfx/drivers/gx2_gfx.c index 9e8c4e16c2..f8dc6e1384 100644 --- a/gfx/drivers/gx2_gfx.c +++ b/gfx/drivers/gx2_gfx.c @@ -1711,13 +1711,14 @@ static void wiiu_gfx_set_osd_msg(void *data, } -static const video_poke_interface_t wiiu_poke_interface = -{ +static const video_poke_interface_t wiiu_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ wiiu_gfx_load_texture, wiiu_gfx_unload_texture, NULL, /* set_video_mode */ + NULL, /* get_refresh_rate */ wiiu_gfx_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/gx_gfx.c b/gfx/drivers/gx_gfx.c index c14d1a7f0c..3118fa944b 100644 --- a/gfx/drivers/gx_gfx.c +++ b/gfx/drivers/gx_gfx.c @@ -1266,11 +1266,13 @@ static void gx_get_video_output_next(void *data) } static const video_poke_interface_t gx_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, gx_set_video_mode, + NULL, /* get_refresh_rate */ NULL, gx_get_video_output_size, gx_get_video_output_prev, diff --git a/gfx/drivers/omap_gfx.c b/gfx/drivers/omap_gfx.c index a97d30f198..5b4fcd0d70 100644 --- a/gfx/drivers/omap_gfx.c +++ b/gfx/drivers/omap_gfx.c @@ -1129,12 +1129,24 @@ static void omap_gfx_set_texture_enable(void *data, bool state, bool full_screen (void) full_screen; } +static float omap_get_refresh_rate(void *data) +{ + omap_video_t *vid = (omap_video_t*)data; + struct fb_var_screeninfo *s = &vid->omap->current_state->si; + + return 1000000.0f / s->pixclock / + (s->xres + s->left_margin + s->right_margin + s->hsync_len) * 1000000.0f / + (s->yres + s->upper_margin + s->lower_margin + s->vsync_len); +} + static const video_poke_interface_t omap_gfx_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, + omap_get_refresh_rate, NULL, /* set_filtering */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/psp1_gfx.c b/gfx/drivers/psp1_gfx.c index 5dc0dd1f74..57b38fe727 100644 --- a/gfx/drivers/psp1_gfx.c +++ b/gfx/drivers/psp1_gfx.c @@ -831,11 +831,13 @@ static void psp_viewport_info(void *data, struct video_viewport *vp) } static const video_poke_interface_t psp_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, + NULL, /* get_refresh_rate */ psp_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/sdl2_gfx.c b/gfx/drivers/sdl2_gfx.c index 9e6074bd79..75f3105e5e 100644 --- a/gfx/drivers/sdl2_gfx.c +++ b/gfx/drivers/sdl2_gfx.c @@ -721,11 +721,13 @@ static void sdl2_grab_mouse_toggle(void *data) } static video_poke_interface_t sdl2_video_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, + NULL, /* get_refresh_rate */ sdl2_poke_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/sdl_gfx.c b/gfx/drivers/sdl_gfx.c index 918d0ec66c..83ad492680 100644 --- a/gfx/drivers/sdl_gfx.c +++ b/gfx/drivers/sdl_gfx.c @@ -517,11 +517,13 @@ static void sdl_grab_mouse_toggle(void *data) } static const video_poke_interface_t sdl_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, + NULL, /* get_refresh_rate */ sdl_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/sunxi_gfx.c b/gfx/drivers/sunxi_gfx.c index 5c71710831..baf909520a 100644 --- a/gfx/drivers/sunxi_gfx.c +++ b/gfx/drivers/sunxi_gfx.c @@ -109,6 +109,7 @@ typedef struct uint32_t framebuffer_size; /* total size of the framebuffer */ int framebuffer_height;/* virtual vertical resolution */ uint32_t gfx_layer_size; /* the size of the primary layer */ + float refresh_rate; /* Layers support */ int gfx_layer_id; @@ -416,6 +417,9 @@ static sunxi_disp_t *sunxi_disp_init(const char *device) ctx->framebuffer_height = ctx->framebuffer_size / (ctx->xres * ctx->bits_per_pixel / 8); ctx->gfx_layer_size = ctx->xres * ctx->yres * fb_var.bits_per_pixel / 8; + ctx->refresh_rate = 1000000.0f / fb_var.pixclock * 1000000.0f / + (fb_var.yres + fb_var.upper_margin + fb_var.lower_margin + fb_var.vsync_len) + (fb_var.xres + fb_var.left_margin + fb_var.right_margin + fb_var.hsync_len); if (ctx->framebuffer_size < ctx->gfx_layer_size) { @@ -931,12 +935,21 @@ static void sunxi_set_aspect_ratio (void *data, unsigned aspect_ratio_idx) } } +static float sunxi_get_refresh_rate (void *data) +{ + struct sunxi_video *_dispvars = (struct sunxi_video*)data; + + return _dispvars->sunxi_disp->refresh_rate; +} + static const video_poke_interface_t sunxi_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, /* set_video_mode */ + NULL, /* get_refresh_rate */ NULL, /* set_filtering */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/switch_gfx.c b/gfx/drivers/switch_gfx.c index 83d22dddb0..529f74e04a 100644 --- a/gfx/drivers/switch_gfx.c +++ b/gfx/drivers/switch_gfx.c @@ -387,11 +387,13 @@ static void switch_set_texture_enable(void *data, bool enable, bool full_screen) } static const video_poke_interface_t switch_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, /* load_texture */ NULL, /* unload_texture */ NULL, /* set_video_mode */ + NULL, /* get_refresh_rate */ NULL, /* set_filtering */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/vga_gfx.c b/gfx/drivers/vga_gfx.c index d9cdcb9182..d1a0dad125 100644 --- a/gfx/drivers/vga_gfx.c +++ b/gfx/drivers/vga_gfx.c @@ -390,6 +390,7 @@ static void vga_set_osd_msg(void *data, } static const video_poke_interface_t vga_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, @@ -403,6 +404,7 @@ static const video_poke_interface_t vga_poke_interface = { NULL, NULL, NULL, + NULL, vga_set_texture_frame, NULL, vga_set_osd_msg, diff --git a/gfx/drivers/vita2d_gfx.c b/gfx/drivers/vita2d_gfx.c index 50692b62e5..7f49756c5c 100644 --- a/gfx/drivers/vita2d_gfx.c +++ b/gfx/drivers/vita2d_gfx.c @@ -790,11 +790,13 @@ static bool vita_get_current_sw_framebuffer(void *data, } static const video_poke_interface_t vita_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ vita_load_texture, vita_unload_texture, NULL, + NULL, /* get_refresh_rate */ vita_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index cb62be8ffc..a4f2c55267 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -201,8 +201,7 @@ static void vulkan_init_pipeline_layout( &layout_info, NULL, &vk->pipelines.layout); } -static void vulkan_init_pipelines( - vk_t *vk) +static void vulkan_init_pipelines(vk_t *vk) { static const uint32_t alpha_blend_vert[] = #include "vulkan_shaders/alpha_blend.vert.inc" @@ -834,7 +833,11 @@ static bool vulkan_init_filter_chain(vk_t *vk) static void vulkan_init_resources(vk_t *vk) { + if (!vk) + return; + vk->num_swapchain_images = vk->context->num_swapchain_images; + vulkan_init_framebuffers(vk); vulkan_init_pipelines(vk); vulkan_init_descriptor_pool(vk); @@ -2289,12 +2292,34 @@ static void vulkan_unload_texture(void *data, uintptr_t handle) free(texture); } +static float vulkan_get_refresh_rate(void *data) +{ + float refresh_rate; + + if (video_context_driver_get_refresh_rate(&refresh_rate)) + return refresh_rate; + + return 0.0f; +} + +static uint32_t vulkan_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES); + BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); + + return flags; +} + static const video_poke_interface_t vulkan_poke_interface = { + vulkan_get_flags, NULL, /* set_coords */ NULL, /* set_mvp */ vulkan_load_texture, vulkan_unload_texture, vulkan_set_video_mode, + vulkan_get_refresh_rate, /* get_refresh_rate */ NULL, NULL, NULL, diff --git a/gfx/drivers/xshm_gfx.c b/gfx/drivers/xshm_gfx.c index 09121a414d..a953f2d052 100644 --- a/gfx/drivers/xshm_gfx.c +++ b/gfx/drivers/xshm_gfx.c @@ -189,7 +189,7 @@ static void xshm_poke_texture_enable(void *data, static void xshm_poke_set_osd_msg(void *data, video_frame_info_t *video_info, const char *msg, - const struct font_params *params, void *font) + const void *params, void *font) { } @@ -204,11 +204,13 @@ static void xshm_grab_mouse_toggle(void *data) } static video_poke_interface_t xshm_video_poke_interface = { + NULL, /* get_flags */ NULL, /* set_coords */ NULL, /* set_mvp */ NULL, NULL, NULL, + x11_get_refresh_rate, xshm_poke_set_filtering, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ diff --git a/gfx/drivers/xvideo.c b/gfx/drivers/xvideo.c index 8df8f528bb..d81bc83d61 100644 --- a/gfx/drivers/xvideo.c +++ b/gfx/drivers/xvideo.c @@ -423,7 +423,6 @@ static void *xv_init(const video_info_t *video, unsigned i; int ret; XWindowAttributes target; - char buf[128] = {0}; char title[128] = {0}; XSetWindowAttributes attributes = {0}; XVisualInfo visualtemplate = {0}; @@ -562,6 +561,16 @@ static void *xv_init(const video_info_t *video, XFree(visualinfo); XSetWindowBackground(g_x11_dpy, g_x11_win, 0); + if (video->fullscreen && settings->bools.video_disable_composition) + { + uint32_t value = 1; + Atom cardinal = XInternAtom(g_x11_dpy, "CARDINAL", False); + Atom net_wm_bypass_compositor = XInternAtom(g_x11_dpy, "_NET_WM_BYPASS_COMPOSITOR", False); + + RARCH_LOG("[XVideo]: Requesting compositor bypass.\n"); + XChangeProperty(g_x11_dpy, g_x11_win, net_wm_bypass_compositor, cardinal, 32, PropModeReplace, (const unsigned char*)&value, 1); + } + XMapWindow(g_x11_dpy, g_x11_win); video_driver_get_window_title(title, sizeof(title)); @@ -573,7 +582,7 @@ static void *xv_init(const video_info_t *video, if (video->fullscreen) { - x11_windowed_fullscreen(g_x11_dpy, g_x11_win); + x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win); x11_show_mouse(g_x11_dpy, g_x11_win, false); } @@ -924,11 +933,37 @@ static bool xv_read_viewport(void *data, uint8_t *buffer, bool is_idle) return true; } +static video_poke_interface_t xv_video_poke_interface = { + NULL, /* get_flags */ + NULL, + NULL, + NULL, + NULL, + NULL, + x11_get_refresh_rate, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + static void xv_get_poke_interface(void *data, const video_poke_interface_t **iface) { (void)data; - (void)iface; + *iface = &xv_video_poke_interface; } static bool xv_set_shader(void *data, diff --git a/gfx/drivers_context/android_ctx.c b/gfx/drivers_context/android_ctx.c index ca0f7911e1..422dc821cf 100644 --- a/gfx/drivers_context/android_ctx.c +++ b/gfx/drivers_context/android_ctx.c @@ -602,6 +602,7 @@ const gfx_ctx_driver_t gfx_ctx_android = { android_gfx_ctx_set_swap_interval, android_gfx_ctx_set_video_mode, android_gfx_ctx_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/cgl_ctx.c b/gfx/drivers_context/cgl_ctx.c index faeb63fc11..fb26355304 100644 --- a/gfx/drivers_context/cgl_ctx.c +++ b/gfx/drivers_context/cgl_ctx.c @@ -343,6 +343,7 @@ const gfx_ctx_driver_t gfx_ctx_cgl = { gfx_ctx_cgl_swap_interval, gfx_ctx_cgl_set_video_mode, gfx_ctx_cgl_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/cocoa_gl_ctx.m b/gfx/drivers_context/cocoa_gl_ctx.m index 8c137375a0..a95478f59d 100644 --- a/gfx/drivers_context/cocoa_gl_ctx.m +++ b/gfx/drivers_context/cocoa_gl_ctx.m @@ -666,6 +666,7 @@ const gfx_ctx_driver_t gfx_ctx_cocoagl = { cocoagl_gfx_ctx_swap_interval, cocoagl_gfx_ctx_set_video_mode, cocoagl_gfx_ctx_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/drm_ctx.c b/gfx/drivers_context/drm_ctx.c index 90fadbba4f..434c79502b 100644 --- a/gfx/drivers_context/drm_ctx.c +++ b/gfx/drivers_context/drm_ctx.c @@ -903,10 +903,12 @@ static void gfx_ctx_drm_set_flags(void *data, uint32_t flags) const gfx_ctx_driver_t gfx_ctx_drm = { gfx_ctx_drm_init, gfx_ctx_drm_destroy, + gfx_ctx_drm_get_api, gfx_ctx_drm_bind_api, gfx_ctx_drm_swap_interval, gfx_ctx_drm_set_video_mode, gfx_ctx_drm_get_video_size, + drm_get_refresh_rate, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/emscriptenegl_ctx.c b/gfx/drivers_context/emscriptenegl_ctx.c index 1bc927e334..9e3234d86f 100644 --- a/gfx/drivers_context/emscriptenegl_ctx.c +++ b/gfx/drivers_context/emscriptenegl_ctx.c @@ -376,6 +376,7 @@ const gfx_ctx_driver_t gfx_ctx_emscripten = { gfx_ctx_emscripten_swap_interval, gfx_ctx_emscripten_set_video_mode, gfx_ctx_emscripten_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/gdi_ctx.c b/gfx/drivers_context/gdi_ctx.c index 6316df83a8..d251d75cb9 100644 --- a/gfx/drivers_context/gdi_ctx.c +++ b/gfx/drivers_context/gdi_ctx.c @@ -352,6 +352,7 @@ const gfx_ctx_driver_t gfx_ctx_gdi = { gfx_ctx_gdi_swap_interval, gfx_ctx_gdi_set_video_mode, gfx_ctx_gdi_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/gfx_null_ctx.c b/gfx/drivers_context/gfx_null_ctx.c index f7884ad08c..cf0c2cc742 100644 --- a/gfx/drivers_context/gfx_null_ctx.c +++ b/gfx/drivers_context/gfx_null_ctx.c @@ -141,6 +141,7 @@ const gfx_ctx_driver_t gfx_ctx_null = { gfx_ctx_null_swap_interval, gfx_ctx_null_set_video_mode, gfx_ctx_null_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/khr_display_ctx.c b/gfx/drivers_context/khr_display_ctx.c index c597383fee..0d671bbe4a 100644 --- a/gfx/drivers_context/khr_display_ctx.c +++ b/gfx/drivers_context/khr_display_ctx.c @@ -236,6 +236,7 @@ const gfx_ctx_driver_t gfx_ctx_khr_display = { gfx_ctx_khr_display_set_swap_interval, gfx_ctx_khr_display_set_video_mode, gfx_ctx_khr_display_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/mali_fbdev_ctx.c b/gfx/drivers_context/mali_fbdev_ctx.c index 565796345d..3ffd90aedf 100644 --- a/gfx/drivers_context/mali_fbdev_ctx.c +++ b/gfx/drivers_context/mali_fbdev_ctx.c @@ -50,6 +50,7 @@ typedef struct } native_window; bool resize; unsigned width, height; + float refresh_rate; } mali_ctx_data_t; static enum gfx_ctx_api mali_api = GFX_CTX_NONE; @@ -178,6 +179,10 @@ static bool gfx_ctx_mali_fbdev_set_video_mode(void *data, mali->native_window.width = vinfo.xres; mali->native_window.height = vinfo.yres; + mali->refresh_rate = 1000000.0f / vinfo.pixclock * 1000000.0f / + (vinfo.yres + vinfo.upper_margin + vinfo.lower_margin + vinfo.vsync_len) / + (vinfo.xres + vinfo.left_margin + vinfo.right_margin + vinfo.hsync_len); + #ifdef HAVE_EGL if (!egl_create_context(&mali->egl, attribs)) { @@ -286,6 +291,13 @@ static void gfx_ctx_mali_fbdev_set_flags(void *data, uint32_t flags) (void)data; } +static float gfx_ctx_mali_fbdev_get_refresh_rate(void *data) +{ + mali_ctx_data_t *mali = (mali_ctx_data_t*)data; + + return mali->refresh_rate; +} + const gfx_ctx_driver_t gfx_ctx_mali_fbdev = { gfx_ctx_mali_fbdev_init, gfx_ctx_mali_fbdev_destroy, @@ -294,6 +306,7 @@ const gfx_ctx_driver_t gfx_ctx_mali_fbdev = { gfx_ctx_mali_fbdev_set_swap_interval, gfx_ctx_mali_fbdev_set_video_mode, gfx_ctx_mali_fbdev_get_video_size, + gfx_ctx_mali_fbdev_get_refresh_rate, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/opendingux_fbdev_ctx.c b/gfx/drivers_context/opendingux_fbdev_ctx.c index 5d6c0bf820..69ff6a58c6 100644 --- a/gfx/drivers_context/opendingux_fbdev_ctx.c +++ b/gfx/drivers_context/opendingux_fbdev_ctx.c @@ -271,6 +271,7 @@ const gfx_ctx_driver_t gfx_ctx_opendingux_fbdev = { gfx_ctx_opendingux_set_swap_interval, gfx_ctx_opendingux_set_video_mode, gfx_ctx_opendingux_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/osmesa_ctx.c b/gfx/drivers_context/osmesa_ctx.c index df460a14d5..a3ffaf5957 100644 --- a/gfx/drivers_context/osmesa_ctx.c +++ b/gfx/drivers_context/osmesa_ctx.c @@ -398,6 +398,7 @@ const gfx_ctx_driver_t gfx_ctx_osmesa = osmesa_ctx_swap_interval, osmesa_ctx_set_video_mode, osmesa_ctx_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/ps3_ctx.c b/gfx/drivers_context/ps3_ctx.c index 9ff04dd84f..72d1587cb6 100644 --- a/gfx/drivers_context/ps3_ctx.c +++ b/gfx/drivers_context/ps3_ctx.c @@ -418,6 +418,7 @@ const gfx_ctx_driver_t gfx_ctx_ps3 = { gfx_ctx_ps3_set_swap_interval, gfx_ctx_ps3_set_video_mode, gfx_ctx_ps3_get_video_size, + NULL, /* get_refresh_rate */ gfx_ctx_ps3_get_video_output_size, gfx_ctx_ps3_get_video_output_prev, gfx_ctx_ps3_get_video_output_next, diff --git a/gfx/drivers_context/qnx_ctx.c b/gfx/drivers_context/qnx_ctx.c index a425aebdac..2ce96ac7aa 100644 --- a/gfx/drivers_context/qnx_ctx.c +++ b/gfx/drivers_context/qnx_ctx.c @@ -471,6 +471,7 @@ const gfx_ctx_driver_t gfx_ctx_qnx = { gfx_ctx_qnx_set_swap_interval, gfx_ctx_qnx_set_video_mode, gfx_ctx_qnx_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/sdl_gl_ctx.c b/gfx/drivers_context/sdl_gl_ctx.c index 5801c4e9a9..aedb29e5dc 100644 --- a/gfx/drivers_context/sdl_gl_ctx.c +++ b/gfx/drivers_context/sdl_gl_ctx.c @@ -422,6 +422,7 @@ const gfx_ctx_driver_t gfx_ctx_sdl_gl = sdl_ctx_swap_interval, sdl_ctx_set_video_mode, sdl_ctx_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/vc_egl_ctx.c b/gfx/drivers_context/vc_egl_ctx.c index a485eb4e43..56b8ba8933 100644 --- a/gfx/drivers_context/vc_egl_ctx.c +++ b/gfx/drivers_context/vc_egl_ctx.c @@ -695,7 +695,7 @@ static gfx_ctx_proc_t gfx_ctx_vc_get_proc_address(const char *symbol) static uint32_t gfx_ctx_vc_get_flags(void *data) { uint32_t flags = 0; - BIT32_SET(flags, GFX_CTX_FLAGS_NONE); + BIT32_SET(flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES); return flags; } @@ -712,6 +712,7 @@ const gfx_ctx_driver_t gfx_ctx_videocore = { gfx_ctx_vc_set_swap_interval, gfx_ctx_vc_set_video_mode, gfx_ctx_vc_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/vivante_fbdev_ctx.c b/gfx/drivers_context/vivante_fbdev_ctx.c index 7176ce976b..512e740add 100644 --- a/gfx/drivers_context/vivante_fbdev_ctx.c +++ b/gfx/drivers_context/vivante_fbdev_ctx.c @@ -277,6 +277,7 @@ const gfx_ctx_driver_t gfx_ctx_vivante_fbdev = { gfx_ctx_vivante_set_swap_interval, gfx_ctx_vivante_set_video_mode, gfx_ctx_vivante_get_video_size, + NULL, /* get_refresh_rate */ NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 0b5e3d7a26..50ebe36e06 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -58,6 +58,7 @@ typedef struct gfx_ctx_wayland_data unsigned height; unsigned physical_width; unsigned physical_height; + int refresh_rate; struct wl_registry *registry; struct wl_compositor *compositor; struct wl_surface *surface; @@ -440,6 +441,7 @@ static void display_handle_mode(void *data, gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; wl->width = width; wl->height = height; + wl->refresh_rate = refresh; /* Certain older Wayland implementations report in Hz, * but it should be mHz. */ @@ -1369,6 +1371,13 @@ static void gfx_ctx_wl_show_mouse(void *data, bool state) wl->cursor.visible = state; } +static float gfx_ctx_wl_get_refresh_rate(void *data) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + return (float) wl->refresh_rate / 1000.0f; +} + const gfx_ctx_driver_t gfx_ctx_wayland = { gfx_ctx_wl_init, gfx_ctx_wl_destroy, @@ -1377,6 +1386,7 @@ const gfx_ctx_driver_t gfx_ctx_wayland = { gfx_ctx_wl_set_swap_interval, gfx_ctx_wl_set_video_mode, gfx_ctx_wl_get_video_size, + gfx_ctx_wl_get_refresh_rate, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index 1545862bd3..47c5ad5a55 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -760,6 +760,7 @@ const gfx_ctx_driver_t gfx_ctx_wgl = { gfx_ctx_wgl_swap_interval, gfx_ctx_wgl_set_video_mode, gfx_ctx_wgl_get_video_size, + win32_get_refresh_rate, gfx_ctx_wgl_get_video_output_size, gfx_ctx_wgl_get_video_output_prev, gfx_ctx_wgl_get_video_output_next, diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index 448f5df631..bc906021bb 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -37,6 +37,7 @@ #endif #include +#include #include "../../configuration.h" #include "../../frontend/frontend_driver.h" @@ -631,6 +632,7 @@ static bool gfx_ctx_x_set_video_mode(void *data, int y_off = 0; XVisualInfo *vi = NULL; XSetWindowAttributes swa = {0}; + char *wm_name = NULL; int (*old_handler)(Display*, XErrorEvent*) = NULL; gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data; Atom net_wm_icon = XInternAtom(g_x11_dpy, "_NET_WM_ICON", False); @@ -678,7 +680,7 @@ static bool gfx_ctx_x_set_video_mode(void *data, swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | LeaveWindowMask | EnterWindowMask | ButtonReleaseMask | ButtonPressMask; - swa.override_redirect = fullscreen ? True : False; + swa.override_redirect = False; if (fullscreen && !windowed_full) { @@ -691,6 +693,21 @@ static bool gfx_ctx_x_set_video_mode(void *data, RARCH_ERR("[GLX]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } + wm_name = x11_get_wm_name(g_x11_dpy); + if (wm_name) + { + RARCH_LOG("[GLX]: Window manager is %s.\n", wm_name); + + if (true_full && strcasestr(wm_name, "xfwm")) + { + RARCH_LOG("[GLX]: Using override-redirect workaround.\n"); + swa.override_redirect = True; + } + free(wm_name); + } + if (!x11_has_net_wm_fullscreen(g_x11_dpy) && true_full) + swa.override_redirect = True; + if (video_info->monitor_index) g_x11_screen = video_info->monitor_index - 1; @@ -720,12 +737,21 @@ static bool gfx_ctx_x_set_video_mode(void *data, g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask | - (true_full ? CWOverrideRedirect : 0), &swa); + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, + &swa); XSetWindowBackground(g_x11_dpy, g_x11_win, 0); XChangeProperty(g_x11_dpy, g_x11_win, net_wm_icon, cardinal, 32, PropModeReplace, (const unsigned char*)retroarch_icon_data, sizeof(retroarch_icon_data) / sizeof(*retroarch_icon_data)); + if (fullscreen && settings->bools.video_disable_composition) + { + uint32_t value = 1; + Atom net_wm_bypass_compositor = XInternAtom(g_x11_dpy, "_NET_WM_BYPASS_COMPOSITOR", False); + + RARCH_LOG("[GLX]: Requesting compositor bypass.\n"); + XChangeProperty(g_x11_dpy, g_x11_win, net_wm_bypass_compositor, cardinal, 32, PropModeReplace, (const unsigned char*)&value, 1); + } + if (opacity < (unsigned)-1) { Atom net_wm_opacity = XInternAtom(g_x11_dpy, "_NET_WM_WINDOW_OPACITY", False); @@ -769,6 +795,7 @@ static bool gfx_ctx_x_set_video_mode(void *data, { RARCH_LOG("[GLX]: Using true fullscreen.\n"); XMapRaised(g_x11_dpy, g_x11_win); + x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win); } else if (fullscreen) { @@ -783,7 +810,7 @@ static bool gfx_ctx_x_set_video_mode(void *data, * x_off and y_off usually get ignored in XCreateWindow(). */ x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height); - x11_windowed_fullscreen(g_x11_dpy, g_x11_win); + x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win); } else { @@ -1198,6 +1225,7 @@ const gfx_ctx_driver_t gfx_ctx_x = { gfx_ctx_x_swap_interval, gfx_ctx_x_set_video_mode, x11_get_video_size, + x11_get_refresh_rate, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_context/xegl_ctx.c b/gfx/drivers_context/xegl_ctx.c index f1e20fd78c..45df7e35c1 100644 --- a/gfx/drivers_context/xegl_ctx.c +++ b/gfx/drivers_context/xegl_ctx.c @@ -24,6 +24,7 @@ #endif #include "../../frontend/frontend_driver.h" +#include "../../configuration.h" #include "../common/egl_common.h" #include "../common/gl_common.h" @@ -271,7 +272,9 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; + char *wm_name = NULL; xegl_ctx_data_t *xegl = (xegl_ctx_data_t*)data; + settings_t *settings = config_get_ptr(); int (*old_handler)(Display*, XErrorEvent*) = NULL; @@ -296,7 +299,7 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, vi->visual, AllocNone); swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask; - swa.override_redirect = fullscreen ? True : False; + swa.override_redirect = False; if (fullscreen && !video_info->windowed_fullscreen) { @@ -309,6 +312,21 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } + wm_name = x11_get_wm_name(g_x11_dpy); + if (wm_name) + { + RARCH_LOG("[X/EGL]: Window manager is %s.\n", wm_name); + + if (true_full && strcasestr(wm_name, "xfwm")) + { + RARCH_LOG("[X/EGL]: Using override-redirect workaround.\n"); + swa.override_redirect = True; + } + free(wm_name); + } + if (!x11_has_net_wm_fullscreen(g_x11_dpy) && true_full) + swa.override_redirect = True; + if (video_info->monitor_index) g_x11_screen = video_info->monitor_index - 1; @@ -338,10 +356,20 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask | - (true_full ? CWOverrideRedirect : 0), &swa); + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, + &swa); XSetWindowBackground(g_x11_dpy, g_x11_win, 0); + if (fullscreen && settings && settings->bools.video_disable_composition) + { + uint32_t value = 1; + Atom cardinal = XInternAtom(g_x11_dpy, "CARDINAL", False); + Atom net_wm_bypass_compositor = XInternAtom(g_x11_dpy, "_NET_WM_BYPASS_COMPOSITOR", False); + + RARCH_LOG("[X/EGL]: Requesting compositor bypass.\n"); + XChangeProperty(g_x11_dpy, g_x11_win, net_wm_bypass_compositor, cardinal, 32, PropModeReplace, (const unsigned char*)&value, 1); + } + if (!egl_create_context(&xegl->egl, (attr != egl_attribs) ? egl_attribs : NULL)) { egl_report_error(); @@ -361,6 +389,7 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, { RARCH_LOG("[X/EGL]: Using true fullscreen.\n"); XMapRaised(g_x11_dpy, g_x11_win); + x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win); } else if (fullscreen) { @@ -374,7 +403,7 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, * x_off and y_off usually get ignored in XCreateWindow(). */ x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height); - x11_windowed_fullscreen(g_x11_dpy, g_x11_win); + x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win); } else { @@ -592,6 +621,7 @@ const gfx_ctx_driver_t gfx_ctx_x_egl = gfx_ctx_xegl_set_swap_interval, gfx_ctx_xegl_set_video_mode, x11_get_video_size, + x11_get_refresh_rate, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ diff --git a/gfx/drivers_font/d3d10_font.c b/gfx/drivers_font/d3d10_font.c new file mode 100644 index 0000000000..3252854303 --- /dev/null +++ b/gfx/drivers_font/d3d10_font.c @@ -0,0 +1,379 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2018 - Daniel De Matteis + * Copyright (C) 2014-2018 - Ali Bouhlel + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#define CINTERFACE + +#include +#include +#include +#include +#include + +#include "../font_driver.h" +#include "../video_driver.h" +#include "../common/d3d10_common.h" + +#include "../../verbosity.h" + +typedef struct +{ + d3d10_texture_t texture; + const font_renderer_driver_t* font_driver; + void* font_data; + struct font_atlas* atlas; +} d3d10_font_t; + +static void* +d3d10_font_init_font(void* data, const char* font_path, float font_size, bool is_threaded) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + d3d10_font_t* font = (d3d10_font_t*)calloc(1, sizeof(*font)); + + if (!font) + return NULL; + + if (!font_renderer_create_default( + (const void**)&font->font_driver, &font->font_data, font_path, font_size)) + { + RARCH_WARN("Couldn't initialize font renderer.\n"); + free(font); + return NULL; + } + + font->atlas = font->font_driver->get_atlas(font->font_data); + font->texture.sampler = d3d10->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_BORDER]; + font->texture.desc.Width = font->atlas->width; + font->texture.desc.Height = font->atlas->height; + font->texture.desc.Format = DXGI_FORMAT_A8_UNORM; + d3d10_init_texture(d3d10->device, &font->texture); + d3d10_update_texture( + d3d10->device, + font->atlas->width, font->atlas->height, font->atlas->width, + DXGI_FORMAT_A8_UNORM, font->atlas->buffer, &font->texture); + font->atlas->dirty = false; + + return font; +} + +static void d3d10_font_free_font(void* data, bool is_threaded) +{ + d3d10_font_t* font = (d3d10_font_t*)data; + + if (!font) + return; + + if (font->font_driver && font->font_data && font->font_driver->free) + font->font_driver->free(font->font_data); + + Release(font->texture.handle); + Release(font->texture.staging); + Release(font->texture.view); + free(font); +} + +static int d3d10_font_get_message_width(void* data, const char* msg, unsigned msg_len, float scale) +{ + d3d10_font_t* font = (d3d10_font_t*)data; + + unsigned i; + int delta_x = 0; + + if (!font) + return 0; + + for (i = 0; i < msg_len; i++) + { + const struct font_glyph *glyph; + const char* msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + glyph = font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + delta_x += glyph->advance_x; + } + + return delta_x * scale; +} + +static void d3d10_font_render_line( + video_frame_info_t* video_info, + d3d10_font_t* font, + const char* msg, + unsigned msg_len, + float scale, + const unsigned int color, + float pos_x, + float pos_y, + unsigned text_align) +{ + unsigned i, count; + void* mapped_vbo; + d3d10_sprite_t* v; + d3d10_video_t* d3d10 = (d3d10_video_t*)video_info->userdata; + unsigned width = video_info->width; + unsigned height = video_info->height; + int x = roundf(pos_x * width); + int y = roundf((1.0 - pos_y) * height); + + if ( !d3d10 || + !d3d10->sprites.enabled || + msg_len > (unsigned)d3d10->sprites.capacity) + return; + + if (d3d10->sprites.offset + msg_len > (unsigned)d3d10->sprites.capacity) + d3d10->sprites.offset = 0; + + switch (text_align) + { + case TEXT_ALIGN_RIGHT: + x -= d3d10_font_get_message_width(font, msg, msg_len, scale); + break; + + case TEXT_ALIGN_CENTER: + x -= d3d10_font_get_message_width(font, msg, msg_len, scale) / 2; + break; + } + + D3D10MapBuffer(d3d10->sprites.vbo, D3D10_MAP_WRITE_NO_OVERWRITE, 0, (void**)&mapped_vbo); + v = (d3d10_sprite_t*)mapped_vbo + d3d10->sprites.offset; + + for (i = 0; i < msg_len; i++) + { + const struct font_glyph* glyph; + const char* msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + glyph = font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + v->pos.x = (x + glyph->draw_offset_x) * scale / (float)d3d10->viewport.Width; + v->pos.y = (y + glyph->draw_offset_y) * scale / (float)d3d10->viewport.Height; + v->pos.w = glyph->width * scale / (float)d3d10->viewport.Width; + v->pos.h = glyph->height * scale / (float)d3d10->viewport.Height; + + v->coords.u = glyph->atlas_offset_x / (float)font->texture.desc.Width; + v->coords.v = glyph->atlas_offset_y / (float)font->texture.desc.Height; + v->coords.w = glyph->width / (float)font->texture.desc.Width; + v->coords.h = glyph->height / (float)font->texture.desc.Height; + + v->params.scaling = 1; + v->params.rotation = 0; + + v->colors[0] = color; + v->colors[1] = color; + v->colors[2] = color; + v->colors[3] = color; + + v++; + + x += glyph->advance_x * scale; + y += glyph->advance_y * scale; + } + + count = v - ((d3d10_sprite_t*)mapped_vbo + d3d10->sprites.offset); + D3D10UnmapBuffer(d3d10->sprites.vbo); + + if (!count) + return; + + if (font->atlas->dirty) + { + d3d10_update_texture( + d3d10->device, + font->atlas->width, font->atlas->height, font->atlas->width, + DXGI_FORMAT_A8_UNORM, font->atlas->buffer, &font->texture); + font->atlas->dirty = false; + } + + d3d10_set_texture_and_sampler(d3d10->device, 0, &font->texture); + D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); + + D3D10SetPShader(d3d10->device, d3d10->sprites.shader_font.ps); + D3D10Draw(d3d10->device, count, d3d10->sprites.offset); + D3D10SetPShader(d3d10->device, d3d10->sprites.shader.ps); + + d3d10->sprites.offset += count; +} + +static void d3d10_font_render_message( + video_frame_info_t* video_info, + d3d10_font_t* font, + const char* msg, + float scale, + const unsigned int color, + float pos_x, + float pos_y, + unsigned text_align) +{ + int lines = 0; + float line_height; + + if (!msg || !*msg) + return; + + /* If the font height is not supported just draw as usual */ + if (!font->font_driver->get_line_height) + { + d3d10_font_render_line( + video_info, font, msg, strlen(msg), scale, color, pos_x, pos_y, text_align); + return; + } + + line_height = font->font_driver->get_line_height(font->font_data) * scale / video_info->height; + + for (;;) + { + const char* delim = strchr(msg, '\n'); + + /* Draw the line */ + if (delim) + { + unsigned msg_len = delim - msg; + d3d10_font_render_line( + video_info, font, msg, msg_len, scale, color, pos_x, + pos_y - (float)lines * line_height, text_align); + msg += msg_len + 1; + lines++; + } + else + { + unsigned msg_len = strlen(msg); + d3d10_font_render_line( + video_info, font, msg, msg_len, scale, color, pos_x, + pos_y - (float)lines * line_height, text_align); + break; + } + } +} + +static void d3d10_font_render_msg( + video_frame_info_t* video_info, void* data, + const char* msg, const struct font_params *params) +{ + float x, y, scale, drop_mod, drop_alpha; + int drop_x, drop_y; + enum text_alignment text_align; + unsigned color, color_dark, r, g, b, + alpha, r_dark, g_dark, b_dark, alpha_dark; + d3d10_font_t* font = (d3d10_font_t*)data; + unsigned width = video_info->width; + unsigned height = video_info->height; + + if (!font || !msg || !*msg) + return; + + if (params) + { + x = params->x; + y = params->y; + scale = params->scale; + text_align = params->text_align; + drop_x = params->drop_x; + drop_y = params->drop_y; + drop_mod = params->drop_mod; + drop_alpha = params->drop_alpha; + + r = FONT_COLOR_GET_RED(params->color); + g = FONT_COLOR_GET_GREEN(params->color); + b = FONT_COLOR_GET_BLUE(params->color); + alpha = FONT_COLOR_GET_ALPHA(params->color); + + color = DXGI_COLOR_RGBA(r, g, b, alpha); + } + else + { + x = video_info->font_msg_pos_x; + y = video_info->font_msg_pos_y; + scale = 1.0f; + text_align = TEXT_ALIGN_LEFT; + + r = (video_info->font_msg_color_r * 255); + g = (video_info->font_msg_color_g * 255); + b = (video_info->font_msg_color_b * 255); + alpha = 255; + color = DXGI_COLOR_RGBA(r, g, b, alpha); + + drop_x = -2; + drop_y = -2; + drop_mod = 0.3f; + drop_alpha = 1.0f; + } + + if (drop_x || drop_y) + { + r_dark = r * drop_mod; + g_dark = g * drop_mod; + b_dark = b * drop_mod; + alpha_dark = alpha * drop_alpha; + color_dark = DXGI_COLOR_RGBA(r_dark, g_dark, b_dark, alpha_dark); + + d3d10_font_render_message( + video_info, font, msg, scale, color_dark, + x + scale * drop_x / width, + y + scale * drop_y / height, text_align); + } + + d3d10_font_render_message(video_info, font, msg, scale, + color, x, y, text_align); +} + +static const struct font_glyph* d3d10_font_get_glyph(void *data, uint32_t code) +{ + d3d10_font_t* font = (d3d10_font_t*)data; + + if (!font || !font->font_driver) + return NULL; + + if (!font->font_driver->ident) + return NULL; + + return font->font_driver->get_glyph((void*)font->font_driver, code); +} + +static void d3d10_font_bind_block(void* data, void *userdata) +{ + (void)data; +} + +font_renderer_t d3d10_font = { + d3d10_font_init_font, + d3d10_font_free_font, + d3d10_font_render_msg, + "d3d10font", + d3d10_font_get_glyph, + d3d10_font_bind_block, + NULL, /* flush */ + d3d10_font_get_message_width, +}; diff --git a/gfx/drivers_font/d3d_w32_font.c b/gfx/drivers_font/d3d_w32_font.c index 6d329cef82..3b2824e12e 100644 --- a/gfx/drivers_font/d3d_w32_font.c +++ b/gfx/drivers_font/d3d_w32_font.c @@ -14,6 +14,8 @@ * If not, see . */ +#define CINTERFACE + #include #include diff --git a/gfx/drivers_font/xdk1_xfonts.c b/gfx/drivers_font/xdk1_xfonts.c index ccfc7b8542..3e7e425e81 100644 --- a/gfx/drivers_font/xdk1_xfonts.c +++ b/gfx/drivers_font/xdk1_xfonts.c @@ -22,8 +22,8 @@ #endif #include "../drivers/d3d.h" -#include "../drivers/d3d_common.h" -#include "../drivers/d3d8_common.h" +#include "../common/d3d_common.h" +#include "../common/d3d8_common.h" #include "../font_driver.h" diff --git a/gfx/drivers_font/xdk360_fonts.cpp b/gfx/drivers_font/xdk360_fonts.cpp index 71d0b82fbd..6d57e8520e 100644 --- a/gfx/drivers_font/xdk360_fonts.cpp +++ b/gfx/drivers_font/xdk360_fonts.cpp @@ -397,7 +397,7 @@ typedef struct float m_fFontBottomPadding; /* Padding below the strike zone. */ float m_fFontYAdvance; /* Number of pixels to move the cursor for a line feed. */ wchar_t * m_TranslatorTable; /* ASCII to glyph lookup table. */ - void *m_pFontTexture; + LPDIRECT3DTEXTURE9 m_pFontTexture; const GLYPH_ATTR* m_Glyphs; /* Array of glyphs. */ } xdk360_video_font_t; @@ -420,7 +420,7 @@ typedef struct static PackedResource m_xprResource; -static bool xdk360_video_font_create_shaders(xdk360_video_font_t * font, void *dev) +static bool xdk360_video_font_create_shaders(xdk360_video_font_t * font, LPDIRECT3DDEVICE9 dev) { ID3DXBuffer* pShaderCode = NULL; @@ -443,7 +443,7 @@ static bool xdk360_video_font_create_shaders(xdk360_video_font_t * font, void *d if (!d3d9_vertex_declaration_new(dev, decl, (void**)&font->s_FontLocals.m_pFontVertexDecl)) goto error; - if (!d3dx_compile_shader( font_hlsl_d3d9_program, sizeof(font_hlsl_d3d9_program)-1 , + if (!d3d9x_compile_shader( font_hlsl_d3d9_program, sizeof(font_hlsl_d3d9_program)-1 , NULL, NULL, "main_vertex", "vs.2.0", 0, &pShaderCode, NULL, NULL )) goto error; @@ -451,9 +451,9 @@ static bool xdk360_video_font_create_shaders(xdk360_video_font_t * font, void *d (void**)&font->s_FontLocals.m_pFontVertexShader )) goto error; - d3dxbuffer_release(pShaderCode); + d3d9x_buffer_release(pShaderCode); - if (!d3dx_compile_shader(font_hlsl_d3d9_program, sizeof(font_hlsl_d3d9_program)-1 , + if (!d3d9x_compile_shader(font_hlsl_d3d9_program, sizeof(font_hlsl_d3d9_program)-1 , NULL, NULL, "main_fragment", "ps.2.0", 0,&pShaderCode, NULL, NULL )) goto error; @@ -461,15 +461,15 @@ static bool xdk360_video_font_create_shaders(xdk360_video_font_t * font, void *d (void**)&font->s_FontLocals.m_pFontPixelShader)) goto error; - d3dxbuffer_release(pShaderCode); + d3d9x_buffer_release(pShaderCode); return true; error: if (pShaderCode) - d3dxbuffer_release(pShaderCode); - d3d9_free_pixel_shader(font->d3d->dev, font->s_FontLocals.m_pFontPixelShader); - d3d9_free_vertex_shader(font->d3d->dev, font->s_FontLocals.m_pFontVertexShader); + d3d9x_buffer_release(pShaderCode); + d3d9_free_pixel_shader((LPDIRECT3DDEVICE9)font->d3d->dev, font->s_FontLocals.m_pFontPixelShader); + d3d9_free_vertex_shader((LPDIRECT3DDEVICE9)font->d3d->dev, font->s_FontLocals.m_pFontVertexShader); d3d9_vertex_declaration_free(font->s_FontLocals.m_pFontVertexDecl); font->s_FontLocals.m_pFontPixelShader = NULL; font->s_FontLocals.m_pFontVertexShader = NULL; @@ -505,11 +505,11 @@ static void *xdk360_init_font(void *video_data, if (FAILED( m_xprResource.Create(font_path, 0, NULL))) goto error; - pFontTexture = m_xprResource.GetTexture( "FontTexture" ); + pFontTexture = (LPDIRECT3DTEXTURE9)m_xprResource.GetTexture( "FontTexture" ); pFontData = m_xprResource.GetData( "FontData"); /* Save a copy of the texture. */ - font->m_pFontTexture = pFontTexture; + font->m_pFontTexture = (LPDIRECT3DTEXTURE9)pFontTexture; /* Check version of file (to make sure it matches up with the FontMaker tool). */ pData = (const uint8_t*)pFontData; @@ -537,7 +537,7 @@ static void *xdk360_init_font(void *video_data, font->m_Glyphs = ((const FontFileStrikesImage_t *)pData)->m_Glyphs; /* Create the vertex and pixel shaders for rendering the font */ - if (!xdk360_video_font_create_shaders(font, font->d3d->dev)) + if (!xdk360_video_font_create_shaders(font, (LPDIRECT3DDEVICE9)font->d3d->dev)) { RARCH_ERR( "Could not create font shaders.\n" ); goto error; @@ -566,8 +566,8 @@ static void xdk360_free_font(void *data, bool is_threaded) font->m_cMaxGlyph = 0; font->m_TranslatorTable = NULL; - d3d9_free_pixel_shader(font->d3d->dev, font->s_FontLocals.m_pFontPixelShader); - d3d9_free_vertex_shader(font->d3d->dev, font->s_FontLocals.m_pFontVertexShader); + d3d9_free_pixel_shader((LPDIRECT3DDEVICE9)font->d3d->dev, font->s_FontLocals.m_pFontPixelShader); + d3d9_free_vertex_shader((LPDIRECT3DDEVICE9)font->d3d->dev, font->s_FontLocals.m_pFontVertexShader); d3d9_vertex_declaration_free(font->s_FontLocals.m_pFontVertexDecl); font->s_FontLocals.m_pFontPixelShader = NULL; @@ -583,24 +583,35 @@ static void xdk360_free_font(void *data, bool is_threaded) static void xdk360_render_msg_post(xdk360_video_font_t * font) { - if (!font || !font->d3d || !font->d3d->dev) + LPDIRECT3DDEVICE9 dev; + if (!font || !font->d3d) return; + dev = (LPDIRECT3DDEVICE9)font->d3d->dev; - d3d9_set_texture(font->d3d->dev, 0, NULL); - d3d9_set_vertex_declaration(font->d3d->dev, NULL); - d3d9_set_vertex_shader(font->d3d->dev, 0, NULL); - d3d9_set_pixel_shader(font->d3d->dev, NULL); - d3d9_set_render_state(font->d3d->dev, D3DRS_VIEWPORTENABLE, font->m_dwSavedState); + if (!dev) + return; + + d3d9_set_texture(dev, 0, NULL); + d3d9_set_vertex_declaration(dev, NULL); + d3d9_set_vertex_shader(dev, 0, NULL); + d3d9_set_pixel_shader(dev, NULL); + d3d9_set_render_state(dev, D3DRS_VIEWPORTENABLE, font->m_dwSavedState); } static void xdk360_render_msg_pre(xdk360_video_font_t * font) { float vTexScale[4]; D3DSURFACE_DESC TextureDesc; + LPDIRECT3DDEVICE9 dev; - if (!font || !font->d3d || !font->d3d->dev) + if (!font || !font->d3d) return; + dev = (LPDIRECT3DDEVICE9)font->d3d->dev; + + if (!dev) + return; + /* Save state. */ d3d9_get_render_state(font->d3d->dev, D3DRS_VIEWPORTENABLE, (DWORD*)&font->m_dwSavedState ); @@ -610,18 +621,18 @@ static void xdk360_render_msg_pre(xdk360_video_font_t * font) d3d9_texture_get_level_desc(font->m_pFontTexture, 0, &TextureDesc); /* Set render state. */ - d3d9_set_texture(font->d3d->dev, 0, font->m_pFontTexture); + d3d9_set_texture(dev, 0, font->m_pFontTexture); vTexScale[0] = 1.0f / TextureDesc.Width; vTexScale[1] = 1.0f / TextureDesc.Height; vTexScale[2] = 0.0f; vTexScale[3] = 0.0f; - d3d9_set_render_state(font->d3d->dev, D3DRS_VIEWPORTENABLE, FALSE); - d3d9_set_vertex_declaration(font->d3d->dev, font->s_FontLocals.m_pFontVertexDecl); - d3d9_set_vertex_shader(font->d3d->dev, 0, font->s_FontLocals.m_pFontVertexShader); - d3d9_set_pixel_shader(font->d3d->dev, font->s_FontLocals.m_pFontPixelShader); - d3d9_set_vertex_shader_constantf(font->d3d->dev, 2, vTexScale, 1); + d3d9_set_render_state(dev, D3DRS_VIEWPORTENABLE, FALSE); + d3d9_set_vertex_declaration(dev, font->s_FontLocals.m_pFontVertexDecl); + d3d9_set_vertex_shader(dev, 0, font->s_FontLocals.m_pFontVertexShader); + d3d9_set_pixel_shader(dev, font->s_FontLocals.m_pFontPixelShader); + d3d9_set_vertex_shader_constantf(dev, 2, vTexScale, 1); } static void xdk360_draw_text(xdk360_video_font_t *font, diff --git a/gfx/drivers_renderchain/d3d9_cg_renderchain.c b/gfx/drivers_renderchain/d3d9_cg_renderchain.c index ed8308e1a6..353fca3ab2 100644 --- a/gfx/drivers_renderchain/d3d9_cg_renderchain.c +++ b/gfx/drivers_renderchain/d3d9_cg_renderchain.c @@ -14,6 +14,8 @@ * If not, see . */ +#define CINTERFACE + #include #include @@ -463,9 +465,9 @@ static void d3d9_cg_renderchain_bind_orig(cg_renderchain_t *chain, index = cgGetParameterResourceIndex(param); d3d9_set_texture(chain->dev, index, chain->passes->data[0].tex); d3d9_set_sampler_magfilter(chain->dev, index, - d3d9_translate_filter(chain->passes->data[0].info.pass->filter)); + d3d_translate_filter(chain->passes->data[0].info.pass->filter)); d3d9_set_sampler_minfilter(chain->dev, index, - d3d9_translate_filter(chain->passes->data[0].info.pass->filter)); + d3d_translate_filter(chain->passes->data[0].info.pass->filter)); d3d9_set_sampler_address_u(chain->dev, index, D3DTADDRESS_BORDER); d3d9_set_sampler_address_v(chain->dev, index, D3DTADDRESS_BORDER); unsigned_vector_list_append(chain->bound_tex, index); @@ -539,9 +541,9 @@ static void d3d9_cg_renderchain_bind_prev(void *data, const void *pass_data) unsigned_vector_list_append(chain->bound_tex, index); d3d9_set_sampler_magfilter(chain->dev, index, - d3d9_translate_filter(chain->passes->data[0].info.pass->filter)); + d3d_translate_filter(chain->passes->data[0].info.pass->filter)); d3d9_set_sampler_minfilter(chain->dev, index, - d3d9_translate_filter(chain->passes->data[0].info.pass->filter)); + d3d_translate_filter(chain->passes->data[0].info.pass->filter)); d3d9_set_sampler_address_u(chain->dev, index, D3DTADDRESS_BORDER); d3d9_set_sampler_address_v(chain->dev, index, D3DTADDRESS_BORDER); } @@ -570,9 +572,9 @@ static void d3d9_cg_renderchain_add_lut_internal(void *data, d3d9_set_texture(chain->dev, index, chain->luts->data[i].tex); d3d9_set_sampler_magfilter(chain->dev, index, - d3d9_translate_filter(chain->luts->data[i].smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST)); + d3d_translate_filter(chain->luts->data[i].smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST)); d3d9_set_sampler_minfilter(chain->dev, index, - d3d9_translate_filter(chain->luts->data[i].smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST)); + d3d_translate_filter(chain->luts->data[i].smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST)); d3d9_set_sampler_address_u(chain->dev, index, D3DTADDRESS_BORDER); d3d9_set_sampler_address_v(chain->dev, index, D3DTADDRESS_BORDER); unsigned_vector_list_append(chain->bound_tex, index); @@ -623,9 +625,9 @@ static void d3d9_cg_renderchain_bind_pass( d3d9_set_texture(chain->dev, index, chain->passes->data[i].tex); d3d9_set_sampler_magfilter(chain->dev, index, - d3d9_translate_filter(chain->passes->data[i].info.pass->filter)); + d3d_translate_filter(chain->passes->data[i].info.pass->filter)); d3d9_set_sampler_minfilter(chain->dev, index, - d3d9_translate_filter(chain->passes->data[i].info.pass->filter)); + d3d_translate_filter(chain->passes->data[i].info.pass->filter)); d3d9_set_sampler_address_u(chain->dev, index, D3DTADDRESS_BORDER); d3d9_set_sampler_address_v(chain->dev, index, D3DTADDRESS_BORDER); } @@ -887,9 +889,9 @@ static bool d3d9_cg_renderchain_create_first_pass( d3d9_set_texture(chain->dev, 0, chain->prev.tex[i]); d3d9_set_sampler_minfilter(chain->dev, 0, - d3d9_translate_filter(info->pass->filter)); + d3d_translate_filter(info->pass->filter)); d3d9_set_sampler_magfilter(chain->dev, 0, - d3d9_translate_filter(info->pass->filter)); + d3d_translate_filter(info->pass->filter)); d3d9_set_sampler_address_u(chain->dev, 0, D3DTADDRESS_BORDER); d3d9_set_sampler_address_v(chain->dev, 0, D3DTADDRESS_BORDER); d3d9_set_texture(chain->dev, 0, NULL); @@ -1331,8 +1333,8 @@ static void cg_d3d9_renderchain_blit_to_texture( unsigned width, unsigned height, unsigned pitch) { - D3DLOCKED_RECT d3dlr; - struct Pass *first = (struct Pass*)&chain->passes->data[0]; + D3DLOCKED_RECT d3dlr = {0, NULL}; + struct Pass *first = (struct Pass*)&chain->passes->data[0]; if ( (first->last_width != width || first->last_height != height) @@ -1426,9 +1428,9 @@ static void cg_d3d9_renderchain_render_pass( d3d9_set_texture(chain->dev, 0, pass->tex); d3d9_set_sampler_minfilter(chain->dev, 0, - d3d9_translate_filter(pass->info.pass->filter)); + d3d_translate_filter(pass->info.pass->filter)); d3d9_set_sampler_magfilter(chain->dev, 0, - d3d9_translate_filter(pass->info.pass->filter)); + d3d_translate_filter(pass->info.pass->filter)); d3d9_set_vertex_declaration(chain->dev, pass->vertex_decl); for (i = 0; i < 4; i++) diff --git a/gfx/drivers_renderchain/d3d9_hlsl_renderchain.c b/gfx/drivers_renderchain/d3d9_hlsl_renderchain.c index 0f61b2b0b3..5944a6c799 100644 --- a/gfx/drivers_renderchain/d3d9_hlsl_renderchain.c +++ b/gfx/drivers_renderchain/d3d9_hlsl_renderchain.c @@ -14,6 +14,8 @@ * If not, see . */ +#define CINTERFACE + #include #include #include @@ -28,6 +30,7 @@ #include "../video_driver.h" #include "../../configuration.h" +#include "../../retroarch.h" #include "../../verbosity.h" typedef struct hlsl_d3d9_renderchain @@ -201,7 +204,7 @@ static void hlsl_d3d9_renderchain_blit_to_texture( void *data, const void *frame, unsigned width, unsigned height, unsigned pitch) { - D3DLOCKED_RECT d3dlr; + D3DLOCKED_RECT d3dlr = { 0, NULL }; hlsl_d3d9_renderchain_t *chain = (hlsl_d3d9_renderchain_t*)data; if (chain->last_width != width || chain->last_height != height) @@ -263,7 +266,6 @@ static bool hlsl_d3d9_renderchain_init_shader(void *data, void *renderchain_data) { video_shader_ctx_init_t init; - bool ret = false; d3d_video_t *d3d = (d3d_video_t*)data; settings_t *settings = config_get_ptr(); (void)renderchain_data; @@ -274,13 +276,11 @@ static bool hlsl_d3d9_renderchain_init_shader(void *data, init.shader_type = RARCH_SHADER_HLSL; init.data = data; init.path = retroarch_get_shader_preset(); - init.shader = &hlsl_backend; + init.shader = NULL; RARCH_LOG("D3D]: Using HLSL shader backend.\n"); - ret = video_shader_driver_init(&init); - - return ret; + return video_shader_driver_init(&init); } static bool hlsl_d3d9_renderchain_init(void *data, diff --git a/gfx/drivers_renderchain/gl1_renderchain.c b/gfx/drivers_renderchain/gl1_renderchain.c index 3eb1f887c7..f4f06acb43 100644 --- a/gfx/drivers_renderchain/gl1_renderchain.c +++ b/gfx/drivers_renderchain/gl1_renderchain.c @@ -55,8 +55,6 @@ typedef struct gl1_renderchain void *empty; } gl1_renderchain_t; -GLenum min_filter_to_mag(GLenum type); - void gl1_renderchain_free(void *data, void *chain_data) { (void)chain_data; diff --git a/gfx/drivers_renderchain/gl2_renderchain.c b/gfx/drivers_renderchain/gl2_renderchain.c index 1cb856c4e8..0a72e89137 100644 --- a/gfx/drivers_renderchain/gl2_renderchain.c +++ b/gfx/drivers_renderchain/gl2_renderchain.c @@ -504,27 +504,30 @@ static void gl2_renderchain_deinit_fbo(void *data, gl_t *gl = (gl_t*)data; gl2_renderchain_t *chain = (gl2_renderchain_t*)chain_data; - if (!gl) - return; + if (gl) + { + if (gl->fbo_feedback) + gl2_delete_fb(1, &gl->fbo_feedback); + if (gl->fbo_feedback_texture) + glDeleteTextures(1, &gl->fbo_feedback_texture); - glDeleteTextures(chain->fbo_pass, chain->fbo_texture); - gl2_delete_fb(chain->fbo_pass, chain->fbo); + gl->fbo_inited = false; + gl->fbo_feedback_enable = false; + gl->fbo_feedback_pass = 0; + gl->fbo_feedback_texture = 0; + gl->fbo_feedback = 0; + } - memset(chain->fbo_texture, 0, sizeof(chain->fbo_texture)); - memset(chain->fbo, 0, sizeof(chain->fbo)); + if (chain) + { + gl2_delete_fb(chain->fbo_pass, chain->fbo); + glDeleteTextures(chain->fbo_pass, chain->fbo_texture); - if (gl->fbo_feedback) - gl2_delete_fb(1, &gl->fbo_feedback); - if (gl->fbo_feedback_texture) - glDeleteTextures(1, &gl->fbo_feedback_texture); + memset(chain->fbo_texture, 0, sizeof(chain->fbo_texture)); + memset(chain->fbo, 0, sizeof(chain->fbo)); - chain->fbo_pass = 0; - - gl->fbo_inited = false; - gl->fbo_feedback_enable = false; - gl->fbo_feedback_pass = 0; - gl->fbo_feedback_texture = 0; - gl->fbo_feedback = 0; + chain->fbo_pass = 0; + } } static void gl2_renderchain_deinit_hw_render( @@ -711,10 +714,9 @@ static void gl_create_fbo_texture(gl_t *gl, } } -static void gl_create_fbo_textures(gl_t *gl, void *chain_data) +static void gl_create_fbo_textures(gl_t *gl, gl2_renderchain_t *chain) { int i; - gl2_renderchain_t *chain = (gl2_renderchain_t*)chain_data; glGenTextures(chain->fbo_pass, chain->fbo_texture); diff --git a/gfx/drivers_renderchain/null_renderchain.c b/gfx/drivers_renderchain/null_renderchain.c deleted file mode 100644 index 6da4458bc2..0000000000 --- a/gfx/drivers_renderchain/null_renderchain.c +++ /dev/null @@ -1,135 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * Copyright (C) 2011-2017 - Daniel De Matteis - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#include -#include -#include - -#include "../video_driver.h" - -typedef struct null_renderchain -{ - void *empty; -} null_renderchain_t; - -static void null_renderchain_free(void *data) -{ -} - -static void *null_renderchain_new(void) -{ - null_renderchain_t *renderchain = (null_renderchain_t*)calloc(1, sizeof(*renderchain)); - if (!renderchain) - return NULL; - - return renderchain; -} - -static bool null_renderchain_init(void *data, - const void *info, - void *dev_data, - const void *final_viewport_data, - const void *info_data, - bool rgb32 - ) -{ - (void)data; - (void)info; - (void)dev_data; - (void)final_viewport_data; - (void)info_data; - (void)rgb32; - - return true; -} - -static void null_renderchain_set_final_viewport(void *data, - void *renderchain_data, const void *viewport_data) -{ - (void)data; - (void)renderchain_data; - (void)viewport_data; -} - -static bool null_renderchain_render(void *data, const void *frame, - unsigned width, unsigned height, - unsigned pitch, unsigned rotation) -{ - (void)data; - (void)frame; - (void)width; - (void)height; - (void)pitch; - (void)rotation; - - return true; -} - -static bool null_renderchain_add_lut(void *data, - const char *id, const char *path, bool smooth) -{ - (void)data; - (void)id; - (void)path; - (void)smooth; - - return true; -} - -static bool null_renderchain_add_pass(void *data, const void *info_data) -{ - (void)data; - (void)info_data; - - return true; -} - -static void null_renderchain_add_state_tracker(void *data, void *tracker_data) -{ - (void)data; - (void)tracker_data; -} - -static void null_renderchain_convert_geometry( - void *data, const void *info_data, - unsigned *out_width, unsigned *out_height, - unsigned width, unsigned height, - void *final_viewport_data) -{ - (void)data; - (void)info_data; - (void)out_width; - (void)out_height; - (void)width; - (void)height; - (void)final_viewport_data; -} - -d3d_renderchain_driver_t null_d3d_renderchain = { - null_renderchain_free, - null_renderchain_new, - null_renderchain_init, - null_renderchain_set_final_viewport, - null_renderchain_add_pass, - null_renderchain_add_lut, - null_renderchain_add_state_tracker, - null_renderchain_render, - null_renderchain_convert_geometry, - NULL, - NULL, - NULL, - "null", -}; diff --git a/gfx/drivers_shader/glslang_util.cpp b/gfx/drivers_shader/glslang_util.cpp index 41d3527b36..05a648ca9b 100644 --- a/gfx/drivers_shader/glslang_util.cpp +++ b/gfx/drivers_shader/glslang_util.cpp @@ -44,7 +44,7 @@ bool glslang_read_shader_file(const char *path, vector *output, bool roo char tmp[PATH_MAX_LENGTH]; char *ptr = NULL; char *buf = nullptr; - ssize_t len = 0; + int64_t len = 0; const char *basename = path_basename(path); include_path[0] = tmp[0] = '\0'; diff --git a/gfx/drivers_shader/glslang_util.h b/gfx/drivers_shader/glslang_util.h index 006fadc490..cd26e42380 100644 --- a/gfx/drivers_shader/glslang_util.h +++ b/gfx/drivers_shader/glslang_util.h @@ -23,7 +23,7 @@ typedef enum glslang_format { SLANG_FORMAT_UNKNOWN = 0, - // 8-bit + /* 8-bit */ SLANG_FORMAT_R8_UNORM, SLANG_FORMAT_R8_UINT, SLANG_FORMAT_R8_SINT, @@ -35,11 +35,11 @@ typedef enum glslang_format SLANG_FORMAT_R8G8B8A8_SINT, SLANG_FORMAT_R8G8B8A8_SRGB, - // 10-bit + /* 10-bit */ SLANG_FORMAT_A2B10G10R10_UNORM_PACK32, SLANG_FORMAT_A2B10G10R10_UINT_PACK32, - // 16-bit + /* 16-bit */ SLANG_FORMAT_R16_UINT, SLANG_FORMAT_R16_SINT, SLANG_FORMAT_R16_SFLOAT, @@ -50,7 +50,7 @@ typedef enum glslang_format SLANG_FORMAT_R16G16B16A16_SINT, SLANG_FORMAT_R16G16B16A16_SFLOAT, - // 32-bit + /* 32-bit */ SLANG_FORMAT_R32_UINT, SLANG_FORMAT_R32_SINT, SLANG_FORMAT_R32_SFLOAT, @@ -105,7 +105,7 @@ struct glslang_output bool glslang_compile_shader(const char *shader_path, glslang_output *output); -// Helpers for internal use. +/* Helpers for internal use. */ bool glslang_read_shader_file(const char *path, std::vector *output, bool root_file); bool glslang_parse_meta(const std::vector &lines, glslang_meta *meta); #endif diff --git a/gfx/drivers_shader/shader_gl_cg.c b/gfx/drivers_shader/shader_gl_cg.c index 2fed59a303..4e89540b63 100644 --- a/gfx/drivers_shader/shader_gl_cg.c +++ b/gfx/drivers_shader/shader_gl_cg.c @@ -1053,10 +1053,50 @@ static void gl_cg_set_program_attributes(void *data, unsigned i) } } +static void gl_cg_init_menu_shaders(void *data) +{ + struct shader_program_info shader_prog_info; + cg_shader_data_t *cg = (cg_shader_data_t*)data; + + if (!cg) + return; + +#ifdef HAVE_SHADERPIPELINE + shader_prog_info.combined = stock_xmb_ribbon_simple; + shader_prog_info.is_file = false; + + gl_cg_compile_program( + cg, + VIDEO_SHADER_MENU, + &cg->prg[VIDEO_SHADER_MENU], + &shader_prog_info); + gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU); + + shader_prog_info.combined = stock_xmb_ribbon_simple; + shader_prog_info.is_file = false; + + gl_cg_compile_program( + cg, + VIDEO_SHADER_MENU_2, + &cg->prg[VIDEO_SHADER_MENU_2], + &shader_prog_info); + gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU_2); + + shader_prog_info.combined = stock_xmb_snow; + shader_prog_info.is_file = false; + + gl_cg_compile_program( + cg, + VIDEO_SHADER_MENU_3, + &cg->prg[VIDEO_SHADER_MENU_3], + &shader_prog_info); + gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU_3); +#endif +} + static void *gl_cg_init(void *data, const char *path) { unsigned i; - struct shader_program_info shader_prog_info; cg_shader_data_t *cg = (cg_shader_data_t*) calloc(1, sizeof(cg_shader_data_t)); @@ -1129,37 +1169,6 @@ static void *gl_cg_init(void *data, const char *path) gl_cg_set_shaders(cg->prg[1].fprg, cg->prg[1].vprg); -#ifdef HAVE_SHADERPIPELINE - shader_prog_info.combined = stock_xmb_ribbon_simple; - shader_prog_info.is_file = false; - - gl_cg_compile_program( - cg, - VIDEO_SHADER_MENU, - &cg->prg[VIDEO_SHADER_MENU], - &shader_prog_info); - gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU); - - shader_prog_info.combined = stock_xmb_ribbon_simple; - shader_prog_info.is_file = false; - - gl_cg_compile_program( - cg, - VIDEO_SHADER_MENU_2, - &cg->prg[VIDEO_SHADER_MENU_2], - &shader_prog_info); - gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU_2); - - shader_prog_info.combined = stock_xmb_snow; - shader_prog_info.is_file = false; - - gl_cg_compile_program( - cg, - VIDEO_SHADER_MENU_3, - &cg->prg[VIDEO_SHADER_MENU_3], - &shader_prog_info); - gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU_3); -#endif gl_cg_reset_attrib(cg); @@ -1271,6 +1280,7 @@ static struct video_shader *gl_cg_get_current_shader(void *data) const shader_backend_t gl_cg_backend = { gl_cg_init, + gl_cg_init_menu_shaders, gl_cg_deinit, gl_cg_set_params, gl_cg_set_uniform_parameter, diff --git a/gfx/drivers_shader/shader_glsl.c b/gfx/drivers_shader/shader_glsl.c index 3f5d077d5c..ad12be1116 100644 --- a/gfx/drivers_shader/shader_glsl.c +++ b/gfx/drivers_shader/shader_glsl.c @@ -493,8 +493,8 @@ static void gl_glsl_strip_parameter_pragmas(char *source) static bool gl_glsl_load_source_path(struct video_shader_pass *pass, const char *path) { - ssize_t len; - int nitems = pass ? filestream_read_file(path, + int64_t len = 0; + int64_t nitems = pass ? filestream_read_file(path, (void**)&pass->source.string.vertex, &len) : 0; if (nitems <= 0 || len <= 0) @@ -790,6 +790,113 @@ static void gl_glsl_deinit(void *data) free(glsl); } +static void gl_glsl_init_menu_shaders(void *data) +{ +#ifdef HAVE_SHADERPIPELINE + struct shader_program_info shader_prog_info; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)data; + + if (!glsl) + return; + +#ifdef HAVE_OPENGLES + if (gl_query_extension("GL_OES_standard_derivatives")) + { + shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; + shader_prog_info.fragment = glsl_core ? core_stock_fragment_xmb : stock_fragment_xmb; + } + else + { + shader_prog_info.vertex = stock_vertex_xmb_ribbon_simple_legacy; + shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; + } +#else + shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; + shader_prog_info.fragment = glsl_core ? core_stock_fragment_xmb : stock_fragment_xmb; +#endif + shader_prog_info.is_file = false; + + gl_glsl_compile_program( + glsl, + VIDEO_SHADER_MENU, + &glsl->prg[VIDEO_SHADER_MENU], + &shader_prog_info); + gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU].id, + &glsl->uniforms[VIDEO_SHADER_MENU]); + + shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_simple_modern : stock_vertex_xmb_ribbon_simple_legacy; + shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; + + gl_glsl_compile_program( + glsl, + VIDEO_SHADER_MENU_2, + &glsl->prg[VIDEO_SHADER_MENU_2], + &shader_prog_info); + gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_2].id, + &glsl->uniforms[VIDEO_SHADER_MENU_2]); + +#if defined(HAVE_OPENGLES) + shader_prog_info.vertex = stock_vertex_xmb_snow_modern; +#else + shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; +#endif + shader_prog_info.fragment = stock_fragment_xmb_simple_snow; + + gl_glsl_compile_program( + glsl, + VIDEO_SHADER_MENU_3, + &glsl->prg[VIDEO_SHADER_MENU_3], + &shader_prog_info); + gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_3].id, + &glsl->uniforms[VIDEO_SHADER_MENU_3]); + +#if defined(HAVE_OPENGLES) + shader_prog_info.vertex = stock_vertex_xmb_snow_modern; +#else + shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; +#endif + shader_prog_info.fragment = stock_fragment_xmb_snow; + + gl_glsl_compile_program( + glsl, + VIDEO_SHADER_MENU_4, + &glsl->prg[VIDEO_SHADER_MENU_4], + &shader_prog_info); + gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_4].id, + &glsl->uniforms[VIDEO_SHADER_MENU_4]); + +#if defined(HAVE_OPENGLES) + shader_prog_info.vertex = stock_vertex_xmb_snow_modern; +#else + shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; +#endif + shader_prog_info.fragment = stock_fragment_xmb_bokeh; + + gl_glsl_compile_program( + glsl, + VIDEO_SHADER_MENU_5, + &glsl->prg[VIDEO_SHADER_MENU_5], + &shader_prog_info); + gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_5].id, + &glsl->uniforms[VIDEO_SHADER_MENU_5]); + +#if defined(HAVE_OPENGLES) + shader_prog_info.vertex = stock_vertex_xmb_snow_modern; +#else + shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; +#endif + shader_prog_info.fragment = stock_fragment_xmb_snowflake; + + gl_glsl_compile_program( + glsl, + VIDEO_SHADER_MENU_6, + &glsl->prg[VIDEO_SHADER_MENU_6], + &shader_prog_info); + gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_6].id, + &glsl->uniforms[VIDEO_SHADER_MENU_6]); +#endif +} + static void *gl_glsl_init(void *data, const char *path) { unsigned i; @@ -1015,104 +1122,6 @@ static void *gl_glsl_init(void *data, const char *path) glsl->uniforms[VIDEO_SHADER_STOCK_BLEND] = glsl->uniforms[0]; } -#ifdef HAVE_SHADERPIPELINE -#ifdef HAVE_OPENGLES - if (gl_query_extension("GL_OES_standard_derivatives")) - { - shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; - shader_prog_info.fragment = glsl_core ? core_stock_fragment_xmb : stock_fragment_xmb; - } - else - { - shader_prog_info.vertex = stock_vertex_xmb_ribbon_simple_legacy; - shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; - } -#else - shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; - shader_prog_info.fragment = glsl_core ? core_stock_fragment_xmb : stock_fragment_xmb; -#endif - shader_prog_info.is_file = false; - - gl_glsl_compile_program( - glsl, - VIDEO_SHADER_MENU, - &glsl->prg[VIDEO_SHADER_MENU], - &shader_prog_info); - gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU].id, - &glsl->uniforms[VIDEO_SHADER_MENU]); - - shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_simple_modern : stock_vertex_xmb_ribbon_simple_legacy; - shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; - - gl_glsl_compile_program( - glsl, - VIDEO_SHADER_MENU_2, - &glsl->prg[VIDEO_SHADER_MENU_2], - &shader_prog_info); - gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_2].id, - &glsl->uniforms[VIDEO_SHADER_MENU_2]); - -#if defined(HAVE_OPENGLES) - shader_prog_info.vertex = stock_vertex_xmb_snow_modern; -#else - shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; -#endif - shader_prog_info.fragment = stock_fragment_xmb_simple_snow; - - gl_glsl_compile_program( - glsl, - VIDEO_SHADER_MENU_3, - &glsl->prg[VIDEO_SHADER_MENU_3], - &shader_prog_info); - gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_3].id, - &glsl->uniforms[VIDEO_SHADER_MENU_3]); - -#if defined(HAVE_OPENGLES) - shader_prog_info.vertex = stock_vertex_xmb_snow_modern; -#else - shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; -#endif - shader_prog_info.fragment = stock_fragment_xmb_snow; - - gl_glsl_compile_program( - glsl, - VIDEO_SHADER_MENU_4, - &glsl->prg[VIDEO_SHADER_MENU_4], - &shader_prog_info); - gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_4].id, - &glsl->uniforms[VIDEO_SHADER_MENU_4]); - -#if defined(HAVE_OPENGLES) - shader_prog_info.vertex = stock_vertex_xmb_snow_modern; -#else - shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; -#endif - shader_prog_info.fragment = stock_fragment_xmb_bokeh; - - gl_glsl_compile_program( - glsl, - VIDEO_SHADER_MENU_5, - &glsl->prg[VIDEO_SHADER_MENU_5], - &shader_prog_info); - gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_5].id, - &glsl->uniforms[VIDEO_SHADER_MENU_5]); - -#if defined(HAVE_OPENGLES) - shader_prog_info.vertex = stock_vertex_xmb_snow_modern; -#else - shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; -#endif - shader_prog_info.fragment = stock_fragment_xmb_snowflake; - - gl_glsl_compile_program( - glsl, - VIDEO_SHADER_MENU_6, - &glsl->prg[VIDEO_SHADER_MENU_6], - &shader_prog_info); - gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_6].id, - &glsl->uniforms[VIDEO_SHADER_MENU_6]); -#endif - gl_glsl_reset_attrib(glsl); for (i = 0; i < GFX_MAX_SHADERS; i++) @@ -1486,9 +1495,9 @@ static bool gl_glsl_set_mvp(void *data, void *shader_data, const void *mat_data) #define gl_glsl_set_coord_array(attribs, coord1, coord2, coords, size, multiplier) \ unsigned y; \ - attribs[attribs_size].loc = coord1; \ - attribs[attribs_size].size = multiplier; \ - attribs[attribs_size].offset = size * sizeof(GLfloat); \ + attribs[attribs_size].loc = (GLint)coord1; \ + attribs[attribs_size].size = (GLsizei)multiplier; \ + attribs[attribs_size].offset = (GLsizei)(size * sizeof(GLfloat)); \ for (y = 0; y < (multiplier * coords->vertices); y++) \ buffer[y + size] = coord2[y]; \ size += multiplier * coords->vertices; \ @@ -1688,6 +1697,7 @@ void gl_glsl_set_context_type(bool core_profile, const shader_backend_t gl_glsl_backend = { gl_glsl_init, + gl_glsl_init_menu_shaders, gl_glsl_deinit, gl_glsl_set_params, gl_glsl_set_uniform_parameter, diff --git a/gfx/drivers_shader/shader_hlsl.c b/gfx/drivers_shader/shader_hlsl.c index be50cad69d..56717b2261 100644 --- a/gfx/drivers_shader/shader_hlsl.c +++ b/gfx/drivers_shader/shader_hlsl.c @@ -14,6 +14,8 @@ * If not, see . */ +#define CINTERFACE + #include #include #include @@ -23,6 +25,7 @@ #include "../../defines/d3d_defines.h" #include "../common/d3d_common.h" +#include "../common/d3d9_common.h" #ifdef HAVE_CONFIG_H #include "../../config.h" @@ -36,48 +39,6 @@ #include "../drivers/d3d_shaders/opaque.hlsl.d3d9.h" #include "shader_hlsl.h" -#ifdef __cplusplus - -#ifndef ID3DXConstantTable_SetDefaults -#define ID3DXConstantTable_SetDefaults(p,a) (p)->SetDefaults(a); -#endif - -#ifndef ID3DXConstantTable_SetFloatArray -#define ID3DXConstantTable_SetFloatArray(p,a,b,c,d) (p)->SetFloatArray(a,b,c,d) -#endif - -#ifndef ID3DXConstantTable_GetConstantByName -#define ID3DXConstantTable_GetConstantByName(p,a,b) ((p)->GetConstantByName(a, b)) -#endif - -#ifndef ID3DXConstantTable_SetMatrix -#define ID3DXConstantTable_SetMatrix(p,a,b,c) ((p)->SetMatrix(a,b,c)) -#endif - -#else - -#ifndef ID3DXConstantTable_SetDefaults -#define ID3DXConstantTable_SetDefaults(p,a) (p)->lpVtbl->SetDefaults(p,a) -#endif - -#ifndef ID3DXConstantTable_SetFloatArray -#define ID3DXConstantTable_SetFloatArray(p,a,b,c,d) (p)->lpVtbl->SetFloatArray(p,a,b,c,d) -#endif - -#ifndef ID3DXConstantTable_GetConstantByName -#define ID3DXConstantTable_GetConstantByName(p,a,b) ((p)->lpVtbl->GetConstantByName(p, a, b)) -#endif - -#ifndef ID3DXConstantTable_SetMatrix -#define ID3DXConstantTable_SetMatrix(p,a,b,c) ((p)->lpVtbl->SetMatrix(p,a,b,c)) -#endif - -#endif - -#define set_param_2f(param, xy, constanttable) if (param) { ID3DXConstantTable_SetFloatArray(constanttable, d3dr, param, xy, 2); } -#define get_constant_by_name(a, b, constanttable) ID3DXConstantTable_GetConstantByName(constanttable, a, b) - - struct shader_program_hlsl_data { LPDIRECT3DVERTEXSHADER9 vprg; @@ -165,65 +126,77 @@ static void hlsl_set_uniform_parameter( static void hlsl_set_params(void *dat, void *shader_data) { float ori_size[2], tex_size[2], out_size[2]; - video_shader_ctx_params_t *params = (video_shader_ctx_params_t*)dat; - void *data = params->data; - unsigned width = params->width; - unsigned height = params->height; - unsigned tex_width = params->tex_width; - unsigned tex_height = params->tex_height; - unsigned out_width = params->out_width; - unsigned out_height = params->out_height; - unsigned frame_count = params->frame_counter; - const void *_info = params->info; - const void *_prev_info = params->prev_info; - const void *_feedback_info = params->feedback_info; - const void *_fbo_info = params->fbo_info; - unsigned fbo_info_cnt = params->fbo_info_cnt; - float frame_cnt = frame_count; - const struct video_tex_info *info = (const struct video_tex_info*)_info; - const struct video_tex_info *prev_info = (const struct video_tex_info*)_prev_info; - const struct video_tex_info *fbo_info = (const struct video_tex_info*)_fbo_info; - hlsl_shader_data_t *hlsl = (hlsl_shader_data_t*)shader_data; - LPDIRECT3DDEVICE9 d3dr = (LPDIRECT3DDEVICE9)hlsl->dev; + video_shader_ctx_params_t *params = (video_shader_ctx_params_t*)dat; + void *data = params->data; + unsigned width = params->width; + unsigned height = params->height; + unsigned tex_width = params->tex_width; + unsigned tex_height = params->tex_height; + unsigned out_width = params->out_width; + unsigned out_height = params->out_height; + unsigned frame_count = params->frame_counter; + const void *_info = params->info; + const void *_prev_info = params->prev_info; + const void *_feedback_info = params->feedback_info; + const void *_fbo_info = params->fbo_info; + unsigned fbo_info_cnt = params->fbo_info_cnt; + float frame_cnt = frame_count; + const struct video_tex_info *info = (const struct video_tex_info*)_info; + const struct video_tex_info *prev_info = (const struct video_tex_info*)_prev_info; + const struct video_tex_info *fbo_info = (const struct video_tex_info*)_fbo_info; + hlsl_shader_data_t *hlsl = (hlsl_shader_data_t*)shader_data; + LPDIRECT3DDEVICE9 d3dr = (LPDIRECT3DDEVICE9)hlsl->dev; + struct shader_program_hlsl_data *program = NULL; if (!hlsl || !d3dr) return; - ori_size[0] = (float)width; - ori_size[1] = (float)height; - tex_size[0] = (float)tex_width; - tex_size[1] = (float)tex_height; - out_size[0] = (float)out_width; - out_size[1] = (float)out_height; + program = &hlsl->prg[hlsl->active_idx]; - ID3DXConstantTable_SetDefaults( - hlsl->prg[hlsl->active_idx].f_ctable, d3dr); - ID3DXConstantTable_SetDefaults( - hlsl->prg[hlsl->active_idx].v_ctable, d3dr); + if (!program) + return; - set_param_2f(hlsl->prg[hlsl->active_idx].vid_size_f, ori_size, hlsl->prg[hlsl->active_idx].f_ctable); - set_param_2f(hlsl->prg[hlsl->active_idx].tex_size_f, tex_size, hlsl->prg[hlsl->active_idx].f_ctable); - set_param_2f(hlsl->prg[hlsl->active_idx].out_size_f, out_size, hlsl->prg[hlsl->active_idx].f_ctable); + ori_size[0] = (float)width; + ori_size[1] = (float)height; + tex_size[0] = (float)tex_width; + tex_size[1] = (float)tex_height; + out_size[0] = (float)out_width; + out_size[1] = (float)out_height; - if (hlsl->prg[hlsl->active_idx].frame_cnt_f) - d3dx_constant_table_set_float(hlsl->prg[hlsl->active_idx].f_ctable, - d3dr,hlsl->prg[hlsl->active_idx].frame_cnt_f, frame_cnt); + d3d9x_constant_table_set_defaults(d3dr, program->f_ctable); + d3d9x_constant_table_set_defaults(d3dr, program->v_ctable); - if (hlsl->prg[hlsl->active_idx].frame_dir_f) - d3dx_constant_table_set_float(hlsl->prg[hlsl->active_idx].f_ctable, - d3dr, hlsl->prg[hlsl->active_idx].frame_dir_f, state_manager_frame_is_reversed() ? -1.0 : 1.0); + if (program->vid_size_f) + d3d9x_constant_table_set_float_array(d3dr, program->f_ctable, (void*)program->vid_size_f, ori_size, 2); + if (program->tex_size_f) + d3d9x_constant_table_set_float_array(d3dr, program->f_ctable, (void*)program->tex_size_f, tex_size, 2); + if (program->out_size_f) + d3d9x_constant_table_set_float_array(d3dr, program->f_ctable, (void*)program->out_size_f, out_size, 2); - set_param_2f(hlsl->prg[hlsl->active_idx].vid_size_v, ori_size, hlsl->prg[hlsl->active_idx].v_ctable); - set_param_2f(hlsl->prg[hlsl->active_idx].tex_size_v, tex_size, hlsl->prg[hlsl->active_idx].v_ctable); - set_param_2f(hlsl->prg[hlsl->active_idx].out_size_v, out_size, hlsl->prg[hlsl->active_idx].v_ctable); + if (program->frame_cnt_f) + d3d9x_constant_table_set_float(program->f_ctable, + d3dr, (void*)program->frame_cnt_f, frame_cnt); - if (hlsl->prg[hlsl->active_idx].frame_cnt_v) - d3dx_constant_table_set_float(hlsl->prg[hlsl->active_idx].v_ctable, - d3dr, hlsl->prg[hlsl->active_idx].frame_cnt_v, frame_cnt); + if (program->frame_dir_f) + d3d9x_constant_table_set_float(program->f_ctable, + d3dr, (void*)program->frame_dir_f, + state_manager_frame_is_reversed() ? -1.0 : 1.0); - if (hlsl->prg[hlsl->active_idx].frame_dir_v) - d3dx_constant_table_set_float(hlsl->prg[hlsl->active_idx].v_ctable, - d3dr, hlsl->prg[hlsl->active_idx].frame_dir_v, state_manager_frame_is_reversed() ? -1.0 : 1.0); + if (program->vid_size_v) + d3d9x_constant_table_set_float_array(d3dr, program->v_ctable, (void*)program->vid_size_v, ori_size, 2); + if (program->tex_size_v) + d3d9x_constant_table_set_float_array(d3dr, program->v_ctable, (void*)program->tex_size_v, tex_size, 2); + if (program->out_size_v) + d3d9x_constant_table_set_float_array(d3dr, program->v_ctable, (void*)program->out_size_v, out_size, 2); + + if (program->frame_cnt_v) + d3d9x_constant_table_set_float(program->v_ctable, + d3dr, (void*)program->frame_cnt_v, frame_cnt); + + if (program->frame_dir_v) + d3d9x_constant_table_set_float(program->v_ctable, + d3dr, (void*)program->frame_dir_v, + state_manager_frame_is_reversed() ? -1.0 : 1.0); /* TODO - set lookup textures/FBO textures/state parameters/etc */ } @@ -247,43 +220,49 @@ static bool hlsl_compile_program( if (program_info->is_file) { - if (!d3dx_compile_shader_from_file(program_info->combined, NULL, NULL, + if (!d3d9x_compile_shader_from_file(program_info->combined, NULL, NULL, "main_fragment", "ps_3_0", 0, &code_f, &listing_f, &program->f_ctable)) goto error; - if (!d3dx_compile_shader_from_file(program_info->combined, NULL, NULL, + if (!d3d9x_compile_shader_from_file(program_info->combined, NULL, NULL, "main_vertex", "vs_3_0", 0, &code_v, &listing_v, &program->v_ctable)) goto error; } else { /* TODO - crashes currently - to do with 'end of line' of stock shader */ - if (!d3dx_compile_shader(program_info->combined, + if (!d3d9x_compile_shader(program_info->combined, strlen(program_info->combined), NULL, NULL, "main_fragment", "ps_3_0", 0, &code_f, &listing_f, &program->f_ctable )) + { + RARCH_ERR("Failure building stock fragment shader..\n"); goto error; - if (!d3dx_compile_shader(program_info->combined, + } + if (!d3d9x_compile_shader(program_info->combined, strlen(program_info->combined), NULL, NULL, "main_vertex", "vs_3_0", 0, &code_v, &listing_v, &program->v_ctable )) + { + RARCH_ERR("Failure building stock vertex shader..\n"); goto error; + } } - d3d_create_pixel_shader(d3dr, (const DWORD*)d3dx_get_buffer_ptr(code_f), (void**)&program->fprg); - d3d_create_vertex_shader(d3dr, (const DWORD*)d3dx_get_buffer_ptr(code_v), (void**)&program->vprg); - d3dxbuffer_release((void*)code_f); - d3dxbuffer_release((void*)code_v); + d3d9_create_pixel_shader(d3dr, (const DWORD*)d3d9x_get_buffer_ptr(code_f), (void**)&program->fprg); + d3d9_create_vertex_shader(d3dr, (const DWORD*)d3d9x_get_buffer_ptr(code_v), (void**)&program->vprg); + d3d9x_buffer_release((void*)code_f); + d3d9x_buffer_release((void*)code_v); return true; error: RARCH_ERR("Cg/HLSL error:\n"); if (listing_f) - RARCH_ERR("Fragment:\n%s\n", (char*)d3dx_get_buffer_ptr(listing_f)); + RARCH_ERR("Fragment:\n%s\n", (char*)d3d9x_get_buffer_ptr(listing_f)); if (listing_v) - RARCH_ERR("Vertex:\n%s\n", (char*)d3dx_get_buffer_ptr(listing_v)); - d3dxbuffer_release((void*)listing_f); - d3dxbuffer_release((void*)listing_v); + RARCH_ERR("Vertex:\n%s\n", (char*)d3d9x_get_buffer_ptr(listing_v)); + d3d9x_buffer_release((void*)listing_f); + d3d9x_buffer_release((void*)listing_v); return false; } @@ -306,21 +285,35 @@ static bool hlsl_load_stock(hlsl_shader_data_t *hlsl) static void hlsl_set_program_attributes(hlsl_shader_data_t *hlsl, unsigned i) { + struct shader_program_hlsl_data *program = NULL; if (!hlsl) return; - hlsl->prg[i].vid_size_f = get_constant_by_name(NULL, "$IN.video_size", hlsl->prg[i].f_ctable); - hlsl->prg[i].tex_size_f = get_constant_by_name(NULL, "$IN.texture_size", hlsl->prg[i].f_ctable); - hlsl->prg[i].out_size_f = get_constant_by_name(NULL, "$IN.output_size", hlsl->prg[i].f_ctable); - hlsl->prg[i].frame_cnt_f = get_constant_by_name(NULL, "$IN.frame_count", hlsl->prg[i].f_ctable); - hlsl->prg[i].frame_dir_f = get_constant_by_name(NULL, "$IN.frame_direction", hlsl->prg[i].f_ctable); - hlsl->prg[i].vid_size_v = get_constant_by_name(NULL, "$IN.video_size", hlsl->prg[i].v_ctable); - hlsl->prg[i].tex_size_v = get_constant_by_name(NULL, "$IN.texture_size", hlsl->prg[i].v_ctable); - hlsl->prg[i].out_size_v = get_constant_by_name(NULL, "$IN.output_size", hlsl->prg[i].v_ctable); - hlsl->prg[i].frame_cnt_v = get_constant_by_name(NULL, "$IN.frame_count", hlsl->prg[i].v_ctable); - hlsl->prg[i].frame_dir_v = get_constant_by_name(NULL, "$IN.frame_direction", hlsl->prg[i].v_ctable); - hlsl->prg[i].mvp = get_constant_by_name(NULL, "$modelViewProj", hlsl->prg[i].v_ctable); - d3d_matrix_identity(&hlsl->prg[i].mvp_val); + program = &hlsl->prg[i]; + + if (!program) + return; + + if (program->f_ctable) + { + program->vid_size_f = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->f_ctable, NULL, "$IN.video_size"); + program->tex_size_f = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->f_ctable, NULL, "$IN.texture_size"); + program->out_size_f = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->f_ctable, NULL, "$IN.output_size"); + program->frame_cnt_f = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->f_ctable, NULL, "$IN.frame_count"); + program->frame_dir_f = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->f_ctable, NULL, "$IN.frame_direction"); + } + + if (program->v_ctable) + { + program->vid_size_v = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->v_ctable, NULL, "$IN.video_size"); + program->tex_size_v = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->v_ctable, NULL, "$IN.texture_size"); + program->out_size_v = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->v_ctable, NULL, "$IN.output_size"); + program->frame_cnt_v = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->v_ctable, NULL, "$IN.frame_count"); + program->frame_dir_v = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->v_ctable, NULL, "$IN.frame_direction"); + program->mvp = (D3DXHANDLE)d3d9x_constant_table_get_constant_by_name(program->v_ctable, NULL, "$modelViewProj"); + } + + d3d_matrix_identity(&program->mvp_val); } static bool hlsl_load_shader(hlsl_shader_data_t *hlsl, @@ -350,7 +343,8 @@ static bool hlsl_load_plain(hlsl_shader_data_t *hlsl, const char *path) if (!hlsl_load_stock(hlsl)) return false; - hlsl->cg_shader = (struct video_shader*)calloc(1, sizeof(*hlsl->cg_shader)); + hlsl->cg_shader = (struct video_shader*) + calloc(1, sizeof(*hlsl->cg_shader)); if (!hlsl->cg_shader) return false; @@ -387,18 +381,18 @@ static void hlsl_deinit_progs(hlsl_shader_data_t *hlsl) for (i = 1; i < RARCH_HLSL_MAX_SHADERS; i++) { if (hlsl->prg[i].fprg && hlsl->prg[i].fprg != hlsl->prg[0].fprg) - d3d_free_pixel_shader(hlsl->dev, hlsl->prg[i].fprg); + d3d9_free_pixel_shader(hlsl->dev, hlsl->prg[i].fprg); if (hlsl->prg[i].vprg && hlsl->prg[i].vprg != hlsl->prg[0].vprg) - d3d_free_vertex_shader(hlsl->dev, hlsl->prg[i].vprg); + d3d9_free_vertex_shader(hlsl->dev, hlsl->prg[i].vprg); hlsl->prg[i].fprg = NULL; hlsl->prg[i].vprg = NULL; } if (hlsl->prg[0].fprg) - d3d_free_pixel_shader(hlsl->dev, hlsl->prg[0].fprg); + d3d9_free_pixel_shader(hlsl->dev, hlsl->prg[0].fprg); if (hlsl->prg[0].vprg) - d3d_free_vertex_shader(hlsl->dev, hlsl->prg[0].vprg); + d3d9_free_vertex_shader(hlsl->dev, hlsl->prg[0].vprg); hlsl->prg[0].fprg = NULL; hlsl->prg[0].vprg = NULL; @@ -419,7 +413,8 @@ static bool hlsl_load_preset(hlsl_shader_data_t *hlsl, const char *path) goto error; if (!hlsl->cg_shader) - hlsl->cg_shader = (struct video_shader*)calloc(1, sizeof(*hlsl->cg_shader)); + hlsl->cg_shader = (struct video_shader*)calloc + (1, sizeof(*hlsl->cg_shader)); if (!hlsl->cg_shader) goto error; @@ -433,7 +428,8 @@ static bool hlsl_load_preset(hlsl_shader_data_t *hlsl, const char *path) if (hlsl->cg_shader->passes > RARCH_HLSL_MAX_SHADERS - 3) { - RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", RARCH_HLSL_MAX_SHADERS - 3); + RARCH_WARN("Too many shaders ... " + "Capping shader amount to %d.\n", RARCH_HLSL_MAX_SHADERS - 3); hlsl->cg_shader->passes = RARCH_HLSL_MAX_SHADERS - 3; } @@ -481,11 +477,16 @@ static void *hlsl_init(void *data, const char *path) goto error; } + RARCH_LOG("Setting up program attributes...\n"); + RARCH_LOG("Shader passes: %d\n", hlsl->cg_shader->passes); + for(i = 1; i <= hlsl->cg_shader->passes; i++) hlsl_set_program_attributes(hlsl, i); - d3d_set_vertex_shader(hlsl->dev, 1, hlsl->prg[1].vprg); - d3d_set_pixel_shader(hlsl->dev, hlsl->prg[1].fprg); + RARCH_LOG("Setting up vertex shader...\n"); + d3d9_set_vertex_shader(hlsl->dev, 1, hlsl->prg[1].vprg); + RARCH_LOG("Setting up pixel shader...\n"); + d3d9_set_pixel_shader(hlsl->dev, hlsl->prg[1].fprg); return hlsl; @@ -513,19 +514,26 @@ static void hlsl_deinit(void *data) free(hlsl); } -static void hlsl_use(void *data, void *shader_data, unsigned idx, bool set_active) +static void hlsl_use(void *data, void *shader_data, + unsigned idx, bool set_active) { - hlsl_shader_data_t *hlsl = (hlsl_shader_data_t*)shader_data; - LPDIRECT3DDEVICE9 d3dr = hlsl ? (LPDIRECT3DDEVICE9)hlsl->dev : NULL; + hlsl_shader_data_t *hlsl = (hlsl_shader_data_t*)shader_data; + LPDIRECT3DDEVICE9 d3dr = hlsl ? (LPDIRECT3DDEVICE9)hlsl->dev : NULL; + struct shader_program_hlsl_data *program = NULL; - if (!hlsl || !hlsl->prg[idx].vprg || !hlsl->prg[idx].fprg) + if (!hlsl) + return; + + program = &hlsl->prg[idx]; + + if (!program || !program->vprg || !program->fprg) return; if (set_active) - hlsl->active_idx = idx; + hlsl->active_idx = idx; - d3d_set_vertex_shader(d3dr, idx, hlsl->prg[idx].vprg); - d3d_set_pixel_shader(d3dr, hlsl->prg[idx].fprg); + d3d9_set_vertex_shader(d3dr, idx, program->vprg); + d3d9_set_pixel_shader(d3dr, program->fprg); } static unsigned hlsl_num(void *data) @@ -549,27 +557,34 @@ static bool hlsl_filter_type(void *data, unsigned idx, bool *smooth) return false; } -static void hlsl_shader_scale(void *data, unsigned idx, struct gfx_fbo_scale *scale) +static void hlsl_shader_scale(void *data, unsigned idx, + struct gfx_fbo_scale *scale) { hlsl_shader_data_t *hlsl = (hlsl_shader_data_t*)data; if (hlsl && idx) - *scale = hlsl->cg_shader->pass[idx - 1].fbo; + *scale = hlsl->cg_shader->pass[idx - 1].fbo; else - scale->valid = false; + scale->valid = false; } static bool hlsl_set_mvp(void *data, void *shader_data, const void *mat_data) { - hlsl_shader_data_t *hlsl = (hlsl_shader_data_t*)shader_data; - LPDIRECT3DDEVICE9 d3dr = hlsl ? (LPDIRECT3DDEVICE9)hlsl->dev : NULL; - const math_matrix_4x4 *mat = (const math_matrix_4x4*)mat_data; + hlsl_shader_data_t *hlsl = (hlsl_shader_data_t*)shader_data; + LPDIRECT3DDEVICE9 d3dr = hlsl ? + (LPDIRECT3DDEVICE9)hlsl->dev : NULL; + const math_matrix_4x4 *mat = (const math_matrix_4x4*)mat_data; + struct shader_program_hlsl_data *program = NULL; - if (!hlsl || !hlsl->prg[hlsl->active_idx].mvp) + if (!hlsl) return false; - ID3DXConstantTable_SetMatrix(hlsl->prg[hlsl->active_idx].v_ctable, d3dr, - hlsl->prg[hlsl->active_idx].mvp, - &hlsl->prg[hlsl->active_idx].mvp_val); + program = &hlsl->prg[hlsl->active_idx]; + + if (!program || !program->mvp) + return false; + + d3d9x_constant_table_set_matrix(d3dr, program->v_ctable, + (void*)program->mvp, &program->mvp_val); return true; } @@ -590,8 +605,24 @@ static struct video_shader *hlsl_get_current_shader(void *data) return NULL; } +static enum gfx_wrap_type hlsl_wrap_type(void *data, unsigned idx) +{ +#if 0 + /* TODO/FIXME - actual implementation */ +#endif + return RARCH_WRAP_BORDER; +} + +static bool hlsl_set_coords(void *handle_data, + void *shader_data, const struct video_coords *coords) +{ + /* TODO/FIXME - actual implementation */ + return false; +} + const shader_backend_t hlsl_backend = { hlsl_init, + NULL, /* hlsl_init_menu_shaders */ hlsl_deinit, hlsl_set_params, hlsl_set_uniform_parameter, @@ -599,9 +630,9 @@ const shader_backend_t hlsl_backend = { hlsl_use, hlsl_num, hlsl_filter_type, - NULL, /* hlsl_wrap_type */ + hlsl_wrap_type, hlsl_shader_scale, - NULL, /* hlsl_set_coords */ + hlsl_set_coords, hlsl_set_mvp, NULL, /* hlsl_get_prev_textures */ hlsl_get_feedback_pass, diff --git a/gfx/drivers_shader/shader_null.c b/gfx/drivers_shader/shader_null.c index d85cfd1b97..792c03f759 100644 --- a/gfx/drivers_shader/shader_null.c +++ b/gfx/drivers_shader/shader_null.c @@ -77,6 +77,7 @@ static bool shader_null_compile_program( const shader_backend_t shader_null_backend = { shader_null_init, + NULL, shader_null_deinit, NULL, shader_null_set_uniform_parameter, diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index de864eaf61..57559d3258 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -56,62 +56,6 @@ static unsigned num_miplevels(unsigned width, unsigned height) return levels; } -static void image_layout_transition_levels( - VkCommandBuffer cmd, VkImage image, uint32_t levels, - VkImageLayout old_layout, VkImageLayout new_layout, - VkAccessFlags src_access, VkAccessFlags dst_access, - VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages) -{ - VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; - - barrier.srcAccessMask = src_access; - barrier.dstAccessMask = dst_access; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.levelCount = levels; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - - vkCmdPipelineBarrier(cmd, - src_stages, - dst_stages, - false, - 0, nullptr, - 0, nullptr, - 1, &barrier); -} - -static void image_layout_transition( - VkCommandBuffer cmd, VkImage image, - VkImageLayout old_layout, VkImageLayout new_layout, - VkAccessFlags src_access, VkAccessFlags dst_access, - VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages) -{ - image_layout_transition_levels(cmd, image, VK_REMAINING_MIP_LEVELS, - old_layout, new_layout, - src_access, dst_access, - src_stages, dst_stages); -} - -static uint32_t find_memory_type( - const VkPhysicalDeviceMemoryProperties &mem_props, - uint32_t device_reqs, uint32_t host_reqs) -{ - uint32_t i; - for (i = 0; i < VK_MAX_MEMORY_TYPES; i++) - { - if ((device_reqs & (1u << i)) && - (mem_props.memoryTypes[i].propertyFlags & host_reqs) == host_reqs) - return i; - } - - RARCH_ERR("[Vulkan]: Failed to find valid memory type. This should never happen."); - abort(); -} - static uint32_t find_memory_type_fallback( const VkPhysicalDeviceMemoryProperties &mem_props, uint32_t device_reqs, uint32_t host_reqs) @@ -124,7 +68,7 @@ static uint32_t find_memory_type_fallback( return i; } - return find_memory_type(mem_props, device_reqs, 0); + return vulkan_find_memory_type(&mem_props, device_reqs, 0); } static void build_identity_matrix(float *data) @@ -1048,8 +992,8 @@ void vulkan_filter_chain::update_history(DeferredDisposer &disposer, VkCommandBu // Transition input texture to something appropriate. if (input_texture.layout != VK_IMAGE_LAYOUT_GENERAL) { - image_layout_transition(cmd, - input_texture.image, + vulkan_image_layout_transition_levels(cmd, + input_texture.image,VK_REMAINING_MIP_LEVELS, input_texture.layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, @@ -1075,8 +1019,8 @@ void vulkan_filter_chain::update_history(DeferredDisposer &disposer, VkCommandBu // Transition input texture back. if (input_texture.layout != VK_IMAGE_LAYOUT_GENERAL) { - image_layout_transition(cmd, - input_texture.image, + vulkan_image_layout_transition_levels(cmd, + input_texture.image,VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, input_texture.layout, 0, @@ -1205,8 +1149,8 @@ Buffer::Buffer(VkDevice device, VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; alloc.allocationSize = mem_reqs.size; - alloc.memoryTypeIndex = find_memory_type( - mem_props, mem_reqs.memoryTypeBits, + alloc.memoryTypeIndex = vulkan_find_memory_type( + &mem_props, mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); @@ -2056,8 +2000,8 @@ void Pass::build_commands( // the passes that end up on-screen. if (!final_pass) { - // Render. - image_layout_transition_levels(cmd, + /* Render. */ + vulkan_image_layout_transition_levels(cmd, framebuffer->get_image(), 1, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, @@ -2140,9 +2084,9 @@ void Pass::build_commands( else { // Barrier to sync with next pass. - image_layout_transition( + vulkan_image_layout_transition_levels( cmd, - framebuffer->get_image(), + framebuffer->get_image(),VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, @@ -2175,7 +2119,7 @@ void Framebuffer::clear(VkCommandBuffer cmd) VkClearColorValue color; VkImageSubresourceRange range; - image_layout_transition(cmd, image, + vulkan_image_layout_transition_levels(cmd, image,VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, @@ -2191,7 +2135,7 @@ void Framebuffer::clear(VkCommandBuffer cmd) vkCmdClearColorImage(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range); - image_layout_transition(cmd, image, + vulkan_image_layout_transition_levels(cmd, image,VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, @@ -2330,7 +2274,7 @@ void Framebuffer::copy(VkCommandBuffer cmd, { VkImageCopy region; - image_layout_transition(cmd, image, + vulkan_image_layout_transition_levels(cmd, image,VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, @@ -2350,7 +2294,7 @@ void Framebuffer::copy(VkCommandBuffer cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - image_layout_transition(cmd, image, + vulkan_image_layout_transition_levels(cmd, image,VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, @@ -2688,9 +2632,9 @@ static unique_ptr vulkan_filter_chain_load_lut(VkCommandBuffer cm image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; vkCreateImage(info->device, &image_info, nullptr, &tex); vkGetImageMemoryRequirements(info->device, tex, &mem_reqs); - alloc.allocationSize = mem_reqs.size; - alloc.memoryTypeIndex = find_memory_type( - *info->memory_properties, + alloc.allocationSize = mem_reqs.size; + alloc.memoryTypeIndex = vulkan_find_memory_type( + &*info->memory_properties, mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); @@ -2717,7 +2661,7 @@ static unique_ptr vulkan_filter_chain_load_lut(VkCommandBuffer cm memcpy(ptr, image.pixels, image.width * image.height * sizeof(uint32_t)); buffer->unmap(); - image_layout_transition(cmd, tex, + vulkan_image_layout_transition_levels(cmd, tex,VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_UNDEFINED, shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT, @@ -2758,7 +2702,7 @@ static unique_ptr vulkan_filter_chain_load_lut(VkCommandBuffer cm /* Only injects execution and memory barriers, * not actual transition. */ - image_layout_transition(cmd, tex, + vulkan_image_layout_transition_levels(cmd, tex, VK_REMAINING_MIP_LEVELS, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, @@ -2772,7 +2716,7 @@ static unique_ptr vulkan_filter_chain_load_lut(VkCommandBuffer cm 1, &blit_region, VK_FILTER_LINEAR); } - image_layout_transition(cmd, tex, + vulkan_image_layout_transition_levels(cmd, tex,VK_REMAINING_MIP_LEVELS, shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, @@ -3011,7 +2955,8 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( pass_info.rt_format = tmpinfo.swapchain.format; if (explicit_format) - RARCH_WARN("[slang]: Using explicit format for last pass in chain, but it is not rendered to framebuffer, using swapchain format instead.\n"); + RARCH_WARN("[slang]: Using explicit format for last pass in chain," + " but it is not rendered to framebuffer, using swapchain format instead.\n"); } else { diff --git a/gfx/drivers_shader/slang_preprocess.cpp b/gfx/drivers_shader/slang_preprocess.cpp index ec4daa666e..0119be2346 100644 --- a/gfx/drivers_shader/slang_preprocess.cpp +++ b/gfx/drivers_shader/slang_preprocess.cpp @@ -18,8 +18,10 @@ #include #include #include + +#include + #include "../../verbosity.h" -#include "../../libretro-common/include/compat/strl.h" using namespace std; @@ -28,28 +30,32 @@ bool slang_preprocess_parse_parameters(glslang_meta& meta, { unsigned old_num_parameters = shader->num_parameters; - // Assumes num_parameters is initialized to something sane. + /* Assumes num_parameters is + * initialized to something sane. */ for (auto ¶m : meta.parameters) { bool mismatch_dup = false; - bool dup = false; - - auto itr = find_if(shader->parameters, shader->parameters + shader->num_parameters, - [&](const video_shader_parameter &parsed_param) { + bool dup = false; + auto itr = find_if(shader->parameters, + shader->parameters + shader->num_parameters, + [&](const video_shader_parameter &parsed_param) + { return param.id == parsed_param.id; }); if (itr != shader->parameters + shader->num_parameters) { dup = true; - // Allow duplicate #pragma parameter, but only if they are exactly the same. + /* Allow duplicate #pragma parameter, but only + * if they are exactly the same. */ if (param.desc != itr->desc || - param.initial != itr->initial || - param.minimum != itr->minimum || - param.maximum != itr->maximum || - param.step != itr->step) + param.initial != itr->initial || + param.minimum != itr->minimum || + param.maximum != itr->maximum || + param.step != itr->step) { - RARCH_ERR("[Vulkan]: Duplicate parameters found for \"%s\", but arguments do not match.\n", + RARCH_ERR("[Vulkan]: Duplicate parameters" + " found for \"%s\", but arguments do not match.\n", itr->id); mismatch_dup = true; } @@ -70,7 +76,7 @@ bool slang_preprocess_parse_parameters(glslang_meta& meta, p.initial = param.initial; p.minimum = param.minimum; p.maximum = param.maximum; - p.step = param.step; + p.step = param.step; p.current = param.initial; } @@ -82,12 +88,11 @@ bool slang_preprocess_parse_parameters(const char *shader_path, { glslang_meta meta; vector lines; + if (!glslang_read_shader_file(shader_path, &lines, true)) return false; - if (!glslang_parse_meta(lines, &meta)) return false; - return slang_preprocess_parse_parameters(meta, shader); } diff --git a/gfx/drivers_shader/slang_process.cpp b/gfx/drivers_shader/slang_process.cpp index c8bbf95761..a6cc60f675 100644 --- a/gfx/drivers_shader/slang_process.cpp +++ b/gfx/drivers_shader/slang_process.cpp @@ -17,7 +17,8 @@ using namespace spirv_cross; using namespace std; template -static bool set_unique_map(unordered_map& m, const string& name, const P& p) +static bool set_unique_map(unordered_map& m, + const string& name, const P& p) { auto itr = m.find(name); if (itr != end(m)) @@ -31,7 +32,8 @@ static bool set_unique_map(unordered_map& m, const string& name, cons } template -static string get_semantic_name(const unordered_map* map, S semantic, unsigned index) +static string get_semantic_name(const unordered_map* map, + S semantic, unsigned index) { for (const pair& m : *map) { @@ -42,7 +44,8 @@ static string get_semantic_name(const unordered_map* map, S semantic, } static string -get_semantic_name(slang_reflection& reflection, slang_semantic semantic, unsigned index) +get_semantic_name(slang_reflection& reflection, + slang_semantic semantic, unsigned index) { static const char* names[] = { "MVP", @@ -57,7 +60,8 @@ get_semantic_name(slang_reflection& reflection, slang_semantic semantic, unsigne } static string -get_semantic_name(slang_reflection& reflection, slang_texture_semantic semantic, unsigned index) +get_semantic_name(slang_reflection& reflection, + slang_texture_semantic semantic, unsigned index) { static const char* names[] = { "Original", "Source", "OriginalHistory", "PassOutput", "PassFeedback", @@ -71,7 +75,8 @@ get_semantic_name(slang_reflection& reflection, slang_texture_semantic semantic, } static string get_size_semantic_name( - slang_reflection& reflection, slang_texture_semantic semantic, unsigned index) + slang_reflection& reflection, + slang_texture_semantic semantic, unsigned index) { static const char* names[] = { "OriginalSize", "SourceSize", "OriginalHistorySize", "PassOutputSize", "PassFeedbackSize", @@ -94,10 +99,14 @@ static bool slang_process_reflection( const semantics_map_t* map, pass_semantics_t* out) { + int semantic; + unsigned i; + vector textures; + vector uniforms[SLANG_CBUFFER_MAX]; unordered_map texture_semantic_map; unordered_map texture_semantic_uniform_map; - for (unsigned i = 0; i <= pass_number; i++) + for (i = 0; i <= pass_number; i++) { if (!*shader_info->pass[i].alias) continue; @@ -106,41 +115,48 @@ static bool slang_process_reflection( if (!set_unique_map( texture_semantic_map, name, - slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i })) + slang_texture_semantic_map{ + SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i })) return false; if (!set_unique_map( texture_semantic_uniform_map, name + "Size", - slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i })) + slang_texture_semantic_map{ + SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i })) return false; if (!set_unique_map( texture_semantic_map, name + "Feedback", - slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i })) + slang_texture_semantic_map{ + SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i })) return false; if (!set_unique_map( texture_semantic_uniform_map, name + "FeedbackSize", - slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i })) + slang_texture_semantic_map{ + SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i })) return false; } - for (unsigned i = 0; i < shader_info->luts; i++) + for (i = 0; i < shader_info->luts; i++) { if (!set_unique_map( texture_semantic_map, shader_info->lut[i].id, - slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_USER, i })) + slang_texture_semantic_map{ + SLANG_TEXTURE_SEMANTIC_USER, i })) return false; if (!set_unique_map( - texture_semantic_uniform_map, string(shader_info->lut[i].id) + "Size", - slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_USER, i })) + texture_semantic_uniform_map, + string(shader_info->lut[i].id) + "Size", + slang_texture_semantic_map{ + SLANG_TEXTURE_SEMANTIC_USER, i })) return false; } unordered_map uniform_semantic_map; - for (unsigned i = 0; i < shader_info->num_parameters; i++) + for (i = 0; i < shader_info->num_parameters; i++) { if (!set_unique_map( uniform_semantic_map, shader_info->parameters[i].id, @@ -154,9 +170,11 @@ static bool slang_process_reflection( sl_reflection.texture_semantic_uniform_map = &texture_semantic_uniform_map; sl_reflection.semantic_map = &uniform_semantic_map; - if (!slang_reflect(*vs_compiler, *ps_compiler, vs_resources, ps_resources, &sl_reflection)) + if (!slang_reflect(*vs_compiler, *ps_compiler, + vs_resources, ps_resources, &sl_reflection)) { - RARCH_ERR("[slang]: Failed to reflect SPIR-V. Resource usage is inconsistent with " + RARCH_ERR("[slang]: Failed to reflect SPIR-V." + " Resource usage is inconsistent with " "expectations.\n"); return false; } @@ -168,18 +186,17 @@ static bool slang_process_reflection( out->cbuffers[SLANG_CBUFFER_PC].binding = sl_reflection.ubo_binding ? 0 : 1; out->cbuffers[SLANG_CBUFFER_PC].size = (sl_reflection.push_constant_size + 0xF) & ~0xF; - vector uniforms[SLANG_CBUFFER_MAX]; - vector textures; - - for (int semantic = 0; semantic < SLANG_NUM_BASE_SEMANTICS; semantic++) + for (semantic = 0; semantic < SLANG_NUM_BASE_SEMANTICS; semantic++) { slang_semantic_meta& src = sl_reflection.semantics[semantic]; if (src.push_constant || src.uniform) { uniform_sem_t uniform = { map->uniforms[semantic], - src.num_components * (unsigned)sizeof(float) }; + src.num_components + * (unsigned)sizeof(float) }; + string uniform_id = get_semantic_name( + sl_reflection, (slang_semantic)semantic, 0); - string uniform_id = get_semantic_name(sl_reflection, (slang_semantic)semantic, 0); strncpy(uniform.id, uniform_id.c_str(), sizeof(uniform.id)); if (src.push_constant) @@ -195,15 +212,17 @@ static bool slang_process_reflection( } } - for (int i = 0; i < sl_reflection.semantic_float_parameters.size(); i++) + for (i = 0; i < sl_reflection.semantic_float_parameters.size(); i++) { slang_semantic_meta& src = sl_reflection.semantic_float_parameters[i]; if (src.push_constant || src.uniform) { - uniform_sem_t uniform = { &shader_info->parameters[i].current, sizeof(float) }; + uniform_sem_t uniform = { + &shader_info->parameters[i].current, sizeof(float) }; - string uniform_id = get_semantic_name(sl_reflection, SLANG_SEMANTIC_FLOAT_PARAMETER, i); + string uniform_id = get_semantic_name( + sl_reflection, SLANG_SEMANTIC_FLOAT_PARAMETER, i); strncpy(uniform.id, uniform_id.c_str(), sizeof(uniform.id)); if (src.push_constant) @@ -219,11 +238,15 @@ static bool slang_process_reflection( } } - for (int semantic = 0; semantic < SLANG_NUM_TEXTURE_SEMANTICS; semantic++) + for (semantic = 0; semantic < SLANG_NUM_TEXTURE_SEMANTICS; semantic++) { - for (int index = 0; index < sl_reflection.semantic_textures[semantic].size(); index++) + unsigned index; + + for (index = 0; index < + sl_reflection.semantic_textures[semantic].size(); index++) { - slang_texture_semantic_meta& src = sl_reflection.semantic_textures[semantic][index]; + slang_texture_semantic_meta& src = + sl_reflection.semantic_textures[semantic][index]; if (src.stage_mask) { @@ -233,17 +256,18 @@ static bool slang_process_reflection( if (semantic == SLANG_TEXTURE_SEMANTIC_USER) { - texture.wrap = shader_info->lut[index].wrap; - texture.filter = shader_info->lut[index].filter; + texture.wrap = shader_info->lut[index].wrap; + texture.filter = shader_info->lut[index].filter; } else { - texture.wrap = shader_info->pass[pass_number].wrap; - texture.filter = shader_info->pass[pass_number].filter; + texture.wrap = shader_info->pass[pass_number].wrap; + texture.filter = shader_info->pass[pass_number].filter; } texture.stage_mask = src.stage_mask; texture.binding = src.binding; - string id = get_semantic_name(sl_reflection, (slang_texture_semantic)semantic, index); + string id = get_semantic_name( + sl_reflection, (slang_texture_semantic)semantic, index); strncpy(texture.id, id.c_str(), sizeof(texture.id)); @@ -260,12 +284,15 @@ static bool slang_process_reflection( if (src.push_constant || src.uniform) { uniform_sem_t uniform = { - (void*)((uintptr_t)map->textures[semantic].size + index * map->textures[semantic].size_stride), + (void*)((uintptr_t)map->textures[semantic].size + + index * map->textures[semantic].size_stride), 4 * sizeof(float) }; string uniform_id = - get_size_semantic_name(sl_reflection, (slang_texture_semantic)semantic, index); + get_size_semantic_name( + sl_reflection, + (slang_texture_semantic)semantic, index); strncpy(uniform.id, uniform_id.c_str(), sizeof(uniform.id)); @@ -286,10 +313,12 @@ static bool slang_process_reflection( out->texture_count = textures.size(); textures.push_back({ NULL }); - out->textures = (texture_sem_t*)malloc(textures.size() * sizeof(*textures.data())); - memcpy(out->textures, textures.data(), textures.size() * sizeof(*textures.data())); + out->textures = (texture_sem_t*) + malloc(textures.size() * sizeof(*textures.data())); + memcpy(out->textures, textures.data(), + textures.size() * sizeof(*textures.data())); - for (int i = 0; i < SLANG_CBUFFER_MAX; i++) + for (i = 0; i < SLANG_CBUFFER_MAX; i++) { if (uniforms[i].empty()) continue; @@ -298,7 +327,9 @@ static bool slang_process_reflection( uniforms[i].push_back({ NULL }); out->cbuffers[i].uniforms = - (uniform_sem_t*)malloc(uniforms[i].size() * sizeof(*uniforms[i].data())); + (uniform_sem_t*) + malloc(uniforms[i].size() * sizeof(*uniforms[i].data())); + memcpy( out->cbuffers[i].uniforms, uniforms[i].data(), uniforms[i].size() * sizeof(*uniforms[i].data())); @@ -315,10 +346,10 @@ bool slang_process( const semantics_map_t* semantics_map, pass_semantics_t* out) { + glslang_output output; Compiler* vs_compiler = NULL; Compiler* ps_compiler = NULL; video_shader_pass& pass = shader_info->pass[pass_number]; - glslang_output output; if (!glslang_compile_shader(pass.source.path, &output)) return false; @@ -366,9 +397,11 @@ bool slang_process( ps_resources = ps_compiler->get_shader_resources(); if (!vs_resources.uniform_buffers.empty()) - vs_compiler->set_decoration(vs_resources.uniform_buffers[0].id, spv::DecorationBinding, 0); + vs_compiler->set_decoration( + vs_resources.uniform_buffers[0].id, spv::DecorationBinding, 0); if (!ps_resources.uniform_buffers.empty()) - ps_compiler->set_decoration(ps_resources.uniform_buffers[0].id, spv::DecorationBinding, 0); + ps_compiler->set_decoration( + ps_resources.uniform_buffers[0].id, spv::DecorationBinding, 0); if (!vs_resources.push_constant_buffers.empty()) vs_compiler->set_decoration( @@ -386,12 +419,12 @@ bool slang_process( vs->set_options(options); ps->set_options(options); - #if 0 +#if 0 CompilerGLSL::Options glsl_options; glsl_options.vertex.flip_vert_y = true; ((CompilerGLSL*)vs)->set_options(glsl_options); ((CompilerGLSL*)ps)->set_options(glsl_options); - #endif +#endif /* not exactly a vertex attribute but this remaps * float2 FragCoord :TEXCOORD# to float4 FragCoord : SV_POSITION */ @@ -400,9 +433,7 @@ bool slang_process( VariableTypeRemapCallback ps_var_remap_cb = [&](const SPIRType& type, const std::string& var_name, std::string& name_of_type) { if (var_name == "FragCoord") - { name_of_type = "float4"; - } }; for (Resource& resource : ps_resources.stage_inputs) { @@ -436,11 +467,13 @@ bool slang_process( pass.source.string.fragment = strdup(ps_code.c_str()); if (!slang_process_reflection( - vs_compiler, ps_compiler, vs_resources, ps_resources, shader_info, pass_number, + vs_compiler, ps_compiler, + vs_resources, ps_resources, shader_info, pass_number, semantics_map, out)) goto error; - } catch (const std::exception& e) + } + catch (const std::exception& e) { RARCH_ERR("[slang]: SPIRV-Cross threw exception: %s.\n", e.what()); goto error; diff --git a/gfx/drivers_shader/slang_reflection.cpp b/gfx/drivers_shader/slang_reflection.cpp index bd951f1e4b..6128e57661 100644 --- a/gfx/drivers_shader/slang_reflection.cpp +++ b/gfx/drivers_shader/slang_reflection.cpp @@ -83,12 +83,13 @@ static slang_texture_semantic slang_name_to_texture_semantic_array(const string unsigned i = 0; while (*names) { - auto n = *names; + auto n = *names; auto semantic = static_cast(i); + if (slang_texture_semantic_is_array(semantic)) { size_t baselen = strlen(n); - int cmp = strncmp(n, name.c_str(), baselen); + int cmp = strncmp(n, name.c_str(), baselen); if (cmp == 0) { @@ -190,7 +191,7 @@ static bool set_ubo_texture_offset(slang_reflection *reflection, } } - active = true; + active = true; active_offset = offset; return true; } @@ -279,7 +280,7 @@ static bool validate_type_for_semantic(const SPIRType &type, slang_semantic sem) return type.basetype == SPIRType::Float && type.vecsize == 4 && type.columns == 4; /* uint */ case SLANG_SEMANTIC_FRAME_COUNT: - return type.basetype == SPIRType::UInt && type.vecsize == 1 && type.columns == 1; + return type.basetype == SPIRType::UInt && type.vecsize == 1 && type.columns == 1; /* float */ case SLANG_SEMANTIC_FLOAT_PARAMETER: return type.basetype == SPIRType::Float && type.vecsize == 1 && type.columns == 1; @@ -303,13 +304,13 @@ static bool add_active_buffer_ranges(const Compiler &compiler, const Resource &r auto ranges = compiler.get_active_buffer_ranges(resource.id); for (auto &range : ranges) { - auto &name = compiler.get_member_name(resource.base_type_id, range.index); - auto &type = compiler.get_type(compiler.get_type(resource.base_type_id).member_types[range.index]); + auto &name = compiler.get_member_name(resource.base_type_id, range.index); + auto &type = compiler.get_type(compiler.get_type(resource.base_type_id).member_types[range.index]); - unsigned sem_index = 0; + unsigned sem_index = 0; unsigned tex_sem_index = 0; - auto sem = slang_uniform_name_to_semantic(*reflection->semantic_map, name, &sem_index); - auto tex_sem = slang_uniform_name_to_texture_semantic(*reflection->texture_semantic_uniform_map, + auto sem = slang_uniform_name_to_semantic(*reflection->semantic_map, name, &sem_index); + auto tex_sem = slang_uniform_name_to_texture_semantic(*reflection->texture_semantic_uniform_map, name, &tex_sem_index); if (tex_sem == SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT && tex_sem_index >= reflection->pass_number) @@ -658,14 +659,15 @@ bool slang_reflect_spirv(const std::vector &vertex, { Compiler vertex_compiler(vertex); Compiler fragment_compiler(fragment); - auto vertex_resources = vertex_compiler.get_shader_resources(); + auto vertex_resources = vertex_compiler.get_shader_resources(); auto fragment_resources = fragment_compiler.get_shader_resources(); if (!slang_reflect(vertex_compiler, fragment_compiler, vertex_resources, fragment_resources, reflection)) { - RARCH_ERR("[slang]: Failed to reflect SPIR-V. Resource usage is inconsistent with expectations.\n"); + RARCH_ERR("[slang]: Failed to reflect SPIR-V." + " Resource usage is inconsistent with expectations.\n"); return false; } diff --git a/gfx/font_driver.c b/gfx/font_driver.c index 63e4333dd7..28080b80a5 100644 --- a/gfx/font_driver.c +++ b/gfx/font_driver.c @@ -310,6 +310,37 @@ static bool vulkan_font_init_first( } #endif +#ifdef HAVE_D3D10 +static const font_renderer_t *d3d10_font_backends[] = { + &d3d10_font, + NULL, +}; + +static bool d3d10_font_init_first( + const void **font_driver, void **font_handle, + void *video_data, const char *font_path, + float font_size, bool is_threaded) +{ + unsigned i; + + for (i = 0; d3d10_font_backends[i]; i++) + { + void *data = d3d10_font_backends[i]->init(video_data, + font_path, font_size, + is_threaded); + + if (!data) + continue; + + *font_driver = d3d10_font_backends[i]; + *font_handle = data; + return true; + } + + return false; +} +#endif + #ifdef HAVE_D3D11 static const font_renderer_t *d3d11_font_backends[] = { &d3d11_font, @@ -493,6 +524,11 @@ static bool font_init_first( return d3d9_font_init_first(font_driver, font_handle, video_data, font_path, font_size, is_threaded); #endif +#ifdef HAVE_D3D10 + case FONT_DRIVER_RENDER_D3D10_API: + return d3d10_font_init_first(font_driver, font_handle, + video_data, font_path, font_size, is_threaded); +#endif #ifdef HAVE_D3D11 case FONT_DRIVER_RENDER_D3D11_API: return d3d11_font_init_first(font_driver, font_handle, @@ -693,10 +729,10 @@ static INLINE unsigned font_get_replacement(const char* src, const char* start) static char* font_driver_reshape_msg(const char* msg) { /* worst case transformations are 2 bytes to 4 bytes */ - char* buffer = (char*)malloc((strlen(msg) * 2) + 1); - const char* src = msg; - char* dst = buffer; - bool reverse = false; + unsigned char* buffer = (unsigned char*)malloc((strlen(msg) * 2) + 1); + const unsigned char* src = (const unsigned char*)msg; + unsigned char* dst = (unsigned char*)buffer; + bool reverse = false; while (*src || reverse) { @@ -708,7 +744,7 @@ static char* font_driver_reshape_msg(const char* msg) if (IS_RTL(src) || IS_DIR_NEUTRAL(src)) { - unsigned replacement = font_get_replacement(src, msg); + unsigned replacement = font_get_replacement((const char*)src, msg); if (replacement) { if (replacement < 0x80) @@ -770,7 +806,7 @@ static char* font_driver_reshape_msg(const char* msg) *dst = '\0'; - return buffer; + return (char*)buffer; } #endif diff --git a/gfx/font_driver.h b/gfx/font_driver.h index 939eccb951..7d1818b4a3 100644 --- a/gfx/font_driver.h +++ b/gfx/font_driver.h @@ -163,6 +163,7 @@ extern font_renderer_t vita2d_vita_font; extern font_renderer_t ctr_font; extern font_renderer_t wiiu_font; extern font_renderer_t vulkan_raster_font; +extern font_renderer_t d3d10_font; extern font_renderer_t d3d11_font; extern font_renderer_t d3d12_font; extern font_renderer_t caca_font; diff --git a/gfx/video_crt_switch.c b/gfx/video_crt_switch.c index d9bded15f9..754776ca09 100644 --- a/gfx/video_crt_switch.c +++ b/gfx/video_crt_switch.c @@ -20,275 +20,166 @@ #include #include -#if defined(_WIN32) - #include -#endif - - #include "video_driver.h" #include "video_crt_switch.h" +#include "video_display_server.h" -static float ra_tmp_core_hz; -static int ra_core_width; -static int ra_core_height; -static int ra_tmp_width; -static int ra_tmp_height; -static float fly_aspect; -static float ra_core_hz; -static int ra_set_core_hz; -static int orig_width; -static int orig_height; -static int first_run; +static unsigned ra_core_width = 0; +static unsigned ra_core_height = 0; +static unsigned ra_tmp_width = 0; +static unsigned ra_tmp_height = 0; +static unsigned ra_set_core_hz = 0; +static unsigned orig_width = 0; +static unsigned orig_height = 0; -void crt_switch_res_core(int width, int height, float hz) +static bool first_run = true; + +static float ra_tmp_core_hz = 0.0f; +static float fly_aspect = 0.0f; +static float ra_core_hz = 0.0f; + +static void crt_check_first_run(void) +{ + if (!first_run) + return; + + video_display_server_get_current_resolution(&orig_width, &orig_height); + + first_run = false; +} + +static void switch_crt_hz(void) { - /* ben_core_hz float passed from with in void video_driver_monitor_adjust_system_rates(void) */ - ra_core_width = width; - ra_core_height = height; - ra_core_hz = hz; - crt_check_first_run(); - - if (ra_tmp_height != ra_core_height || ra_core_width != ra_tmp_width) - { /* detect resolution change and switch */ - crt_screen_setup_aspect(width,height); - } - - ra_tmp_height = ra_core_height; - ra_tmp_width = ra_core_width; - - if (video_driver_get_aspect_ratio() != fly_aspect) - { /* check aspect is correct else change */ - video_driver_set_aspect_ratio_value((float)fly_aspect); - crt_poke_video(); - } + if (ra_core_hz == ra_tmp_core_hz) + return; + + /* set hz float an int for windows switching */ + if (ra_core_hz < 53) + ra_set_core_hz = 50; + if (ra_core_hz >= 53 && ra_core_hz < 57) + ra_set_core_hz = 55; + if (ra_core_hz >= 57) + ra_set_core_hz = 60; + video_monitor_set_refresh_rate(ra_set_core_hz); + ra_tmp_core_hz = ra_core_hz; } -void crt_check_first_run() -{ /* ruin of first boot to get current display resolution */ - if (first_run != 1) - { - #if defined(_WIN32) - orig_height = GetSystemMetrics(SM_CYSCREEN); - orig_width = GetSystemMetrics(SM_CXSCREEN); - #endif - - } - first_run = 1; -} - - -void crt_screen_setup_aspect(int width, int height) -{ /* create correct aspect to fit video if resolution does not exist */ - switch_crt_hz(); - /* get original resolution of core */ - - - if (height == 4) - { - if (width < 1920) - { - width = 640; - }/* detect menu only */ - height = 480; - crt_aspect_ratio_switch(width,height); - } - if (height < 191 && height != 144) - { - crt_aspect_ratio_switch(width,height); - height = 200; - } - if (height > 191) - { - crt_aspect_ratio_switch(width,height); - } - if (height == 144 && ra_set_core_hz == 50) - { - height = 288; - crt_aspect_ratio_switch(width,height); - } - if (height > 200 && height < 224) - { - crt_aspect_ratio_switch(width,height); - height = 224; - } - if (height > 224 && height < 240) - { - crt_aspect_ratio_switch(width,height); - height = 240; - } - if (height > 240 && height < 255 ) - { - crt_aspect_ratio_switch(width,height); - height = 254; - } - if (height == 528 && ra_set_core_hz == 60) - { - crt_aspect_ratio_switch(width,height); - height = 480; - } - if (height >= 240 && height < 255 && ra_set_core_hz == 55) - { - crt_aspect_ratio_switch(width,height); - height = 254; - } - - switch_res_crt(width, height); -} - -void switch_res_crt(int width, int height){ - - if ( height > 100) - { - - crt_switch_res(width, height,0,ra_set_core_hz); - crt_poke_video(); - } -} - -void crt_aspect_ratio_switch(int width,int height) -{ /* send aspect float to videeo_driver */ - fly_aspect = (float)width/height; +static void crt_aspect_ratio_switch(unsigned width, unsigned height) +{ + /* send aspect float to videeo_driver */ + fly_aspect = (float)width / height; video_driver_set_aspect_ratio_value((float)fly_aspect); } -void switch_crt_hz() -{ /* set hz float an int for windows switching */ - - if (ra_core_hz != ra_tmp_core_hz) - { - if (ra_core_hz < 53 ) - { - ra_set_core_hz = 50; - } - if (ra_core_hz >= 53 && ra_core_hz < 57) - { - ra_set_core_hz = 55; - } - if (ra_core_hz >= 57 ) - { - ra_set_core_hz = 60; - } - video_monitor_set_refresh_rate(ra_set_core_hz); - ra_tmp_core_hz = ra_core_hz; - } -} - -void crt_video_restore() +static void switch_res_crt(unsigned width, unsigned height) { + if (height > 100) + { + video_display_server_switch_resolution(width, height, + 0, ra_set_core_hz); + video_driver_apply_state_changes(); + } +} - crt_switch_res(orig_width, orig_height,0,60); +/* Create correct aspect to fit video if resolution does not exist */ +static void crt_screen_setup_aspect(unsigned width, unsigned height) +{ + switch_crt_hz(); + /* get original resolution of core */ + if (height == 4) + { + /* detect menu only */ + if (width < 1920) + width = 640; + height = 480; + crt_aspect_ratio_switch(width, height); + } + + if (height < 191 && height != 144) + { + crt_aspect_ratio_switch(width, height); + height = 200; + } + + if (height > 191) + crt_aspect_ratio_switch(width, height); + + if (height == 144 && ra_set_core_hz == 50) + { + height = 288; + crt_aspect_ratio_switch(width, height); + } + + if (height > 200 && height < 224) + { + crt_aspect_ratio_switch(width, height); + height = 224; + } + + if (height > 224 && height < 240) + { + crt_aspect_ratio_switch(width, height); + height = 240; + } + + if (height > 240 && height < 255) + { + crt_aspect_ratio_switch(width, height); + height = 254; + } + + if (height == 528 && ra_set_core_hz == 60) + { + crt_aspect_ratio_switch(width, height); + height = 480; + } + + if (height >= 240 && height < 255 && ra_set_core_hz == 55) + { + crt_aspect_ratio_switch(width, height); + height = 254; + } + + switch_res_crt(width, height); } -void crt_switch_res(int width, int height, int f_restore,int ra_hz) -{ /* windows function to swith resolutions */ +void crt_switch_res_core(unsigned width, unsigned height, float hz) +{ + /* ra_core_hz float passed from within + * void video_driver_monitor_adjust_system_rates(void) */ + ra_core_width = width; + ra_core_height = height; + ra_core_hz = hz; - #if defined(_WIN32) - DEVMODE curDevmode; - DEVMODE devmode; - DWORD flags = 0; + crt_check_first_run(); + + /* Detect resolution change and switch */ + if ( + (ra_tmp_height != ra_core_height) || + (ra_core_width != ra_tmp_width) + ) + crt_screen_setup_aspect(width, height); - int iModeNum; - int depth = 0; - int freq; - LONG res; + ra_tmp_height = ra_core_height; + ra_tmp_width = ra_core_width; - if (f_restore == 0) - { - freq = ra_hz; - } - else - { - freq = 0; - } - - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &curDevmode); - - if (width == curDevmode.dmPelsWidth) - { - width = 0; /* used to stop superresolution bug */ - } - if (width == 0) - { - width = curDevmode.dmPelsWidth; - } - if (height == 0) - { - height = curDevmode.dmPelsHeight; - } - if (depth == 0) - { - depth = curDevmode.dmBitsPerPel; - } - if (freq == 0) - { - freq = curDevmode.dmDisplayFrequency; - } - - for (iModeNum = 0; ; iModeNum++) - { - if (EnumDisplaySettings(NULL, iModeNum, &devmode)) - { - - if (devmode.dmPelsWidth != width) - { - continue; - } - - if (devmode.dmPelsHeight != height) - { - continue; - } - - if (devmode.dmBitsPerPel != depth) - { - continue; - } - - if (devmode.dmDisplayFrequency != freq) - { - continue; - } - - devmode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; - res = ChangeDisplaySettings(&devmode, CDS_TEST); - - switch (res) - { - case DISP_CHANGE_SUCCESSFUL: - res = ChangeDisplaySettings(&devmode, flags); - switch (res) - { - case DISP_CHANGE_SUCCESSFUL: - return; - - case DISP_CHANGE_NOTUPDATED: - return; - - default: - - break; - } - break; - - case DISP_CHANGE_RESTART: - - break; - - default: - - break; - } - } - else - { - break; - } - } - #endif - - #if defined(linux) - - #endif + /* Check if aspect is correct, if notchange */ + if (video_driver_get_aspect_ratio() != fly_aspect) + { + video_driver_set_aspect_ratio_value((float)fly_aspect); + video_driver_apply_state_changes(); + } +} + +void crt_video_restore(void) +{ + if (first_run) + return; + + video_display_server_switch_resolution(orig_width, orig_height, + 0, 60); + + first_run = true; } diff --git a/gfx/video_crt_switch.h b/gfx/video_crt_switch.h index c93d9dea0e..4e86ec4352 100644 --- a/gfx/video_crt_switch.h +++ b/gfx/video_crt_switch.h @@ -17,11 +17,20 @@ * If not, see . */ -void crt_check_first_run(); -void crt_switch_res_core(int width, int height, float hz); -void crt_screen_setup_aspect(int width, int height); -void switch_res_crt(int width, int height); -void crt_aspect_ratio_switch(int width,int height); -void switch_crt_hz(); -void crt_video_restore(); -void crt_switch_res(int width, int height, int f_restore,int ra_hz); +#ifndef __VIDEO_CRT_SWITCH_H__ +#define __VIDEO_CRT_SWITCH_H__ + +#include + +#include +#include + +RETRO_BEGIN_DECLS + +void crt_switch_res_core(unsigned width, unsigned height, float hz); + +void crt_video_restore(void); + +RETRO_END_DECLS + +#endif diff --git a/gfx/video_defines.h b/gfx/video_defines.h index 96437c0590..997850b856 100644 --- a/gfx/video_defines.h +++ b/gfx/video_defines.h @@ -84,6 +84,7 @@ enum font_driver_render_api FONT_DRIVER_RENDER_OPENGL_API, FONT_DRIVER_RENDER_D3D8_API, FONT_DRIVER_RENDER_D3D9_API, + FONT_DRIVER_RENDER_D3D10_API, FONT_DRIVER_RENDER_D3D11_API, FONT_DRIVER_RENDER_D3D12_API, FONT_DRIVER_RENDER_VITA2D, diff --git a/gfx/video_display_server.c b/gfx/video_display_server.c index 55baa165a2..1229720896 100644 --- a/gfx/video_display_server.c +++ b/gfx/video_display_server.c @@ -81,3 +81,21 @@ bool video_display_server_set_window_decorations(bool on) return current_display_server->set_window_decorations(current_display_server_data, on); return false; } + +bool video_display_server_get_current_resolution(unsigned *width, unsigned *height) +{ + if (current_display_server && current_display_server->get_current_resolution) + { + current_display_server->get_current_resolution(width, height); + return true; + } + return false; +} + +bool video_display_server_switch_resolution(unsigned width, unsigned height, + int f_restore, int hz) +{ + if (current_display_server && current_display_server->switch_resolution) + return current_display_server->switch_resolution(current_display_server_data, width, height, f_restore, hz); + return false; +} diff --git a/gfx/video_display_server.h b/gfx/video_display_server.h index 4f93a55e15..5e2fda7c77 100644 --- a/gfx/video_display_server.h +++ b/gfx/video_display_server.h @@ -30,15 +30,29 @@ typedef struct video_display_server bool (*set_window_opacity)(void *data, unsigned opacity); bool (*set_window_progress)(void *data, int progress, bool finished); bool (*set_window_decorations)(void *data, bool on); + void (*get_current_resolution)(unsigned *width, unsigned *height); + bool (*switch_resolution)(void *data, unsigned width, + unsigned height, int f_restore, int hz); const char *ident; } video_display_server_t; void* video_display_server_init(void); + void video_display_server_destroy(void); + bool video_display_server_set_window_opacity(unsigned opacity); + bool video_display_server_set_window_progress(int progress, bool finished); + +bool video_display_server_get_current_resolution( + unsigned *width, unsigned *height); + bool video_display_server_set_window_decorations(bool on); +bool video_display_server_switch_resolution( + unsigned width, unsigned height, + int f_restore, int hz); + extern const video_display_server_t dispserv_win32; extern const video_display_server_t dispserv_x11; extern const video_display_server_t dispserv_null; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index d2832ede8c..acd5eb8152 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -119,9 +119,6 @@ #define video_driver_context_unlock() ((void)0) #endif -static bool crt_switching_active; -static float video_driver_core_hz; - typedef struct video_pixel_scaler { @@ -146,10 +143,12 @@ static rarch_softfilter_t *video_driver_state_filter = NULL; static void *video_driver_state_buffer = NULL; static unsigned video_driver_state_scale = 0; static unsigned video_driver_state_out_bpp = 0; -static bool video_driver_state_out_rgb32 = false; +static bool video_driver_state_out_rgb32 = false; +static bool video_driver_crt_switching_active = false; static struct retro_system_av_info video_driver_av_info; + static enum retro_pixel_format video_driver_pix_fmt = RETRO_PIXEL_FORMAT_0RGB1555; static const void *frame_cache_data = NULL; @@ -158,6 +157,7 @@ static unsigned frame_cache_height = 0; static size_t frame_cache_pitch = 0; static bool video_driver_threaded = false; +static float video_driver_core_hz = 0.0f; static float video_driver_aspect_ratio = 0.0f; static unsigned video_driver_width = 0; static unsigned video_driver_height = 0; @@ -878,7 +878,9 @@ static bool video_driver_pixel_converter_init(unsigned size) if (hwr && hwr->context_type != RETRO_HW_CONTEXT_NONE) return true; - RARCH_WARN("0RGB1555 pixel format is deprecated, and will be slower. For 15/16-bit, RGB565 format is preferred.\n"); + RARCH_WARN("0RGB1555 pixel format is deprecated," + " and will be slower. For 15/16-bit, RGB565" + " format is preferred.\n"); scalr = (video_pixel_scaler_t*)calloc(1, sizeof(*scalr)); @@ -1017,6 +1019,7 @@ static bool video_driver_init_internal(bool *video_is_threaded) video.rgb32 = video_driver_state_filter ? video_driver_state_out_rgb32 : (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888); + video.parent = 0; /* Reset video frame count */ video_driver_frame_count = 0; @@ -1045,7 +1048,8 @@ static bool video_driver_init_internal(bool *video_is_threaded) } else #endif - video_driver_data = current_video->init(&video, input_get_double_ptr(), + video_driver_data = current_video->init( + &video, input_get_double_ptr(), input_driver_get_data_ptr()); if (!video_driver_data) @@ -1413,43 +1417,37 @@ bool video_driver_cached_frame(void) void video_driver_monitor_adjust_system_rates(void) { - float timing_skew; + float timing_skew = 0.0f; settings_t *settings = config_get_ptr(); float video_refresh_rate = settings->floats.video_refresh_rate; + float timing_skew_hz = video_refresh_rate; const struct retro_system_timing *info = (const struct retro_system_timing*)&video_driver_av_info.timing; rarch_ctl(RARCH_CTL_UNSET_NONBLOCK_FORCED, NULL); - video_driver_core_hz = info->fps; if (!info || info->fps <= 0.0) return; - if (crt_switching_active == true) - { - timing_skew = fabs(1.0f - info->fps / video_driver_core_hz); - } - else - { - timing_skew = fabs(1.0f - info->fps / video_refresh_rate); - } + video_driver_core_hz = info->fps; + + if (video_driver_crt_switching_active) + timing_skew_hz = video_driver_core_hz; + timing_skew = fabs( + 1.0f - info->fps / timing_skew_hz); + /* We don't want to adjust pitch too much. If we have extreme cases, * just don't readjust at all. */ if (timing_skew <= settings->floats.audio_max_timing_skew) return; - RARCH_LOG("[Video]: Timings deviate too much. Will not adjust. (Display = %.2f Hz, Game = %.2f Hz)\n", + RARCH_LOG("[Video]: Timings deviate too much. Will not adjust." + " (Display = %.2f Hz, Game = %.2f Hz)\n", video_refresh_rate, (float)info->fps); - - if (crt_switching_active == true){ - if (info->fps <= video_driver_core_hz) - return; - } - else - { - if (info->fps <= video_refresh_rate) - return; - } + + if (info->fps <= timing_skew_hz) + return; + /* We won't be able to do VSync reliably when game FPS > monitor FPS. */ rarch_ctl(RARCH_CTL_SET_NONBLOCK_FORCED, NULL); RARCH_LOG("[Video]: Game FPS > Monitor FPS. Cannot rely on VSync.\n"); @@ -1555,7 +1553,8 @@ void video_driver_menu_settings(void **list_data, void *list_info_data, parent_group, general_write_handler, general_read_handler); - menu_settings_list_current_add_range(list, list_info, 0, 5, 1, true, true); + menu_settings_list_current_add_range(list, list_info, + 0, 5, 1, true, true); #endif #endif } @@ -1577,7 +1576,8 @@ static void video_driver_lock_new(void) void video_driver_destroy(void) { video_display_server_destroy(); - crt_video_restore(); + crt_video_restore(); + video_driver_cb_has_focus = null_driver_has_focus; video_driver_use_rgba = false; video_driver_data_own = false; @@ -1616,7 +1616,8 @@ bool video_driver_is_stub_frame(void) bool video_driver_supports_recording(void) { settings_t *settings = config_get_ptr(); - return settings->bools.video_gpu_record && current_video->read_viewport; + return settings->bools.video_gpu_record + && current_video->read_viewport; } bool video_driver_supports_viewport_read(void) @@ -1642,7 +1643,8 @@ void video_driver_set_viewport_config(void) { struct retro_game_geometry *geom = &video_driver_av_info.geometry; - if (geom->aspect_ratio > 0.0f && settings->bools.video_aspect_ratio_auto) + if (geom->aspect_ratio > 0.0f && + settings->bools.video_aspect_ratio_auto) aspectratio_lut[ASPECT_RATIO_CONFIG].value = geom->aspect_ratio; else { @@ -1869,7 +1871,8 @@ void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bo } else if (device_aspect > desired_aspect) { - delta = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f; + delta = (desired_aspect / device_aspect - 1.0f) + / 2.0f + 0.5f; vp->x = (int)roundf(vp->full_width * (0.5f - delta)); vp->width = (unsigned)roundf(2.0f * vp->full_width * delta); vp->y = 0; @@ -1879,7 +1882,8 @@ void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bo { vp->x = 0; vp->width = vp->full_width; - delta = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f; + delta = (device_aspect / desired_aspect - 1.0f) + / 2.0f + 0.5f; vp->y = (int)roundf(vp->full_height * (0.5f - delta)); vp->height = (unsigned)roundf(2.0f * vp->full_height * delta); } @@ -1986,18 +1990,17 @@ bool video_driver_find_driver(void) void video_driver_apply_state_changes(void) { - if (!video_driver_poke) - return; - if (video_driver_poke->apply_state_changes) + if (video_driver_poke && + video_driver_poke->apply_state_changes) video_driver_poke->apply_state_changes(video_driver_data); } bool video_driver_read_viewport(uint8_t *buffer, bool is_idle) { if ( current_video->read_viewport - && current_video->read_viewport(video_driver_data, buffer, is_idle)) + && current_video->read_viewport( + video_driver_data, buffer, is_idle)) return true; - return false; } @@ -2206,7 +2209,8 @@ void video_driver_gpu_record_deinit(void) video_driver_record_gpu_buffer = NULL; } -bool video_driver_get_current_software_framebuffer(struct retro_framebuffer *fb) +bool video_driver_get_current_software_framebuffer( + struct retro_framebuffer *fb) { if ( video_driver_poke @@ -2293,7 +2297,8 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, unsigned base_width; /* Use system reported sizes as these define the * geometry for the "normal" case. */ - unsigned base_height = video_driver_av_info.geometry.base_height; + unsigned base_height = + video_driver_av_info.geometry.base_height; if (base_height == 0) base_height = 1; @@ -2454,7 +2459,6 @@ void video_driver_frame(const void *data, unsigned width, if (video_info.fps_show) { if (video_info.framecount_show) - { snprintf( video_info.fps_text, sizeof(video_info.fps_text), @@ -2462,15 +2466,12 @@ void video_driver_frame(const void *data, unsigned width, last_fps, msg_hash_to_str(MSG_FRAMES), (uint64_t)video_driver_frame_count); - } else - { snprintf( video_info.fps_text, sizeof(video_info.fps_text), "FPS: %6.1f", last_fps); - } } } else @@ -2506,7 +2507,8 @@ void video_driver_frame(const void *data, unsigned width, || video_driver_record_gpu_buffer ) && recording_data ) - recording_dump_frame(data, width, height, pitch, video_info.runloop_is_idle); + recording_dump_frame(data, width, height, + pitch, video_info.runloop_is_idle); if (data && video_driver_state_filter && video_driver_frame_filter(data, &video_info, width, height, pitch, @@ -2539,12 +2541,13 @@ void video_driver_frame(const void *data, unsigned width, audio_statistics_t audio_stats = {0.0f}; double stddev = 0.0; struct retro_system_av_info *av_info = &video_driver_av_info; - bool measure_frame_time = video_monitor_fps_statistics(NULL, &stddev, NULL); unsigned red = 255; unsigned green = 255; unsigned blue = 255; unsigned alpha = 255; + video_monitor_fps_statistics(NULL, &stddev, NULL); + video_info.osd_stat_params.x = 0.010f; video_info.osd_stat_params.y = 0.950f; video_info.osd_stat_params.scale = 1.0f; @@ -2553,7 +2556,8 @@ void video_driver_frame(const void *data, unsigned width, video_info.osd_stat_params.drop_y = -2; video_info.osd_stat_params.drop_mod = 0.3f; video_info.osd_stat_params.drop_alpha = 1.0f; - video_info.osd_stat_params.color = COLOR_ABGR(red, green, blue, alpha); + video_info.osd_stat_params.color = COLOR_ABGR( + red, green, blue, alpha); compute_audio_buffer_statistics(&audio_stats); @@ -2602,29 +2606,22 @@ void video_driver_frame(const void *data, unsigned width, runloop_msg_queue_push(video_info.fps_text, 2, 1, true); /* trigger set resolution*/ - if (video_info.crt_switch_resolution == true){ - crt_switching_active = true; + if (video_info.crt_switch_resolution) + { + video_driver_crt_switching_active = true; - if (video_info.crt_switch_resolution_super == 2560){ - width = 2560; - } - if (video_info.crt_switch_resolution_super == 3840){ - width = 3840; - } - if (video_info.crt_switch_resolution_super == 1920){ - width = 1920; - } - crt_switch_res_core(width, height, video_driver_core_hz); - } else if (video_info.crt_switch_resolution == false){ - crt_switching_active = false; - } + if (video_info.crt_switch_resolution_super == 2560) + width = 2560; + if (video_info.crt_switch_resolution_super == 3840) + width = 3840; + if (video_info.crt_switch_resolution_super == 1920) + width = 1920; + crt_switch_res_core(width, height, video_driver_core_hz); + } + else if (!video_info.crt_switch_resolution) + video_driver_crt_switching_active = false; /* trigger set resolution*/ - -} - -void crt_poke_video(){ - video_driver_poke->apply_state_changes(video_driver_data); } void video_driver_display_type_set(enum rarch_display_type type) @@ -2811,9 +2808,6 @@ void video_driver_build_info(video_frame_info_t *video_info) video_info->cb_set_mvp = video_driver_cb_shader_set_mvp; video_info->userdata = video_driver_get_ptr(false); -#if 0 - video_info->cb_set_coords = video_driver_cb_set_coords; -#endif #ifdef HAVE_THREADS video_driver_threaded_unlock(is_threaded); @@ -2852,12 +2846,14 @@ bool video_driver_translate_coord_viewport( return false; if (mouse_x >= 0 && mouse_x <= norm_full_vp_width) - scaled_screen_x = ((2 * mouse_x * 0x7fff) / norm_full_vp_width) - 0x7fff; + scaled_screen_x = ((2 * mouse_x * 0x7fff) + / norm_full_vp_width) - 0x7fff; else scaled_screen_x = -0x8000; /* OOB */ if (mouse_y >= 0 && mouse_y <= norm_full_vp_height) - scaled_screen_y = ((2 * mouse_y * 0x7fff) / norm_full_vp_height) - 0x7fff; + scaled_screen_y = ((2 * mouse_y * 0x7fff) + / norm_full_vp_height) - 0x7fff; else scaled_screen_y = -0x8000; /* OOB */ @@ -2865,12 +2861,14 @@ bool video_driver_translate_coord_viewport( mouse_y -= vp->y; if (mouse_x >= 0 && mouse_x <= norm_vp_width) - scaled_x = ((2 * mouse_x * 0x7fff) / norm_vp_width) - 0x7fff; + scaled_x = ((2 * mouse_x * 0x7fff) + / norm_vp_width) - 0x7fff; else scaled_x = -0x8000; /* OOB */ if (mouse_y >= 0 && mouse_y <= norm_vp_height) - scaled_y = ((2 * mouse_y * 0x7fff) / norm_vp_height) - 0x7fff; + scaled_y = ((2 * mouse_y * 0x7fff) + / norm_vp_height) - 0x7fff; else scaled_y = -0x8000; /* OOB */ @@ -2895,7 +2893,8 @@ void video_driver_get_status(uint64_t *frame_count, bool * is_alive, bool *is_focused) { *frame_count = video_driver_frame_count; - *is_alive = current_video ? current_video->alive(video_driver_data) : true; + *is_alive = current_video ? + current_video->alive(video_driver_data) : true; *is_focused = video_driver_cb_has_focus(); } @@ -2948,7 +2947,8 @@ bool video_context_driver_find_prev_driver(void) bool video_context_driver_find_next_driver(void) { settings_t *settings = config_get_ptr(); - int i = find_video_context_driver_index(settings->arrays.video_context_driver); + int i = find_video_context_driver_index( + settings->arrays.video_context_driver); if (i >= 0 && gfx_ctx_drivers[i + 1]) { @@ -2975,7 +2975,8 @@ bool video_context_driver_find_next_driver(void) * * Initialize graphics context driver. * - * Returns: graphics context driver if successfully initialized, otherwise NULL. + * Returns: graphics context driver if successfully initialized, + * otherwise NULL. **/ static const gfx_ctx_driver_t *video_context_driver_init( void *data, @@ -3096,7 +3097,8 @@ bool video_context_driver_init_image_buffer(const video_info_t *data) { if ( current_video_context.image_buffer_init - && current_video_context.image_buffer_init(video_context_data, data)) + && current_video_context.image_buffer_init( + video_context_data, data)) return true; return false; } @@ -3201,10 +3203,25 @@ bool video_context_driver_get_metrics(gfx_ctx_metrics_t *metrics) return false; } +bool video_context_driver_get_refresh_rate(float *refresh_rate) +{ + if (!current_video_context.get_refresh_rate || !refresh_rate) + return false; + if (!video_context_data) + return false; + + if (refresh_rate) + *refresh_rate = + current_video_context.get_refresh_rate(video_context_data); + + return true; +} + bool video_context_driver_input_driver(gfx_ctx_input_t *inp) { settings_t *settings = config_get_ptr(); - const char *joypad_name = settings ? settings->arrays.input_joypad_driver : NULL; + const char *joypad_name = settings ? + settings->arrays.input_joypad_driver : NULL; if (!current_video_context.input_driver) return false; @@ -3260,7 +3277,8 @@ bool video_context_driver_get_context_data(void *data) { if (!current_video_context.get_context_data) return false; - *(void**)data = current_video_context.get_context_data(video_context_data); + *(void**)data = current_video_context.get_context_data( + video_context_data); return true; } @@ -3277,16 +3295,22 @@ void video_context_driver_set_data(void *data) video_context_data = data; } +bool video_driver_get_flags(gfx_ctx_flags_t *flags) +{ + if (!flags || !video_driver_poke || !video_driver_poke->get_flags) + return false; + flags->flags = video_driver_poke->get_flags(video_driver_data); + return true; +} + bool video_context_driver_get_flags(gfx_ctx_flags_t *flags) { - if (!flags) - return false; - if (!current_video_context.get_flags) + if (!flags || !current_video_context.get_flags) return false; if (deferred_video_context_driver_set_flags) { - flags->flags = deferred_flag_data.flags; + flags->flags = deferred_flag_data.flags; deferred_video_context_driver_set_flags = false; return true; } @@ -3301,7 +3325,7 @@ bool video_context_driver_set_flags(gfx_ctx_flags_t *flags) return false; if (!current_video_context.set_flags) { - deferred_flag_data.flags = flags->flags; + deferred_flag_data.flags = flags->flags; deferred_video_context_driver_set_flags = true; return false; } @@ -3361,7 +3385,8 @@ bool video_driver_cached_frame_has_valid_framebuffer(void) return false; } -static const shader_backend_t *video_shader_set_backend(enum rarch_shader_type type) +static const shader_backend_t *video_shader_set_backend( + enum rarch_shader_type type) { switch (type) { @@ -3391,6 +3416,13 @@ static const shader_backend_t *video_shader_set_backend(enum rarch_shader_type t return &gl_glsl_backend; #else break; +#endif + case RARCH_SHADER_HLSL: +#ifdef HAVE_HLSL + RARCH_LOG("[Shader driver]: Using HLSL shader backend.\n"); + return &hlsl_backend; +#else + break; #endif case RARCH_SHADER_NONE: default: @@ -3430,7 +3462,8 @@ void video_shader_driver_set_parameters(void *data) } } -bool video_shader_driver_get_prev_textures(video_shader_ctx_texture_t *texture) +bool video_shader_driver_get_prev_textures( + video_shader_ctx_texture_t *texture) { if (!texture || !current_shader) return false; @@ -3459,7 +3492,8 @@ bool video_shader_driver_get_current_shader(video_shader_ctx_t *shader) return true; } -bool video_shader_driver_direct_get_current_shader(video_shader_ctx_t *shader) +bool video_shader_driver_direct_get_current_shader( + video_shader_ctx_t *shader) { shader->data = current_shader->get_current_shader(current_shader_data); @@ -3475,7 +3509,7 @@ bool video_shader_driver_deinit(void) current_shader->deinit(current_shader_data); current_shader_data = NULL; - current_shader = NULL; + current_shader = NULL; return true; } @@ -3496,7 +3530,8 @@ static bool video_driver_cb_set_mvp(void *data, return true; } -static struct video_shader *video_shader_driver_get_current_shader_null(void *data) +static struct video_shader * +video_shader_driver_get_current_shader_null(void *data) { return NULL; } @@ -3513,13 +3548,15 @@ static void video_shader_driver_scale_null(void *data, (void)scale; } -static bool video_shader_driver_mipmap_input_null(void *data, unsigned idx) +static bool video_shader_driver_mipmap_input_null( + void *data, unsigned idx) { (void)idx; return false; } -static bool video_shader_driver_filter_type_null(void *data, unsigned idx, bool *smooth) +static bool video_shader_driver_filter_type_null( + void *data, unsigned idx, bool *smooth) { (void)idx; (void)smooth; @@ -3531,7 +3568,8 @@ static unsigned video_shader_driver_num_null(void *data) return 0; } -static bool video_shader_driver_get_feedback_pass_null(void *data, unsigned *idx) +static bool video_shader_driver_get_feedback_pass_null( + void *data, unsigned *idx) { (void)idx; return false; @@ -3587,7 +3625,8 @@ bool video_shader_driver_init_first(void) bool video_shader_driver_init(video_shader_ctx_init_t *init) { - void *tmp = NULL; + void *tmp = NULL; + settings_t *settings = config_get_ptr(); if (!init->shader || !init->shader->init) { @@ -3602,7 +3641,17 @@ bool video_shader_driver_init(video_shader_ctx_init_t *init) if (!tmp) return false; + if (string_is_equal(settings->arrays.menu_driver, "xmb") + && init->shader->init_menu_shaders) + { + RARCH_LOG("Setting up menu pipeline shaders for XMB ... \n"); + init->shader->init_menu_shaders(tmp); + } + current_shader_data = tmp; + + RARCH_LOG("Resetting shader to defaults ... \n"); + current_shader = (shader_backend_t*)init->shader; video_shader_driver_reset_to_defaults(); @@ -3669,12 +3718,14 @@ void video_driver_set_coords(video_shader_ctx_coords_t *coords) { if (current_shader && current_shader->set_coords) current_shader->set_coords(coords->handle_data, - current_shader_data, (const struct video_coords*)coords->data); + current_shader_data, + (const struct video_coords*)coords->data); else { if (video_driver_poke && video_driver_poke->set_coords) video_driver_poke->set_coords(coords->handle_data, - current_shader_data, (const struct video_coords*)coords->data); + current_shader_data, + (const struct video_coords*)coords->data); } } @@ -3684,10 +3735,20 @@ void video_driver_set_mvp(video_shader_ctx_mvp_t *mvp) return; if (current_shader && current_shader->set_mvp) - current_shader->set_mvp(mvp->data, current_shader_data, mvp->matrix); + current_shader->set_mvp(mvp->data, + current_shader_data, mvp->matrix); else { if (video_driver_poke && video_driver_poke->set_mvp) - video_driver_poke->set_mvp(mvp->data, current_shader_data, mvp->matrix); + video_driver_poke->set_mvp(mvp->data, + current_shader_data, mvp->matrix); } } + +float video_driver_get_refresh_rate(void) +{ + if (video_driver_poke && video_driver_poke->get_refresh_rate) + return video_driver_poke->get_refresh_rate(video_driver_data); + + return 0.0f; +} diff --git a/gfx/video_driver.h b/gfx/video_driver.h index c97ed31000..4563e9a3b7 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -71,12 +71,6 @@ RETRO_BEGIN_DECLS #define MAX_VARIABLES 64 -/* Added for resolution wswitching */ -void crt_poke_video(); - -/* Added for resolution wswitching */ - - enum { TEXTURES = 8, @@ -119,7 +113,10 @@ enum display_flags GFX_CTX_FLAGS_NONE = 0, GFX_CTX_FLAGS_GL_CORE_CONTEXT, GFX_CTX_FLAGS_MULTISAMPLING, - GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES + GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES, + GFX_CTX_FLAGS_HARD_SYNC, + GFX_CTX_FLAGS_BLACK_FRAME_INSERTION, + GFX_CTX_FLAGS_MENU_FRAME_FILTERING }; enum shader_uniform_type @@ -206,6 +203,7 @@ struct uniform_info typedef struct shader_backend { void *(*init)(void *data, const char *path); + void (*init_menu_shaders)(void *data); void (*deinit)(void *data); /* Set shader parameters. */ @@ -531,6 +529,8 @@ typedef struct gfx_ctx_driver * If not initialized yet, it returns current screen size. */ void (*get_video_size)(void*, unsigned*, unsigned*); + float (*get_refresh_rate)(void*); + void (*get_video_output_size)(void*, unsigned*, unsigned*); void (*get_video_output_prev)(void*); @@ -697,6 +697,7 @@ struct aspect_ratio_elem typedef struct video_poke_interface { + uint32_t (*get_flags)(void *data); void (*set_coords)(void *handle_data, void *shader_data, const struct video_coords *coords); void (*set_mvp)(void *data, void *shader_data, @@ -706,6 +707,7 @@ typedef struct video_poke_interface void (*unload_texture)(void *data, uintptr_t id); void (*set_video_mode)(void *data, unsigned width, unsigned height, bool fullscreen); + float (*get_refresh_rate)(void *data); void (*set_filtering)(void *data, unsigned index, bool smooth); void (*get_video_output_size)(void *data, unsigned *width, unsigned *height); @@ -1279,12 +1281,16 @@ bool video_context_driver_set_video_mode(gfx_ctx_mode_t *mode_info); bool video_context_driver_get_video_size(gfx_ctx_mode_t *mode_info); +bool video_context_driver_get_refresh_rate(float *refresh_rate); + bool video_context_driver_get_context_data(void *data); bool video_context_driver_show_mouse(bool *bool_data); void video_context_driver_set_data(void *data); +bool video_driver_get_flags(gfx_ctx_flags_t *flags); + bool video_context_driver_get_flags(gfx_ctx_flags_t *flags); bool video_context_driver_set_flags(gfx_ctx_flags_t *flags); @@ -1337,6 +1343,8 @@ void video_shader_driver_use(void *data); bool video_shader_driver_wrap_type(video_shader_ctx_wrap_t *wrap); +float video_driver_get_refresh_rate(void); + extern bool (*video_driver_cb_has_focus)(void); extern video_driver_t video_gl; diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 38f0655827..ed78aa8189 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -1215,6 +1215,7 @@ enum rarch_shader_type video_shader_get_type_from_ext( { switch (api) { + case GFX_CTX_DIRECT3D10_API: case GFX_CTX_DIRECT3D11_API: case GFX_CTX_DIRECT3D12_API: case GFX_CTX_GX2_API: @@ -1232,6 +1233,7 @@ enum rarch_shader_type video_shader_get_type_from_ext( switch (api) { + case GFX_CTX_DIRECT3D10_API: case GFX_CTX_DIRECT3D11_API: case GFX_CTX_DIRECT3D12_API: case GFX_CTX_GX2_API: diff --git a/gfx/video_thread_wrapper.c b/gfx/video_thread_wrapper.c index 027e4a0daf..147ec5782b 100644 --- a/gfx/video_thread_wrapper.c +++ b/gfx/video_thread_wrapper.c @@ -1252,12 +1252,22 @@ static struct video_shader *thread_get_current_shader(void *data) return thr->poke->get_current_shader(thr->driver_data); } +static uint32_t thread_get_flags(void *data) +{ + thread_video_t *thr = (thread_video_t*)data; + if (!thr || !thr->poke || !thr->poke->get_flags) + return 0; + return thr->poke->get_flags(thr->driver_data); +} + static const video_poke_interface_t thread_poke = { + thread_get_flags, NULL, /* set_coords */ NULL, /* set_mvp */ thread_load_texture, thread_unload_texture, thread_set_video_mode, + NULL, thread_set_filtering, thread_get_video_output_size, thread_get_video_output_prev, diff --git a/griffin/griffin.c b/griffin/griffin.c index 6b41b8448e..8f73ea6e0c 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -394,7 +394,6 @@ VIDEO DRIVER #include "../gfx/drivers/drm_gfx.c" #endif -#include "../gfx/drivers_renderchain/null_renderchain.c" #include "../gfx/display_servers/dispserv_null.c" #ifdef HAVE_OPENGL @@ -510,6 +509,10 @@ FONTS #include "../gfx/drivers_font/vulkan_raster_font.c" #endif +#if defined(HAVE_D3D10) +#include "../gfx/drivers_font/d3d10_font.c" +#endif + #if defined(HAVE_D3D11) #include "../gfx/drivers_font/d3d11_font.c" #endif @@ -1169,6 +1172,10 @@ MENU #include "../menu/drivers_display/menu_display_d3d9.c" #endif +#if defined(HAVE_D3D10) +#include "../menu/drivers_display/menu_display_d3d10.c" +#endif + #if defined(HAVE_D3D11) #include "../menu/drivers_display/menu_display_d3d11.c" #endif @@ -1243,9 +1250,7 @@ MENU #include "../cores/libretro-net-retropad/net_retropad_core.c" #endif -#ifdef HAVE_KEYMAPPER #include "../input/input_mapper.c" -#endif #include "../command.c" @@ -1253,13 +1258,22 @@ MENU #include "../libretro-common/net/net_http_parse.c" #endif +#ifdef HAVE_RUNAHEAD +#include "../runahead/mem_util.c" +#include "../runahead/secondary_core.c" +#include "../runahead/run_ahead.c" +#include "../runahead/copy_load_info.c" +#include "../runahead/dirty_input.c" +#include "../runahead/mylist.c" +#endif + /*============================================================ DEPENDENCIES ============================================================ */ #ifdef WANT_ZLIB #include "../deps/libz/adler32.c" #include "../deps/libz/compress.c" -#include "../deps/libz/crc32.c" +#include "../deps/libz/libz-crc32.c" #include "../deps/libz/deflate.c" #include "../deps/libz/gzclose.c" #include "../deps/libz/gzlib.c" @@ -1292,11 +1306,24 @@ DEPENDENCIES #endif #ifdef HAVE_CHD -#include "../libretro-common/formats/libchdr/bitstream.c" -#include "../libretro-common/formats/libchdr/cdrom.c" -#include "../libretro-common/formats/libchdr/chd.c" -#include "../libretro-common/formats/libchdr/flac.c" -#include "../libretro-common/formats/libchdr/huffman.c" +#include "../libretro-common/formats/libchdr/libchdr_bitstream.c" +#include "../libretro-common/formats/libchdr/libchdr_cdrom.c" +#include "../libretro-common/formats/libchdr/libchdr_chd.c" + +#ifdef HAVE_FLAC +#include "../libretro-common/formats/libchdr/libchdr_flac.c" +#include "../libretro-common/formats/libchdr/libchdr_flac_codec.c" +#endif + +#ifdef HAVE_ZLIB +#include "../libretro-common/formats/libchdr/libchdr_zlib.c" +#endif + +#ifdef HAVE_7ZIP +#include "../libretro-common/formats/libchdr/libchdr_lzma.c" +#endif + +#include "../libretro-common/formats/libchdr/libchdr_huffman.c" #include "../libretro-common/streams/chd_stream.c" #endif diff --git a/input/common/hid/device_ds3.c b/input/common/hid/device_ds3.c new file mode 100644 index 0000000000..4b26cd5634 --- /dev/null +++ b/input/common/hid/device_ds3.c @@ -0,0 +1,356 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "hid_device_driver.h" + +#define DS3_ACTIVATION_REPORT_ID 0xf4 +#define DS3_RUMBLE_REPORT_ID 0x01 + +typedef struct ds3_instance { + void *handle; + joypad_connection_t *pad; + int slot; + bool led_set; + uint32_t buttons; + int16_t analog_state[3][2]; + uint16_t motors[2]; + uint8_t data[64]; +} ds3_instance_t; + +static uint8_t activation_packet[] = { +#if defined(IOS) + 0x53, 0xF4, +#elif defined(HAVE_WIIUSB_HID) + 0x02, +#endif + 0x42, 0x0c, 0x00, 0x00 +}; + +#if defined(WIIU) +#define PACKET_OFFSET 2 +#elif defined(HAVE_WIIUSB_HID) +#define PACKET_OFFSET 1 +#else +#define PACKET_OFFSET 0 +#endif + +#define LED_OFFSET 11 +#define MOTOR1_OFFSET 4 +#define MOTOR2_OFFSET 6 + +static uint8_t control_packet[] = { + 0x52, 0x01, + 0x00, 0xff, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +static int control_packet_size = sizeof(control_packet); + +extern pad_connection_interface_t ds3_pad_connection; + +static void update_pad_state(ds3_instance_t *instance); +static void update_analog_state(ds3_instance_t *instance); + +static int32_t send_activation_packet(ds3_instance_t *instance) +{ + int32_t result; +#if defined(WIIU) + result = HID_SET_REPORT(instance->handle, + HID_REPORT_FEATURE, + DS3_ACTIVATION_REPORT_ID, + activation_packet, + sizeof(activation_packet)); +#else + HID_SEND_CONTROL(instance->handle, + activation_packet, sizeof(activation_packet)); +#endif + + return result; +} + +static uint32_t set_protocol(ds3_instance_t *instance, int protocol) +{ + uint32_t result = 0; +#if defined(WIIU) + result = HID_SET_PROTOCOL(instance->handle, 1); +#endif + + return result; +} + +static int32_t send_control_packet(ds3_instance_t *instance) +{ + uint8_t packet_buffer[control_packet_size]; + int32_t result = 0; + memcpy(packet_buffer, control_packet, control_packet_size); + + packet_buffer[LED_OFFSET] = 0; + if(instance->pad) { + packet_buffer[LED_OFFSET] = 1 << ((instance->slot % 4) + 1); + } + packet_buffer[MOTOR1_OFFSET] = instance->motors[1] >> 8; + packet_buffer[MOTOR2_OFFSET] = instance->motors[0] >> 8; + +#if defined(HAVE_WIIUSB_HID) + packet_buffer[1] = 0x03; +#endif + +#if defined(WIIU) + result = HID_SET_REPORT(instance->handle, + HID_REPORT_OUTPUT, + DS3_RUMBLE_REPORT_ID, + packet_buffer+PACKET_OFFSET, + control_packet_size-PACKET_OFFSET); +#else + HID_SEND_CONTROL(instance->handle, + packet_buffer+PACKET_OFFSET, + control_packet_size-PACKET_OFFSET); +#endif /* WIIU */ + return result; +} + +static void *ds3_init(void *handle) +{ + ds3_instance_t *instance; + int errors = 0; + RARCH_LOG("[ds3]: init\n"); + instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t)); + if(!instance) + goto error; + + memset(instance, 0, sizeof(ds3_instance_t)); + instance->handle = handle; + + RARCH_LOG("[ds3]: setting protocol\n"); + + /* this might fail, but we don't care. */ + set_protocol(instance, 1); + + RARCH_LOG("[ds3]: sending control packet\n"); + if(send_control_packet(instance) < 0) + errors++; + + RARCH_LOG("[ds3]: sending activation packet\n"); + if(send_activation_packet(instance) < 0) + errors++; + + if(errors) + goto error; + + instance->pad = hid_pad_register(instance, &ds3_pad_connection); + if(!instance->pad) + goto error; + + RARCH_LOG("[ds3]: init complete.\n"); + return instance; + + error: + RARCH_ERR("[ds3]: init failed.\n"); + if(instance) + free(instance); + return NULL; +} + +static void ds3_free(void *data) +{ + ds3_instance_t *instance = (ds3_instance_t *)data; + + if(instance) { + hid_pad_deregister(instance->pad); + free(instance); + } +} + +static void ds3_handle_packet(void *data, uint8_t *packet, size_t size) +{ + ds3_instance_t *instance = (ds3_instance_t *)data; + + if(!instance || !instance->pad) + return; + + instance->pad->iface->packet_handler(data, packet, size); +} + +static bool ds3_detect(uint16_t vendor_id, uint16_t product_id) +{ + return vendor_id == VID_SONY && product_id == PID_SONY_DS3; +} + +hid_device_t ds3_hid_device = { + ds3_init, + ds3_free, + ds3_handle_packet, + ds3_detect, + "Sony DualShock 3" +}; + +/** + * pad interface implementation + */ + +static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + pad->slot = slot; + + return data; +} + +static void ds3_pad_deinit(void *data) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + if(pad) { + input_autoconfigure_disconnect(pad->slot, ds3_pad_connection.get_name(pad)); + } +} + +static void ds3_get_buttons(void *data, input_bits_t *state) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + + if(pad) + { + BITS_COPY16_PTR(state, pad->buttons); + + if(pad->buttons & 0x10000) + BIT256_SET_PTR(state, RARCH_MENU_TOGGLE); + } else { + BIT256_CLEAR_ALL_PTR(state); + } +} + +static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size) +{ + ds3_instance_t *instance = (ds3_instance_t *)data; + + if(instance->pad && !instance->led_set) + { + send_control_packet(instance); + instance->led_set = true; + } + + if(size > control_packet_size) + { + RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n", + control_packet_size, size); + return; + } + + memcpy(instance->data, packet, size); + update_pad_state(instance); + update_analog_state(instance); +} + +static void update_analog_state(ds3_instance_t *instance) +{ + int pad_axis; + int16_t interpolated; + unsigned stick, axis; + + for(pad_axis = 0; pad_axis < 4; pad_axis++) + { + axis = pad_axis % 2 ? 0 : 1; + stick = pad_axis / 2; + interpolated = instance->data[6+pad_axis]; + instance->analog_state[stick][axis] = (interpolated - 128) * 256; + } +} + +static void update_pad_state(ds3_instance_t *instance) +{ + uint32_t i, pressed_keys; + + static const uint32_t button_mapping[17] = + { + RETRO_DEVICE_ID_JOYPAD_SELECT, + RETRO_DEVICE_ID_JOYPAD_L3, + RETRO_DEVICE_ID_JOYPAD_R3, + RETRO_DEVICE_ID_JOYPAD_START, + RETRO_DEVICE_ID_JOYPAD_UP, + RETRO_DEVICE_ID_JOYPAD_RIGHT, + RETRO_DEVICE_ID_JOYPAD_DOWN, + RETRO_DEVICE_ID_JOYPAD_LEFT, + RETRO_DEVICE_ID_JOYPAD_L2, + RETRO_DEVICE_ID_JOYPAD_R2, + RETRO_DEVICE_ID_JOYPAD_L, + RETRO_DEVICE_ID_JOYPAD_R, + RETRO_DEVICE_ID_JOYPAD_X, + RETRO_DEVICE_ID_JOYPAD_A, + RETRO_DEVICE_ID_JOYPAD_B, + RETRO_DEVICE_ID_JOYPAD_Y, + 16 /* PS button */ + }; + + instance->buttons = 0; + + pressed_keys = instance->data[2]|(instance->data[3] << 8)|((instance->data[4] & 0x01) << 16); + + for(i = 0; i < 17; i++) + instance->buttons |= (pressed_keys & (1 << i)) ? + (1 << button_mapping[i]) : 0; +} + +static void ds3_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; +} + +static int16_t ds3_get_axis(void *data, unsigned axis) +{ + axis_data axis_data; + ds3_instance_t *pad = (ds3_instance_t *)data; + + gamepad_read_axis_data(axis, &axis_data); + + if(!pad || axis_data.axis >= 4) + return 0; + + return gamepad_get_axis_value(pad->analog_state, &axis_data); +} + +static const char *ds3_get_name(void *data) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + return "Sony DualShock 3"; +} + +static bool ds3_button(void *data, uint16_t joykey) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + if(!pad || joykey > 31) + return false; + + return pad->buttons & (1 << joykey); +} + +pad_connection_interface_t ds3_pad_connection = { + ds3_pad_init, + ds3_pad_deinit, + ds3_packet_handler, + ds3_set_rumble, + ds3_get_buttons, + ds3_get_axis, + ds3_get_name, + ds3_button +}; diff --git a/input/common/hid/device_ds4.c b/input/common/hid/device_ds4.c new file mode 100644 index 0000000000..af923cee13 --- /dev/null +++ b/input/common/hid/device_ds4.c @@ -0,0 +1,154 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "hid_device_driver.h" + +extern pad_connection_interface_t ds4_pad_connection; + +typedef struct ds4_instance { + void *handle; + joypad_connection_t *pad; + int slot; + uint32_t buttons; + uint16_t motors[2]; + uint8_t data[64]; +} ds4_instance_t; + +/** + * I'm leaving this code in here for posterity, and because maybe it can + * be used on other platforms. But using the DS4 on the Wii U directly is + * impossible because it doesn't generate a HID event. Which makes me think + * it's not a HID device at all--at least, not over USB. + * + * I imagine it might be useful in Bluetooth mode, though. + */ +static void *ds4_init(void *handle) +{ + ds4_instance_t *instance; + instance = (ds4_instance_t *)calloc(1, sizeof(ds4_instance_t)); + if(!instance) + goto error; + + memset(instance, 0, sizeof(ds4_instance_t)); + instance->handle = handle; + instance->pad = hid_pad_register(instance, &ds4_pad_connection); + if(!instance->pad) + goto error; + + RARCH_LOG("[ds4]: init complete.\n"); + return instance; + + error: + RARCH_ERR("[ds4]: init failed.\n"); + if(instance) + free(instance); + + return NULL; +} + +static void ds4_free(void *data) +{ + ds4_instance_t *instance = (ds4_instance_t *)data; + + if(instance) { + hid_pad_deregister(instance->pad); + free(instance); + } +} + +static void ds4_handle_packet(void *data, uint8_t *buffer, size_t size) +{ + ds4_instance_t *instance = (ds4_instance_t *)data; + + if(instance && instance->pad) + instance->pad->iface->packet_handler(instance->pad->data, buffer, size); +} + +static bool ds4_detect(uint16_t vendor_id, uint16_t product_id) +{ + return vendor_id == VID_SONY && product_id == PID_SONY_DS4; +} + +hid_device_t ds4_hid_device = { + ds4_init, + ds4_free, + ds4_handle_packet, + ds4_detect, + "Sony DualShock 4" +}; + +static void *ds4_pad_init(void *data, uint32_t slot, hid_driver_t *driver) +{ + ds4_instance_t *instance = (ds4_instance_t *)data; + + if(!instance) + return NULL; + + instance->slot = slot; + return instance; +} + +static void ds4_pad_deinit(void *data) +{ +} + +static void ds4_get_buttons(void *data, input_bits_t *state) +{ + ds4_instance_t *instance = (ds4_instance_t *)data; + if(!instance) + return; + + /* TODO: get buttons */ +} + +static void ds4_packet_handler(void *data, uint8_t *packet, uint16_t size) +{ + ds4_instance_t *instance = (ds4_instance_t *)data; + if(!instance) + return; + + RARCH_LOG_BUFFER(packet, size); +} + +static void ds4_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) +{ +} + +static int16_t ds4_get_axis(void *data, unsigned axis) +{ + return 0; +} + +static const char *ds4_get_name(void *data) +{ + return "Sony DualShock 4"; +} + +static bool ds4_button(void *data, uint16_t joykey) +{ + return false; +} + +pad_connection_interface_t ds4_pad_connection = { + ds4_pad_init, + ds4_pad_deinit, + ds4_packet_handler, + ds4_set_rumble, + ds4_get_buttons, + ds4_get_axis, + ds4_get_name, + ds4_button +}; diff --git a/input/common/hid/device_null.c b/input/common/hid/device_null.c new file mode 100644 index 0000000000..f5676c87b7 --- /dev/null +++ b/input/common/hid/device_null.c @@ -0,0 +1,219 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "hid_device_driver.h" + +extern pad_connection_interface_t null_pad_connection; + +/* + * This is the instance data structure for the pad you are implementing. + * This is a good starting point, but you can add/remove things as makes + * sense for the pad you're writing for. The pointer to this structure + * will be passed in as a void pointer to the methods you implement below. + */ +typedef struct null_instance { + void *handle; /* a handle to the HID subsystem adapter */ + joypad_connection_t *pad; /* a pointer to the joypad connection you assign + in init() */ + int slot; /* which slot does this pad occupy? */ + uint32_t buttons; /* a bitmap of the digital buttons for the pad */ + uint16_t motors[2]; /* rumble strength, if appropriate */ + uint8_t data[64]; /* a buffer large enough to hold the device's + max rx packet */ +} null_instance_t; + +/** + * Use the HID_ macros (see input/include/hid_driver.h) to send data packets + * to the device. When this method returns, the device needs to be in a state + * where we can read data packets from the device. So, if there's any + * activation packets (see the ds3 and Wii U GameCube adapter drivers for + * examples), send them here. + * + * While you *can* allocate the retro pad here, it isn't mandatory (see + * the Wii U GC adapter). + * + * If initialization fails, return NULL. + */ +static void *null_init(void *handle) +{ + null_instance_t *instance; + instance = (null_instance_t *)calloc(1, sizeof(null_instance_t)); + if(!instance) + goto error; + + memset(instance, 0, sizeof(null_instance_t)); + instance->handle = handle; + instance->pad = hid_pad_register(instance, &null_pad_connection); + if(!instance->pad) + goto error; + + RARCH_LOG("[null]: init complete.\n"); + return instance; + + error: + RARCH_ERR("[null]: init failed.\n"); + if(instance) + free(instance); + + return NULL; +} + +/* + * Gets called when the pad is disconnected. It must clean up any memory + * allocated and used by the instance data. + */ +static void null_free(void *data) +{ + null_instance_t *instance = (null_instance_t *)data; + + if(instance) { + hid_pad_deregister(instance->pad); + free(instance); + } +} + +/** + * Handle a single packet from the device. + * For most pads you'd just forward it onto the pad driver (see below). + * A more complicated example is in the Wii U GC adapter driver. + */ +static void null_handle_packet(void *data, uint8_t *buffer, size_t size) +{ + null_instance_t *instance = (null_instance_t *)data; + + if(instance && instance->pad) + instance->pad->iface->packet_handler(instance->pad->data, buffer, size); +} + +/** + * Return true if the passed in VID and PID are supported by the driver. + */ +static bool null_detect(uint16_t vendor_id, uint16_t product_id) +{ + return vendor_id == VID_NONE && product_id == PID_NONE; +} + +/** + * Assign function pointers to the driver structure. + */ +hid_device_t null_hid_device = { + null_init, + null_free, + null_handle_packet, + null_detect, + "Null HID device" +}; + +/** + * This is called via hid_pad_register(). In the common case where the + * device only controls one pad, you can simply return the data parameter. + * But if you need to track multiple pads attached to the same HID device + * (see: Wii U GC adapter), you can allocate that memory here. + */ +static void *null_pad_init(void *data, uint32_t slot, hid_driver_t *driver) +{ + null_instance_t *instance = (null_instance_t *)data; + + if(!instance) + return NULL; + + instance->slot = slot; + return instance; +} + +/** + * If you allocate any memory in null_pad_init() above, de-allocate it here. + */ +static void null_pad_deinit(void *data) +{ +} + +/** + * Translate the button data from the pad into the input_bits_t format + * that RetroArch can use. + */ +static void null_get_buttons(void *data, input_bits_t *state) +{ + null_instance_t *instance = (null_instance_t *)data; + if(!instance) + return; + + /* TODO: get buttons */ +} + +/** + * Handle a single packet for the pad. + */ +static void null_packet_handler(void *data, uint8_t *packet, uint16_t size) +{ + null_instance_t *instance = (null_instance_t *)data; + if(!instance) + return; + + RARCH_LOG_BUFFER(packet, size); +} + +/** + * If the pad doesn't support rumble, then this can just be a no-op. + */ +static void null_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) +{ +} + +/** + * Read analog sticks. + * If the pad doesn't have any analog axis, just return 0 here. + * + * The return value must conform to the following characteristics: + * - (0, 0) is center + * - (-32768,-32768) is top-left + * - (32767,32767) is bottom-right + */ +static int16_t null_get_axis(void *data, unsigned axis) +{ + return 0; +} + +/** + * The name the pad will show up as in the UI, also used to auto-assign + * buttons in input/input_autodetect_builtin.c + */ +static const char *null_get_name(void *data) +{ + return "Null HID Pad"; +} + +/** + * Read the state of a single button. + */ +static bool null_button(void *data, uint16_t joykey) +{ + return false; +} + +/** + * Fill in the joypad interface + */ +pad_connection_interface_t null_pad_connection = { + null_pad_init, + null_pad_deinit, + null_packet_handler, + null_set_rumble, + null_get_buttons, + null_get_axis, + null_get_name, + null_button +}; diff --git a/input/common/hid/device_wiiu_gca.c b/input/common/hid/device_wiiu_gca.c new file mode 100644 index 0000000000..73e58681fb --- /dev/null +++ b/input/common/hid/device_wiiu_gca.c @@ -0,0 +1,362 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ +#include +#include "hid_device_driver.h" + +#ifdef WII +static uint8_t activation_packet[] = { 0x01, 0x13 }; +#else +static uint8_t activation_packet[] = { 0x13 }; +#endif + +#define GCA_PORT_INITIALIZING 0x00 +#define GCA_PORT_POWERED 0x04 +#define GCA_PORT_CONNECTED 0x10 +#define GCA_WAVEBIRD_CONNECTED 0x22 + +typedef struct wiiu_gca_instance { + void *handle; + bool online; + uint8_t device_state[37]; + joypad_connection_t *pads[4]; +} wiiu_gca_instance_t; + +typedef struct gca_pad_data +{ + void *gca_handle; // instance handle for the GCA adapter + hid_driver_t *driver; // HID system driver interface + uint8_t data[9]; // pad data + uint32_t slot; // slot this pad occupies + uint32_t buttons; // digital button state + int16_t analog_state[3][2]; // analog state +} gca_pad_t; + + +static void update_pad_state(wiiu_gca_instance_t *instance); +static void unregister_pad(wiiu_gca_instance_t *instance, int port); + +extern pad_connection_interface_t wiiu_gca_pad_connection; + +static void *wiiu_gca_init(void *handle) +{ + RARCH_LOG("[gca]: allocating driver instance...\n"); + wiiu_gca_instance_t *instance = calloc(1, sizeof(wiiu_gca_instance_t)); + if(instance == NULL) goto error; + memset(instance, 0, sizeof(wiiu_gca_instance_t)); + instance->handle = handle; + + hid_instance.os_driver->send_control(handle, activation_packet, sizeof(activation_packet)); + hid_instance.os_driver->read(handle, instance->device_state, sizeof(instance->device_state)); + instance->online = true; + + RARCH_LOG("[gca]: init done\n"); + return instance; + + error: + RARCH_ERR("[gca]: init failed\n"); + if(instance) + free(instance); + return NULL; +} + +static void wiiu_gca_free(void *data) { + wiiu_gca_instance_t *instance = (wiiu_gca_instance_t *)data; + int i; + + if(instance) { + instance->online = false; + + for(i = 0; i < 4; i++) + unregister_pad(instance, i); + + free(instance); + } +} + +static void wiiu_gca_handle_packet(void *data, uint8_t *buffer, size_t size) +{ + wiiu_gca_instance_t *instance = (wiiu_gca_instance_t *)data; + if(!instance || !instance->online) + { + RARCH_WARN("[gca]: instance null or not ready yet.\n"); + return; + } + + if(size > sizeof(instance->device_state)) + { + RARCH_WARN("[gca]: packet size %d is too big for buffer of size %d\n", + size, sizeof(instance->device_state)); + return; + } + + memcpy(instance->device_state, buffer, size); + update_pad_state(instance); +} + +static void update_pad_state(wiiu_gca_instance_t *instance) +{ + int i, port; + unsigned char port_connected; + + if(!instance || !instance->online) + return; + + joypad_connection_t *pad; + /* process each pad */ + for(i = 1; i < 37; i += 9) + { + port = i / 9; + pad = instance->pads[port]; + + port_connected = instance->device_state[i]; + + if(port_connected > GCA_PORT_POWERED) + { + if(pad == NULL) + { + RARCH_LOG("[gca]: Gamepad at port %d connected.\n", port+1); + instance->pads[port] = hid_pad_register(instance, &wiiu_gca_pad_connection); + pad = instance->pads[port]; + if(pad == NULL) + { + RARCH_ERR("[gca]: Failed to register pad.\n"); + break; + } + } + + pad->iface->packet_handler(pad->data, &instance->device_state[i], 9); + } else { + if(pad != NULL) { + RARCH_LOG("[gca]: Gamepad at port %d disconnected.\n", port+1); + unregister_pad(instance, port); + } + } + } +} + +static void unregister_pad(wiiu_gca_instance_t *instance, int slot) +{ + if(!instance || slot < 0 || slot >= 4 || instance->pads[slot] == NULL) + return; + + joypad_connection_t *pad = instance->pads[slot]; + instance->pads[slot] = NULL; + + hid_pad_deregister(pad); +} + +static bool wiiu_gca_detect(uint16_t vendor_id, uint16_t product_id) { + return vendor_id == VID_NINTENDO && product_id == PID_NINTENDO_GCA; +} + +hid_device_t wiiu_gca_hid_device = { + wiiu_gca_init, + wiiu_gca_free, + wiiu_gca_handle_packet, + wiiu_gca_detect, + "Wii U Gamecube Adapter" +}; + +/** + * Pad connection interface implementation. This handles each individual + * GC controller (as opposed to the above that handles the GCA itself). + */ + +static void *wiiu_gca_pad_init(void *data, uint32_t slot, hid_driver_t *driver) +{ + gca_pad_t *pad = (gca_pad_t *)calloc(1, sizeof(gca_pad_t)); + + if(!pad) + return NULL; + + memset(pad, 0, sizeof(gca_pad_t)); + + pad->gca_handle = data; + pad->driver = driver; + pad->slot = slot; + + return pad; +} + +static void wiiu_gca_pad_deinit(void *data) +{ + gca_pad_t *pad = (gca_pad_t *)data; + + if(pad) + { + input_autoconfigure_disconnect(pad->slot, wiiu_gca_pad_connection.get_name(pad)); + free(pad); + } +} + +static void wiiu_gca_get_buttons(void *data, input_bits_t *state) +{ + gca_pad_t *pad = (gca_pad_t *)data; + if(pad) + { + BITS_COPY16_PTR(state, pad->buttons); + } else { + BIT256_CLEAR_ALL_PTR(state); + } +} + +static void update_buttons(gca_pad_t *pad) +{ + uint32_t i, pressed_keys; + + static const uint32_t button_mapping[12] = + { + RETRO_DEVICE_ID_JOYPAD_A, + RETRO_DEVICE_ID_JOYPAD_B, + RETRO_DEVICE_ID_JOYPAD_X, + RETRO_DEVICE_ID_JOYPAD_Y, + RETRO_DEVICE_ID_JOYPAD_LEFT, + RETRO_DEVICE_ID_JOYPAD_RIGHT, + RETRO_DEVICE_ID_JOYPAD_DOWN, + RETRO_DEVICE_ID_JOYPAD_UP, + RETRO_DEVICE_ID_JOYPAD_START, + RETRO_DEVICE_ID_JOYPAD_SELECT, + RETRO_DEVICE_ID_JOYPAD_R, + RETRO_DEVICE_ID_JOYPAD_L, + }; + + if(!pad) + return; + + pressed_keys = pad->data[1] | (pad->data[2] << 8); + pad->buttons = 0; + + for(i = 0; i < 12; i++) + pad->buttons |= (pressed_keys & (1 << i)) ? + (1 << button_mapping[i]) : 0; +} + +#if 0 +const char *axes[] = { + "left x", + "left y", + "right x", + "right y" +}; +#endif + +static void update_analog_state(gca_pad_t *pad) +{ + int pad_axis; + int16_t interpolated; + unsigned stick, axis; + + /* GameCube analog axis are 8-bit unsigned, where 128/128 is center. + * So, we subtract 128 to get a signed, 0-based value and then mulitply + * by 256 to get the 16-bit range RetroArch expects. */ + for(pad_axis = 0; pad_axis < 4; pad_axis++) + { + axis = pad_axis % 2 ? 0 : 1; + stick = pad_axis / 2; + interpolated = pad->data[3 + pad_axis]; + /* libretro requires "up" to be negative, so we invert the y axis */ + interpolated = (axis) ? + ((interpolated - 128) * 256) : + ((interpolated - 128) * -256); + + pad->analog_state[stick][axis] = interpolated; +#if 0 + RARCH_LOG("%s: %d\n", axes[pad_axis], interpolated); +#endif + } +} + + +/** + * The USB packet provides a 9-byte data packet for each pad. + * + * byte 0: connection status (0x14 = connected, 0x04 = disconnected) + * bytes 1-2: digital buttons + * bytes 3-4: left analog stick x/y + * bytes 5-6: right analog stick x/y + * bytes 7-8: L/R analog state (note that these have digital buttons too) + */ +static void wiiu_gca_packet_handler(void *data, uint8_t *packet, uint16_t size) +{ + gca_pad_t *pad = (gca_pad_t *)data; + uint32_t i, pressed_keys; + + if(!pad || !packet || size > sizeof(pad->data)) + return; + + memcpy(pad->data, packet, size); + update_buttons(pad); + update_analog_state(pad); +} + + + +static void wiiu_gca_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) +{ + (void)data; + (void)effect; + (void)strength; +} + +static int16_t wiiu_gca_get_axis(void *data, unsigned axis) +{ + axis_data axis_data; + + gca_pad_t *pad = (gca_pad_t *)data; + + gamepad_read_axis_data(axis, &axis_data); + + if(!pad || axis_data.axis >= 4) + return 0; + + return gamepad_get_axis_value(pad->analog_state, &axis_data); +} + +static const char *wiiu_gca_get_name(void *data) +{ + gca_pad_t *pad = (gca_pad_t *)data; + + return "GameCube Controller"; +} + +/** + * Button bitmask values: + * 0x0001 - A 0x0010 - left 0x0100 - Start/Pause + * 0x0002 - B 0x0020 - right 0x0200 - Z + * 0x0004 - X 0x0040 - down 0x0400 - R + * 0x0008 - Y 0x0080 - up 0x0800 - L + */ + +static bool wiiu_gca_button(void *data, uint16_t joykey) +{ + gca_pad_t *pad = (gca_pad_t *)data; + + if(!pad || joykey > 31) + return false; + + return pad->buttons & (1 << joykey); +} + +pad_connection_interface_t wiiu_gca_pad_connection = { + wiiu_gca_pad_init, + wiiu_gca_pad_deinit, + wiiu_gca_packet_handler, + wiiu_gca_set_rumble, + wiiu_gca_get_buttons, + wiiu_gca_get_axis, + wiiu_gca_get_name, + wiiu_gca_button +}; diff --git a/input/common/hid/hid_device_driver.c b/input/common/hid/hid_device_driver.c new file mode 100644 index 0000000000..ccab2dc569 --- /dev/null +++ b/input/common/hid/hid_device_driver.c @@ -0,0 +1,156 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "hid_device_driver.h" + +hid_driver_instance_t hid_instance = {0}; + +hid_device_t *hid_device_list[] = { + &wiiu_gca_hid_device, + &ds3_hid_device, +/* &ds4_hid_device, */ + NULL /* must be last entry in list */ +}; + +hid_device_t *hid_device_driver_lookup(uint16_t vendor_id, uint16_t product_id) { + int i = 0; + + for(i = 0; hid_device_list[i] != NULL; i++) { + if(hid_device_list[i]->detect(vendor_id, product_id)) + return hid_device_list[i]; + } + + return NULL; +} + +joypad_connection_t *hid_pad_register(void *pad_handle, pad_connection_interface_t *iface) +{ + int slot; + joypad_connection_t *result; + + if(!pad_handle) + return NULL; + + slot = pad_connection_find_vacant_pad(hid_instance.pad_list); + if(slot < 0) + { + RARCH_ERR("[hid]: failed to find a vacant pad.\n"); + return NULL; + } + + result = &(hid_instance.pad_list[slot]); + result->iface = iface; + result->data = iface->init(pad_handle, slot, hid_instance.os_driver); + result->connected = true; + input_pad_connect(slot, hid_instance.pad_driver); + + return result; +} + +void hid_pad_deregister(joypad_connection_t *pad) +{ + if(!pad) + return; + + if(pad->data) { + pad->iface->deinit(pad->data); + pad->data = NULL; + } + + pad->iface = NULL; + pad->connected = false; +} + +static bool init_pad_list(hid_driver_instance_t *instance, unsigned slots) +{ + if(!instance || slots > MAX_USERS) + return false; + + if(instance->pad_list) + return true; + + RARCH_LOG("[hid]: initializing pad list...\n"); + instance->pad_list = pad_connection_init(slots); + if(!instance->pad_list) + return false; + + instance->max_slot = slots; + + return true; +} + +/** + * Fill in instance with data from initialized hid subsystem. + * + * @argument instance the hid_driver_instance_t struct to fill in + * @argument hid_driver the HID driver to initialize + * @argument pad_driver the gamepad driver to handle HID pads detected by the HID driver. + * + * @returns true if init is successful, false otherwise. + */ +bool hid_init(hid_driver_instance_t *instance, + hid_driver_t *hid_driver, + input_device_driver_t *pad_driver, + unsigned slots) +{ + RARCH_LOG("[hid]: initializing instance with %d pad slots\n", slots); + if(!instance || !hid_driver || !pad_driver || slots > MAX_USERS) + return false; + + RARCH_LOG("[hid]: initializing HID subsystem driver...\n"); + instance->os_driver_data = hid_driver->init(); + if(!instance->os_driver_data) + return false; + + if(!init_pad_list(instance, slots)) + { + hid_driver->free(instance->os_driver_data); + instance->os_driver_data = NULL; + return false; + } + + instance->os_driver = hid_driver; + instance->pad_driver = pad_driver; + + RARCH_LOG("[hid]: instance initialization complete.\n"); + + return true; +} + +/** + * Tear down the HID system set up by hid_init() + * + * @argument instance the hid_driver_instance_t to tear down. + */ +void hid_deinit(hid_driver_instance_t *instance) +{ + if(!instance) + return; + + RARCH_LOG("[hid]: destroying instance\n"); + + if(instance->os_driver && instance->os_driver_data) + { + RARCH_LOG("[hid]: tearing down HID subsystem driver...\n"); + instance->os_driver->free(instance->os_driver_data); + } + + RARCH_LOG("[hid]: destroying pad data...\n"); + pad_connection_destroy(instance->pad_list); + + RARCH_LOG("[hid]: wiping instance data...\n"); + memset(instance, 0, sizeof(hid_driver_instance_t)); +} diff --git a/input/common/hid/hid_device_driver.h b/input/common/hid/hid_device_driver.h new file mode 100644 index 0000000000..8e764f0f78 --- /dev/null +++ b/input/common/hid/hid_device_driver.h @@ -0,0 +1,46 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef HID_DEVICE_DRIVER__H +#define HID_DEVICE_DRIVER__H + +#include "../../input_driver.h" +#include "../../connect/joypad_connection.h" +#include "../../include/hid_driver.h" +#include "../../include/gamepad.h" +#include "../../../verbosity.h" +#include "../../../tasks/tasks_internal.h" + +typedef struct hid_device { + void *(*init)(void *handle); + void (*free)(void *data); + void (*handle_packet)(void *data, uint8_t *buffer, size_t size); + bool (*detect)(uint16_t vid, uint16_t pid); + const char *name; +} hid_device_t; + +extern hid_device_t wiiu_gca_hid_device; +extern hid_device_t ds3_hid_device; +extern hid_device_t ds4_hid_device; +extern hid_driver_instance_t hid_instance; + +hid_device_t *hid_device_driver_lookup(uint16_t vendor_id, uint16_t product_id); +joypad_connection_t *hid_pad_register(void *pad_handle, pad_connection_interface_t *iface); +void hid_pad_deregister(joypad_connection_t *pad); +bool hid_init(hid_driver_instance_t *instance, hid_driver_t *hid_driver, input_device_driver_t *pad_driver, unsigned slots); +void hid_deinit(hid_driver_instance_t *instance); + +#endif /* HID_DEVICE_DRIVER__H */ diff --git a/input/common/input_common.c b/input/common/input_common.c new file mode 100644 index 0000000000..4f6e656363 --- /dev/null +++ b/input/common/input_common.c @@ -0,0 +1,78 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "../include/gamepad.h" + +enum pad_axes { + AXIS_LEFT_ANALOG_X, + AXIS_LEFT_ANALOG_Y, + AXIS_RIGHT_ANALOG_X, + AXIS_RIGHT_ANALOG_Y, + AXIS_INVALID +}; + +static int16_t clamp_axis(int16_t value, bool is_negative) +{ + if(is_negative && value > 0) + return 0; + if(!is_negative && value < 0) + return 0; + + return value; +} + +void gamepad_read_axis_data(uint32_t axis, axis_data *data) +{ + if(!data) + return; + + data->axis = AXIS_POS_GET(axis); + data->is_negative = false; + + if(data->axis >= AXIS_INVALID) + { + data->axis = AXIS_NEG_GET(axis); + data->is_negative = true; + } +} + +int16_t gamepad_get_axis_value(int16_t state[3][2], axis_data *data) +{ + int16_t value = 0; + + if(!data) + return 0; + + switch(data->axis) + { + case AXIS_LEFT_ANALOG_X: + value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X]; + break; + case AXIS_LEFT_ANALOG_Y: + value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y]; + break; + case AXIS_RIGHT_ANALOG_X: + value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X]; + break; + case AXIS_RIGHT_ANALOG_Y: + value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y]; + break; + } + + return clamp_axis(value, data->is_negative); +} + + diff --git a/input/connect/connect_nesusb.c b/input/connect/connect_nesusb.c index 43f1f2d51b..fc484ea88d 100644 --- a/input/connect/connect_nesusb.c +++ b/input/connect/connect_nesusb.c @@ -59,7 +59,7 @@ static void hidpad_nesusb_deinit(void *data) free(device); } -static void hidpad_nesusb_get_buttons(void *data, retro_bits_t* state) +static void hidpad_nesusb_get_buttons(void *data, input_bits_t* state) { struct hidpad_nesusb_data *device = (struct hidpad_nesusb_data*)data; if (device) diff --git a/input/connect/connect_ps2adapter.c b/input/connect/connect_ps2adapter.c index c805cb85e2..4ee0e5e6cb 100644 --- a/input/connect/connect_ps2adapter.c +++ b/input/connect/connect_ps2adapter.c @@ -59,9 +59,11 @@ static void hidpad_ps2adapter_deinit(void *data) free(device); } -static void hidpad_ps2adapter_get_buttons(void *data, retro_bits_t *state) +static void hidpad_ps2adapter_get_buttons(void *data, input_bits_t *state) { - struct hidpad_ps2adapter_data *device = (struct hidpad_ps2adapter_data*)data; + struct hidpad_ps2adapter_data *device = (struct hidpad_ps2adapter_data*) + data; + if (device) { BITS_COPY16_PTR(state, device->buttons); diff --git a/input/connect/connect_ps3.c b/input/connect/connect_ps3.c index 61269a9e88..52d0032ecd 100644 --- a/input/connect/connect_ps3.c +++ b/input/connect/connect_ps3.c @@ -21,10 +21,7 @@ #include #include "joypad_connection.h" #include "../input_defines.h" - -#ifdef WIIU -#include -#endif +#include "../common/hid/hid_device_driver.h" struct hidpad_ps3_data { @@ -134,7 +131,7 @@ static void hidpad_ps3_deinit(void *data) free(device); } -static void hidpad_ps3_get_buttons(void *data, retro_bits_t *state) +static void hidpad_ps3_get_buttons(void *data, input_bits_t *state) { struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data; if ( device ) diff --git a/input/connect/connect_ps4.c b/input/connect/connect_ps4.c index 0356a91537..f33844e6b1 100644 --- a/input/connect/connect_ps4.c +++ b/input/connect/connect_ps4.c @@ -25,6 +25,7 @@ #include "joypad_connection.h" #include "../input_defines.h" #include "../../driver.h" +#include "../common/hid/hid_device_driver.h" enum connect_ps4_dpad_states { @@ -185,7 +186,7 @@ static bool hidpad_ps4_check_dpad(struct ps4 *rpt, unsigned id) return false; } -static void hidpad_ps4_get_buttons(void *data, retro_bits_t* state) +static void hidpad_ps4_get_buttons(void *data, input_bits_t* state) { struct hidpad_ps4_data *device = (struct hidpad_ps4_data*)data; struct ps4 *rpt = device ? diff --git a/input/connect/connect_psxadapter.c b/input/connect/connect_psxadapter.c index 68f921b0b6..cbc6a402f9 100644 --- a/input/connect/connect_psxadapter.c +++ b/input/connect/connect_psxadapter.c @@ -59,9 +59,11 @@ static void hidpad_psxadapter_deinit(void *data) free(device); } -static void hidpad_psxadapter_get_buttons(void *data, retro_bits_t *state) +static void hidpad_psxadapter_get_buttons(void *data, input_bits_t *state) { - struct hidpad_psxadapter_data *device = (struct hidpad_psxadapter_data*)data; + struct hidpad_psxadapter_data *device = (struct hidpad_psxadapter_data*) + data; + if (device) { BITS_COPY16_PTR(state, device->buttons); diff --git a/input/connect/connect_snesusb.c b/input/connect/connect_snesusb.c index bdc9b16a05..314577d863 100644 --- a/input/connect/connect_snesusb.c +++ b/input/connect/connect_snesusb.c @@ -60,7 +60,7 @@ static void hidpad_snesusb_deinit(void *data) free(device); } -static void hidpad_snesusb_get_buttons(void *data, retro_bits_t *state) +static void hidpad_snesusb_get_buttons(void *data, input_bits_t *state) { struct hidpad_snesusb_data *device = (struct hidpad_snesusb_data*)data; if (device) diff --git a/input/connect/connect_wii.c b/input/connect/connect_wii.c index f02e1735be..2008be9ecc 100644 --- a/input/connect/connect_wii.c +++ b/input/connect/connect_wii.c @@ -26,6 +26,7 @@ #include "joypad_connection.h" #include "../input_defines.h" +#include "../common/hid/hid_device_driver.h" /* wiimote state flags*/ #define WIIMOTE_STATE_DEV_FOUND 0x0001 @@ -672,7 +673,7 @@ static int16_t hidpad_wii_get_axis(void *data, unsigned axis) return 0; } -static void hidpad_wii_get_buttons(void *data, retro_bits_t *state) +static void hidpad_wii_get_buttons(void *data, input_bits_t *state) { struct connect_wii_wiimote_t* device = (struct connect_wii_wiimote_t*)data; if ( device ) diff --git a/input/connect/connect_wiiugca.c b/input/connect/connect_wiiugca.c index 7e49969fd2..357e479b58 100644 --- a/input/connect/connect_wiiugca.c +++ b/input/connect/connect_wiiugca.c @@ -21,6 +21,7 @@ #include #include "joypad_connection.h" #include "../input_defines.h" +#include "../common/hid/hid_device_driver.h" struct hidpad_wiiugca_data { @@ -68,7 +69,7 @@ static void hidpad_wiiugca_deinit(void *data) free(device); } -static void hidpad_wiiugca_get_buttons(void *data, retro_bits_t *state) +static void hidpad_wiiugca_get_buttons(void *data, input_bits_t *state) { struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data; if (device) diff --git a/input/connect/connect_wiiupro.c b/input/connect/connect_wiiupro.c index 836f17856e..a6194fb922 100644 --- a/input/connect/connect_wiiupro.c +++ b/input/connect/connect_wiiupro.c @@ -23,6 +23,7 @@ #include "joypad_connection.h" #include "../input_defines.h" #include "../../driver.h" +#include "../common/hid/hid_device_driver.h" struct wiiupro_buttons { @@ -118,7 +119,7 @@ static void hidpad_wiiupro_deinit(void *data) free(device); } -static void hidpad_wiiupro_get_buttons(void *data, retro_bits_t *state) +static void hidpad_wiiupro_get_buttons(void *data, input_bits_t *state) { struct hidpad_wiiupro_data *device = (struct hidpad_wiiupro_data*)data; struct wiiupro *rpt = device ? diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 1c7c75353b..777ac5874d 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -228,7 +228,8 @@ void pad_connection_packet(joypad_connection_t *joyconn, uint32_t pad, joyconn->iface->packet_handler(joyconn->data, data, length); } -void pad_connection_get_buttons(joypad_connection_t *joyconn, unsigned pad, retro_bits_t* state) +void pad_connection_get_buttons(joypad_connection_t *joyconn, + unsigned pad, input_bits_t *state) { if (joyconn && joyconn->iface) joyconn->iface->get_buttons(joyconn->data, state); diff --git a/input/connect/joypad_connection.h b/input/connect/joypad_connection.h index ec78b3c4df..62a454609a 100644 --- a/input/connect/joypad_connection.h +++ b/input/connect/joypad_connection.h @@ -58,13 +58,12 @@ typedef struct pad_connection_interface void (*packet_handler)(void* device, uint8_t *packet, uint16_t size); void (*set_rumble)(void* device, enum retro_rumble_effect effect, uint16_t strength); - void (*get_buttons)(void *data, retro_bits_t *state); + void (*get_buttons)(void *data, input_bits_t *state); int16_t (*get_axis)(void *data, unsigned axis); const char* (*get_name)(void *data); + bool (*button)(void *data, uint16_t joykey); } pad_connection_interface_t; -typedef struct joypad_connection joypad_connection_t; - extern pad_connection_interface_t pad_connection_wii; extern pad_connection_interface_t pad_connection_wiiupro; extern pad_connection_interface_t pad_connection_ps3; @@ -90,7 +89,7 @@ void pad_connection_packet(joypad_connection_t *joyconn, uint32_t idx, uint8_t* data, uint32_t length); void pad_connection_get_buttons(joypad_connection_t *joyconn, - unsigned idx, retro_bits_t* state); + unsigned idx, input_bits_t* state); int16_t pad_connection_get_axis(joypad_connection_t *joyconn, unsigned idx, unsigned i); diff --git a/input/drivers/cocoa_input.c b/input/drivers/cocoa_input.c index da33ccef83..2cba64d44f 100644 --- a/input/drivers/cocoa_input.c +++ b/input/drivers/cocoa_input.c @@ -53,7 +53,7 @@ int32_t cocoa_input_find_any_key(void) } static int cocoa_input_find_any_button_ret(cocoa_input_data_t *apple, - retro_bits_t * state, unsigned port) + input_bits_t * state, unsigned port) { unsigned i; @@ -78,7 +78,7 @@ int32_t cocoa_input_find_any_button(uint32_t port) if (apple->joypad->get_buttons) { - retro_bits_t state; + input_bits_t state; apple->joypad->get_buttons(port,&state); ret = cocoa_input_find_any_button_ret(apple, &state, port); } @@ -93,7 +93,7 @@ int32_t cocoa_input_find_any_button(uint32_t port) if (apple->sec_joypad->get_buttons) { - retro_bits_t state; + input_bits_t state; apple->sec_joypad->poll(); apple->sec_joypad->get_buttons(port,&state); ret = cocoa_input_find_any_button_ret(apple, &state, port); diff --git a/input/drivers/wiiu_input.c b/input/drivers/wiiu_input.c index 5a188c1f21..ba00ed971a 100644 --- a/input/drivers/wiiu_input.c +++ b/input/drivers/wiiu_input.c @@ -33,7 +33,11 @@ #include "wiiu_dbg.h" +#ifdef WIIU_HID +#define MAX_PADS 16 +#else #define MAX_PADS 5 +#endif static uint8_t keyboardChannel = 0x00; static bool keyboardState[RETROK_LAST] = { 0 }; @@ -100,7 +104,7 @@ static int16_t wiiu_pointer_device_state(wiiu_input_t* wiiu, unsigned id) { case RETRO_DEVICE_ID_POINTER_PRESSED: { - retro_bits_t state; + input_bits_t state; wiiu->joypad->get_buttons(0, &state); return BIT256_GET(state, VPAD_BUTTON_TOUCH_BIT) ? 1 : 0; } diff --git a/input/drivers_hid/btstack_hid.c b/input/drivers_hid/btstack_hid.c index 1d277484aa..fb701e7505 100644 --- a/input/drivers_hid/btstack_hid.c +++ b/input/drivers_hid/btstack_hid.c @@ -1364,7 +1364,8 @@ static const char *btstack_hid_joypad_name(void *data, unsigned pad) return NULL; } -static void btstack_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_t *state) +static void btstack_hid_joypad_get_buttons(void *data, unsigned port, + input_bits_t *state) { btstack_hid_t *hid = (btstack_hid_t*)data; if (hid) @@ -1373,9 +1374,10 @@ static void btstack_hid_joypad_get_buttons(void *data, unsigned port, retro_bits BIT256_CLEAR_ALL_PTR(state); } -static bool btstack_hid_joypad_button(void *data, unsigned port, uint16_t joykey) +static bool btstack_hid_joypad_button(void *data, + unsigned port, uint16_t joykey) { - retro_bits_t buttons; + input_bits_t buttons; btstack_hid_joypad_get_buttons(data, port, &buttons); /* Check hat. */ diff --git a/input/drivers_hid/iohidmanager_hid.c b/input/drivers_hid/iohidmanager_hid.c index 9ad99ebe2f..8c1556c652 100644 --- a/input/drivers_hid/iohidmanager_hid.c +++ b/input/drivers_hid/iohidmanager_hid.c @@ -70,7 +70,7 @@ CFComparisonResult iohidmanager_sort_elements(const void *val1, const void *val2 if (page1 != page2) return (CFComparisonResult)(page1 > page2); - if(use1 != use2) + if (use1 != use2) return (CFComparisonResult)(use1 > use2); return (CFComparisonResult)(cookie1 > cookie2); @@ -78,9 +78,9 @@ CFComparisonResult iohidmanager_sort_elements(const void *val1, const void *val2 static bool iohidmanager_check_for_id(apple_input_rec_t *rec, uint32_t id) { - while(rec) + while (rec) { - if(rec->id == id) + if (rec->id == id) return true; rec = rec->next; } @@ -90,7 +90,7 @@ static bool iohidmanager_check_for_id(apple_input_rec_t *rec, uint32_t id) static void iohidmanager_append_record(apple_input_rec_t *rec, apple_input_rec_t *b) { apple_input_rec_t *tmp = rec; - while(tmp->next) + while (tmp->next) tmp = tmp->next; tmp->next = b; } @@ -110,12 +110,13 @@ static void iohidmanager_append_record(apple_input_rec_t *rec, apple_input_rec_t static void iohidmanager_append_record_ordered(apple_input_rec_t **p_rec, apple_input_rec_t *b) { apple_input_rec_t *tmp = *p_rec; - while(tmp && (tmp->id <= b->id)) { - p_rec = &tmp->next; - tmp = tmp->next; + while (tmp && (tmp->id <= b->id)) + { + p_rec = &tmp->next; + tmp = tmp->next; } - b->next = tmp; - *p_rec = b; + b->next = tmp; + *p_rec = b; } static bool iohidmanager_hid_joypad_query(void *data, unsigned pad) @@ -132,7 +133,8 @@ static const char *iohidmanager_hid_joypad_name(void *data, unsigned pad) return NULL; } -static void iohidmanager_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_t *state) +static void iohidmanager_hid_joypad_get_buttons(void *data, + unsigned port, input_bits_t *state) { iohidmanager_hid_t *hid = (iohidmanager_hid_t*)data; if (hid) @@ -144,7 +146,7 @@ static void iohidmanager_hid_joypad_get_buttons(void *data, unsigned port, retro static bool iohidmanager_hid_joypad_button(void *data, unsigned port, uint16_t joykey) { - retro_bits_t buttons; + input_bits_t buttons; iohidmanager_hid_t *hid = (iohidmanager_hid_t*)data; unsigned hat_dir = GET_HAT_DIR(joykey); @@ -154,7 +156,7 @@ static bool iohidmanager_hid_joypad_button(void *data, if (hat_dir) { unsigned h = GET_HAT(joykey); - if(h >= 1) + if (h >= 1) return false; switch(hat_dir) @@ -207,7 +209,7 @@ static int16_t iohidmanager_hid_joypad_axis(void *data, if (val >= 0) val = 0; } - else if(AXIS_POS_GET(joyaxis) < 6) + else if (AXIS_POS_GET(joyaxis) < 6) { val += hid->axes[port][AXIS_POS_GET(joyaxis)]; val += pad_connection_get_axis(&hid->slots[port], @@ -282,15 +284,15 @@ static void iohidmanager_hid_device_input_callback(void *data, IOReturn result, { tmp = adapter->hats; - while(tmp && tmp->cookie != (IOHIDElementCookie)cookie) + while (tmp && tmp->cookie != (IOHIDElementCookie)cookie) tmp = tmp->next; - if(tmp->cookie == (IOHIDElementCookie)cookie) + if (tmp->cookie == (IOHIDElementCookie)cookie) { CFIndex range = IOHIDElementGetLogicalMax(element) - IOHIDElementGetLogicalMin(element); CFIndex val = IOHIDValueGetIntegerValue(value); - if(range == 3) + if (range == 3) val *= 2; switch(val) @@ -347,12 +349,12 @@ static void iohidmanager_hid_device_input_callback(void *data, IOReturn result, default: tmp = adapter->axes; - while(tmp && tmp->cookie != (IOHIDElementCookie)cookie) + while (tmp && tmp->cookie != (IOHIDElementCookie)cookie) tmp = tmp->next; if (tmp) { - if(tmp->cookie == (IOHIDElementCookie)cookie) + if (tmp->cookie == (IOHIDElementCookie)cookie) { CFIndex min = IOHIDElementGetPhysicalMin(element); CFIndex state = IOHIDValueGetIntegerValue(value) - min; @@ -384,16 +386,17 @@ static void iohidmanager_hid_device_input_callback(void *data, IOReturn result, if (pushed_button) { - tmp = adapter->buttons; - uint8_t bit = 0; - while(tmp && tmp->cookie != (IOHIDElementCookie)cookie) + + tmp = adapter->buttons; + + while (tmp && tmp->cookie != (IOHIDElementCookie)cookie) { bit++; tmp = tmp->next; } - if(tmp && tmp->cookie == (IOHIDElementCookie)cookie) + if (tmp && tmp->cookie == (IOHIDElementCookie)cookie) { CFIndex state = IOHIDValueGetIntegerValue(value); if (state) @@ -425,19 +428,21 @@ static void iohidmanager_hid_device_remove(void *data, if (adapter) { apple_input_rec_t* tmp = NULL; - while(adapter->hats != NULL) + while (adapter->hats != NULL) { tmp = adapter->hats; adapter->hats = adapter->hats->next; free(tmp); } - while(adapter->axes != NULL) + + while (adapter->axes != NULL) { tmp = adapter->axes; adapter->axes = adapter->axes->next; free(tmp); } - while(adapter->buttons != NULL) + + while (adapter->buttons != NULL) { tmp = adapter->buttons; adapter->buttons = adapter->buttons->next; @@ -450,11 +455,11 @@ static void iohidmanager_hid_device_remove(void *data, static int32_t iohidmanager_hid_device_get_int_property( IOHIDDeviceRef device, CFStringRef key) { - int32_t value; CFNumberRef ref = (CFNumberRef)IOHIDDeviceGetProperty(device, key); if (ref && (CFGetTypeID(ref) == CFNumberGetTypeID())) { + int32_t value = 0; CFNumberGetValue((CFNumberRef)ref, kCFNumberIntType, &value); return value; } @@ -474,6 +479,12 @@ static uint16_t iohidmanager_hid_device_get_product_id(IOHIDDeviceRef device) CFSTR(kIOHIDProductIDKey)); } +static uint32_t iohidmanager_hid_device_get_location_id(IOHIDDeviceRef device) +{ + return iohidmanager_hid_device_get_int_property(device, + CFSTR(kIOHIDLocationIDKey)); +} + static void iohidmanager_hid_device_get_product_string( IOHIDDeviceRef device, char *buf, size_t len) { @@ -501,8 +512,8 @@ static void iohidmanager_hid_device_add_autodetect(unsigned idx, RARCH_LOG("Port %d: %s.\n", idx, device_name); } -static void iohidmanager_hid_device_add(void *data, IOReturn result, - void* sender, IOHIDDeviceRef device) +static void iohidmanager_hid_device_add(IOHIDDeviceRef device, iohidmanager_hid_t* hid) + { int i; IOReturn ret; @@ -516,8 +527,6 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result, apple_input_rec_t *tmp = NULL; apple_input_rec_t *tmpButtons = NULL; apple_input_rec_t *tmpAxes = NULL; - iohidmanager_hid_t *hid = (iohidmanager_hid_t*) - hid_driver_get_data(); struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*) calloc(1, sizeof(*adapter)); @@ -577,17 +586,18 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result, for (i = 0; i < count; i++) { + IOHIDElementType type; + uint32_t page, use, cookie; + int detected_button = 0; IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i); if (!element) continue; - IOHIDElementType type = IOHIDElementGetType(element); - uint32_t page = (uint32_t)IOHIDElementGetUsagePage(element); - uint32_t use = (uint32_t)IOHIDElementGetUsage(element); - uint32_t cookie = (uint32_t)IOHIDElementGetCookie(element); - - int detected_button = 0; + type = IOHIDElementGetType(element); + page = (uint32_t)IOHIDElementGetUsagePage(element); + use = (uint32_t)IOHIDElementGetUsage(element); + cookie = (uint32_t)IOHIDElementGetCookie(element); switch (page) { @@ -632,21 +642,21 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result, axis->cookie = (IOHIDElementCookie)cookie; axis->next = NULL; - if(iohidmanager_check_for_id(adapter->axes,i)) + if (iohidmanager_check_for_id(adapter->axes,i)) { /* axis ID already exists, save to tmp for appending later */ - if(tmpAxes) + if (tmpAxes) iohidmanager_append_record(tmpAxes, axis); else - tmpAxes = axis; + tmpAxes = axis; } else { found_axis[axis->id] = true; - if(adapter->axes) + if (adapter->axes) iohidmanager_append_record(adapter->axes, axis); else - adapter->axes = axis; + adapter->axes = axis; } } else @@ -683,16 +693,16 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result, btn->cookie = (IOHIDElementCookie)cookie; btn->next = NULL; - if(iohidmanager_check_for_id(adapter->buttons,btn->id)) + if (iohidmanager_check_for_id(adapter->buttons,btn->id)) { - if(tmpButtons) + if (tmpButtons) iohidmanager_append_record_ordered(&tmpButtons, btn); else tmpButtons = btn; } else { - if(adapter->buttons) + if (adapter->buttons) iohidmanager_append_record_ordered(&adapter->buttons, btn); else adapter->buttons = btn; @@ -703,13 +713,13 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result, /* take care of buttons/axes with duplicate 'use' values */ for (i = 0; i < 6; i++) { - if(found_axis[i] == false && tmpAxes) + if (found_axis[i] == false && tmpAxes) { apple_input_rec_t *next = tmpAxes->next; tmpAxes->id = i; tmpAxes->next = NULL; iohidmanager_append_record(adapter->axes, tmpAxes); - tmpAxes = next; + tmpAxes = next; } } @@ -717,11 +727,11 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result, if (tmp) { - while(tmp->next) + while (tmp->next) tmp = tmp->next; } - while(tmpButtons) + while (tmpButtons) { apple_input_rec_t *next = tmpButtons->next; @@ -742,34 +752,34 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result, error: { apple_input_rec_t *tmp = NULL; - while(adapter->hats != NULL) + while (adapter->hats != NULL) { - tmp = adapter->hats; - adapter->hats = adapter->hats->next; + tmp = adapter->hats; + adapter->hats = adapter->hats->next; free(tmp); } - while(adapter->axes != NULL) + while (adapter->axes != NULL) { - tmp = adapter->axes; - adapter->axes = adapter->axes->next; + tmp = adapter->axes; + adapter->axes = adapter->axes->next; free(tmp); } - while(adapter->buttons != NULL) + while (adapter->buttons != NULL) { tmp = adapter->buttons; adapter->buttons = adapter->buttons->next; free(tmp); } - while(tmpAxes != NULL) + while (tmpAxes != NULL) { - tmp = tmpAxes; - tmpAxes = tmpAxes->next; + tmp = tmpAxes; + tmpAxes = tmpAxes->next; free(tmp); } - while(tmpButtons != NULL) + while (tmpButtons != NULL) { - tmp = tmpButtons; - tmpButtons = tmpButtons->next; + tmp = tmpButtons; + tmpButtons = tmpButtons->next; free(tmp); } free(adapter); @@ -829,27 +839,81 @@ static int iohidmanager_hid_manager_free(iohidmanager_hid_t *hid) return 0; } + /* re order device by location id */ + typedef struct hid_list + { + IOHIDDeviceRef device; + uint32_t lid; + struct hid_list *next; + } hid_list_t; + static int iohidmanager_hid_manager_set_device_matching( iohidmanager_hid_t *hid) { - CFMutableArrayRef matcher = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); + unsigned i; + hid_list_t* devList = NULL; + CFSetRef set = IOHIDManagerCopyDevices(hid->ptr); + CFIndex num_devices = CFSetGetCount(set); + IOHIDDeviceRef *device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef)); - if (!matcher) - return -1; + CFSetGetValues(set, (const void **) device_array); + + for (i = 0; i < num_devices; i++) + { + IOHIDDeviceRef dev = device_array[i]; - iohidmanager_hid_append_matching_dictionary(matcher, - kHIDPage_GenericDesktop, - kHIDUsage_GD_Joystick); - iohidmanager_hid_append_matching_dictionary(matcher, - kHIDPage_GenericDesktop, - kHIDUsage_GD_GamePad); + /* filter gamepad/joystick devices */ + if ( IOHIDDeviceConformsTo(dev, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) + || IOHIDDeviceConformsTo(dev, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad) + ) + { + if (!devList) + { + devList = (hid_list_t *)malloc(sizeof(hid_list_t)); + devList->device = dev; + devList->lid = iohidmanager_hid_device_get_location_id(dev); + devList->next = NULL; + } + else + { + hid_list_t *ptr = NULL; + hid_list_t *new = (hid_list_t *)malloc(sizeof(hid_list_t)); + new->device = dev; + new->lid = iohidmanager_hid_device_get_location_id(dev); + new->next = NULL; - IOHIDManagerSetDeviceMatchingMultiple(hid->ptr, matcher); - IOHIDManagerRegisterDeviceMatchingCallback(hid->ptr, - iohidmanager_hid_device_add, 0); + ptr = devList; - CFRelease(matcher); + if ( new->lid < ptr->lid ) + { + new->next = ptr; + devList = new; + } + else + { + while ((ptr->lid < new->lid ) && ptr->next) + ptr = ptr->next; + + new->next = ptr->next; + ptr->next = new; + } + } + } + } + + { + /* register devices */ + hid_list_t * ptr = devList; + while (ptr) + { + iohidmanager_hid_device_add(ptr->device, hid); + ptr = ptr->next; + free(devList); + devList = ptr; + } + } + + free(device_array); return 0; } @@ -860,7 +924,8 @@ static void *iohidmanager_hid_init(void) calloc(1, sizeof(*hid_apple)); if (!hid_apple) - goto error; + return NULL; + hid_apple->slots = pad_connection_init(MAX_USERS); if (!hid_apple->slots) diff --git a/input/drivers_hid/libusb_hid.c b/input/drivers_hid/libusb_hid.c index 44580359fa..b7622b92c1 100644 --- a/input/drivers_hid/libusb_hid.c +++ b/input/drivers_hid/libusb_hid.c @@ -443,7 +443,8 @@ static const char *libusb_hid_joypad_name(void *data, unsigned pad) return NULL; } -static void libusb_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_t *state) +static void libusb_hid_joypad_get_buttons(void *data, unsigned port, + input_bits_t *state) { libusb_hid_t *hid = (libusb_hid_t*)data; if (hid) @@ -458,7 +459,7 @@ static void libusb_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_ static bool libusb_hid_joypad_button(void *data, unsigned port, uint16_t joykey) { - retro_bits_t buttons; + input_bits_t buttons; libusb_hid_joypad_get_buttons(data, port, &buttons); /* Check hat. */ diff --git a/input/drivers_hid/null_hid.c b/input/drivers_hid/null_hid.c index 70a34d4bf8..44d1cc397b 100644 --- a/input/drivers_hid/null_hid.c +++ b/input/drivers_hid/null_hid.c @@ -18,6 +18,7 @@ #include "../input_defines.h" #include "../input_driver.h" +#include "../include/hid_driver.h" typedef struct null_hid { @@ -38,7 +39,8 @@ static const char *null_hid_joypad_name(void *data, unsigned pad) return NULL; } -static void null_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_t *state) +static void null_hid_joypad_get_buttons(void *data, + unsigned port, input_bits_t *state) { (void)data; (void)port; diff --git a/input/drivers_hid/wiiusb_hid.c b/input/drivers_hid/wiiusb_hid.c index 397f0a0a64..9f4fea629a 100644 --- a/input/drivers_hid/wiiusb_hid.c +++ b/input/drivers_hid/wiiusb_hid.c @@ -478,7 +478,8 @@ static bool wiiusb_hid_joypad_query(void *data, unsigned pad) return pad < MAX_USERS; } -static void wiiusb_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_t *state) +static void wiiusb_hid_joypad_get_buttons(void *data, + unsigned port, input_bits_t *state) { wiiusb_hid_t *hid = (wiiusb_hid_t*)data; if (hid) @@ -489,9 +490,10 @@ static void wiiusb_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_ BIT256_CLEAR_ALL_PTR(state); } -static bool wiiusb_hid_joypad_button(void *data, unsigned port, uint16_t joykey) +static bool wiiusb_hid_joypad_button(void *data, + unsigned port, uint16_t joykey) { - retro_bits_t buttons; + input_bits_t buttons; wiiusb_hid_joypad_get_buttons(data, port, &buttons); diff --git a/input/drivers_joypad/ctr_joypad.c b/input/drivers_joypad/ctr_joypad.c index 711b88493d..1bfd559cd2 100644 --- a/input/drivers_joypad/ctr_joypad.c +++ b/input/drivers_joypad/ctr_joypad.c @@ -70,7 +70,7 @@ static bool ctr_joypad_button(unsigned port_num, uint16_t key) return (pad_state & (1 << key)); } -static void ctr_joypad_get_buttons(unsigned port_num, retro_bits_t *state) +static void ctr_joypad_get_buttons(unsigned port_num, input_bits_t *state) { if ( port_num < MAX_PADS ) { diff --git a/input/drivers_joypad/gx_joypad.c b/input/drivers_joypad/gx_joypad.c index 392cb602a9..1e4c0b9a4b 100644 --- a/input/drivers_joypad/gx_joypad.c +++ b/input/drivers_joypad/gx_joypad.c @@ -162,7 +162,7 @@ static bool gx_joypad_button(unsigned port, uint16_t key) return (pad_state[port] & (UINT64_C(1) << key)); } -static void gx_joypad_get_buttons(unsigned port, retro_bits_t *state) +static void gx_joypad_get_buttons(unsigned port, input_bits_t *state) { if (port < MAX_PADS) { diff --git a/input/drivers_joypad/hid_joypad.c b/input/drivers_joypad/hid_joypad.c index 203a272922..c35aff850d 100644 --- a/input/drivers_joypad/hid_joypad.c +++ b/input/drivers_joypad/hid_joypad.c @@ -55,7 +55,7 @@ static bool hid_joypad_button(unsigned port, uint16_t joykey) return false; } -static void hid_joypad_get_buttons(unsigned port, retro_bits_t *state) +static void hid_joypad_get_buttons(unsigned port, input_bits_t *state) { if (generic_hid && generic_hid->get_buttons) generic_hid->get_buttons((void*)hid_driver_get_data(), port, state); diff --git a/input/drivers_joypad/linuxraw_joypad.c b/input/drivers_joypad/linuxraw_joypad.c index 4d852f406b..b87a6e7bd0 100644 --- a/input/drivers_joypad/linuxraw_joypad.c +++ b/input/drivers_joypad/linuxraw_joypad.c @@ -326,9 +326,11 @@ static bool linuxraw_joypad_button(unsigned port, uint16_t joykey) return joykey < NUM_BUTTONS && BIT32_GET(pad->buttons, joykey); } -static void linuxraw_joypad_get_buttons(unsigned port, retro_bits_t *state) +static void linuxraw_joypad_get_buttons(unsigned port, input_bits_t *state) { - const struct linuxraw_joypad *pad = (const struct linuxraw_joypad*)&linuxraw_pads[port]; + const struct linuxraw_joypad *pad = (const struct linuxraw_joypad*) + &linuxraw_pads[port]; + if (pad) { BITS_COPY16_PTR(state, pad->buttons); diff --git a/input/drivers_joypad/mfi_joypad.m b/input/drivers_joypad/mfi_joypad.m index 94f56b2147..32f52e334c 100644 --- a/input/drivers_joypad/mfi_joypad.m +++ b/input/drivers_joypad/mfi_joypad.m @@ -221,7 +221,8 @@ static bool apple_gamecontroller_joypad_button(unsigned port, uint16_t joykey) return false; } -static void apple_gamecontroller_joypad_get_buttons(unsigned port, retro_bits_t *state) +static void apple_gamecontroller_joypad_get_buttons(unsigned port, + input_bits_t *state) { BITS_COPY16_PTR(state, mfi_buttons[port]); } diff --git a/input/drivers_joypad/null_joypad.c b/input/drivers_joypad/null_joypad.c index 058d01d5b3..d41198a8bf 100644 --- a/input/drivers_joypad/null_joypad.c +++ b/input/drivers_joypad/null_joypad.c @@ -37,7 +37,7 @@ static bool null_joypad_button(unsigned port_num, uint16_t joykey) return false; } -static void null_joypad_get_buttons(unsigned port_num, retro_bits_t *state) +static void null_joypad_get_buttons(unsigned port_num, input_bits_t *state) { BIT256_CLEAR_ALL_PTR(state); } diff --git a/input/drivers_joypad/parport_joypad.c b/input/drivers_joypad/parport_joypad.c index e236a36fc5..d392745acf 100644 --- a/input/drivers_joypad/parport_joypad.c +++ b/input/drivers_joypad/parport_joypad.c @@ -340,9 +340,11 @@ static bool parport_joypad_button(unsigned port, uint16_t joykey) return joykey < PARPORT_NUM_BUTTONS && BIT32_GET(pad->buttons, joykey); } -static void parport_joypad_get_buttons(unsigned port, retro_bits_t *state) +static void parport_joypad_get_buttons(unsigned port, input_bits_t *state) { - const struct parport_joypad *pad = (const struct parport_joypad*)&parport_pads[port]; + const struct parport_joypad *pad = (const struct parport_joypad*) + &parport_pads[port]; + if (pad) { BITS_COPY16_PTR(state, pad->buttons); diff --git a/input/drivers_joypad/ps3_joypad.c b/input/drivers_joypad/ps3_joypad.c index a85a23fcf9..0088f6d256 100644 --- a/input/drivers_joypad/ps3_joypad.c +++ b/input/drivers_joypad/ps3_joypad.c @@ -68,7 +68,7 @@ static bool ps3_joypad_button(unsigned port_num, uint16_t joykey) return pad_state[port_num] & (UINT64_C(1) << joykey); } -static void ps3_joypad_get_buttons(unsigned port_num, retro_bits_t *state) +static void ps3_joypad_get_buttons(unsigned port_num, input_bits_t *state) { if (port_num < MAX_PADS) { diff --git a/input/drivers_joypad/psp_joypad.c b/input/drivers_joypad/psp_joypad.c index d9cb4dd65a..309a8a0f3c 100644 --- a/input/drivers_joypad/psp_joypad.c +++ b/input/drivers_joypad/psp_joypad.c @@ -124,7 +124,7 @@ static bool psp_joypad_button(unsigned port_num, uint16_t key) return (pad_state[port_num] & (UINT64_C(1) << key)); } -static void psp_joypad_get_buttons(unsigned port_num, retro_bits_t *state) +static void psp_joypad_get_buttons(unsigned port_num, input_bits_t *state) { if (port_num < PSP_MAX_PADS) { diff --git a/input/drivers_joypad/rwebpad_joypad.c b/input/drivers_joypad/rwebpad_joypad.c index f061996e6e..4278afb757 100644 --- a/input/drivers_joypad/rwebpad_joypad.c +++ b/input/drivers_joypad/rwebpad_joypad.c @@ -130,12 +130,11 @@ static bool rwebpad_joypad_button(unsigned port_num, uint16_t joykey) return false; } -static void rwebpad_joypad_get_buttons(unsigned port_num, retro_bits_t *state) +static void rwebpad_joypad_get_buttons(unsigned port_num, input_bits_t *state) { EmscriptenGamepadEvent gamepad_state; - EMSCRIPTEN_RESULT r; - - r = emscripten_get_gamepad_status(port_num, &gamepad_state); + EMSCRIPTEN_RESULT r = emscripten_get_gamepad_status( + port_num, &gamepad_state); if (r == EMSCRIPTEN_RESULT_SUCCESS) { diff --git a/input/drivers_joypad/switch_joypad.c b/input/drivers_joypad/switch_joypad.c index 5a88d9c70b..eb18024ee4 100644 --- a/input/drivers_joypad/switch_joypad.c +++ b/input/drivers_joypad/switch_joypad.c @@ -60,7 +60,7 @@ static bool switch_joypad_button(unsigned port_num, uint16_t key) return (pad_state[port_num] & (1 << key)); } -static void switch_joypad_get_buttons(unsigned port_num, retro_bits_t *state) +static void switch_joypad_get_buttons(unsigned port_num, input_bits_t *state) { if(port_num < MAX_PADS) { diff --git a/input/drivers_joypad/udev_joypad.c b/input/drivers_joypad/udev_joypad.c index 9f79b19f7f..4475c62e5f 100644 --- a/input/drivers_joypad/udev_joypad.c +++ b/input/drivers_joypad/udev_joypad.c @@ -637,9 +637,11 @@ static bool udev_joypad_button(unsigned port, uint16_t joykey) return joykey < UDEV_NUM_BUTTONS && BIT64_GET(pad->buttons, joykey); } -static void udev_joypad_get_buttons(unsigned port, retro_bits_t *state) +static void udev_joypad_get_buttons(unsigned port, input_bits_t *state) { - const struct udev_joypad *pad = (const struct udev_joypad*)&udev_pads[port]; + const struct udev_joypad *pad = (const struct udev_joypad*) + &udev_pads[port]; + if (pad) { BITS_COPY16_PTR( state, pad->buttons ); diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index 4ae4a4863a..5728a90c6d 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -14,11 +14,13 @@ * If not, see . */ -#include +#include "../../wiiu/input/wiiu_input.h" #include "wiiu_dbg.h" static input_device_driver_t *pad_drivers[MAX_USERS]; +extern pad_connection_listener_t wiiu_pad_connection_listener; + static bool ready = false; @@ -26,69 +28,35 @@ static bool wiiu_joypad_init(void *data); static bool wiiu_joypad_query_pad(unsigned pad); static void wiiu_joypad_destroy(void); static bool wiiu_joypad_button(unsigned pad, uint16_t button); -static void wiiu_joypad_get_buttons(unsigned pad, retro_bits_t *state); +static void wiiu_joypad_get_buttons(unsigned pad, input_bits_t *state); static int16_t wiiu_joypad_axis(unsigned pad, uint32_t axis); static void wiiu_joypad_poll(void); static const char *wiiu_joypad_name(unsigned pad); -/** - * Translates a pad to its appropriate driver. - * Note that this is a helper for build_pad_map and shouldn't be - * used directly. - */ -static input_device_driver_t *get_driver_for_pad(unsigned pad) -{ - if(wpad_driver.query_pad(pad)) - return &wpad_driver; - if(kpad_driver.query_pad(pad)) - return &kpad_driver; - -#ifdef WIIU_HID - return &hidpad_driver; -#else - return NULL; -#endif -} - -/** - * Populates the pad_driver array. We do this once at init time so - * that lookups at runtime are constant time. - */ -static void build_pad_map(void) -{ - unsigned i; - - for(i = 0; i < MAX_USERS; i++) - { - pad_drivers[i] = get_driver_for_pad(i); - } -} - static bool wiiu_joypad_init(void* data) { - /* the sub-drivers have to init first, otherwise - * build_pad_map will fail (because all lookups will return false). */ - wpad_driver.init(data); - kpad_driver.init(data); + set_connection_listener(&wiiu_pad_connection_listener); + hid_instance.pad_list = pad_connection_init(MAX_USERS); + hid_instance.max_slot = MAX_USERS; + + wpad_driver.init(data); + kpad_driver.init(data); #ifdef WIIU_HID - hidpad_driver.init(data); + hidpad_driver.init(data); #endif - build_pad_map(); + ready = true; + (void)data; - ready = true; - (void)data; - - return true; + return true; } static bool wiiu_joypad_query_pad(unsigned pad) { -#ifdef WIIU_HID - return ready && pad < MAX_USERS; -#else - return ready && pad < 5; -#endif + return ready && + pad < MAX_USERS && + pad_drivers[pad] != NULL && + pad_drivers[pad]->query_pad(pad); } static void wiiu_joypad_destroy(void) @@ -110,7 +78,7 @@ static bool wiiu_joypad_button(unsigned pad, uint16_t key) return pad_drivers[pad]->button(pad, key); } -static void wiiu_joypad_get_buttons(unsigned pad, retro_bits_t *state) +static void wiiu_joypad_get_buttons(unsigned pad, input_bits_t *state) { if(!wiiu_joypad_query_pad(pad)) return; @@ -137,10 +105,17 @@ static void wiiu_joypad_poll(void) static const char* wiiu_joypad_name(unsigned pad) { - if(!wiiu_joypad_query_pad(pad)) - return "N/A"; + if(!wiiu_joypad_query_pad(pad)) + return "N/A"; - return pad_drivers[pad]->name(pad); + return pad_drivers[pad]->name(pad); +} + +static void wiiu_joypad_connection_listener(unsigned pad, + input_device_driver_t *driver) +{ + if(pad < MAX_USERS) + pad_drivers[pad] = driver; } input_device_driver_t wiiu_joypad = @@ -156,3 +131,8 @@ input_device_driver_t wiiu_joypad = wiiu_joypad_name, "wiiu", }; + +pad_connection_listener_t wiiu_pad_connection_listener = +{ + wiiu_joypad_connection_listener +}; diff --git a/input/include/gamepad.h b/input/include/gamepad.h new file mode 100644 index 0000000000..d895b55f25 --- /dev/null +++ b/input/include/gamepad.h @@ -0,0 +1,35 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2016-2017 - Andrés Suárez + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef GAMEPAD_H__ +#define GAMEPAD_H__ + +#include "../input_driver.h" + +struct pad_connection_listener_interface { + void (*connected)(unsigned port, input_device_driver_t *driver); +}; + +typedef struct _axis_data { + int32_t axis; + bool is_negative; +} axis_data; + +void gamepad_read_axis_data(uint32_t axis, axis_data *data); +int16_t gamepad_get_axis_value(int16_t state[3][2], axis_data *data); + +#endif /* GAMEPAD_H__ */ diff --git a/input/include/hid_driver.h b/input/include/hid_driver.h new file mode 100644 index 0000000000..02b6529f63 --- /dev/null +++ b/input/include/hid_driver.h @@ -0,0 +1,84 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2016-2017 - Andrés Suárez + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef HID_DRIVER_H__ +#define HID_DRIVER_H__ + +#include "../connect/joypad_connection.h" +#include "../input_driver.h" + +/* what is 1? */ +#define HID_REPORT_OUTPUT 2 +#define HID_REPORT_FEATURE 3 +/* are there more? */ + +/* + * This is the interface for the HID subsystem. + * + * The handle parameter is the pointer returned by init() and stores the implementation + * state data for the HID driver. + */ + +struct hid_driver +{ + void *(*init)(void); + bool (*query_pad)(void *handle, unsigned pad); + void (*free)(const void *handle); + bool (*button)(void *handle, unsigned pad, uint16_t button); + void (*get_buttons)(void *handle, unsigned pad, input_bits_t *state); + int16_t (*axis)(void *handle, unsigned pad, uint32_t axis); + void (*poll)(void *handle); + bool (*set_rumble)(void *handle, unsigned pad, enum retro_rumble_effect effect, uint16_t); + const char *(*name)(void *handle, unsigned pad); + const char *ident; + void (*send_control)(void *handle, uint8_t *buf, size_t size); + int32_t (*set_report)(void *handle, uint8_t, uint8_t, void *data, uint32_t size); + int32_t (*set_idle)(void *handle, uint8_t amount); + int32_t (*set_protocol)(void *handle, uint8_t protocol); + int32_t (*read)(void *handle, void *buf, size_t size); +}; + +#define HID_GET_BUTTONS(pad, state) hid_instance.os_driver->get_buttons( \ + hid_instance.os_driver_data, pad, state) +#define HID_BUTTON(pad, key) hid_instance.os_driver->button( \ + hid_instance.os_driver_data, pad, key) +#define HID_AXIS(pad, axis) hid_instance.os_driver->axis( \ + hid_instance.os_driver_data, pad, axis) +#define HID_PAD_NAME(pad) \ + hid_instance.os_driver->name(hid_instance.os_driver_data, pad) +#define HID_SET_PROTOCOL(pad, protocol) \ + hid_instance.os_driver->set_protocol(pad, protocol) +#define HID_SET_REPORT(pad, rpttype, rptid, data, len) \ + hid_instance.os_driver->set_report(pad, rpttype, rptid, data, len) +#define HID_SEND_CONTROL(pad, data, len) \ + hid_instance.os_driver->send_control(pad, data, len) +#define HID_POLL() hid_instance.os_driver->poll( \ + hid_instance.os_driver_data) +#define HID_MAX_SLOT() hid_instance.max_slot +#define HID_PAD_CONNECTION_PTR(slot) &(hid_instance.pad_list[(slot)]) + + + +struct hid_driver_instance { + hid_driver_t *os_driver; + void *os_driver_data; + input_device_driver_t *pad_driver; + joypad_connection_t *pad_list; + unsigned max_slot; +}; + +#endif /* HID_DRIVER_H__ */ diff --git a/input/include/hid_types.h b/input/include/hid_types.h new file mode 100644 index 0000000000..28734e9dd8 --- /dev/null +++ b/input/include/hid_types.h @@ -0,0 +1,24 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2016-2017 - Andrés Suárez + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef HID_TYPES_H__ +#define HID_TYPES_H__ + +typedef struct hid_driver hid_driver_t; +typedef struct hid_driver_instance hid_driver_instance_t; + +#endif /* HID_TYPES_H__ */ diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index 0e76b04f4e..db3443cd45 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -29,7 +29,7 @@ #endif #ifdef WIIU -#include +#include #endif #define DECL_BTN(btn, bind) "input_" #btn "_btn = " #bind "\n" @@ -228,6 +228,56 @@ DECL_AXIS(r_y_minus, +3) #ifdef WIIU +#define WIIUINPUT_GAMECUBE_DEFAULT_BINDS \ +DECL_BTN_EX(a, 8, "A") \ +DECL_BTN_EX(b, 0, "B") \ +DECL_BTN_EX(x, 9, "X") \ +DECL_BTN_EX(y, 1, "Y") \ +DECL_BTN_EX(left, 6, "D-Pad Left") \ +DECL_BTN_EX(right, 7, "D-Pad Right") \ +DECL_BTN_EX(down, 5, "D-Pad Down") \ +DECL_BTN_EX(up, 4, "D-Pad Up") \ +DECL_BTN_EX(start, 3, "Start/Pause") \ +DECL_BTN_EX(select, 2, "Z") \ +DECL_BTN_EX(r, 10, "R Trigger") \ +DECL_BTN_EX(l, 11, "L Trigger") \ +DECL_AXIS_EX(l_x_plus, +1, "Analog right") \ +DECL_AXIS_EX(l_x_minus, -1, "Analog left") \ +DECL_AXIS_EX(l_y_plus, +0, "Analog up") \ +DECL_AXIS_EX(l_y_minus, -0, "Analog down") \ +DECL_AXIS_EX(r_x_plus, +3, "C-stick right") \ +DECL_AXIS_EX(r_x_minus, -3, "C-stick left") \ +DECL_AXIS_EX(r_y_plus, +2, "C-stick up") \ +DECL_AXIS_EX(r_y_minus, -2, "C-stick down") + +#define WIIUINPUT_DS3_DEFAULT_BINDS \ +DECL_BTN_EX(menu_toggle, 16, "Playstation") \ +DECL_BTN_EX(select, 2, "Select") \ +DECL_BTN_EX(start, 3, "Start") \ +DECL_BTN_EX(a, 8, "Circle") \ +DECL_BTN_EX(y, 1, "Triangle") \ +DECL_BTN_EX(b, 0, "Cross") \ +DECL_BTN_EX(x, 9, "Square") \ +DECL_BTN_EX(r, 11, "R1") \ +DECL_BTN_EX(l, 10, "L1") \ +DECL_BTN_EX(r2, 13, "R2") \ +DECL_BTN_EX(l2, 12, "L2") \ +DECL_BTN_EX(up, 4, "D-Pad Up") \ +DECL_BTN_EX(down, 5, "D-Pad Down") \ +DECL_BTN_EX(left, 6, "D-Pad left") \ +DECL_BTN_EX(right, 7, "D-Pad Right") \ +DECL_BTN_EX(r3, 15, "R3") \ +DECL_BTN_EX(l3, 14, "L3") \ +DECL_AXIS_EX(l_x_plus, +1, "L Analog right") \ +DECL_AXIS_EX(l_x_minus, -1, "L Analog left") \ +DECL_AXIS_EX(l_y_plus, +0, "L Analog up") \ +DECL_AXIS_EX(l_y_minus, -0, "L Analog down") \ +DECL_AXIS_EX(r_x_plus, +3, "R Analog right") \ +DECL_AXIS_EX(r_x_minus, -3, "R Analog left") \ +DECL_AXIS_EX(r_y_plus, +2, "R Analog up") \ +DECL_AXIS_EX(r_y_minus, -2, "R Analog down") + + #define WIIUINPUT_GAMEPAD_DEFAULT_BINDS \ DECL_BTN_EX(menu_toggle, 1, "Home") \ DECL_BTN_EX(select, 2, "-") \ @@ -612,6 +662,8 @@ const char* const input_builtin_autoconfs[] = DECL_AUTOCONF_DEVICE(PAD_NAME_NUNCHUK, "wiiu", WIIUINPUT_NUNCHUK_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS), + DECL_AUTOCONF_DEVICE("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS), + DECL_AUTOCONF_DEVICE("Sony DualShock 3", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS), #endif #ifdef __CELLOS_LV2__ DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS), diff --git a/input/input_defines.h b/input/input_defines.h index 91f14d2766..12e2be7e97 100644 --- a/input/input_defines.h +++ b/input/input_defines.h @@ -28,11 +28,15 @@ RETRO_BEGIN_DECLS #define MAX_INPUT_DEVICES 16 +#define RARCH_MAX_KEYS 136 + #define RARCH_FIRST_CUSTOM_BIND 16 #define RARCH_FIRST_LIGHTGUN_BIND RARCH_ANALOG_BIND_LIST_END #define RARCH_FIRST_MISC_CUSTOM_BIND RARCH_LIGHTGUN_BIND_LIST_END #define RARCH_FIRST_META_KEY RARCH_CUSTOM_BIND_LIST_END +#define RARCH_UNMAPPED 1024 + /* RetroArch specific bind IDs. */ enum { diff --git a/input/input_driver.c b/input/input_driver.c index 14ed1c17a9..742b34b1b9 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -34,9 +34,7 @@ #include "input_remote.h" #endif -#ifdef HAVE_KEYMAPPER #include "input_mapper.h" -#endif #include "input_driver.h" #include "input_keymaps.h" @@ -60,6 +58,22 @@ #include "../verbosity.h" #include "../tasks/tasks_internal.h" #include "../command.h" +#include "include/gamepad.h" + +static pad_connection_listener_t *pad_connection_listener = NULL; + +void set_connection_listener(pad_connection_listener_t *listener) +{ + pad_connection_listener = listener; +} + +void fire_connection_listener(unsigned port, input_device_driver_t *driver) +{ + if(!pad_connection_listener) + return; + + pad_connection_listener->connected(port, driver); +} static const input_driver_t *input_drivers[] = { #ifdef __CELLOS_LV2__ @@ -377,9 +391,7 @@ static command_t *input_driver_command = NULL; #ifdef HAVE_NETWORKGAMEPAD static input_remote_t *input_driver_remote = NULL; #endif -#ifdef HAVE_KEYMAPPER static input_mapper_t *input_driver_mapper = NULL; -#endif static const input_driver_t *current_input = NULL; static void *current_input_data = NULL; static bool input_driver_block_hotkey = false; @@ -579,6 +591,8 @@ void input_poll(void) if (input_driver_block_libretro_input) return; + + for (i = 0; i < max_users; i++) { if (libretro_input_binds[i][RARCH_TURBO_ENABLE].valid) @@ -603,6 +617,9 @@ void input_poll(void) input_driver_axis_threshold); #endif + if (settings->bools.input_remap_binds_enable && input_driver_mapper) + input_mapper_poll(input_driver_mapper); + #ifdef HAVE_COMMAND if (input_driver_command) command_poll(input_driver_command); @@ -612,11 +629,6 @@ void input_poll(void) if (input_driver_remote) input_remote_poll(input_driver_remote, max_users); #endif - -#ifdef HAVE_KEYMAPPER - if (input_driver_mapper) - input_mapper_poll(input_driver_mapper); -#endif } /** @@ -634,7 +646,11 @@ void input_poll(void) int16_t input_state(unsigned port, unsigned device, unsigned idx, unsigned id) { - int16_t res = 0; + int16_t res = 0; + + /* used to reset input state of a button when the gamepad mapper + is in action for that button*/ + bool reset_state = false; device &= RETRO_DEVICE_MASK; @@ -657,17 +673,17 @@ int16_t input_state(unsigned port, unsigned device, switch (device) { case RETRO_DEVICE_JOYPAD: - if (id < RARCH_FIRST_CUSTOM_BIND) - id = settings->uints.input_remap_ids[port][id]; + if (id != settings->uints.input_remap_ids[port][id]) + reset_state = true; break; case RETRO_DEVICE_ANALOG: if (idx < 2 && id < 2) { - unsigned new_id = RARCH_FIRST_CUSTOM_BIND + (idx * 2 + id); - - new_id = settings->uints.input_remap_ids[port][new_id]; - idx = (new_id & 2) >> 1; - id = new_id & 1; + unsigned offset = RARCH_FIRST_CUSTOM_BIND + (idx * 4) + (id * 2); + if (settings->uints.input_remap_ids[port][offset] != offset) + reset_state = true; + if (settings->uints.input_remap_ids[port][offset+1] != (offset+1)) + reset_state = true; } break; } @@ -680,16 +696,22 @@ int16_t input_state(unsigned port, unsigned device, if (bind_valid || device == RETRO_DEVICE_KEYBOARD) { rarch_joypad_info_t joypad_info; - joypad_info.axis_threshold = input_driver_axis_threshold; joypad_info.joy_idx = settings->uints.input_joypad_map[port]; joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx]; - res = current_input->input_state( - current_input_data, joypad_info, libretro_input_binds, port, device, idx, id); + if (!reset_state) + res = current_input->input_state( + current_input_data, joypad_info, libretro_input_binds, port, device, idx, id); + else + res = 0; } } + if (settings->bools.input_remap_binds_enable && input_driver_mapper) + input_mapper_state(input_driver_mapper, + &res, port, device, idx, id); + #ifdef HAVE_OVERLAY if (overlay_ptr) input_state_overlay(overlay_ptr, &res, port, device, idx, id); @@ -700,12 +722,6 @@ int16_t input_state(unsigned port, unsigned device, input_remote_state(&res, port, device, idx, id); #endif -#ifdef HAVE_KEYMAPPER - if (input_driver_mapper) - input_mapper_state(input_driver_mapper, - &res, port, device, idx, id); -#endif - /* Don't allow turbo for D-pad. */ if (device == RETRO_DEVICE_JOYPAD && (id < RETRO_DEVICE_ID_JOYPAD_UP || id > RETRO_DEVICE_ID_JOYPAD_RIGHT)) @@ -805,7 +821,7 @@ void state_tracker_update_input(uint16_t *input1, uint16_t *input2) } static INLINE bool input_keys_pressed_iterate(unsigned i, - retro_bits_t* p_new_state) + input_bits_t* p_new_state) { if ((i >= RARCH_FIRST_META_KEY) && BIT64_GET(lifecycle_state, i) @@ -850,14 +866,12 @@ static INLINE bool input_keys_pressed_iterate(unsigned i, * * Returns: Input sample containing a mask of all pressed keys. */ -void input_menu_keys_pressed(void *data, retro_bits_t* p_new_state) +void input_menu_keys_pressed(void *data, input_bits_t *p_new_state) { unsigned i, port; rarch_joypad_info_t joypad_info; const struct retro_keybind *binds[MAX_USERS] = {NULL}; settings_t *settings = (settings_t*)data; - const struct retro_keybind *binds_norm = NULL; - const struct retro_keybind *binds_auto = NULL; uint8_t max_users = (uint8_t)input_driver_max_users; uint8_t port_max = settings->bools.input_all_users_control_menu @@ -866,8 +880,6 @@ void input_menu_keys_pressed(void *data, retro_bits_t* p_new_state) joypad_info.joy_idx = 0; joypad_info.auto_binds = NULL; - BIT256_CLEAR_ALL_PTR(p_new_state); - input_driver_block_libretro_input = false; input_driver_block_hotkey = false; @@ -885,8 +897,8 @@ void input_menu_keys_pressed(void *data, retro_bits_t* p_new_state) for (port = 0; port < port_max; port++) { - binds_norm = &input_config_binds[port][RARCH_ENABLE_HOTKEY]; - binds_auto = &input_autoconf_binds[port][RARCH_ENABLE_HOTKEY]; + const struct retro_keybind *binds_norm = &input_config_binds[port][RARCH_ENABLE_HOTKEY]; + const struct retro_keybind *binds_auto = &input_autoconf_binds[port][RARCH_ENABLE_HOTKEY]; if (check_input_driver_block_hotkey(binds_norm, binds_auto)) { @@ -972,7 +984,10 @@ void input_menu_keys_pressed(void *data, retro_bits_t* p_new_state) } } - if (bit_pressed || input_keys_pressed_iterate(i, p_new_state)) + if (!bit_pressed) + bit_pressed = input_keys_pressed_iterate(i, p_new_state); + + if (bit_pressed) { BIT256_SET_PTR(p_new_state, i); } @@ -1055,7 +1070,7 @@ int16_t input_driver_input_state( * * Returns: Input sample containing a mask of all pressed keys. */ -void input_keys_pressed(void *data, retro_bits_t* p_new_state) +void input_keys_pressed(void *data, input_bits_t *p_new_state) { unsigned i; rarch_joypad_info_t joypad_info; @@ -1064,13 +1079,6 @@ void input_keys_pressed(void *data, retro_bits_t* p_new_state) const struct retro_keybind *binds_auto = &input_autoconf_binds[0][RARCH_ENABLE_HOTKEY]; const struct retro_keybind *binds_norm = &binds[RARCH_ENABLE_HOTKEY]; - const struct retro_keybind *focus_binds_auto = &input_autoconf_binds[0][RARCH_GAME_FOCUS_TOGGLE]; - const struct retro_keybind *focus_normal = &binds[RARCH_GAME_FOCUS_TOGGLE]; - const struct retro_keybind *enable_hotkey = &input_config_binds[0][RARCH_ENABLE_HOTKEY]; - bool game_focus_toggle_valid = false; - - BIT256_CLEAR_ALL_PTR(p_new_state); - joypad_info.joy_idx = settings->uints.input_joypad_map[0]; joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx]; joypad_info.axis_threshold = input_driver_axis_threshold; @@ -1084,7 +1092,10 @@ void input_keys_pressed(void *data, retro_bits_t* p_new_state) if (check_input_driver_block_hotkey(binds_norm, binds_auto)) { - if ( enable_hotkey->valid + const struct retro_keybind *enable_hotkey = + &input_config_binds[0][RARCH_ENABLE_HOTKEY]; + + if ( enable_hotkey && enable_hotkey->valid && current_input->input_state( current_input_data, joypad_info, &binds, 0, RETRO_DEVICE_JOYPAD, 0, RARCH_ENABLE_HOTKEY)) @@ -1093,16 +1104,22 @@ void input_keys_pressed(void *data, retro_bits_t* p_new_state) input_driver_block_hotkey = true; } - game_focus_toggle_valid = binds[RARCH_GAME_FOCUS_TOGGLE].valid; - - /* Allows rarch_focus_toggle hotkey to still work - * even though every hotkey is blocked */ - if (check_input_driver_block_hotkey( - focus_normal, focus_binds_auto) && game_focus_toggle_valid) + if (binds[RARCH_GAME_FOCUS_TOGGLE].valid) { - if (current_input->input_state(current_input_data, joypad_info, &binds, 0, - RETRO_DEVICE_JOYPAD, 0, RARCH_GAME_FOCUS_TOGGLE)) - input_driver_block_hotkey = false; + const struct retro_keybind *focus_binds_auto = + &input_autoconf_binds[0][RARCH_GAME_FOCUS_TOGGLE]; + const struct retro_keybind *focus_normal = + &binds[RARCH_GAME_FOCUS_TOGGLE]; + + /* Allows rarch_focus_toggle hotkey to still work + * even though every hotkey is blocked */ + if (check_input_driver_block_hotkey( + focus_normal, focus_binds_auto)) + { + if (current_input->input_state(current_input_data, joypad_info, &binds, 0, + RETRO_DEVICE_JOYPAD, 0, RARCH_GAME_FOCUS_TOGGLE)) + input_driver_block_hotkey = false; + } } for (i = 0; i < RARCH_BIND_LIST_END; i++) @@ -1117,14 +1134,55 @@ void input_keys_pressed(void *data, retro_bits_t* p_new_state) 0, RETRO_DEVICE_JOYPAD, 0, i) ) bit_pressed = true; + else if (input_keys_pressed_iterate(i, p_new_state)) + bit_pressed = true; - if (bit_pressed || input_keys_pressed_iterate(i, p_new_state)) + if (bit_pressed) { BIT256_SET_PTR(p_new_state, i); } } } +void input_get_state_for_port(void *data, unsigned port, input_bits_t *p_new_state) +{ + unsigned i, j; + rarch_joypad_info_t joypad_info; + settings_t *settings = (settings_t*)data; + const input_device_driver_t *joypad_driver = input_driver_get_joypad_driver(); + + joypad_info.joy_idx = settings->uints.input_joypad_map[port]; + joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx]; + joypad_info.axis_threshold = input_driver_axis_threshold; + + for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++) + { + bool bit_pressed = false; + + if (input_driver_input_state(joypad_info, libretro_input_binds, + port, RETRO_DEVICE_JOYPAD, 0, i) != 0) + bit_pressed = true; + + if (bit_pressed) + BIT256_SET_PTR(p_new_state, i); + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + { + unsigned offset = 0 + (i * 4) + (j * 2); + int16_t val = input_joypad_analog(joypad_driver, + joypad_info, port, i, j, libretro_input_binds[port]); + + if (val >= 0) + p_new_state->analogs[offset] = val; + else + p_new_state->analogs[offset+1] = val; + } + } +} + void *input_driver_get_data(void) { return current_input_data; @@ -1343,11 +1401,9 @@ void input_driver_deinit_remote(void) void input_driver_deinit_mapper(void) { -#ifdef HAVE_KEYMAPPER if (input_driver_mapper) input_mapper_free(input_driver_mapper); input_driver_mapper = NULL; -#endif } bool input_driver_init_remote(void) @@ -1372,20 +1428,17 @@ bool input_driver_init_remote(void) bool input_driver_init_mapper(void) { -#ifdef HAVE_KEYMAPPER settings_t *settings = config_get_ptr(); - if (!settings->bools.keymapper_enable) + if (!settings->bools.input_remap_binds_enable) return false; - input_driver_mapper = input_mapper_new( - settings->uints.keymapper_port); + input_driver_mapper = input_mapper_new(); if (input_driver_mapper) return true; RARCH_ERR("Failed to initialize input mapper.\n"); -#endif return false; } @@ -1782,6 +1835,21 @@ bool input_mouse_button_raw(unsigned port, unsigned id) return false; } +void input_pad_connect(unsigned port, input_device_driver_t *driver) +{ + if(port >= MAX_USERS || !driver) + { + RARCH_ERR("[input]: input_pad_connect: bad parameters\n"); + return; + } + + fire_connection_listener(port, driver); + + if(!input_autoconfigure_connect(driver->name(port), NULL, driver->ident, + port, 0, 0)) + input_config_set_device_name(port, driver->name(port)); +} + /** * input_conv_analog_id_to_bind_id: * @idx : Analog key index. @@ -2536,7 +2604,7 @@ static void input_config_get_bind_string_joykey( { if (bind->joykey_label && !string_is_empty(bind->joykey_label) && label_show) - snprintf(buf, size, "%s %s ", prefix, bind->joykey_label); + snprintf(buf, size, "%s %s (hat)", prefix, bind->joykey_label); else { const char *dir = "?"; diff --git a/input/input_driver.h b/input/input_driver.h index 2ef47c7d24..f47e8830eb 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -22,6 +22,8 @@ #include #include +#include "input_types.h" + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -35,16 +37,12 @@ #include "input_defines.h" #include "../msg_hash.h" +#include "include/hid_types.h" +#include "include/hid_driver.h" +#include "include/gamepad.h" RETRO_BEGIN_DECLS -typedef struct rarch_joypad_driver input_device_driver_t; - -typedef struct hid_driver hid_driver_t; - -/* Keyboard line reader. Handles textual input in a direct fashion. */ -typedef struct input_keyboard_line input_keyboard_line_t; - enum input_device_type { INPUT_DEVICE_TYPE_NONE = 0, @@ -121,14 +119,14 @@ struct retro_keybind char *joyaxis_label; }; -typedef struct rarch_joypad_info +struct rarch_joypad_info { uint16_t joy_idx; const struct retro_keybind *auto_binds; float axis_threshold; -} rarch_joypad_info_t; +}; -typedef struct input_driver +struct input_driver { /* Inits input driver. */ @@ -164,7 +162,7 @@ typedef struct input_driver const input_device_driver_t *(*get_sec_joypad_driver)(void *data); bool (*keyboard_mapping_is_blocked)(void *data); void (*keyboard_mapping_set_block)(void *data, bool value); -} input_driver_t; +}; struct rarch_joypad_driver { @@ -172,7 +170,7 @@ struct rarch_joypad_driver bool (*query_pad)(unsigned); void (*destroy)(void); bool (*button)(unsigned, uint16_t); - void (*get_buttons)(unsigned, retro_bits_t *); + void (*get_buttons)(unsigned, input_bits_t *); int16_t (*axis)(unsigned, uint32_t); void (*poll)(void); bool (*set_rumble)(unsigned, enum retro_rumble_effect, uint16_t); @@ -181,25 +179,6 @@ struct rarch_joypad_driver const char *ident; }; -struct hid_driver -{ - void *(*init)(void); - bool (*query_pad)(void *, unsigned); - void (*free)(const void *); - bool (*button)(void *, unsigned, uint16_t); - void (*get_buttons)(void *, unsigned, retro_bits_t *); - int16_t (*axis)(void *, unsigned, uint32_t); - void (*poll)(void *); - bool (*set_rumble)(void *, unsigned, enum retro_rumble_effect, uint16_t); - const char *(*name)(void *, unsigned); - const char *ident; - void (*send_control)(void *data, uint8_t *buf, size_t size); - int32_t (*set_report)(void *, uint8_t, uint8_t, void *, uint32_t); - int32_t (*set_idle)(void *, uint8_t); - int32_t (*set_protocol)(void *, uint8_t); - -}; - /** * input_driver_find_handle: * @index : index of driver to get handle to. @@ -335,14 +314,16 @@ void input_poll(void); int16_t input_state(unsigned port, unsigned device, unsigned idx, unsigned id); -void input_keys_pressed(void *data, retro_bits_t* new_state); +void input_keys_pressed(void *data, input_bits_t* new_state); #ifdef HAVE_MENU -void input_menu_keys_pressed(void *data, retro_bits_t* new_state); +void input_menu_keys_pressed(void *data, input_bits_t* new_state); #endif void *input_driver_get_data(void); +void input_get_state_for_port(void *data, unsigned port, input_bits_t *p_new_state); + const input_driver_t *input_get_ptr(void); void *input_get_data(void); @@ -591,6 +572,15 @@ bool input_joypad_button_raw(const input_device_driver_t *driver, bool input_joypad_hat_raw(const input_device_driver_t *driver, unsigned joypad, unsigned hat_dir, unsigned hat); +/** + * input_pad_connect: + * @port : Joystick number. + * @driver : handle for joypad driver handling joystick's input + * + * Registers a newly connected pad with RetroArch. + **/ +void input_pad_connect(unsigned port, input_device_driver_t *driver); + /** * input_mouse_button_raw: * @port : Mouse number. @@ -619,6 +609,9 @@ const char *input_joypad_name(const input_device_driver_t *driver, bool input_config_get_bind_idx(unsigned port, unsigned *joy_idx_real); #ifdef HAVE_HID + +#include "include/hid_driver.h" + /** * hid_driver_find_handle: * @index : index of driver to get handle to. @@ -668,11 +661,11 @@ typedef void (*input_keyboard_line_complete_t)(void *userdata, typedef bool (*input_keyboard_press_t)(void *userdata, unsigned code); -typedef struct input_keyboard_ctx_wait +struct input_keyboard_ctx_wait { void *userdata; input_keyboard_press_t cb; -} input_keyboard_ctx_wait_t; +}; /** * input_keyboard_event: @@ -800,6 +793,9 @@ uint16_t input_config_get_vid(unsigned port); void input_config_reset(void); +void set_connection_listener(pad_connection_listener_t *listener); +void fire_connection_listener(unsigned port, input_device_driver_t *driver); + extern input_device_driver_t dinput_joypad; extern input_device_driver_t linuxraw_joypad; extern input_device_driver_t parport_joypad; @@ -848,7 +844,6 @@ extern hid_driver_t iohidmanager_hid; extern hid_driver_t btstack_hid; extern hid_driver_t libusb_hid; extern hid_driver_t wiiusb_hid; -extern hid_driver_t wiiu_hid; extern hid_driver_t null_hid; #endif diff --git a/input/input_mapper.c b/input/input_mapper.c index 2b58e9b701..e4140765ee 100644 --- a/input/input_mapper.c +++ b/input/input_mapper.c @@ -50,17 +50,20 @@ struct input_mapper { - /* The controller port that will be polled*/ - uint8_t port; /* Left X, Left Y, Right X, Right Y */ - int16_t analog[4]; + int16_t analog_value[MAX_USERS][8]; /* the whole keyboard state */ uint32_t keys[RETROK_LAST / 32 + 1]; /* This is a bitmask of (1 << key_bind_id). */ - uint64_t buttons; + input_bits_t buttons[MAX_USERS]; }; -input_mapper_t *input_mapper_new(uint16_t port) +static bool input_mapper_button_pressed(input_mapper_t *handle, unsigned port, unsigned id) +{ + return BIT256_GET(handle->buttons[port], id); +} + +input_mapper_t *input_mapper_new(void) { input_mapper_t* handle = (input_mapper_t*) calloc(1, sizeof(*handle)); @@ -68,8 +71,6 @@ input_mapper_t *input_mapper_new(uint16_t port) if (!handle) return NULL; - handle->port = port; - return handle; } @@ -82,41 +83,149 @@ void input_mapper_free(input_mapper_t *handle) void input_mapper_poll(input_mapper_t *handle) { - int i; - settings_t *settings = config_get_ptr(); - unsigned device = settings->uints.input_libretro_device[handle->port]; -#ifdef HAVE_MENU - bool menu_is_alive = menu_driver_is_alive(); -#endif + unsigned i, j; + input_bits_t current_input; + settings_t *settings = config_get_ptr(); + unsigned max_users = + *(input_driver_get_uint(INPUT_ACTION_MAX_USERS)); + bool key_event[RARCH_CUSTOM_BIND_LIST_END] = { false }; - device &= RETRO_DEVICE_MASK; - - /* for now we only handle keyboard inputs */ - if (device != RETRO_DEVICE_KEYBOARD) - return; #ifdef HAVE_MENU - if (menu_is_alive) + if (menu_driver_is_alive()) return; #endif memset(handle->keys, 0, sizeof(handle->keys)); - for (i = 0; i < RARCH_CUSTOM_BIND_LIST_END; i++) + for (i = 0; i < max_users; i++) { - if (i < RETROK_LAST) + unsigned device = settings->uints.input_libretro_device[i]; + device &= RETRO_DEVICE_MASK; + + switch (device) { - if (input_state(handle->port, RETRO_DEVICE_JOYPAD, 0, i)) - { - MAPPER_SET_KEY (handle, - settings->uints.input_keymapper_ids[i]); - input_keyboard_event(true, - settings->uints.input_keymapper_ids[i], - 0, 0, RETRO_DEVICE_KEYBOARD); - } - else - input_keyboard_event(false, - settings->uints.input_keymapper_ids[i], - 0, 0, RETRO_DEVICE_KEYBOARD); + /* keyboard to gamepad remapping */ + case RETRO_DEVICE_KEYBOARD: + BIT256_CLEAR_ALL_PTR(¤t_input); + input_get_state_for_port(settings, i, ¤t_input); + for (j = 0; j < RARCH_CUSTOM_BIND_LIST_END; j++) + { + unsigned remap_button = + settings->uints.input_keymapper_ids[i][j]; + bool remap_valid = remap_button != RETROK_UNKNOWN; + + if (remap_valid) + { + unsigned current_button_value = BIT256_GET(current_input, j); + + if ((current_button_value == 1) && (j != remap_button)) + { + MAPPER_SET_KEY (handle, + remap_button); + input_keyboard_event(true, + remap_button, + 0, 0, RETRO_DEVICE_KEYBOARD); + key_event[j] = true; + } + /* key_event tracks if a key is pressed for ANY PLAYER, so we must check + if the key was used by any player before releasing */ + else if (!key_event[j]) + { + input_keyboard_event(false, + remap_button, + 0, 0, RETRO_DEVICE_KEYBOARD); + } + } + } + break; + + /* gamepad remapping */ + case RETRO_DEVICE_JOYPAD: + case RETRO_DEVICE_ANALOG: + /* this loop iterates on all users and all buttons, + * and checks if a pressed button is assigned to any + * other button than the default one, then it sets + * the bit on the mapper input bitmap, later on the + * original input is cleared in input_state */ + BIT256_CLEAR_ALL(handle->buttons[i]); + BIT256_CLEAR_ALL_PTR(¤t_input); + + for (j = 0; j < 8; j++) + handle->analog_value[i][j] = 0; + + input_get_state_for_port(settings, i, ¤t_input); + + for (j = 0; j < RARCH_FIRST_CUSTOM_BIND; j++) + { + unsigned current_button_value = BIT256_GET(current_input, j); + unsigned remap_button = + settings->uints.input_remap_ids[i][j]; + bool remap_valid = (current_button_value == 1) && + (j != remap_button) && (remap_button != RARCH_UNMAPPED); + + if (remap_valid) + { + if (remap_button < RARCH_FIRST_CUSTOM_BIND) + { + BIT256_SET(handle->buttons[i], remap_button); + } + else if (remap_button >= RARCH_FIRST_CUSTOM_BIND) + { + int invert = 1; + + if (remap_button % 2 != 0) + invert = -1; + + handle->analog_value[i][ + remap_button - RARCH_FIRST_CUSTOM_BIND] = + 32767 * invert; + } + } + } + + for (j = 0; j < 8; j++) + { + unsigned k = j + RARCH_FIRST_CUSTOM_BIND; + int16_t current_axis_value = current_input.analogs[j]; + unsigned remap_axis = + settings->uints.input_remap_ids[i][k]; + + if ( + (abs(current_axis_value) > + *input_driver_get_float(INPUT_ACTION_AXIS_THRESHOLD) * 32767) && + (k != remap_axis) && + (remap_axis != RARCH_UNMAPPED) + ) + { + if (remap_axis < RARCH_FIRST_CUSTOM_BIND) + { + BIT256_SET(handle->buttons[i], remap_axis); + } + else + { + int invert = 1; + + if ( (k % 2 == 0 && remap_axis % 2 != 0) || + (k % 2 != 0 && remap_axis % 2 == 0) + ) + invert = -1; + + handle->analog_value[i][ + remap_axis - RARCH_FIRST_CUSTOM_BIND] = + current_axis_value * invert; +#if 0 + RARCH_LOG("axis %d(%d) remapped to axis %d val %d\n", + j, k, + remap_axis - RARCH_FIRST_CUSTOM_BIND, + current_axis_value); +#endif + } + } + + } + break; + default: + break; } } } @@ -134,22 +243,34 @@ void input_mapper_state( switch (device) { + case RETRO_DEVICE_JOYPAD: + if (input_mapper_button_pressed(handle, port, id)) + *ret = 1; + break; + case RETRO_DEVICE_ANALOG: + if (idx < 2 && id < 2) + { + int val = 0; + unsigned offset = 0 + (idx * 4) + (id * 2); + int val1 = handle->analog_value[port][offset]; + int val2 = handle->analog_value[port][offset+1]; + + if (val1) + val = val1; + else if (val2) + val = val2; + + if (val1 || val2) + *ret |= val; + } + break; case RETRO_DEVICE_KEYBOARD: if (id < RETROK_LAST) - { - /* - RARCH_LOG("State: UDLR %u %u %u %u\n", - MAPPER_GET_KEY(handle, RETROK_UP), - MAPPER_GET_KEY(handle, RETROK_DOWN), - MAPPER_GET_KEY(handle, RETROK_LEFT), - MAPPER_GET_KEY(handle, RETROK_RIGHT) - );*/ - if (MAPPER_GET_KEY(handle, id)) *ret |= 1; - } break; default: break; } + return; } diff --git a/input/input_mapper.h b/input/input_mapper.h index c50519acd8..21741d008e 100644 --- a/input/input_mapper.h +++ b/input/input_mapper.h @@ -31,13 +31,13 @@ RETRO_BEGIN_DECLS typedef struct input_mapper input_mapper_t; -input_mapper_t *input_mapper_new(uint16_t port); +input_mapper_t *input_mapper_new(void); void input_mapper_free(input_mapper_t *handle); void input_mapper_poll(input_mapper_t *handle); -bool input_mapper_key_pressed(int key); +bool input_mapper_key_pressed(input_mapper_t *handle, int key); void input_mapper_state( input_mapper_t *handle, diff --git a/input/input_overlay.c b/input/input_overlay.c index 9eac1e8012..858457cf76 100644 --- a/input/input_overlay.c +++ b/input/input_overlay.c @@ -46,7 +46,7 @@ typedef struct input_overlay_state int16_t analog[4]; uint32_t keys[RETROK_LAST / 32 + 1]; /* This is a bitmask of (1 << key_bind_id). */ - retro_bits_t buttons; + input_bits_t buttons; } input_overlay_state_t; struct input_overlay @@ -72,8 +72,117 @@ struct input_overlay input_overlay_t *overlay_ptr = NULL; +/** + * input_overlay_add_inputs: + * @ol : pointer to overlay + * @port : the user to show the inputs of + * + * Adds inputs from current_input to the overlay, so it's displayed + * returns true if an input that is pressed will change the overlay + */ +static bool input_overlay_add_inputs_inner(overlay_desc_t *desc, + unsigned port, unsigned analog_dpad_mode) +{ + switch(desc->type) + { + case OVERLAY_TYPE_BUTTONS: + { + unsigned i; + bool all_buttons_pressed = false; + + /*Check each bank of the mask*/ + for (i = 0; i < ARRAY_SIZE(desc->button_mask.data); ++i) + { + /*Get bank*/ + uint32_t bank_mask = BITS_GET_ELEM(desc->button_mask,i); + unsigned id = i * 32; + + /*Worth pursuing? Have we got any bits left in here?*/ + while (bank_mask) + { + /*If this bit is set then we need to query the pad + *The button must be pressed.*/ + if (bank_mask & 1) + { + /* Light up the button if pressed */ + if (!input_state(port, RETRO_DEVICE_JOYPAD, 0, id)) + { + /* We need ALL of the inputs to be active, + * abort. */ + desc->updated = false; + return false; + } + + all_buttons_pressed = true; + desc->updated = true; + } + + bank_mask >>= 1; + ++id; + } + } + + return all_buttons_pressed; + } + + case OVERLAY_TYPE_ANALOG_LEFT: + case OVERLAY_TYPE_ANALOG_RIGHT: + { + unsigned int index = (desc->type == OVERLAY_TYPE_ANALOG_RIGHT) ? + RETRO_DEVICE_INDEX_ANALOG_RIGHT : RETRO_DEVICE_INDEX_ANALOG_LEFT; + + float analog_x = input_state(port, RETRO_DEVICE_ANALOG, + index, RETRO_DEVICE_ID_ANALOG_X); + float analog_y = input_state(port, RETRO_DEVICE_ANALOG, + index, RETRO_DEVICE_ID_ANALOG_Y); + float dx = (analog_x/0x8000)*(desc->range_x/2); + float dy = (analog_y/0x8000)*(desc->range_y/2); + + desc->delta_x = dx; + desc->delta_y = dy; + + /*Maybe use some option here instead of 0, only display + changes greater than some magnitude. + */ + if ((dx * dx) > 0 || (dy*dy) > 0) + return true; + } + break; + + case OVERLAY_TYPE_KEYBOARD: + if (input_state(port, RETRO_DEVICE_KEYBOARD, 0, desc->retro_key_idx)) + { + desc->updated = true; + return true; + } + break; + + default: + break; + } + + return false; +} + static bool input_overlay_add_inputs(input_overlay_t *ol, - unsigned port, unsigned analog_dpad_mode); + unsigned port, unsigned analog_dpad_mode) +{ + unsigned i; + bool button_pressed = false; + input_overlay_state_t *ol_state = &ol->overlay_state; + + if (!ol_state) + return false; + + for (i = 0; i < ol->active->size; i++) + { + overlay_desc_t *desc = &(ol->active->descs[i]); + button_pressed |= input_overlay_add_inputs_inner(desc, + port, analog_dpad_mode); + } + + return button_pressed; +} /** * input_overlay_scale: * @ol : Overlay handle. @@ -234,7 +343,8 @@ static void input_overlay_enable(input_overlay_t *ol, bool enable) * Check whether the given @x and @y coordinates of the overlay * descriptor @desc is inside the overlay descriptor's hitbox. * - * Returns: true (1) if X, Y coordinates are inside a hitbox, otherwise false (0). + * Returns: true (1) if X, Y coordinates are inside a hitbox, + * otherwise false (0). **/ static bool inside_hitbox(const struct overlay_desc *desc, float x, float y) { @@ -305,7 +415,9 @@ static void input_overlay_poll( { case OVERLAY_TYPE_BUTTONS: { - bits_or_bits(out->buttons.data, desc->button_mask.data, ARRAY_SIZE(desc->button_mask.data)); + bits_or_bits(out->buttons.data, + desc->button_mask.data, + ARRAY_SIZE(desc->button_mask.data)); if (BIT256_GET(desc->button_mask, RARCH_OVERLAY_NEXT)) ol->next_index = desc->next_index; @@ -317,15 +429,19 @@ static void input_overlay_poll( break; default: { - float x_val = x_dist / desc->range_x; - float y_val = y_dist / desc->range_y; - float x_val_sat = x_val / desc->analog_saturate_pct; - float y_val_sat = y_val / desc->analog_saturate_pct; + float x_val = x_dist / desc->range_x; + float y_val = y_dist / desc->range_y; + float x_val_sat = x_val / desc->analog_saturate_pct; + float y_val_sat = y_val / desc->analog_saturate_pct; - unsigned int base = (desc->type == OVERLAY_TYPE_ANALOG_RIGHT) ? 2 : 0; + unsigned int base = + (desc->type == OVERLAY_TYPE_ANALOG_RIGHT) + ? 2 : 0; - out->analog[base + 0] = clamp_float(x_val_sat, -1.0f, 1.0f) * 32767.0f; - out->analog[base + 1] = clamp_float(y_val_sat, -1.0f, 1.0f) * 32767.0f; + out->analog[base + 0] = clamp_float(x_val_sat, -1.0f, 1.0f) + * 32767.0f; + out->analog[base + 1] = clamp_float(y_val_sat, -1.0f, 1.0f) + * 32767.0f; } break; } @@ -498,9 +614,12 @@ void input_overlay_loaded(void *task_data, void *user_data, const char *err) } #endif - if (!data->overlay_enable || !video_driver_overlay_interface(&iface) || !iface) + if ( !data->overlay_enable || + !video_driver_overlay_interface(&iface) || + !iface) { - RARCH_ERR("Overlay interface is not present in video driver, or not enabled.\n"); + RARCH_ERR("Overlay interface is not present in video driver," + " or not enabled.\n"); goto abort_load; } @@ -532,37 +651,42 @@ abort_load: free(data); } -void input_overlay_set_visibility(int overlay_idx,enum overlay_visibility vis) +void input_overlay_set_visibility(int overlay_idx, + enum overlay_visibility vis) { - int i; input_overlay_t *ol = overlay_ptr; - if(visibility == NULL) + if (!visibility) { - visibility = (enum overlay_visibility *)calloc(MAX_VISIBILITY,sizeof(enum overlay_visibility)); - for(i=0;iiface->set_alpha(ol->iface_data, overlay_idx, 0.0); } static enum overlay_visibility input_overlay_get_visibility(int overlay_idx) { - if(visibility == NULL) return OVERLAY_VISIBILITY_DEFAULT; - if((overlay_idx < 0) || (overlay_idx >= MAX_VISIBILITY)) return OVERLAY_VISIBILITY_DEFAULT; + if (!visibility) + return OVERLAY_VISIBILITY_DEFAULT; + if ((overlay_idx < 0) || (overlay_idx >= MAX_VISIBILITY)) + return OVERLAY_VISIBILITY_DEFAULT; return visibility[overlay_idx]; } static bool input_overlay_is_hidden(int overlay_idx) { - return (input_overlay_get_visibility(overlay_idx) == OVERLAY_VISIBILITY_HIDDEN); + return (input_overlay_get_visibility(overlay_idx) + == OVERLAY_VISIBILITY_HIDDEN); } /** @@ -582,7 +706,7 @@ void input_overlay_set_alpha_mod(input_overlay_t *ol, float mod) for (i = 0; i < ol->active->load_images_size; i++) { - if(input_overlay_is_hidden(i)) + if (input_overlay_is_hidden(i)) ol->iface->set_alpha(ol->iface_data, i, 0.0); else ol->iface->set_alpha(ol->iface_data, i, mod); @@ -609,7 +733,8 @@ bool input_overlay_key_pressed(input_overlay_t *ol, unsigned key) * * Poll pressed buttons/keys on currently active overlay. **/ -void input_poll_overlay(input_overlay_t *ol, float opacity, unsigned analog_dpad_mode, +void input_poll_overlay(input_overlay_t *ol, float opacity, + unsigned analog_dpad_mode, float axis_threshold) { rarch_joypad_info_t joypad_info; @@ -658,7 +783,9 @@ void input_poll_overlay(input_overlay_t *ol, float opacity, unsigned analog_dpad else ol->blocked = false; - bits_or_bits(ol_state->buttons.data, polled_data.buttons.data, ARRAY_SIZE(polled_data.buttons.data)); + bits_or_bits(ol_state->buttons.data, + polled_data.buttons.data, + ARRAY_SIZE(polled_data.buttons.data)); for (j = 0; j < ARRAY_SIZE(ol_state->keys); j++) ol_state->keys[j] |= polled_data.keys[j]; @@ -749,10 +876,11 @@ void input_poll_overlay(input_overlay_t *ol, float opacity, unsigned analog_dpad break; } - if(settings->bools.input_overlay_show_physical_inputs) - { - button_pressed = input_overlay_add_inputs(ol, settings->uints.input_overlay_show_physical_inputs_port, analog_dpad_mode); - } + if (settings->bools.input_overlay_show_physical_inputs) + button_pressed = input_overlay_add_inputs(ol, + settings->uints.input_overlay_show_physical_inputs_port, + analog_dpad_mode); + if (button_pressed || polled) input_overlay_post_poll(ol, opacity); else @@ -777,12 +905,14 @@ void input_state_overlay(input_overlay_t *ol, int16_t *ret, case RETRO_DEVICE_KEYBOARD: if (id < RETROK_LAST) { - /*RARCH_LOG("UDLR %u %u %u %u\n", - OVERLAY_GET_KEY(ol_state, RETROK_UP), - OVERLAY_GET_KEY(ol_state, RETROK_DOWN), - OVERLAY_GET_KEY(ol_state, RETROK_LEFT), - OVERLAY_GET_KEY(ol_state, RETROK_RIGHT) - );*/ +#if 0 + RARCH_LOG("UDLR %u %u %u %u\n", + OVERLAY_GET_KEY(ol_state, RETROK_UP), + OVERLAY_GET_KEY(ol_state, RETROK_DOWN), + OVERLAY_GET_KEY(ol_state, RETROK_LEFT), + OVERLAY_GET_KEY(ol_state, RETROK_RIGHT) + ); +#endif if (OVERLAY_GET_KEY(ol_state, id)) *ret |= 1; } @@ -801,118 +931,3 @@ void input_state_overlay(input_overlay_t *ol, int16_t *ret, break; } } -/** - * input_overlay_add_inputs: - * @ol : pointer to overlay - * @port : the user to show the inputs of - * - * Adds inputs from current_input to the overlay, so it's displayed - * returns true if an input that is pressed will change the overlay - */ -static bool input_overlay_add_inputs_inner(overlay_desc_t *desc, - unsigned port, unsigned analog_dpad_mode) -{ - switch(desc->type) - { - case OVERLAY_TYPE_BUTTONS: - { - unsigned i; - unsigned id; - uint32_t bank_mask; - bool all_buttons_pressed = false; - - /*Check each bank of the mask*/ - for (i=0; ibutton_mask.data); ++i) - { - /*Get bank*/ - bank_mask = BITS_GET_ELEM(desc->button_mask,i); - id = i*32; - - /*Worth pursuing? Have we got any bits left in here?*/ - while (bank_mask) - { - /*If this bit is set then we need to query the pad - *The button must be pressed.*/ - if (bank_mask & 1) - { - /* Light up the button if pressed */ - if(input_state(port, RETRO_DEVICE_JOYPAD, 0, id)) - { - all_buttons_pressed = true; - desc->updated = true; - } - else - { - /*we need ALL of the inputs to be active*/ - all_buttons_pressed = false; - desc->updated = false; - - /*abort*/ - return false; - } - } - - bank_mask >>= 1; - ++id; - } - } - - return all_buttons_pressed; - } - - case OVERLAY_TYPE_ANALOG_LEFT: - case OVERLAY_TYPE_ANALOG_RIGHT: - { - float analog_x, analog_y; - float dx, dy; - unsigned int index = (desc->type == OVERLAY_TYPE_ANALOG_RIGHT) ? - RETRO_DEVICE_INDEX_ANALOG_RIGHT : RETRO_DEVICE_INDEX_ANALOG_LEFT; - - analog_x = input_state(port, RETRO_DEVICE_ANALOG, index, RETRO_DEVICE_ID_ANALOG_X); - analog_y = input_state(port, RETRO_DEVICE_ANALOG, index, RETRO_DEVICE_ID_ANALOG_Y); - dx = (analog_x/0x8000)*(desc->range_x/2); - dy = (analog_y/0x8000)*(desc->range_y/2); - - desc->delta_x = dx; - desc->delta_y = dy; - /*Maybe use some option here instead of 0, only display - changes greater than some magnitude. - */ - if((dx*dx) > 0 || (dy*dy) > 0) - return true; - } - break; - - case OVERLAY_TYPE_KEYBOARD: - if(input_state(port, RETRO_DEVICE_KEYBOARD, 0, desc->retro_key_idx)) - { - desc->updated = true; - return true; - } - break; - - default: - break; - } - - return false; -} - -static bool input_overlay_add_inputs(input_overlay_t *ol, - unsigned port, unsigned analog_dpad_mode) -{ - unsigned i; - bool button_pressed = false; - input_overlay_state_t *ol_state = &ol->overlay_state; - - if(!ol_state) - return false; - - for(i = 0; i < ol->active->size; i++) - { - overlay_desc_t *desc = &(ol->active->descs[i]); - button_pressed |= input_overlay_add_inputs_inner(desc, port, analog_dpad_mode); - } - - return button_pressed; -} diff --git a/input/input_overlay.h b/input/input_overlay.h index 468e6e5141..ed70af4cd6 100644 --- a/input/input_overlay.h +++ b/input/input_overlay.h @@ -177,7 +177,7 @@ struct overlay_desc unsigned retro_key_idx; /* This is a bit mask of all input binds to set with this overlay control */ - retro_bits_t button_mask; + input_bits_t button_mask; char next_index_name[64]; diff --git a/input/input_remapping.c b/input/input_remapping.c index 5830565e09..f92eb20d86 100644 --- a/input/input_remapping.c +++ b/input/input_remapping.c @@ -39,7 +39,7 @@ static unsigned old_libretro_device[MAX_USERS]; **/ bool input_remapping_load_file(void *data, const char *path) { - unsigned i, j; + unsigned i, j, k; config_file_t *conf = (config_file_t*)data; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); @@ -53,69 +53,77 @@ bool input_remapping_load_file(void *data, const char *path) for (i = 0; i < MAX_USERS; i++) { - char s1[64], s2[64]; - char key_ident[RARCH_FIRST_CUSTOM_BIND + 4][128] = {{0}}; - char keymapper_ident[RARCH_FIRST_CUSTOM_BIND + 4][128] = {{0}}; - char key_strings[RARCH_FIRST_CUSTOM_BIND + 4][128] = - { "b", "y", "select", "start", + char s1[64], s2[64], s3[64]; + char btn_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; + char key_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; + char stk_ident[8][128] = {{0}}; + + char key_strings[RARCH_FIRST_CUSTOM_BIND + 8][128] = { + "b", "y", "select", "start", "up", "down", "left", "right", "a", "x", "l", "r", "l2", "r2", - "l3", "r3", "l_x", "l_y", "r_x", "r_y" }; + "l3", "r3", "l_x+", "l_x-", "l_y+", "l_y-", "r_x+", "r_x-", "r_y+", "r_y-" }; old_analog_dpad_mode[i] = settings->uints.input_analog_dpad_mode[i]; old_libretro_device[i] = settings->uints.input_libretro_device[i]; s1[0] = '\0'; s2[0] = '\0'; + s3[0] = '\0'; - snprintf(s1, sizeof(s1), "input_player%u", i + 1); + snprintf(s1, sizeof(s1), "input_player%u_btn", i + 1); snprintf(s2, sizeof(s2), "input_player%u_key", i + 1); + snprintf(s3, sizeof(s3), "input_player%u_stk", i + 1); - for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 4; j++) + for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 8; j++) { - int key_remap = -1; - - fill_pathname_join_delim(key_ident[j], s1, - key_strings[j], '_', sizeof(key_ident[j])); - fill_pathname_join_delim(keymapper_ident[j], s2, - key_strings[j], '_', sizeof(key_ident[j])); - - if (config_get_int(conf, key_ident[j], &key_remap) - && key_remap < RARCH_FIRST_CUSTOM_BIND) - settings->uints.input_remap_ids[i][j] = key_remap; - - key_remap = -1; - - if (settings->uints.keymapper_port == i) + if (j < RARCH_FIRST_CUSTOM_BIND) { - if (config_get_int(conf, keymapper_ident[j], &key_remap)) - { - settings->uints.input_keymapper_ids[j] = key_remap; -#if 0 - RARCH_LOG ("%s: %u\n", keymapper_ident[j], settings->uints.input_keymapper_ids[j]); -#endif - } + int btn_remap = -1; + int key_remap = -1; + + fill_pathname_join_delim(btn_ident[j], s1, + key_strings[j], '_', sizeof(btn_ident[j])); + fill_pathname_join_delim(key_ident[j], s2, + key_strings[j], '_', sizeof(btn_ident[j])); + + if (config_get_int(conf, btn_ident[j], &btn_remap) + && btn_remap != -1) + settings->uints.input_remap_ids[i][j] = btn_remap; + else if (config_get_int(conf, btn_ident[j], &btn_remap) + && btn_remap == -1) + settings->uints.input_remap_ids[i][j] = RARCH_UNMAPPED; + /* else do nothing, important */ + + if (config_get_int(conf, key_ident[j], &key_remap)) + settings->uints.input_keymapper_ids[i][j] = key_remap; else - settings->uints.input_keymapper_ids[j] = RETROK_UNKNOWN; + settings->uints.input_keymapper_ids[i][j] = RETROK_UNKNOWN; } + else + { + int stk_remap = -1; + k = j - RARCH_FIRST_CUSTOM_BIND; + fill_pathname_join_delim(stk_ident[k], s3, + key_strings[j], '$', sizeof(stk_ident[k])); - } + snprintf(stk_ident[k], + sizeof(stk_ident[k]), + "%s_%s", + s3, + key_strings[j]); - for (j = 0; j < 4; j++) - { - int key_remap = -1; + /* RARCH_LOG("pre_ident: %s:%d\n", stk_ident[j], settings->uints.input_remap_ids[i][j]); */ - snprintf(key_ident[RARCH_FIRST_CUSTOM_BIND + j], - sizeof(key_ident[RARCH_FIRST_CUSTOM_BIND + j]), - "%s_%s", - s1, - key_strings[RARCH_FIRST_CUSTOM_BIND + j]); + if (config_get_int(conf, stk_ident[k], &stk_remap) && stk_remap != -1) + settings->uints.input_remap_ids[i][j] = stk_remap; + else if (config_get_int(conf, stk_ident[k], &stk_remap) && stk_remap == -1) + settings->uints.input_remap_ids[i][j] = RARCH_UNMAPPED; + /* else do nothing, important */ - if (config_get_int(conf, key_ident[RARCH_FIRST_CUSTOM_BIND + j], - &key_remap) && (key_remap < 4)) - settings->uints.input_remap_ids[i][RARCH_FIRST_CUSTOM_BIND + j] = - key_remap; + /*RARCH_LOG("stk_ident: %s:%d\n", stk_ident[j], settings->uints.input_remap_ids[i][j]);*/ + } } snprintf(s1, sizeof(s1), "input_player%u_analog_dpad_mode", i + 1); @@ -141,7 +149,7 @@ bool input_remapping_load_file(void *data, const char *path) bool input_remapping_save_file(const char *path) { bool ret; - unsigned i, j; + unsigned i, j, k; size_t path_size = PATH_MAX_LENGTH * sizeof(char); char *buf = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *remap_file = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); @@ -172,46 +180,63 @@ bool input_remapping_save_file(const char *path) for (i = 0; i < max_users; i++) { - char s1[64], s2[64]; - char key_ident[RARCH_FIRST_CUSTOM_BIND + 4][128] = {{0}}; - char keymapper_ident[RARCH_FIRST_CUSTOM_BIND + 4][128] = {{0}}; - char key_strings[RARCH_FIRST_CUSTOM_BIND + 4][128] = { + char s1[64], s2[64], s3[64]; + char btn_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; + char key_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; + char stk_ident[8][128] = {{0}}; + + char key_strings[RARCH_FIRST_CUSTOM_BIND + 8][128] = { "b", "y", "select", "start", "up", "down", "left", "right", "a", "x", "l", "r", "l2", "r2", - "l3", "r3", "l_x", "l_y", "r_x", "r_y" }; + "l3", "r3", "l_x+", "l_x-", "l_y+", "l_y-", "r_x+", "r_x-", "r_y+", "r_y-" }; s1[0] = '\0'; s2[0] = '\0'; - snprintf(s1, sizeof(s1), "input_player%u", i + 1); + snprintf(s1, sizeof(s1), "input_player%u_btn", i + 1); snprintf(s2, sizeof(s2), "input_player%u_key", i + 1); + snprintf(s3, sizeof(s1), "input_player%u_stk", i + 1); - for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 4; j++) + for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 8; j++) { - fill_pathname_join_delim(key_ident[j], s1, - key_strings[j], '_', sizeof(key_ident[j])); - fill_pathname_join_delim(keymapper_ident[j], s2, - key_strings[j], '_', sizeof(key_ident[j])); - /* only save values that have been modified */ if(j < RARCH_FIRST_CUSTOM_BIND) { - if(settings->uints.input_remap_ids[i][j] != j) - config_set_int(conf, key_ident[j], settings->uints.input_remap_ids[i][j]); - else - config_unset(conf,key_ident[j]); + fill_pathname_join_delim(btn_ident[j], s1, + key_strings[j], '_', sizeof(btn_ident[j])); + fill_pathname_join_delim(key_ident[j], s2, + key_strings[j], '_', sizeof(btn_ident[j])); - if (settings->uints.keymapper_port == i && - settings->uints.input_keymapper_ids[j] != RETROK_UNKNOWN) - config_set_int(conf, keymapper_ident[j], settings->uints.input_keymapper_ids[j]); + /* only save values that have been modified */ + if(settings->uints.input_remap_ids[i][j] != j && + settings->uints.input_remap_ids[i][j] != RARCH_UNMAPPED) + config_set_int(conf, btn_ident[j], settings->uints.input_remap_ids[i][j]); + else if (settings->uints.input_remap_ids[i][j] != j && + settings->uints.input_remap_ids[i][j] == RARCH_UNMAPPED) + config_set_int(conf, btn_ident[j], -1); + else + config_unset(conf,btn_ident[j]); + + if (settings->uints.input_keymapper_ids[i][j] != RETROK_UNKNOWN) + config_set_int(conf, key_ident[j], + settings->uints.input_keymapper_ids[i][j]); } else { - if(settings->uints.input_remap_ids[i][j] != j - RARCH_FIRST_CUSTOM_BIND) - config_set_int(conf, key_ident[j], settings->uints.input_remap_ids[i][j]); + k = j - RARCH_FIRST_CUSTOM_BIND; + fill_pathname_join_delim(stk_ident[k], s3, + key_strings[j], '_', sizeof(stk_ident[k])); + if(settings->uints.input_remap_ids[i][j] != j && + settings->uints.input_remap_ids[i][j] != RARCH_UNMAPPED) + config_set_int(conf, stk_ident[k], + settings->uints.input_remap_ids[i][j]); + else if(settings->uints.input_remap_ids[i][j] != j && + settings->uints.input_remap_ids[i][j] == RARCH_UNMAPPED) + config_set_int(conf, stk_ident[k], + -1); else - config_unset(conf,key_ident[j]); + config_unset(conf, stk_ident[k]); } } snprintf(s1, sizeof(s1), "input_libretro_device_p%u", i + 1); @@ -268,16 +293,18 @@ void input_remapping_set_defaults(bool deinit) for (i = 0; i < MAX_USERS; i++) { - for (j = 0; j < RARCH_FIRST_CUSTOM_BIND; j++) + for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 8; j++) { - const struct retro_keybind *keybind = &input_config_binds[i][j]; - if (keybind) - settings->uints.input_remap_ids[i][j] = keybind->id; - settings->uints.input_keymapper_ids[j] = RETROK_UNKNOWN; - + if (j < RARCH_FIRST_CUSTOM_BIND) + { + const struct retro_keybind *keybind = &input_config_binds[i][j]; + if (keybind) + settings->uints.input_remap_ids[i][j] = keybind->id; + settings->uints.input_keymapper_ids[i][j] = RETROK_UNKNOWN; + } + else + settings->uints.input_remap_ids[i][j] = j; } - for (j = 0; j < 4; j++) - settings->uints.input_remap_ids[i][RARCH_FIRST_CUSTOM_BIND + j] = j; if (old_analog_dpad_mode[i]) settings->uints.input_analog_dpad_mode[i] = old_analog_dpad_mode[i]; diff --git a/input/input_types.h b/input/input_types.h new file mode 100644 index 0000000000..0bc64d8c42 --- /dev/null +++ b/input/input_types.h @@ -0,0 +1,32 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef __INPUT_TYPES__H +#define __INPUT_TYPES__H + +typedef struct rarch_joypad_driver input_device_driver_t; +typedef struct input_keyboard_line input_keyboard_line_t; +typedef struct rarch_joypad_info rarch_joypad_info_t; +typedef struct input_driver input_driver_t; +typedef struct input_keyboard_ctx_wait input_keyboard_ctx_wait_t; +typedef struct { + uint32_t data[8]; + uint16_t analogs[8]; +} input_bits_t; +typedef struct joypad_connection joypad_connection_t; +typedef struct pad_connection_listener_interface pad_connection_listener_t; + +#endif /* __INPUT_TYPES__H */ diff --git a/intl/msg_hash_ar.h b/intl/msg_hash_ar.h index bc8f846966..0a01f9ecb3 100644 --- a/intl/msg_hash_ar.h +++ b/intl/msg_hash_ar.h @@ -460,7 +460,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, - "Achievements Hardcore Mode" + "Hardcore Mode" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_LEADERBOARDS_ENABLE, @@ -500,7 +500,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_VERBOSE_ENABLE, - "Achievements Verbose Mode" + "Verbose Mode" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT, @@ -1747,6 +1747,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Vertical Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Estimated Screen Framerate") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotation") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1877,6 +1879,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_HISTORY, "Show History Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_ADD, "Show Import content Tab") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_PLAYLISTS, + "Show Playlist Tabs") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_FAVORITES, "Show Favorites Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_IMAGES, @@ -1889,6 +1893,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Show Video Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Show Netplay Tab") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Menu Icon Theme") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1900,7 +1906,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, "Enable or disable unofficial achievements and/or beta features for testing purposes.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, - "Enable or disable savestates, cheats, rewind, fast-forward, pause, and slow-motion for all games.") + "Enable or disable savestates, cheats, rewind, pause, and slow-motion for all games.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_LEADERBOARDS_ENABLE, "Enable or disable in-game leaderboards. Has no effect if Hardcore Mode is disabled.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE, @@ -1995,6 +2001,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Selects which display screen to use.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "The accurate estimated refresh rate of the screen in Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Change video output settings.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2565,7 +2573,7 @@ MSG_HASH(MSG_NETPLAY_LAN_SCANNING, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "Pause gameplay when RetroArch is not the active window.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "Enable or disable recent playlist for games, images, music, and videos.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -3047,6 +3055,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3077,6 +3087,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Show the recent history tab inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3423,3 +3435,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_chs.h b/intl/msg_hash_chs.h index 73c5ac25af..792f553a67 100644 --- a/intl/msg_hash_chs.h +++ b/intl/msg_hash_chs.h @@ -413,7 +413,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, -/* FIXME? Translate 'Achievements Hardcore Mode' */ +/* FIXME? Translate 'Hardcore Mode' */ "专家模式" ) MSG_HASH( @@ -1626,6 +1626,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "刷新率") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "估算的显示器帧率") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "旋转") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1756,6 +1758,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS, "显示设置页") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "显示视频页") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "菜单图标主题") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1857,6 +1861,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "选择将要使用哪一个显示器。") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "估算的显示器刷新率(Hz)。") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "调整视频输出的选项。") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2407,7 +2413,7 @@ MSG_HASH(MSG_NETPLAY_LAN_SCANNING, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "当窗口失去焦点时暂停游戏。") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "为游戏、图片、音乐和视频启用/禁用历史记录。") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -2877,6 +2883,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -2905,6 +2913,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Show the recent history tab inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3211,3 +3221,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_cht.h b/intl/msg_hash_cht.h index fea49f44f3..151e074bcc 100644 --- a/intl/msg_hash_cht.h +++ b/intl/msg_hash_cht.h @@ -413,7 +413,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, -/* FIXME? Translate 'Achievements Hardcore Mode' */ +/* FIXME? Translate 'Hardcore Mode' */ "成就-專家模式" ) MSG_HASH( @@ -1626,6 +1626,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "刷新率") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "估算的顯示器幀率") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "旋轉") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1748,6 +1750,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS, "顯示設定頁") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "顯示視訊頁") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "選單圖標主題") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1849,6 +1853,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "選擇將要使用哪一個顯示器。") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "估算的顯示器刷新率(Hz)。") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "調整視訊輸出的選項。") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2399,7 +2405,7 @@ MSG_HASH(MSG_NETPLAY_LAN_SCANNING, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "當窗口失去焦點時暫停遊戲。") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "為遊戲、圖片、音樂和視訊啟用/禁用歷史記錄。") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -2869,6 +2875,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -2897,6 +2905,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Show the recent history tab inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3203,3 +3213,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_de.h b/intl/msg_hash_de.h index 311affa126..db9dd3ab65 100644 --- a/intl/msg_hash_de.h +++ b/intl/msg_hash_de.h @@ -1673,6 +1673,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Bildwiederholrate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Geschätzte Bildwiederholrate") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotation") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1809,6 +1811,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Zeige Tab 'Video'") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Zeige Tab 'Netplay'") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Menü-Design") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1911,6 +1915,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Wält den Bildschirm aus, der für RetroArch verwendet wird.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "Die geschätzte Bildwiederholrate des Bildschirms in Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Einstellungen für die Videoausgabe anpassen.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2959,6 +2965,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Wähle ein Datenträger-Abbild, das eingelegt werden soll.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Stelle sicher, dass die Bildwiederholrate im Menü begrenzt wird.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Wähle ein anderes Thema für das Menü aus. Änderungen werden übernommen, nachdem Du das Programm neu gestartet hast.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3319,3 +3327,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_eo.h b/intl/msg_hash_eo.h index 2914287c26..24bdb595b0 100644 --- a/intl/msg_hash_eo.h +++ b/intl/msg_hash_eo.h @@ -345,7 +345,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, - "Achievements Hardcore Mode" + "Hardcore Mode" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ACHIEVEMENTS, @@ -1526,6 +1526,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Vertical Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Estimated Screen Framerate") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotation") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1652,6 +1654,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS, "Display Settings Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Display Video Tab") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Menu Icon Theme") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1663,7 +1667,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, "Enable or disable unofficial achievements and/or beta features for testing purposes.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, - "Enable or disable savestates, cheats, rewind, fast-forward, pause, and slow-motion for all games.") + "Enable or disable savestates, cheats, rewind, pause, and slow-motion for all games.") MSG_HASH(MENU_ENUM_SUBLABEL_DRIVER_SETTINGS, "Change drivers for this system.") MSG_HASH(MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS, @@ -1750,6 +1754,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Selects which display screen to use.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "The accurate estimated refresh rate of the screen in Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Adjusts settings for video output.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2286,7 +2292,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_DATABASE_INFO, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "Pause gameplay when window focus is lost.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "Enable or disable recent playlist for games, images, music, and videos.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -2740,6 +2746,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -2770,6 +2778,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Show the recent history tab inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3076,3 +3086,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_es.h b/intl/msg_hash_es.h index 5371d79e03..f299360f60 100644 --- a/intl/msg_hash_es.h +++ b/intl/msg_hash_es.h @@ -2953,6 +2953,10 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Frecuencia estimada del monitor" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotación" @@ -3229,6 +3233,8 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Mostrar pestaña juego en red" ) +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH( MENU_ENUM_LABEL_VALUE_XMB_THEME, "Tema de iconos del menú" @@ -3441,6 +3447,10 @@ MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "Estimado preciso de refresco de la pantalla en Hz" ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver." + ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Opciones de salida de video" @@ -5117,6 +5127,8 @@ MSG_HASH( MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Limita los FPS en el menú" ) +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH( MENU_ENUM_SUBLABEL_XMB_THEME, "Seleccionar un tema de iconos diferente. Los cambios tendrán efecto al reiniciar" @@ -5805,3 +5817,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_fr.h b/intl/msg_hash_fr.h index 5950a9a29b..5d6ad67cf8 100644 --- a/intl/msg_hash_fr.h +++ b/intl/msg_hash_fr.h @@ -1643,6 +1643,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Fréquence de rafraîchissement verticale") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Fréquence estimée de l'écran") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotation") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1773,6 +1775,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS, "Afficher l'onglet Paramètres") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Afficher l'onglet Vidéo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Thème XMB") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1873,6 +1877,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Sélectionne l'écran à utiliser.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "Taux de rafraîchissement estimé de l'écran en Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Ajuster les paramètres de sortie vidéo.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2907,6 +2913,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -2935,6 +2943,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Affiche l'onglet de l'historique dans le menu principal.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3241,3 +3251,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_it.h b/intl/msg_hash_it.h index a81f223b8c..7aa0753964 100644 --- a/intl/msg_hash_it.h +++ b/intl/msg_hash_it.h @@ -1671,6 +1671,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Frequenza di aggiornamento verticale") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Framerate dello schermo stimato") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotazione") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1807,6 +1809,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Visualizza colonna Video") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Visualizza colonna Stanze Netplay ") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Icone del Menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1909,6 +1913,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Seleziona lo schermo da utilizzare.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "La stima precisa di aggiornamento dello schermo in Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Cambia le impostazioni per l'uscita video.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2957,6 +2963,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Seleziona un'immagine disco da inserire") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Assicura che i fotogrammi siano attivi all'interno del menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Seleziona un tema diverso per l'icona. Le modifiche avranno effetto dopo il riavvio del programma.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -2987,6 +2995,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Mostra la colonna cronologia all'interno del menu principale.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Mostra la colonna importa contenuto all'interno del menu principale.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Mostra le colonne delle playlist all'interno del menu principale") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Mostra la schermata di avvio nel menu. Questo viene automaticamente impostato su off dopo l'avvio del programma per la prima volta.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3299,3 +3309,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Mostra statistiche") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Mostra statistiche tecniche su schermo.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index 42c28851b2..9a67ef3a85 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -1737,6 +1737,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "リフレッシュレート") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "画面の予想フレームレート") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "回転") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1875,6 +1877,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "ビデオタブを表示") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "ネットプレイタブを表示") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "メニューのアイコンテーマ") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1975,6 +1979,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "希望する画面を選択する。") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "画面の正確な推定のリフレッシュレート") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "ビデオ出力の設定を変える。") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2525,7 +2531,7 @@ MSG_HASH(MSG_NETPLAY_LAN_SCANNING, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "Pause gameplay when window focus is lost.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "Enable or disable recent playlist for games, images, music, and videos.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -2981,6 +2987,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "ディスクイメージを追加する。") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3317,3 +3325,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_ko.h b/intl/msg_hash_ko.h index b900c8370d..dd9a97e9a1 100644 --- a/intl/msg_hash_ko.h +++ b/intl/msg_hash_ko.h @@ -1621,6 +1621,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_POST_FILTER_RECORD, "필터 적용된 녹화 사용") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "수직 리프레시 비율") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "화면 프레임레이트 측정치") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, @@ -1753,6 +1755,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "비디오 탭 보이기") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "넷플레이 탭 보이기") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "메뉴 아이콘 테마") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1853,6 +1857,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "사용할 디스플레이를 선택.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "화면의 정확한 리프레시 비율(Hz) 측정치.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "비디오 출력 설정 변경.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2871,6 +2877,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "삽입할 디스크 이미지를 선택하십시오.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "메뉴상에 있을 시에는 프레임 제한을 설정.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "다른 아이콘 테마 선택. 변경 내용은 프로그램을 다시 시작 후 적용됩니다.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3204,3 +3212,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index ada305e886..653c906773 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -301,6 +301,8 @@ MSG_HASH(MENU_ENUM_LABEL_DEFERRED_INPUT_HOTKEY_BINDS_LIST, "deferred_input_hotkey_binds") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_INPUT_SETTINGS_LIST, "deferred_input_settings_list") +MSG_HASH(MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST, + "deferred_latency_settings_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_LAKKA_LIST, "deferred_lakka_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_LAKKA_SERVICES_LIST, @@ -529,6 +531,8 @@ MSG_HASH(MENU_ENUM_LABEL_INPUT_SETTINGS, "input_settings") MSG_HASH(MENU_ENUM_LABEL_INPUT_SETTINGS_BEGIN, "input_settings_begin") +MSG_HASH(MENU_ENUM_LABEL_LATENCY_SETTINGS, + "latency_settings") MSG_HASH(MENU_ENUM_LABEL_INPUT_SMALL_KEYBOARD_ENABLE, "input_small_keyboard_enable") MSG_HASH(MENU_ENUM_LABEL_INPUT_TOUCH_ENABLE, @@ -989,6 +993,12 @@ MSG_HASH(MENU_ENUM_LABEL_SHUTDOWN, "shutdown") MSG_HASH(MENU_ENUM_LABEL_SLOWMOTION_RATIO, "slowmotion_ratio") +MSG_HASH(MENU_ENUM_LABEL_RUN_AHEAD_ENABLED, + "run_ahead_enabled") +MSG_HASH(MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE, + "run_ahead_secondary_instance") +MSG_HASH(MENU_ENUM_LABEL_RUN_AHEAD_FRAMES, + "run_ahead_frames") MSG_HASH(MENU_ENUM_LABEL_SORT_SAVEFILES_ENABLE, "sort_savefiles_enable") MSG_HASH(MENU_ENUM_LABEL_SORT_SAVESTATES_ENABLE, @@ -1029,6 +1039,10 @@ MSG_HASH(MENU_ENUM_LABEL_THREADED_DATA_RUNLOOP_ENABLE, "threaded_data_runloop_enable") MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS, "thumbnails") +MSG_HASH(MENU_ENUM_LABEL_LEFT_THUMBNAILS, + "left thumbnails") +MSG_HASH(MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, + "xmb_vertical_thumbnails") MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_DIRECTORY, "thumbnails_directory") MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST, @@ -1147,6 +1161,8 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_REFRESH_RATE, "video_refresh_rate") MSG_HASH(MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_AUTO, "video_refresh_rate_auto") +MSG_HASH(MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED, + "video_refresh_rate_polled") MSG_HASH(MENU_ENUM_LABEL_VIDEO_ROTATION, "video_rotation") MSG_HASH(MENU_ENUM_LABEL_VIDEO_SCALE, @@ -1237,6 +1253,8 @@ MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_HISTORY, "content_show_history") MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_ADD, "content_show_add") +MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_PLAYLISTS, + "content_show_playlists") MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_FAVORITES, "content_show_favorites") MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_IMAGES, @@ -1251,6 +1269,8 @@ MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_VIDEO, "content_show_video") MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_NETPLAY, "content_show_netplay") +MSG_HASH(MENU_ENUM_LABEL_XMB_LAYOUT, + "xmb_layout") MSG_HASH(MENU_ENUM_LABEL_XMB_THEME, "xmb_theme") MSG_HASH(MSG_BRINGING_UP_COMMAND_INTERFACE_ON_PORT, @@ -1453,3 +1473,15 @@ MSG_HASH(MENU_ENUM_LABEL_INPUT_DRIVER_LINUXRAW, "linuxraw") MSG_HASH(MENU_ENUM_LABEL_VIDEO_WINDOW_SHOW_DECORATIONS, "video_window_show_decorations") +MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_ENABLE, + "menu_rgui_border_filler_enable") +MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "menu_rgui_border_filler_thickness_enable") +MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "menu_rgui_background_filler_thickness_enable") +MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_REWIND, + "menu_show_rewind_settings") +MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY, + "menu_show_latency_settings") +MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_OVERLAYS, + "menu_show_overlay_settings") diff --git a/intl/msg_hash_nl.h b/intl/msg_hash_nl.h index 90eb92fd77..f2a087ba70 100644 --- a/intl/msg_hash_nl.h +++ b/intl/msg_hash_nl.h @@ -345,7 +345,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, - "Achievements Hardcore Mode" + "Hardcore Mode" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ACHIEVEMENTS, @@ -1524,6 +1524,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Vertical Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Geschatte Scherm Framerate") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotatie") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1650,6 +1652,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS, "Instellingentab weergeven") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Videotab weergeven") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Menu Icon Theme") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1661,7 +1665,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, "Enable or disable unofficial achievements and/or beta features for testing purposes.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, - "Enable or disable savestates, cheats, rewind, fast-forward, pause, and slow-motion for all games.") + "Enable or disable savestates, cheats, rewind, pause, and slow-motion for all games.") MSG_HASH(MENU_ENUM_SUBLABEL_DRIVER_SETTINGS, "Change drivers for this system.") MSG_HASH(MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS, @@ -1748,6 +1752,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Selects which display screen to use.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "The accurate estimated refresh rate of the screen in Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Adjusts settings for video output.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2288,7 +2294,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_DATABASE_INFO, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "Pause gameplay when window focus is lost.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "Enable or disable recent playlist for games, images, music, and videos.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -2744,6 +2750,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -2772,6 +2780,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Show the recent history tab inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3078,3 +3088,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_pl.h b/intl/msg_hash_pl.h index b26d250b0b..5f422ca915 100644 --- a/intl/msg_hash_pl.h +++ b/intl/msg_hash_pl.h @@ -12,7 +12,7 @@ MSG_HASH( ) MSG_HASH( MSG_UNKNOWN_NETPLAY_COMMAND_RECEIVED, - "Otrzymano nieznane polecenie netplay" + "Otrzymano nieznane polecenie gry internetwoej" ) MSG_HASH( MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER, @@ -50,17 +50,53 @@ MSG_HASH( MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N, "Dołączyłeś jako gracz %u" ) +MSG_HASH( + MSG_NETPLAY_YOU_HAVE_JOINED_WITH_INPUT_DEVICES_S, + "Dołączyłeś do urządzeń wejściowych %.*s" + ) +MSG_HASH( + MSG_NETPLAY_PLAYER_S_LEFT, + "Gracz %.*s opuścił grę" + ) +MSG_HASH( + MSG_NETPLAY_S_HAS_JOINED_AS_PLAYER_N, + "%.*s dołączył jako gracz %u" + ) +MSG_HASH( + MSG_NETPLAY_S_HAS_JOINED_WITH_INPUT_DEVICES_S, + "%.*s dołączył do urządzeń wejściowych %.*s" + ) +MSG_HASH( + MSG_NETPLAY_NOT_RETROARCH, + "Próba połączenia online nie powiodła się, ponieważ peer nie działa w trybie RetroArch lub działa w starej wersji RetroArch." + ) +MSG_HASH( + MSG_NETPLAY_OUT_OF_DATE, + "Grający online, peer ma starą wersję RetroArch. Nie można połączyć." + ) +MSG_HASH( + MSG_NETPLAY_DIFFERENT_VERSIONS, + "OSTRZEŻENIE: Grający w online ma inną wersję RetroArch. Jeśli wystąpią problemy, użyj tej samej wersji." + ) +MSG_HASH( + MSG_NETPLAY_DIFFERENT_CORES, + "Grający w online ma inny rdzeń. Nie można połączyć." + ) +MSG_HASH( + MSG_NETPLAY_DIFFERENT_CORE_VERSIONS, + "OSTRZEŻENIE: Grający w online ma inną wersję rdzenia. Jeśli wystąpią problemy, użyj tej samej wersji." + ) MSG_HASH( MSG_NETPLAY_ENDIAN_DEPENDENT, - "Ten rdzeń nie obsługuje net-play między architekturami w tych systemach" + "Ten rdzeń nie obsługuje gry internetwoej między architekturami w tych systemach" ) MSG_HASH( MSG_NETPLAY_PLATFORM_DEPENDENT, - "Ten rdzeń nie obsługuje netplay między architekturami" + "Ten rdzeń nie obsługuje gry online między architekturami" ) MSG_HASH( MSG_NETPLAY_ENTER_PASSWORD, - "Wprowadź hasło do serwera netplay:" + "Wprowadź hasło do serwera gry online:" ) MSG_HASH( MSG_NETPLAY_INCORRECT_PASSWORD, @@ -72,11 +108,11 @@ MSG_HASH( ) MSG_HASH( MSG_NETPLAY_SERVER_HANGUP, - "Klient netplay został odłączony" + "Klient gry online został odłączony" ) MSG_HASH( MSG_NETPLAY_CLIENT_HANGUP, - "Netplay odłączony" + "Gracz online odłączony" ) MSG_HASH( MSG_NETPLAY_CANNOT_PLAY_UNPRIVILEGED, @@ -86,13 +122,17 @@ MSG_HASH( MSG_NETPLAY_CANNOT_PLAY_NO_SLOTS, "Nie ma wolnych miejsc dla graczy" ) +MSG_HASH( + MSG_NETPLAY_CANNOT_PLAY_NOT_AVAILABLE, + "Żądane urządzenia wejściowe nie są dostępne" + ) MSG_HASH( MSG_NETPLAY_CANNOT_PLAY, "Nie można przełączyć do trybu odtwarzania" ) MSG_HASH( MSG_NETPLAY_PEER_PAUSED, - "Netplay \"%s\" wstrzymano" + "Gra online \"%s\" wstrzymano" ) MSG_HASH( MSG_NETPLAY_CHANGED_NICK, @@ -108,11 +148,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_HARD_SYNC, - "Hard-synchronize CPU i GPU. Zmniejsza opóźnienie kosztem wydajności." + "Trudna synchronizacja CPU i GPU. Zmniejsza opóźnienie kosztem wydajności." ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_THREADED, - "Poprawia wydajność kosztem opóźnień i częstszego rwania wideo. Używaj tylko wtedy, gdy nie możesz uzyskać pełnej prędkości w przeciwnym razie." + "Poprawia wydajność kosztem opóźnień i częstszego rwania obrazu. Używaj tylko wtedy, gdy nie możesz uzyskać pełnej prędkości w przeciwnym razie." ) MSG_HASH( MSG_AUDIO_VOLUME, @@ -192,7 +232,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_TAB, - "Pokoje Netplay" + "Pokoje gry online" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ASK_ARCHIVE, @@ -280,7 +320,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUTOSAVE_INTERVAL, - "SaveRAM Autozapis Interwału" + "Autozapis SaveRAM" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUTO_OVERRIDES_ENABLE, @@ -292,7 +332,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUTO_SHADERS_ENABLE, - "Automatycznie załaduj Presety Shadera" + "Automatycznie załaduj Shadery" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_BACK, @@ -304,7 +344,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_INFO, - "Info" + "Informacje" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_QUIT, @@ -336,11 +376,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_CONFIRM, - "Potwierdz/OK" + "Potwierdź/OK" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_INFO, - "Info" + "Informacje" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_QUIT, @@ -368,7 +408,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BLUETOOTH_ENABLE, - "Bluetooth Włącz" + "Włącz Bluetooth" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_BUILDBOT_ASSETS_URL, @@ -396,11 +436,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEAT_DATABASE_PATH, - "Oszukane Pliki" + "Oszukane pliki" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEAT_FILE, - "Oszukane Pliki" + "Oszukane pliki" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEAT_FILE_LOAD, @@ -420,7 +460,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, - "Osiągnięcia Trybu Hardcore" + "Osiągnięcia trybu hardcore" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_LEADERBOARDS_ENABLE, @@ -460,7 +500,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_VERBOSE_ENABLE, - "Osiągnięcia trybu Pełnego" + "Osiągnięcia trybu pełnego" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_AUTO_SCREENSHOT, + "Osiągnięcia automatyczne screenshot" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT, @@ -496,7 +540,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CONTENT_HISTORY_SIZE, - "Rozmiar listy historii") + "Rozmiar listy Historii") MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_ENTRY_REMOVE, "Zezwalaj na usuwanie wpisów") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SETTINGS, @@ -514,9 +558,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_ENABLE, MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFORMATION, "Informacje podstawowe") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_AUTHORS, - "Autorski") + "Autor") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_CATEGORIES, - "Kategorie") + "Kategoria") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_LABEL, "Etykieta rdzenia") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_NAME, @@ -524,7 +568,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_NAME, MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE, "Firmware(s)") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_LICENSES, - "Licencje") + "Licencja") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_PERMISSIONS, "Uprawnienia") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_SUPPORTED_EXTENSIONS, @@ -532,7 +576,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_SUPPORTED_EXTENSIONS, MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_MANUFACTURER, "Producent systemu") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_NAME, - "Nawa systemu") + "Nazwa systemu") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INPUT_REMAPPING_OPTIONS, "Sterowanie") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_LIST, @@ -578,7 +622,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_NONE, MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND, "Nie znaleziono katalogu.") MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_SETTINGS, - "Informator") + "Informacja") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_CYCLE_TRAY_STATUS, "Status tacy cyklowej dysku") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_IMAGE_APPEND, @@ -588,7 +632,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_INDEX, MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_OPTIONS, "Kontrola dysku") MSG_HASH(MENU_ENUM_LABEL_VALUE_DONT_CARE, - "Nie przejmuj się") + "Brak") MSG_HASH(MENU_ENUM_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST, "Pliki do pobrania") MSG_HASH(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE, @@ -638,11 +682,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_OPTIONS_IN_USE, MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP, "Pomoc") MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_AUDIO_VIDEO_TROUBLESHOOTING, - "Rozwiązywanie problemów audio / wideo") + "Rozwiązywanie problemów audio/wideo") MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_CHANGE_VIRTUAL_GAMEPAD, "Zmiana nakładki wirtualnego gamepada") MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_CONTROLS, - "Podstawowe kontrolki menu") + "Podstawowa kontrola menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_LIST, "Pomoc") MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_LOADING_CONTENT, @@ -668,57 +712,57 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ADC_TYPE, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ALL_USERS_CONTROL_MENU, "Menu sterowania wszystkich użytkowników") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X, - "Lewy Analog X") + "Lewy analog X") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_MINUS, - "Lewy analog X - (lewy)") + "Lewy analog X- (lewy)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_PLUS, - "Lewy analog X + (po prawej)") + "Lewy analog X+ (po prawej)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y, - "Left Analog Y") + "Lewy analog Y") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_MINUS, - "Lewy analogo Y- (w górę)") + "Lewy analog Y- (w górę)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_PLUS, - "Lewy analogo Y + (dół)") + "Lewy analog Y+ (dół)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X, - "Prawo Analog X") + "Prawo analog X") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_MINUS, "Prawy analog X- (po lewej)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_PLUS, - "Prawy analog X + (po prawej)") + "Prawy analog X+ (po prawej)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y, "Prawo analog Y") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_MINUS, "Prawy analog Y- (w górę)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_PLUS, - "Prawe analog Y + (w dół)") + "Prawy analog Y+ (w dół)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, - "Spust broni") + "Spust pada") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_RELOAD, - "Przeładowanie broni") + "Przeładowanie pada") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_A, - "Aux A broni") + "Aux A") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_B, - "Aux B broni") + "Aux B") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_C, - "Gun Aux C") + "Aux C") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_START, "Start broni") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_SELECT, - "Wybierz broń") + "Wybierz") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_UP, - "D-pad góra broń") + "D-pad góra") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_DOWN, - "D-pad dół broń") + "D-pad dół") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_LEFT, - "D-pad lewo broń") + "D-pad lewo") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_RIGHT, - "D-pad prawo broń") + "D-pad prawo") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_AUTODETECT_ENABLE, - "Włącz Autoconfig") + "Włącz autoconfig") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_AXIS_THRESHOLD, "Martwa strefa gałki analogowej") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_INPUT_SWAP_OK_CANCEL, - "Zamień Menu OK i Anuluj przyciski") + "Zamień menu ok i anuluj przyciski") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_BIND_ALL, "Zwiąż wszystko") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_BIND_DEFAULT_ALL, @@ -738,7 +782,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_INDEX, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DRIVER, "Sterownik wejściowy") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DUTY_CYCLE, - "Cykl obciążenia") + "Cykl zapisu") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BINDS, "Wejściowe powiązania skrótów") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ICADE_ENABLE, @@ -828,7 +872,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_GRAB_MOUSE_TOGGLE, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_GAME_FOCUS_TOGGLE, "Przełącznik ostrości gry") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_LOAD_STATE_KEY, - "Stan obciążenia") + "Wczytaj zapis") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE, "Przełączanie menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE, @@ -836,7 +880,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE, "Przełącznik wyciszania dźwięku") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH, - "Netplay przełącza tryb play / spectate") + "Netplay przełącza tryb play/spectate") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK, "Przełączanie klawiatury ekranowej") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OVERLAY_NEXT, @@ -859,6 +903,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_PREV, "Poprzedni moduł cieniujący") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION_HOLD_KEY, "Zwolnione tempo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION_KEY, + "Slow motion toggle") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS, "Slot zapisu -") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS, @@ -874,7 +920,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_HIDE_IN_MENU, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS, "Pokaż nakładki na nakładce") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS_PORT, - "Pokaż wejścia Posłuchaj portu") + "Pokaż wejścia portu") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR, "Zachowanie typu ankiety") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_EARLY, @@ -888,11 +934,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_PREFER_FRONT_TOUCH, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_REMAPPING_DIRECTORY, "Odwzorowanie wejścia") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_REMAP_BINDS_ENABLE, - "Włącz Remap Binds") + "Włącz Remap Powiązań") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_SAVE_AUTOCONFIG, "Zapisz Autoconfig") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_SETTINGS, - "Wkład") + "Sterowanie") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_SMALL_KEYBOARD_ENABLE, "Włącz małą klawiaturę") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_TOUCH_ENABLE, @@ -902,7 +948,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_TURBO_ENABLE, MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD, "Okres Turbo") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_USER_BINDS, - "Wprowadź użytkownika %u Binds") + "Wprowadź powiązania użytkownika %u") MSG_HASH(MENU_ENUM_LABEL_VALUE_INTERNAL_STORAGE_STATUS, "Status wewnętrznej pamięci") MSG_HASH(MENU_ENUM_LABEL_VALUE_JOYPAD_AUTOCONFIG_DIR, @@ -912,7 +958,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_JOYPAD_DRIVER, MSG_HASH(MENU_ENUM_LABEL_VALUE_LAKKA_SERVICES, "Usługi") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_CHINESE_SIMPLIFIED, - "chiński (Simplified)") + "chiński (Uproszczony)") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_CHINESE_TRADITIONAL, "chiński (Tradycyjny)") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_DUTCH, @@ -922,7 +968,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ENGLISH, MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ESPERANTO, "esperanto") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_FRENCH, - "Francuski") + "francuski") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_GERMAN, "niemiecki") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ITALIAN, @@ -938,15 +984,15 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_PORTUGUESE_BRAZIL, MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_PORTUGUESE_PORTUGAL, "portugalski (portugalia)") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_RUSSIAN, - "Russianrosyjski") + "rosyjski") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_SPANISH, - "Spanish") + "hiszpański") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_VIETNAMESE, "wietnamski") MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ARABIC, - "Arabic") + "arabski") MSG_HASH(MENU_ENUM_LABEL_VALUE_LEFT_ANALOG, - "Lewy analogowy") + "Lewy analog") MSG_HASH(MENU_ENUM_LABEL_VALUE_LIBRETRO_DIR_PATH, "Rdzeń") MSG_HASH(MENU_ENUM_LABEL_VALUE_LIBRETRO_INFO_PATH, @@ -962,7 +1008,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_HISTORY, MSG_HASH(MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST, "Załaduj zawartość") MSG_HASH(MENU_ENUM_LABEL_VALUE_LOAD_STATE, - "Stan obciążenia") + "Wczytaj zapis") MSG_HASH(MENU_ENUM_LABEL_VALUE_LOCATION_ALLOW, "Zezwalaj na lokalizację") MSG_HASH(MENU_ENUM_LABEL_VALUE_LOCATION_DRIVER, @@ -1028,25 +1074,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NAVIGATION_WRAPAROUND, MSG_HASH(MENU_ENUM_LABEL_VALUE_NEAREST, "Najbliższy") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY, - "Netplay") + "Gra online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ALLOW_SLAVES, "Zezwalaj na klientów w trybie slave") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CHECK_FRAMES, - "Netplay sprawdź klatki") + "Sprawdź klatki gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN, "Wejściowe klatki opóźnień") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE, "Zakres latencji wejściowych klatek") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES, - "Netplay opóźnij klatki") + "Opóźnij klatki gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT, - "Odłącz od hosta netplay") + "Odłącz od hosta gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE, - "Włącz Netplay") + "Włącz gre online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_CLIENT, - "Połącz się z hostem netplay") + "Połącz się z hostem gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_HOST, - "Uruchom hosta netplay") + "Uruchom hosta gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISABLE_HOST, "Zatrzymaj hosta gry") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_IP_ADDRESS, @@ -1054,29 +1100,49 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_IP_ADDRESS, MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_LAN_SCAN_SETTINGS, "Zeskanuj sieć lokalną") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_MODE, - "Włącz klienta Netplay") + "Włącz klienta gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_NICKNAME, "Nazwa Użytkownika") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD, "Hasło serwera") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PUBLIC_ANNOUNCE, - "Publicznie ogłosić grę na Netplay") + "Publicznie ogłosić grę na online") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUEST_DEVICE_I, + "Zażądaj urządzenia %u") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUIRE_SLAVES, "Odmów klientów w trybie innym niż slave") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SETTINGS, - "Ustawienia Netplay") + "Ustawienia gry online") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG, + "Udostępnianie wejścia analogowego") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_MAX, + "Max") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_AVERAGE, + "Średni") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL, + "Udostępnianie wejścia cyfrowego") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_OR, + "Podziel") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_XOR, + "Zahacz") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_VOTE, + "Głosuj") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NONE, + "Żaden") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NO_PREFERENCE, + "Bez preferencji") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_START_AS_SPECTATOR, - "Tryb Netplay Spectator") + "Tryb widza gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_STATELESS_MODE, - "Tryb bezstanowej Netplay") + "Tryb bezstanowej gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SPECTATE_PASSWORD, "Hasło spontaniczne serwera") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SPECTATOR_MODE_ENABLE, - "Netplay Spectator Włączone") + "Widz gry online Włączone") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_TCP_UDP_PORT, - "Port TCP Netplay") + "Port TCP gry online") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_NAT_TRAVERSAL, - "Netplay NAT Traversal") + "Gra online NAT Traversal") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_CMD_ENABLE, "Polecenia sieciowe") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_CMD_PORT, @@ -1112,7 +1178,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_HISTORY_AVAILABLE, MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_INFORMATION_AVAILABLE, "Brak informacji.") MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_ITEMS, - "Nie ma przedmiotów.") + "Nie ma plików.") MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_NETPLAY_HOSTS_FOUND, "Nie znaleziono hostów netplay.") MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_NETWORKS_FOUND, @@ -1128,13 +1194,13 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND, MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_SHADER_PARAMETERS, "Brak parametrów modułu cieniującego.") MSG_HASH(MENU_ENUM_LABEL_VALUE_OFF, - "OFF") + "Wyłącz") MSG_HASH(MENU_ENUM_LABEL_VALUE_ON, - "ON") + "Włącz") MSG_HASH(MENU_ENUM_LABEL_VALUE_ONLINE, "Online") MSG_HASH(MENU_ENUM_LABEL_VALUE_ONLINE_UPDATER, - "Online Updater") + "Aktualizacja online") MSG_HASH(MENU_ENUM_LABEL_VALUE_ONSCREEN_DISPLAY_SETTINGS, "Wyświetlacz na ekranie") MSG_HASH(MENU_ENUM_LABEL_VALUE_ONSCREEN_OVERLAY_SETTINGS, @@ -1162,7 +1228,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY_SETTINGS, MSG_HASH(MENU_ENUM_LABEL_VALUE_PAL60_ENABLE, "Użyj trybu PAL60") MSG_HASH(MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY, - "Nadrzędna Lokalizacja") + "Nadrzędny katalog") MSG_HASH(MENU_ENUM_LABEL_VALUE_PAUSE_LIBRETRO, "Wstrzymaj przy włączonym menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_PAUSE_NONACTIVE, @@ -1176,7 +1242,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_DIRECTORY, MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_SETTINGS, "Listy odtwarzania") MSG_HASH(MENU_ENUM_LABEL_VALUE_POINTER_ENABLE, - "Dotknij Wsparcie") + "Wsparcie dotyku") MSG_HASH(MENU_ENUM_LABEL_VALUE_PORT, "Port") MSG_HASH(MENU_ENUM_LABEL_VALUE_PRESENT, @@ -1256,7 +1322,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_DRIVER, MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_ENABLE, "Włącz nagrywanie") MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_PATH, - "Zapisz zapisywanie wyjścia jako...") + "Zapisz wyjścia jako...") MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_USE_OUTPUT_DIRECTORY, "Zapisz nagrania w katalogu wyjściowym") MSG_HASH(MENU_ENUM_LABEL_VALUE_REMAP_FILE, @@ -1286,7 +1352,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROKEYBOARD, MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROPAD, "Retro pad") MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROPAD_WITH_ANALOG, - "Retro pad w/ Analog") + "Retro pad w/Analog") MSG_HASH(MENU_ENUM_LABEL_VALUE_RETRO_ACHIEVEMENTS_SETTINGS, "Osiągnięcia") MSG_HASH(MENU_ENUM_LABEL_VALUE_REWIND_ENABLE, @@ -1307,6 +1373,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES, "Dodaj do ulubionych") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES_PLAYLIST, "Dodaj do ulubionych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RESET_CORE_ASSOCIATION, + "Resetuj podstawowy rdzeń") MSG_HASH(MENU_ENUM_LABEL_VALUE_RUN, "Biec") MSG_HASH(MENU_ENUM_LABEL_VALUE_RUN_MUSIC, @@ -1324,7 +1392,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_SAVE, MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_DIRECTORY, "Zapisz stan") MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_THUMBNAIL_ENABLE, - "Zapisz Miniatury") + "Zapisz miniatury") MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG, "Zapisz bieżącą konfigurację") MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_CORE, @@ -1334,7 +1402,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_GAME, MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_NEW_CONFIG, "Zapisz nową konfigurację") MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_STATE, - "Zapisz stans") + "Zapisz stan") MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVING_SETTINGS, "Zapisywanie") MSG_HASH(MENU_ENUM_LABEL_VALUE_SCAN_DIRECTORY, @@ -1378,9 +1446,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SHUTDOWN, MSG_HASH(MENU_ENUM_LABEL_VALUE_SLOWMOTION_RATIO, "Współczynnik powolnego ruchu") MSG_HASH(MENU_ENUM_LABEL_VALUE_SORT_SAVEFILES_ENABLE, - "Sort Saves In Folders") + "Sortuj zapisy w folderach") MSG_HASH(MENU_ENUM_LABEL_VALUE_SORT_SAVESTATES_ENABLE, - "Sortuj zapisz stany w folderach") + "Sortuj zapis w folderach") MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATES_IN_CONTENT_DIR_ENABLE, "Napisz zapis stanów do treści dir") MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVEFILES_IN_CONTENT_DIR_ENABLE, @@ -1398,7 +1466,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_START_NET_RETROPAD, MSG_HASH(MENU_ENUM_LABEL_VALUE_START_VIDEO_PROCESSOR, "Uruchom procesor wideo") MSG_HASH(MENU_ENUM_LABEL_VALUE_STATE_SLOT, - "Slot stanu") + "Slot zapisu") MSG_HASH(MENU_ENUM_LABEL_VALUE_STATUS, "Status") MSG_HASH(MENU_ENUM_LABEL_VALUE_STDIN_CMD_ENABLE, @@ -1446,7 +1514,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DYNAMIC_SUPPORT, MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_EGL_SUPPORT, "Wsparcie EGL") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FBO_SUPPORT, - "Obsługuje renderowanie do tekstury (shadery wieloprzebiegowe) OpenGL / Direct3D") + "Obsługuje renderowanie do tekstury (shadery wieloprzebiegowe) OpenGL/Direct3D") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FFMPEG_SUPPORT, "Wsparcie FFmpeg") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FREETYPE_SUPPORT, @@ -1466,7 +1534,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_HLSL_SUPPORT, MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_JACK_SUPPORT, "Obsługa JACK") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_KMS_SUPPORT, - "Obsługa KMS / EGL") + "Obsługa KMS/EGL") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LAKKA_VERSION, "Wersja Lakka") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBRETRODB_SUPPORT, @@ -1474,11 +1542,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBRETRODB_SUPPORT, MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBUSB_SUPPORT, "Wsparcie Libusb") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBXML2_SUPPORT, - "libxml2 Obsługa parsowania XML") + "libxml2 obsługa parowania XML") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETPLAY_SUPPORT, "Wsparcie Netplay (peer-to-peer)") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETWORK_COMMAND_IFACE_SUPPORT, - "Obsługa interfejsu sieciowego Command") + "Obsługa interfejsu dowodzenia sieciowego") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETWORK_REMOTE_SUPPORT, "Obsługa sieciowego gamepada") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENAL_SUPPORT, @@ -1512,7 +1580,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_PYTHON_SUPPORT, MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RBMP_SUPPORT, "Obsługa BMP (RBMP)") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RETRORATING_LEVEL, - "Poziom RetroRating") + "Poziom Oceny Retro") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RJPEG_SUPPORT, "Obsługa JPEG (RJPEG)") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ROARAUDIO_SUPPORT, @@ -1552,7 +1620,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_XVIDEO_SUPPORT, MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ZLIB_SUPPORT, "Obsługa Zlib") MSG_HASH(MENU_ENUM_LABEL_VALUE_TAKE_SCREENSHOT, - "Zrobić zrzut ekranu") + "Zrób zrzut ekranu") MSG_HASH(MENU_ENUM_LABEL_VALUE_THREADED_DATA_RUNLOOP_ENABLE, "Zadania z wątkami") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS, @@ -1560,7 +1628,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS, MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY, "Miniatury") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST, - "Zaktualizuj Miniatury") + "Zaktualizuj miniatury") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_BOXARTS, "Boxarts") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_SCREENSHOTS, @@ -1568,7 +1636,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_SCREENSHOTS, MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_TITLE_SCREENS, "Ekrany tytułowe") MSG_HASH(MENU_ENUM_LABEL_VALUE_TIMEDATE_ENABLE, - "Pokaż datę / czas") + "Pokaż datę/czas") MSG_HASH(MENU_ENUM_LABEL_VALUE_TITLE_COLOR, "Kolor tytułu menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_TRUE, @@ -1588,7 +1656,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_UNDO_SAVE_STATE, MSG_HASH(MENU_ENUM_LABEL_VALUE_UNKNOWN, "Nieznany") MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATER_SETTINGS, - "Aktualizator") + "Aktualizacja") MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_ASSETS, "Zaktualizuj zasoby") MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_AUTOCONFIG_PROFILES, @@ -1658,7 +1726,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FORCE_ASPECT, MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FORCE_SRGB_DISABLE, "Wymuś wyłączenie sRGB FBO") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY, - "Opóźnienie ramki") + "Opóźnienie klatki") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FULLSCREEN, "Użyj trybu pełnoekranowego") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GAMMA, @@ -1670,7 +1738,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GPU_SCREENSHOT, MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC, "Trudna synchronizacja z GPU") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC_FRAMES, - "Twarde ramki do synchronizacji z GPU") + "Twarde klatki do synchronizacji z GPU") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES, "Maksymalne obrazy swapchain") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_POS_X, @@ -1684,7 +1752,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_POST_FILTER_RECORD, MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Odświeżanie w pionie") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, - "Szacunkowa liczba klatek na sekundę na ekranie") + "Szacowana liczba klatek na sekundę na ekranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Obrót") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1696,7 +1766,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SETTINGS, MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_DIR, "Moduł cieniujący wideo") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_NUM_PASSES, - "Shader Pass") + "Przepustka Shadera") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS, "Podgląd parametrów modułu cieniującego") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET, @@ -1705,6 +1775,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS, "Zapisz ustawienie Shadera jako") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_CORE, "Zapis ustawienia podstawowe rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_PARENT, + "Zapisz ustawienie zawartości katalogu \"zawartości\"") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_GAME, "Zapisz ustawienie gry") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHARED_CONTEXT, @@ -1748,7 +1820,13 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_WIFI_DRIVER, MSG_HASH(MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS, "Wi-Fi") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ALPHA_FACTOR, - "Menu Czynnik alfa") + "Menu czynnika alfa") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FONT_COLOR_RED, + "Kolor czcionki czerwony") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FONT_COLOR_GREEN, + "Kolor czcionki zielony") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FONT_COLOR_BLUE, + "Kolor czcionki niebieski") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_FONT, "Czcionka menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_CUSTOM, @@ -1758,7 +1836,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_FLATUI, MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_MONOCHROME, "Monochromia") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_MONOCHROME_INVERTED, - "Monochromia Inverted") + "Odwrócona monochromia") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_SYSTEMATIC, "Systematyczny") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_NEOACTIVE, @@ -1777,6 +1855,10 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_APPLE_GREEN, "Zielone jabłko") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_DARK, "Ciemny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_LIGHT, + "Jasny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_MORNING_BLUE, + "Poranny błękit") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_DARK_PURPLE, "Ciemny fiolet") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_ELECTRIC_BLUE, @@ -1794,13 +1876,13 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_UNDERSEA, MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_VOLCANIC_RED, "Czerwień wulkaniczna") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_RIBBON_ENABLE, - "Menu Shader Pipeline") + "Animowany efekt tłą") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SCALE_FACTOR, "Współczynnik skali menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHADOWS_ENABLE, "Włącz cienie ikony") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_HISTORY, - "Pokaż kartę historii") + "Pokaż kartę Historii") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_ADD, "Pokaż kartę Importuj zawartość") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_FAVORITES, @@ -1814,7 +1896,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS, MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Pokaż kartę Wideo") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, - "Pokaż kartę Netplay") + "Pokaż kartę Gry Online") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Motyw ikon menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1824,7 +1908,7 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_TWO, MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, "Włącz lub wyłącz osiągnięcia. Aby uzyskać więcej informacji, odwiedź http://retroachievements.org") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, - "Włącz lub wyłącz nieoficjalne osiągnięcia i / lub funkcje beta do celów testowych.") + "Włącz lub wyłącz nieoficjalne osiągnięcia i/lub funkcje beta do celów testowych.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, "Włączanie i wyłączanie stanów save, cheats, rewind, fast forward, pause i slow-motion dla wszystkich gier.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_LEADERBOARDS_ENABLE, @@ -1833,6 +1917,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE, "Włącz lub wyłącz wyświetlanie znaczków na liście osiągnięć.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_VERBOSE_ENABLE, "Włącz lub wyłącz powiadomienia OSD dla osiągnięć.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_AUTO_SCREENSHOT, + "Automatycznie wykonuj zrzut ekranu po uruchomieniu osiągnięcia.") MSG_HASH(MENU_ENUM_SUBLABEL_DRIVER_SETTINGS, "Zmień sterowniki używane przez system.") MSG_HASH(MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS, @@ -1888,9 +1974,9 @@ MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_USER_BINDS, MSG_HASH(MENU_ENUM_SUBLABEL_LOG_VERBOSITY, "Włącz lub wyłącz rejestrowanie w terminalu.") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY, - "Dołącz lub obsługuj sesję netplay.") + "Dołącz lub obsługuj sesję gry online.") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_LAN_SCAN_SETTINGS, - "Wyszukaj i połącz się z hostami netplay w sieci lokalnej.") + "Wyszukaj i połącz się z hostami gry online w sieci lokalnej.") MSG_HASH(MENU_ENUM_SUBLABEL_INFORMATION_LIST_LIST, "Wyświetl informacje o systemie.") MSG_HASH(MENU_ENUM_SUBLABEL_ONLINE_UPDATER, @@ -1900,7 +1986,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SAMBA_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_SERVICES_SETTINGS, "Zarządzaj usługami na poziomie systemu operacyjnego.") MSG_HASH(MENU_ENUM_SUBLABEL_SHOW_HIDDEN_FILES, - "Pokaż ukryte pliki / katalogi w przeglądarce plików.") + "Pokaż ukryte pliki/katalogi w przeglądarce plików.") MSG_HASH(MENU_ENUM_SUBLABEL_SSH_ENABLE, "Włącz lub wyłącz zdalny dostęp do wiersza poleceń.") MSG_HASH(MENU_ENUM_SUBLABEL_SUSPEND_SCREENSAVER_ENABLE, @@ -1912,15 +1998,17 @@ MSG_HASH(MENU_ENUM_SUBLABEL_USER_LANGUAGE, MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_BLACK_FRAME_INSERTION, "Wstawia czarną klatke między klatkami. Przydatny dla użytkowników z ekranami 120Hz, którzy chcą odtwarzać zawartość 60 Hz, aby wyeliminować efekt duchów.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FRAME_DELAY, - "Zmniejsza opóźnienie kosztem większego ryzyka rwania wideo. Dodaje opóźnienie po V-Sync (w ms).") + "Zmniejsza opóźnienie kosztem większego ryzyka rwania obrazu. Dodaje opóźnienie po V-Sync (w ms).") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_HARD_SYNC_FRAMES, - "Określa liczbę klatek, jaką procesor może uruchomić przed GPU, gdy używana jest 'Hard GPU Sync'.") + "Określa liczbę klatek, jaką procesor może uruchomić przed GPU, gdy używana jest 'Trudna synchronizacja z GPU'.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, "Informuje sterownik wideo, aby jawnie użył określonego trybu buforowania.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Określa, który ekran wyświetlacza ma być używany.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "Dokładna szacowana częstotliwość odświeżania ekranu w Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Zmień ustawienia wyjścia wideo.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -1929,6 +2017,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_HELP_LIST, "Dowiedz się więcej o tym, jak działa program.") MSG_HASH(MSG_ADDED_TO_FAVORITES, "Dodano do ulubionych") +MSG_HASH(MSG_RESET_CORE_ASSOCIATION, + "Playlist entry core association has been reset.") MSG_HASH(MSG_APPENDED_DISK, "Dołączony dysk") MSG_HASH(MSG_APPLICATION_DIR, @@ -1942,7 +2032,7 @@ MSG_HASH(MSG_AUDIO_MUTED, MSG_HASH(MSG_AUDIO_UNMUTED, "Dźwięk nie jest wyciszony.") MSG_HASH(MSG_AUTOCONFIG_FILE_ERROR_SAVING, - "Błąd podczas zapisywania pliku autoconf.") + "Błąd podczas zapisywania pliku autoconfig.") MSG_HASH(MSG_AUTOCONFIG_FILE_SAVED_SUCCESSFULLY, "Plik Autoconfig został pomyślnie zapisany.") MSG_HASH(MSG_AUTOSAVE_FAILED, @@ -1958,7 +2048,7 @@ MSG_HASH(MSG_BYTES, MSG_HASH(MSG_CANNOT_INFER_NEW_CONFIG_PATH, "Nie można określić nowej ścieżki konfiguracji. Użyj bieżącego czasu.") MSG_HASH(MSG_CHEEVOS_HARDCORE_MODE_ENABLE, - "Tryb Hardcore włączony, savestate i rewind były wyłączone.") + "Tryb Hardcore włączony, stan zapisu i przewijanie do tyłu były wyłączone.") MSG_HASH(MSG_COMPARING_WITH_KNOWN_MAGIC_NUMBERS, "Porównując ze znanymi magicznymi liczbami...") MSG_HASH(MSG_COMPILED_AGAINST_API, @@ -2009,6 +2099,8 @@ MSG_HASH(MSG_DISK_EJECTED, "Wyrzucony") MSG_HASH(MSG_DOWNLOADING, "Ściąganie") +MSG_HASH(MSG_INDEX_FILE, + "Index") MSG_HASH(MSG_DOWNLOAD_FAILED, "Pobieranie nie udane") MSG_HASH(MSG_ERROR, @@ -2138,9 +2230,9 @@ MSG_HASH(MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING, MSG_HASH(MSG_INFLATED_CHECKSUM_DID_NOT_MATCH_CRC32, "Skomplikowana suma kontrolna nie pasuje do CRC32.") MSG_HASH(MSG_INPUT_CHEAT, - "Wejdź w Cheat") + "Wejdź w kod") MSG_HASH(MSG_INPUT_CHEAT_FILENAME, - "Wprowadź nazwe Cheata") + "Wprowadź nazwe kodu") MSG_HASH(MSG_INPUT_PRESET_FILENAME, "Wprowadź wstępnie ustawioną nazwę pliku") MSG_HASH(MSG_INPUT_RENAME_ENTRY, @@ -2294,7 +2386,7 @@ MSG_HASH(MSG_TAKING_SCREENSHOT, MSG_HASH(MSG_TO, "do") MSG_HASH(MSG_UNDID_LOAD_STATE, - "Anulować stan obciążenia.") + "Anulować stan zpisu.") MSG_HASH(MSG_UNDOING_SAVE_STATE, "Cofanie stanu zapisu") MSG_HASH(MSG_UNKNOWN, @@ -2320,11 +2412,11 @@ MSG_HASH(MSG_VERSION_OF_LIBRETRO_API, MSG_HASH(MSG_VIEWPORT_SIZE_CALCULATION_FAILED, "Obliczenie wielkości wyświetlania nie powiodło się! Będzie nadal korzystać z nieprzetworzonych danych. Prawdopodobnie to nie zadziała ...") MSG_HASH(MSG_VIRTUAL_DISK_TRAY, - "wirtualna taca dysku.") + "Wirtualna taca dysku.") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_LATENCY, "Pożądane opóźnienie dźwięku w milisekundach. Może nie być honorowane, jeśli sterownik audio nie może zapewnić określonego opóźnienia.") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MUTE, - "Wycisz / włącz dźwięk.") + "Wycisz/włącz dźwięk.") MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_RATE_CONTROL_DELTA, "Pomaga wygładzać niedoskonałości w synchronizacji czasu podczas synchronizowania dźwięku i obrazu. Pamiętaj, że jeśli jest wyłączona, właściwa synchronizacja jest prawie niemożliwa do uzyskania." @@ -2475,9 +2567,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_RELEASEDATE_BY_MONTH, MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_RELEASEDATE_BY_YEAR, "Baza danych - Filtr: Data wydania na rok") MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_EDGE_MAGAZINE_ISSUE, - "Baza danych - Filter: Edge Magazine Issue") + "Baza danych - Filter: Problem z magazynem Edge") MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_EDGE_MAGAZINE_RATING, - "Baza danych - Filtr: Ocena czasopisma Edge") + "Baza danych - Filtr: Ocena magazynu Edge") MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_DATABASE_INFO, "Informacje o bazie danych") MSG_HASH(MSG_WIFI_SCAN_COMPLETE, @@ -2485,7 +2577,7 @@ MSG_HASH(MSG_WIFI_SCAN_COMPLETE, MSG_HASH(MSG_SCANNING_WIRELESS_NETWORKS, "Skanowanie sieci bezprzewodowych...") MSG_HASH(MSG_NETPLAY_LAN_SCAN_COMPLETE, - "Zakończono skanowanie Netplay.") + "Zakończono skanowanie gry online.") MSG_HASH(MSG_NETPLAY_LAN_SCANNING, "Skanowanie w poszukiwaniu hostów netplay...") MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, @@ -2553,7 +2645,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_USERNAME, MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_PASSWORD, "Wprowadź hasło do swojego konta RetroAchievements.") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_NICKNAME, - "Wprowadź tutaj swoją nazwę użytkownika. Będzie to wykorzystywane między innymi do sesji netplay.") + "Wprowadź tutaj swoją nazwę użytkownika. Będzie to wykorzystywane między innymi do gry internetowej.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_POST_FILTER_RECORD, "Przechwyć obraz po zastosowaniu filtrów (ale nie shaderów). Twój film będzie wyglądał tak fantazyjnie jak to, co widzisz na ekranie.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_LIST, @@ -2583,7 +2675,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FONT_SIZE, MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_OVERLAY_HIDE_IN_MENU, "Ukryj nakładkę w menu i pokaż ją ponownie po wyjściu z menu.") MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS, - "Pokaż wejścia klawiatury / kontrolera na nakładce ekranowej.") + "Pokaż wejścia klawiatury/kontrolera na nakładce ekranowej.") MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS_PORT, "Wybierz port dla nakładki, aby usłyszeć, czy opcja Pokaż nakładki na nakładkę jest włączona.") MSG_HASH( @@ -2592,7 +2684,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER, - "Skaluje wideo tylko w krokach całkowitych. Rozmiar bazy zależy od raportowanej przez system geometrii i współczynnika kształtu. Jeśli 'Force Aspect' nie jest ustawione, X / Y będzie liczbą całkowitą skalowaną niezależnie." + "Skaluje wideo tylko w krokach całkowitych. Rozmiar bazy zależy od raportowanej przez system geometrii i współczynnika kształtu. Jeśli 'Force Aspect' nie jest ustawione, X/Y będzie liczbą całkowitą skalowaną niezależnie." ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_GPU_SCREENSHOT, @@ -2620,7 +2712,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_INDEX, - "WPodczas zapisywania stanu, wskaźnik stanu zapisu jest automatycznie zwiększany przed zapisaniem. Podczas ładowania zawartości indeks zostanie ustawiony na najwyższy istniejący indeks." + "Podczas zapisywania stanu, wskaźnik stanu zapisu jest automatycznie zwiększany przed zapisaniem. Podczas ładowania zawartości indeks zostanie ustawiony na najwyższy istniejący indeks." ) MSG_HASH( MENU_ENUM_SUBLABEL_BLOCK_SRAM_OVERWRITE, @@ -2632,7 +2724,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_SLOWMOTION_RATIO, - "W zwolnionym tempie zawartość spowalnia o określony / ustawiony współczynnik." + "W zwolnionym tempie zawartość spowalnia o określony/ustawiony współczynnik." ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_ENABLE, @@ -2676,7 +2768,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL, - "Zamień przyciski na OK / Cancel. Wyłączone to orientacja japońskiego przycisku, włączona jest orientacja zachodnia." + "Zamień przyciski na OK/Anuluj. Wyłączone to orientacja japońskiego przycisku, włączona jest orientacja zachodnia." ) MSG_HASH( MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO, @@ -2688,7 +2780,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_DRIVER, - "Sterownik audio do nase." + "Sterownik audio do użycia." ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_DRIVER, @@ -2824,7 +2916,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE, - "Pokazuje aktualną datę i / lub czas w menu." + "Pokazuje aktualną datę i/lub czas w menu." ) MSG_HASH( MENU_ENUM_SUBLABEL_BATTERY_LEVEL_ENABLE, @@ -2832,7 +2924,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_NAVIGATION_WRAPAROUND, - "Oblewanie do początku i / lub końca, jeśli granica listy jest osiągnięta poziomo lub pionowo." + "Przewijanie do początku i/lub końca, jeśli granica listy jest osiągnięta poziomo lub pionowo." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_ENABLE_HOST, @@ -2855,6 +2947,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE, "Sortuj stany zachowywania w folderach nazwanych po używanym rdzeniu." ) +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_REQUEST_DEVICE_I, + "Request to play with the given input device.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL, "Adres URL do głównego katalogu Updater na kompilatorze Libretro.") MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL, @@ -2903,9 +2997,9 @@ MSG_HASH(MENU_ENUM_SUBLABEL_LOAD_STATE, MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_STATE, "Zapisz stan w aktualnie wybranym gnieździe.") MSG_HASH(MENU_ENUM_SUBLABEL_RESUME, - "Wznów aktualnie uruchomioną zawartość i opuść Szybkie menu.") + "Wznów aktualnie uruchomioną zawartość i opuść szybkie menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RESUME_CONTENT, - "Wznów aktualnie uruchomioną zawartość i opuść Szybkie men.") + "Wznów aktualnie uruchomioną zawartość i opuść szybkie menu.") MSG_HASH(MENU_ENUM_SUBLABEL_STATE_SLOT, "Zmienia aktualnie wybrany przedział stanu.") MSG_HASH(MENU_ENUM_SUBLABEL_UNDO_LOAD_STATE, @@ -2929,7 +3023,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CORE, MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_CURRENT_CONFIG_OVERRIDE_GAME, "Zapisuje plik konfiguracji zastąpienia, który będzie dotyczył tylko bieżącej treści. Ma pierwszeństwo przed główną konfiguracją.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_CHEAT_OPTIONS, - "Skonfiguruj kody oszustw.") + "Skonfiguruj kody.") MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_OPTIONS, "Skonfiguruj shadery, aby wizualnie powiększyć obraz.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_INPUT_REMAPPING_OPTIONS, @@ -2948,12 +3042,12 @@ MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_BROWSER_DIRECTORY, "Ustawia katalog startowy dla przeglądarki plików.") MSG_HASH( MENU_ENUM_SUBLABEL_CONTENT_DIR, - "Zwykle ustawiane przez programistów, którzy pakują aplikacje libretro / RetroArch, aby wskazywały na zasoby." + "Zwykle ustawiane przez programistów, którzy pakują aplikacje libretro/RetroArch, aby wskazywały na zasoby." ) MSG_HASH(MENU_ENUM_SUBLABEL_DYNAMIC_WALLPAPERS_DIRECTORY, "Katalog do przechowywania tapet dynamicznie ładowanych przez menu w zależności od kontekstu.") MSG_HASH(MENU_ENUM_SUBLABEL_THUMBNAILS_DIRECTORY, - "Dodatkowe miniaturki (boxarty / miscale itp.) Są tutaj przechowywane." + "Dodatkowe miniaturki (boxarty/miscale itp.) Są tutaj przechowywane." ) MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_CONFIG_DIRECTORY, "Ustawia katalog początkowy dla przeglądarki konfiguracji menu.") @@ -2971,6 +3065,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Wybierz obraz dysku, który chcesz wstawić.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Upewnia się, że liczba klatek na sekundę jest ograniczona w menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Wybierz inny motyw dla ikony. Zmiany zaczną obowiązywać po ponownym uruchomieniu programu.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3016,9 +3112,9 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CORE_ASSETS_DIRECTORY, MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_REMAPPING_DIRECTORY, "Zapisz wszystkie zmienione kontrolki do tego katalogu.") MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_DIR_PATH, - "Katalog, w którym program szuka treści / rdzeni.") + "Katalog, w którym program szuka treści/rdzeni.") MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_INFO_PATH, - "Pliki informacji o aplikacji / rdzeniu są tutaj przechowywane.") + "Pliki informacji o aplikacji/rdzeniu są tutaj przechowywane.") MSG_HASH(MENU_ENUM_SUBLABEL_JOYPAD_AUTOCONFIG_DIR, "Jeśli joypad jest podłączony, to joypad zostanie automatycznie skonfigurowany, jeśli plik konfiguracyjny odpowiadający mu jest obecny w tym katalogu.") MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_DIRECTORY, @@ -3076,7 +3172,9 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET, MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_AS, "Zapisz bieżące ustawienia modułu cieniującego jako nowe ustawienie domyślne modułu cieniującego.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_CORE, - "Zapisz bieżące ustawienia modułu cieniującego jako ustawienia domyślne dla tej aplikacji / rdzenia.") + "Zapisz bieżące ustawienia modułu cieniującego jako ustawienia domyślne dla tej aplikacji/rdzenia.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_PARENT, + "Save the current shader settings as the default settings for all files in the current content directory.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_GAME, "Zapisz bieżące ustawienia modułu cieniującego jako ustawienia domyślne dla zawartości.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PARAMETERS, @@ -3085,10 +3183,10 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_PARAMETERS, "Modyfikuje sam domyślne ustawienie modułu cieniującego w menu.") MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_NUM_PASSES, - "Zwiększ lub zmniejsz ilość cheatów." + "Zwiększ lub zmniejsz ilość kodów." ) MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_APPLY_CHANGES, - "Zmiany Cheat odniosą skutek natychmiast.") + "Zmiany kodu odniosą skutek natychmiast.") MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_FILE_LOAD, "Załaduj plik oszukiwać." @@ -3100,25 +3198,29 @@ MSG_HASH( MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SETTINGS, "Szybki dostęp do wszystkich istotnych ustawień w grze.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_INFORMATION, - "Wyświetl informacje dotyczące aplikacji / rdzenia.") + "Wyświetl informacje dotyczące aplikacji/rdzenia.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_ASPECT_RATIO, - "Wartość zmiennoprzecinkowa dla współczynnika proporcji wideo (szerokość / wysokość), jeśli współczynnik proporcji jest ustawiony na 'Config'.") + "Wartość zmiennoprzecinkowa dla współczynnika proporcji wideo (szerokość/wysokość), jeśli współczynnik proporcji jest ustawiony na 'Config'.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT, - "Niestandardowa wysokość rzutni, która jest używana, jeśli współczynnik proporcji jest ustawiony na 'Niestandardowy'.") + "Niestandardowa wysokość ekranu, która jest używana, jeśli współczynnik proporcji jest ustawiony na 'Niestandardowy'.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH, - "Niestandardowa szerokość rzutni, która jest używana, jeśli współczynnik proporcji jest ustawiony na 'Niestandardowy'.") + "Niestandardowa szerokość ekranu, która jest używana, jeśli współczynnik proporcji jest ustawiony na 'Niestandardowy'.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_X, - "Niestandardowe przesunięcie wyświetlania używane do definiowania położenia osi X w rzutni. Są one ignorowane, jeśli włączona jest opcja 'Integer Scale'. Zostanie wtedy automatycznie wyśrodkowany.") + "Niestandardowe przesunięcie wyświetlania używane do definiowania położenia osi X. Są one ignorowane, jeśli włączona jest opcja 'Integer Scale'. Zostanie wtedy automatycznie wyśrodkowany.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_Y, - "Niestandardowe przesunięcie wyświetlania używane do definiowania położenia osi Y w rzutni. Są one ignorowane, jeśli włączona jest opcja 'Integer Scale'. Zostanie wtedy automatycznie wyśrodkowany.") + "Niestandardowe przesunięcie wyświetlania używane do definiowania położenia osi Y. Są one ignorowane, jeśli włączona jest opcja 'Integer Scale'. Zostanie wtedy automatycznie wyśrodkowany.") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_USE_MITM_SERVER, "Użyj serwera przekazywania") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_USE_MITM_SERVER, - "Przekaż połączenia sieciowe przez serwer pośredniczący. Przydatne, jeśli host znajduje się za zaporą lub ma problemy z NAT / UPnP.") + "Przekaż połączenia sieciowe przez serwer pośredniczący. Przydatne, jeśli host znajduje sięs za zaporą lub ma problemy z NAT/UPnP.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_MITM_SERVER, + "Lokalizacja serwera przekaźnikowego") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_MITM_SERVER, + "Wybierz określony serwer przekazujący, którego chcesz użyć. Geograficznie bliższe lokalizacje mają zazwyczaj mniejsze opóźnienie.") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER, - "Dodaj do mikser") + "Dodaj do miksera") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION, - "Dodaj do mikser") + "Dodaj do miksera") MSG_HASH(MENU_ENUM_LABEL_VALUE_FILTER_BY_CURRENT_CORE, "Filtruj według bieżącego rdzenia") MSG_HASH( @@ -3135,14 +3237,14 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_MUTE, - "Mikser dźwięku Wycisz" + "Wycisz mikser dźwięku" ) MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MIXER_MUTE, - "Wycisz / włącz dźwięk miksera.") + "Wycisz/włącz dźwięk miksera.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_ONLINE_UPDATER, - "Pokaż Online Updater") + "Pokaż aktualizacje online") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_ONLINE_UPDATER, - "Pokaż / ukryj opcję 'Online Update'.") + "Pokaż/ukryj opcję 'Aktualizacja online'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_VIEWS_SETTINGS, "Widok") MSG_HASH( @@ -3152,7 +3254,7 @@ MSG_HASH( MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CORE_UPDATER, "Pokaż program Updater rdzenia") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CORE_UPDATER, - "Pokaż / ukryj możliwość aktualizacji rdzeni (i podstawowych plików informacyjnych).") + "Pokaż/ukryj możliwość aktualizacji rdzeni (i podstawowych plików informacyjnych).") MSG_HASH(MSG_PREPARING_FOR_CONTENT_SCAN, "Przygotowanie do skanowania zawartości...") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_DELETE, @@ -3160,7 +3262,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_DELETE, MSG_HASH(MENU_ENUM_SUBLABEL_CORE_DELETE, "Usuń ten rdzeń z dysku.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FRAMEBUFFER_OPACITY, - "Framebuffer Opacity") + "Nieprzezroczysty buffor klatki") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_FRAMEBUFFER_OPACITY, "Zmodyfikuj krycie bufora klatki.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES, @@ -3182,7 +3284,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_VIDEO, MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_ICONS_ENABLE, "Ikony menu") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_ICONS_ENABLE, - "Włącz / wyłącz ikony menu pokazane po lewej stronie wpisów menu.") + "Włącz/wyłącz ikony menu pokazane po lewej stronie wpisów menu.") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MAIN_MENU_ENABLE_SETTINGS, "Włącz kartę Ustawienia") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS_PASSWORD, @@ -3208,31 +3310,31 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY, MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CORE, "Pokaż ładowanie rdzenia") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CORE, - "Pokaż / ukryj opcję 'Załaduj rdzeń'.") + "Pokaż/ukryj opcję 'Załaduj rdzeń'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CONTENT, "Pokaż ładunek zawartości") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CONTENT, - "Pokaż / ukryj opcję \"Wczytaj zawartość\".") + "Pokaż/ukryj opcję \"Wczytaj zawartość\".") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_INFORMATION, "Pokaż informacje") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_INFORMATION, - "Show/hide the 'Information' option.") + "Pokaż/ukryj opcję 'Informacje'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CONFIGURATIONS, "Pokaż konfiguracje") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CONFIGURATIONS, - "Pokaż / ukryj opcję 'Konfiguracje'.") + "Pokaż/ukryj opcję 'Konfiguracje'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_HELP, "Pokaż pomoc") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_HELP, - "Pokaż / ukryj opcję \"Pomoc\".") + "Pokaż/ukryj opcję \"Pomoc\".") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_QUIT_RETROARCH, "Pokaż Zamknij RetroArch") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_QUIT_RETROARCH, - "Pokaż / ukryj opcję 'Zamknij RetroArch'.") + "Pokaż/ukryj opcję 'Zamknij RetroArch'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_REBOOT, "Pokaż restart") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_REBOOT, - "Pokaż / ukryj opcję 'Reboot'.") + "Pokaż/ukryj opcję 'Restart'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_VIEWS_SETTINGS, "Szybkie menu") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_VIEWS_SETTINGS, @@ -3240,47 +3342,47 @@ MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_VIEWS_SETTINGS, MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_TAKE_SCREENSHOT, "Pokaż zrzut ekranu") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_TAKE_SCREENSHOT, - "Pokaż / ukryj opcję \"Zrób zrzut ekranu\".") + "Pokaż/ukryj opcję \"Zrób zrzut ekranu\".") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_LOAD_STATE, - "Pokaż stan zapisywania / ładowania") + "Pokaż stan zapisywania/ładowania") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_LOAD_STATE, - "Pokaż / ukryj opcje zapisywania / ładowania stanu.") + "Pokaż/ukryj opcje zapisywania/ładowania stanu.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, - "Pokaż Cofnij zapisanie / załadowanie stanu") + "Pokaż cofnij zapisanie/załadowanie stanu") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, - "Pokaż / ukryj opcje cofania stanu zapisywania / ładowania.") + "Pokaż/ukryj opcje cofania stanu zapisywania/ładowania.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_ADD_TO_FAVORITES, - "Pokaż Dodaj do ulubionych") + "Pokaż dodaj do ulubionych") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_ADD_TO_FAVORITES, - "Pokaż / ukryj opcję 'Dodaj do ulubionych'.") + "Pokaż/ukryj opcję 'Dodaj do ulubionych'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_OPTIONS, "Pokaż opcje") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_OPTIONS, - "Pokaż / ukryj opcję 'Opcje'.") + "Pokaż/ukryj opcję 'Opcje'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CONTROLS, "Pokaż elementy sterujące") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CONTROLS, - "Pokaż / ukryj opcję 'Sterowanie'.") + "Pokaż/ukryj opcję 'Sterowanie'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CHEATS, "Pokaż kody") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CHEATS, - "Pokaż / ukryj opcję 'Cheaty'.") + "Pokaż/ukryj opcję 'Kody'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SHADERS, "Pokaż shadery") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SHADERS, - "Pokaż / ukryj opcję 'Shader'.") + "Pokaż/ukryj opcję 'Shadery'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, "Pokaż zapis nadpisu rdzenia") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, - "Pokaż / ukryj opcję 'Zapisz przesłonięcia podstawowe'.") + "Pokaż/ukryj opcję 'Zapisz podstawowe przesłonięcia'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, - "Pokaż zapisywanie zmian gry") + "Pokaż zapisy gry") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, - "Pokaż / ukryj opcję 'Zachowaj pominięcia gry'.") + "Pokaż/ukryj opcję 'Zachowaj pominięcia gry'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_INFORMATION, "Pokaż informacje") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_INFORMATION, - "Pokaż / ukryj opcję 'Informacje'.") + "Pokaż/ukryj opcję 'Informacje'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_ENABLE, "Tło powiadomień Włącz") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_RED, @@ -3332,10 +3434,38 @@ MSG_HASH(MSG_SCANNING_OF_FILE_FINISHED, MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OPACITY, "Przezroczystość okna") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, - "Audio Resampler Quality") + "Jakość resamplera audio") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, - "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") + "Obniż tę wartość, aby faworyzować wydajność/zmniejszyć opóźnienie w stosunku do jakości dźwięku, zwiększaj, jeśli chcesz uzyskać lepszą jakość dźwięku kosztem wydajności/mniejszego opóźnienia.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES, + "Oglądaj pliki modułu cieniującego w poszukiwaniu zmian") +MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES, + "Automatycznie zastosuj zmiany wprowadzone w plikach modułu cieniującego na dysku.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_SHOW_DECORATIONS, + "Pokaż dekoracje okien") MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, - "Display Statistics") + "Wyświetl statystyki") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, - "Show onscreen technical statistics.") + "Pokaż techniczne statystyki na ekranie.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_pt_br.h b/intl/msg_hash_pt_br.h index 109f33450a..6befea4583 100644 --- a/intl/msg_hash_pt_br.h +++ b/intl/msg_hash_pt_br.h @@ -1,4 +1,4 @@ -MSG_HASH(MSG_COMPILER, +MSG_HASH(MSG_COMPILER, "Compilador" ) MSG_HASH(MSG_UNKNOWN_COMPILER, @@ -37,6 +37,42 @@ MSG_HASH(MSG_NETPLAY_YOU_HAVE_LEFT_THE_GAME, MSG_HASH(MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N, "Você se juntou como jogador %u" ) +MSG_HASH( + MSG_NETPLAY_YOU_HAVE_JOINED_WITH_INPUT_DEVICES_S, + "Você se juntou aos dispositivos de entrada %.*s" + ) +MSG_HASH( + MSG_NETPLAY_PLAYER_S_LEFT, + "O jogador %.*s deixou o jogo" + ) +MSG_HASH( + MSG_NETPLAY_S_HAS_JOINED_AS_PLAYER_N, + "%.*s se juntou como jogador %u" + ) +MSG_HASH( + MSG_NETPLAY_S_HAS_JOINED_WITH_INPUT_DEVICES_S, + "%.*s juntou-se a dispositivos de entrada %.*s" + ) +MSG_HASH( + MSG_NETPLAY_NOT_RETROARCH, + "Uma tentativa de conexão com o netplay falhou porque o par não está executando o RetroArch ou está executando uma versão antiga do RetroArch." + ) +MSG_HASH( + MSG_NETPLAY_OUT_OF_DATE, + "O par netplay está executando uma versão antiga do RetroArch. Não pode conectar." + ) +MSG_HASH( + MSG_NETPLAY_DIFFERENT_VERSIONS, + "ATENÇÃO: Um par de Netplay está executando uma versão diferente do RetroArch. Se ocorrerem problemas, use a mesma versão." + ) +MSG_HASH( + MSG_NETPLAY_DIFFERENT_CORES, + "Um par de netplay está executando um núcleo diferente. Não pode conectar." + ) +MSG_HASH( + MSG_NETPLAY_DIFFERENT_CORE_VERSIONS, + "ATENÇÃO: Um par de Netplay está executando uma versão diferente do núcleo. Se ocorrerem problemas, use a mesma versão." + ) MSG_HASH(MSG_NETPLAY_ENDIAN_DEPENDENT, "Este núcleo não suporta Netplay inter-arquitetura entre estes sistemas" ) @@ -316,6 +352,14 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_DESCRIPTION, MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, "Conquistas no Modo Hardcore" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_LEADERBOARDS_ENABLE, + "Tabelas de Classificação" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_BADGES_ENABLE, + "Insígnias de Conquistas" + ) MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ACHIEVEMENTS, "Conquistas Bloqueadas:" ) @@ -328,17 +372,27 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_SETTINGS, MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_TEST_UNOFFICIAL, "Testar Conquistas Não Oficiais" ) -MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_VERBOSE_ENABLE, - "Modo Detalhado das Conquistas" - ) MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ACHIEVEMENTS, "Conquistas Desbloqueadas:" ) MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY, "Desbloqueada" ) -MSG_HASH(MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT, - "Fechar Conteúdo" +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY_HARDCORE, + "Hardcore" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_VERBOSE_ENABLE, + "Conquistas Modo Verboso" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_AUTO_SCREENSHOT, + "Captura de Conquistas Automática" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT, + "Fechar Conteúdo" ) MSG_HASH(MENU_ENUM_LABEL_VALUE_CONFIG, "Configuração" @@ -1189,14 +1243,32 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD, "Senha do Servidor" ) MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PUBLIC_ANNOUNCE, - "Anunciar Netplay Publicamente" - ) + "Anunciar Netplay Publicamente") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUEST_DEVICE_I, + "Solicitar Dispositivo %u") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUIRE_SLAVES, "Não Permitir Clientes em Modo Não Escravo" ) MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SETTINGS, - "Configurações do Netplay" - ) + "Configurações do Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG, + "Compartilhamento de Entrada Analógica") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_MAX, + "Máximo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_AVERAGE, + "Médio") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL, + "Compartilhamento de Entrada Digital") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_OR, + "Compartilhar") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_XOR, + "Agarrar") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_VOTE, + "Eleger") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NONE, + "Nenhum") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NO_PREFERENCE, + "Sem preferência") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_START_AS_SPECTATOR, "Modo Espectador do Netplay" ) @@ -1933,8 +2005,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_THREADED_DATA_RUNLOOP_ENABLE, "Paralelismo de tarefas" ) MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS, - "Miniaturas" - ) + "Miniaturas") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS, + "Miniaturas à esquerda") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY, "Miniaturas" ) @@ -2124,6 +2197,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Taxa de Quadros Estimada da Tela" ) +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate" + ) MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotação" ) @@ -2319,6 +2395,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Exibir Aba de Netplay" ) +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Tema de Ícones do Menu" ) @@ -2335,11 +2413,15 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, "Habilitar ou desabilitar conquistas não oficiais e/ou recursos beta para fins de teste." ) MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, - "Habilitar ou desabilitar Estado de Jogo, Trapaças, Voltar Atrás, Avanço Rápido, Pausa e Câmera Lenta para todos os jogos." - ) + "Habilitar ou desabilitar Estado de Jogo, Trapaças, Voltar Atrás, Pausa e Câmera Lenta para todos os jogos.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_LEADERBOARDS_ENABLE, + "Ativar ou desativar tabelas de classificação no jogo. Não tem efeito se o modo Hardcore estiver desativado.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE, + "Ativar ou desativar a exibição de insígnia na Lista de Conquistas.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_VERBOSE_ENABLE, - "Habilitar ou desabilitar detalhes das conquistas na tela." - ) + "Habilitar ou desabilitar detalhes das conquistas na tela.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_AUTO_SCREENSHOT, + "Obter automaticamente uma captura de tela quando uma conquista é acionada.") MSG_HASH(MENU_ENUM_SUBLABEL_DRIVER_SETTINGS, "Alterar os drivers utilizados pelo sistema." ) @@ -2472,6 +2554,9 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "A taxa de atualização estimada da tela em Hz." ) +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver." + ) MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Alterar as configurações de saída de vídeo." ) @@ -2748,6 +2833,46 @@ MSG_HASH(MSG_FAILED_TO_UNDO_LOAD_STATE, MSG_HASH(MSG_FAILED_TO_UNDO_SAVE_STATE, "Falha em desfazer o salvamento de Estado de Jogo." ) +MSG_HASH( + MENU_ENUM_SUBLABEL_SAVESTATE_THUMBNAIL_ENABLE, + "Mostrar miniaturas de estados salvos dentro do menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUTOSAVE_INTERVAL, + "Salvar automaticamente o Save RAM não-volátil em um intervalo regular. Isso está desabilitado por padrão, a menos que seja definido de outra forma. O intervalo é medido em segundos. Um valor de 0 desativa o salvamento automático." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE, + "Se ativado, substitui os vínculos de entrada com as associações remapeadas definidas para o núcleo atual." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE, + "Ativa a detecção automática de entrada. Tentará autoconfigurar joypads, estilo Plug-and-Play." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL, + "Troca de botões para OK/Cancelar. Desabilitado é o estilo de botão japonês, habilitada é oestilo ocidental." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO, + "Se desabilitado, o conteúdo continuará sendo executado em segundo plano quando o menu do RetroArch for alternado." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_DRIVER, + "Driver de vídeo para usar." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_DRIVER, + "Driver de áudio para usar." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_DRIVER, + "Driver de entrada para usar. Dependendo do driver de vídeo, pode forçar um driver de entrada diferente." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_JOYPAD_DRIVER, + "Driver do Joypad para usar." + ) MSG_HASH(MSG_FAILED_TO_UNMUTE_AUDIO, "Falha em desativar o áudio mudo." ) @@ -3414,36 +3539,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_SAVE, MSG_HASH(MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_LOAD, "Autocarrega o último Estado de Jogo autosalvo na inicialização do RetroArch." ) -MSG_HASH(MENU_ENUM_SUBLABEL_SAVESTATE_THUMBNAIL_ENABLE, - "Exibe miniaturas dos Estados de Jogo salvos dentro do menu." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_AUTOSAVE_INTERVAL, - "Salva automaticamente a SRAM não volátil em um intervalo regular. Isto é desativado por padrão a menos que seja definido de outra forma. O intervalo é medido em segundos. O valor 0 desativa o salvamento automático." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE, - "Se habilitado, substitui os vínculos de entrada com os vínculos remapeados definidos pelo núcleo atual." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE, - "Habilita a detecção automática de entrada. Isto tentará configurar automaticamente Joypads no estilo 'Plug-and-Play'." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL, - "Inverte os botões para OK/Cancelar. Desabilitado é o estilo japonês, habilitado é o estilo ocidental." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO, - "Se desabilitado, o conteúdo continuará rodando em segundo plano quando o menu do RetroArch é alternado." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DRIVER, - "Driver de vídeo a ser utilizado." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_DRIVER, - "Driver de áudio a ser utilizado." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_DRIVER, - "Driver de entrada a ser utilizado. Dependendo do driver de vídeo, pode forçar um driver de entrada diferente." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_JOYPAD_DRIVER, - "Driver de Joypad a ser utilizado." - ) MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_DRIVER, "Driver de reamostragem de áudio a ser utilizado." ) @@ -3536,7 +3631,11 @@ MSG_HASH(MENU_ENUM_SUBLABEL_POINTER_ENABLE, ) MSG_HASH(MENU_ENUM_SUBLABEL_THUMBNAILS, "Tipo de miniatura a ser exibida." - ) + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS, + "Tipo de miniatura para exibir à esquerda." + ) MSG_HASH(MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE, "Exibir data e/ou hora atuais dentro do menu." ) @@ -3570,6 +3669,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE, "Ordenar os Estados de Jogo em pastas com o nome do núcleo utilizado." ) +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_REQUEST_DEVICE_I, + "Solicitar jogar com o dispositivo de entrada dado.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL, "URL para o diretório de atualização de núcleos no buildbot do Libreto." ) @@ -3723,6 +3824,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Certifica-se de que a taxa de quadros é controlada enquanto estiver dentro do menu." ) +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Selecionar um tema diferente para os ícones. As alterações terão efeito após reiniciar o programa." ) @@ -3907,8 +4010,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_USE_MITM_SERVER, "Utilizar Servidor MITM" ) MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_USE_MITM_SERVER, - "Encaminhar conexões do Netplay através de um servidor 'homem no meio' (MITM). Útil se o hospedeiro estiver atrás de um firewall ou tiver problemas de NAT/UPnP." - ) + "Encaminhar conexões do Netplay através de um servidor 'homem no meio' (MITM). Útil se o hospedeiro estiver atrás de um firewall ou tiver problemas de NAT/UPnP.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_MITM_SERVER, + "Localização do Servidor de Retransmissão") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_MITM_SERVER, + "Escolha um servidor de retransmissão específico para usar. Locais geograficamente mais próximos tendem a ter menor latência.") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER, "Adicionar ao mixer" ) @@ -3940,11 +4046,11 @@ MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_ONLINE_UPDATER, "Exibir a opção 'Atualizador Online'." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_VIEWS_SETTINGS, - "Visualizações" - ) -MSG_HASH(MENU_ENUM_SUBLABEL_MENU_VIEWS_SETTINGS, - "Exibir elementos na tela de menu." - ) + "Visualizações") +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_VIEWS_SETTINGS, + "Exibir elementos na tela de menu." + ) MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CORE_UPDATER, "Exibir Atualizador de Núcleos" ) @@ -3958,14 +4064,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_DELETE, "Remover núcleo" ) MSG_HASH(MENU_ENUM_SUBLABEL_CORE_DELETE, - "Remover este núcleo do disco." - ) -MSG_HASH(MENU_ENUM_SUBLABEL_RENAME_ENTRY, - "Renomear o título do item." - ) -MSG_HASH(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY, - "Renomear" - ) + "Remover este núcleo do disco.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FRAMEBUFFER_OPACITY, "Opacidade do Framebuffer" ) @@ -4027,8 +4126,11 @@ MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_ENTRY_RENAME, "Permita que o usuário renomeie as entradas nas coleções." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_ENTRY_RENAME, - "Permitir renomear entradas" - ) + "Permitir renomear entradas" ) +MSG_HASH(MENU_ENUM_SUBLABEL_RENAME_ENTRY, + "Renomear o título da entrada.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY, + "Renomear") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CORE, "Exibir Carregar Núcleo" ) @@ -4141,13 +4243,22 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_INFORMATION, "Exibir Informação" ) MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_INFORMATION, - "Exibir/ocultar a opção 'Informação'." - ) + "Exibir/ocultar a opção 'Informação'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_ENABLE, + "Ativar Notificação de Fundo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_RED, + "Notificação de Fundo em Cor Vermelha") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_GREEN, + "Notificação de Fundo em Cor Verde") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_BLUE, + "Notificação de Fundo em Cor Azul") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_OPACITY, + "Opacidade da Notificação de Fundo") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_DISABLE_KIOSK_MODE, "Desabilitar o Modo Quiosque" ) MSG_HASH(MENU_ENUM_SUBLABEL_MENU_DISABLE_KIOSK_MODE, - "Desabilita o Modo Quiosque . É necessária uma reinicialização para que a mudança tenha total efeito." + "Desabilita o Modo Quiosque. É necessária uma reinicialização para que a mudança tenha total efeito." ) MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_ENABLE_KIOSK_MODE, "Habilitar o Modo Quiosque" @@ -4168,19 +4279,62 @@ MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_OK, "Senha correta." ) MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_NOK, - "Senha incorreta." - ) + "Senha incorreta.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_RED, + "Notificação em Cor Vermelha") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_GREEN, + "Notificação em Cor Verde") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_BLUE, + "Notificação em Cor Azul") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FRAMECOUNT_SHOW, + "Mostrar contagem de quadros na tela FPS") +MSG_HASH(MSG_CONFIG_OVERRIDE_LOADED, + "Substituição de configuração carregada.") +MSG_HASH(MSG_GAME_REMAP_FILE_LOADED, + "Arquivo de remapeamento do jogo carregado.") +MSG_HASH(MSG_CORE_REMAP_FILE_LOADED, + "Arquivo de remapeamento principal carregado.") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, "Adicione automaticamente conteúdo à lista de reprodução") MSG_HASH(MENU_ENUM_SUBLABEL_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, "Verifica automaticamente o conteúdo carregado para que eles apareçam dentro das listas de reprodução.") MSG_HASH(MSG_SCANNING_OF_FILE_FINISHED, "Verificação do arquivo terminado") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OPACITY, + "Opacidade da Janela") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Qualidade da Reamostragem do Áudio") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Abaixe esse valor para favorecer o desempenho/baixa latência em relação à qualidade de áudio, aumente se desejar melhor qualidade de áudio à custa do desempenho/baixa latência.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES, + "Ver arquivos de shader para mudanças") +MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES, + "Aplicar automaticamente as alterações feitas nos arquivos de shader no disco.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_SHOW_DECORATIONS, + "Mostrar Decorações da Janela") MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, - "Display Statistics") + "Exibir estatísticas") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, - "Show onscreen technical statistics.") + "Mostrar estatísticas técnicas na tela.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_pt_pt.h b/intl/msg_hash_pt_pt.h index 3e50847c9a..5dffae031a 100644 --- a/intl/msg_hash_pt_pt.h +++ b/intl/msg_hash_pt_pt.h @@ -1615,6 +1615,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Taxa de atualização") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Taxa de atualização estimada do ecrã") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotação") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1743,6 +1745,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS, "Mostrar separador de definições") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Mostrar separador de vídeo") +MSG_HASH(MENU_ENUM_LABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Ícone do tema do menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1843,6 +1847,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Seleciona o ecrã a ser utilizado.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "A taxa de atualização do ecrã estimada em Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Alterar as definições da saída de vídeo.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2848,6 +2854,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Selecione uma imagem de disco para inserir.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Certifique-se de que a taxa de fotogramas atingida enquanto estiver dentro do menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Selecionar um tema diferente para este ícone. As alterações terão efeito após o reinício do programa.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3178,3 +3186,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_ru.h b/intl/msg_hash_ru.h index 52eaa1288a..a44acae10a 100644 --- a/intl/msg_hash_ru.h +++ b/intl/msg_hash_ru.h @@ -1652,6 +1652,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Вертикальная частота обновления") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Оценочная частота экрана") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Вращение") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1786,6 +1788,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Показать вкладку Видео") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Показать вкладку Сетевая игра") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Тема значка меню") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1888,6 +1892,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Выбирает, какой экран дисплея использовать.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "Точная оценка частоты обновления экрана в Гц.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Настройка параметров вывода видео.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2922,6 +2928,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Выберите образ диска для загрузки.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Убедитесь, что частота кадров ограничена внутри меню.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Выберите другую тему для значка. Изменения заработают после перезагрузки.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3262,3 +3270,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_us.c b/intl/msg_hash_us.c index 21aa5e06ee..5acc456d3f 100644 --- a/intl/msg_hash_us.c +++ b/intl/msg_hash_us.c @@ -22,9 +22,11 @@ #include #include "../msg_hash.h" -#include "../configuration.h" #include "../verbosity.h" +#ifdef RARCH_INTERNAL +#include "../configuration.h" + int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len) { settings_t *settings = config_get_ptr(); @@ -1201,6 +1203,13 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len) "not run at 60Hz, or something close to it, \n" "disable VSync, and leave this at its default."); break; + case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED: + snprintf(s, len, + "Set Polled Refresh Rate\n" + " \n" + "Sets the refresh rate to the actual value\n" + "polled from the display driver."); + break; case MENU_ENUM_LABEL_VIDEO_ROTATION: snprintf(s, len, "Forces a certain rotation \n" @@ -2036,6 +2045,7 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len) return 0; } +#endif #ifdef HAVE_MENU static const char *menu_hash_to_str_us_label_enum(enum msg_hash_enums msg) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index bf396393b1..72fb4f19bb 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -460,7 +460,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, - "Achievements Hardcore Mode" + "Hardcore Mode" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_LEADERBOARDS_ENABLE, @@ -500,11 +500,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_VERBOSE_ENABLE, - "Achievements Verbose Mode" + "Verbose Mode" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_AUTO_SCREENSHOT, - "Achievements Automatic Screenshot" + "Automatic Screenshot" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT, @@ -949,6 +949,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD, "Turbo Period") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_USER_BINDS, "Input User %u Binds") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LATENCY_SETTINGS, + "Latency") MSG_HASH(MENU_ENUM_LABEL_VALUE_INTERNAL_STORAGE_STATUS, "Internal storage status") MSG_HASH(MENU_ENUM_LABEL_VALUE_JOYPAD_AUTOCONFIG_DIR, @@ -1445,6 +1447,12 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SHUTDOWN, "Shutdown") MSG_HASH(MENU_ENUM_LABEL_VALUE_SLOWMOTION_RATIO, "Slow-Motion Ratio") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RUN_AHEAD_ENABLED, + "Run-Ahead to Reduce Latency") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RUN_AHEAD_FRAMES, + "Number of Frames to Run Ahead") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RUN_AHEAD_SECONDARY_INSTANCE, + "Runahead Use Second Instance") MSG_HASH(MENU_ENUM_LABEL_VALUE_SORT_SAVEFILES_ENABLE, "Sort Saves In Folders") MSG_HASH(MENU_ENUM_LABEL_VALUE_SORT_SAVESTATES_ENABLE, @@ -1625,6 +1633,10 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_THREADED_DATA_RUNLOOP_ENABLE, "Threaded tasks") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS, "Thumbnails") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS, + "Left Thumbnails") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_VERTICAL_THUMBNAILS, + "Thumbnails Vertical Disposition") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY, "Thumbnails") MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST, @@ -1753,6 +1765,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Vertical Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Estimated Screen Framerate") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotation") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1883,6 +1897,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_HISTORY, "Show History Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_ADD, "Show Import content Tab") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_PLAYLISTS, + "Show Playlist Tabs") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_FAVORITES, "Show Favorites Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_IMAGES, @@ -1895,6 +1911,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Show Video Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Show Netplay Tab") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Menu Icon Theme") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1906,7 +1924,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, "Enable or disable unofficial achievements and/or beta features for testing purposes.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, - "Enable or disable savestates, cheats, rewind, fast-forward, pause, and slow-motion for all games.") + "Enable or disable savestates, cheats, rewind, pause, and slow-motion for all games.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_LEADERBOARDS_ENABLE, "Enable or disable in-game leaderboards. Has no effect if Hardcore Mode is disabled.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE, @@ -1967,6 +1985,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_SETTINGS, "Change joypad, keyboard, and mouse settings.") MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_USER_BINDS, "Configure controls for this user.") +MSG_HASH(MENU_ENUM_SUBLABEL_LATENCY_SETTINGS, + "Change settings related to video, audio and input latency.") MSG_HASH(MENU_ENUM_SUBLABEL_LOG_VERBOSITY, "Enable or disable logging to the terminal.") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY, @@ -2003,6 +2023,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Selects which display screen to use.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "The accurate estimated refresh rate of the screen in Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Change video output settings.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2577,7 +2599,7 @@ MSG_HASH(MSG_NETPLAY_LAN_SCANNING, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "Pause gameplay when RetroArch is not the active window.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "Enable or disable recent playlist for games, images, music, and videos.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -2720,6 +2742,18 @@ MSG_HASH( MENU_ENUM_SUBLABEL_SLOWMOTION_RATIO, "When in slow motion, content will slow down by the factor specified/set." ) +MSG_HASH( + MENU_ENUM_SUBLABEL_RUN_AHEAD_ENABLED, + "Run core logic one or more frames ahead then load the state back to reduce perceived input lag." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_RUN_AHEAD_FRAMES, + "The number of frames to run ahead. Causes gameplay issues such as jitter if you exceed the number of lag frames internal to the game." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_RUN_AHEAD_SECONDARY_INSTANCE, + "Use a second instance of the RetroArch core to run ahead. Prevents audio problems due to loading state." + ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_ENABLE, "Enable rewinding. This will take a performance hit when playing." @@ -2908,6 +2942,13 @@ MSG_HASH( MENU_ENUM_SUBLABEL_THUMBNAILS, "Type of thumbnail to display." ) +MSG_HASH( + MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS, + "Type of thumbnail to display at the left." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_XMB_VERTICAL_THUMBNAILS, + "Display the left thumbnail under the right one, on the right side of the screen.") MSG_HASH( MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE, "Shows current date and/or time inside the menu." @@ -3059,6 +3100,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -3089,6 +3132,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Show the recent history tab inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3431,13 +3476,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES, "Watch shader files for changes") -MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") - -MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") - -MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") - -MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES, "Auto-apply changes made to shader files on disk.") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_SHOW_DECORATIONS, @@ -3446,3 +3484,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/intl/msg_hash_vn.h b/intl/msg_hash_vn.h index 1597d8109c..75c7cf8820 100644 --- a/intl/msg_hash_vn.h +++ b/intl/msg_hash_vn.h @@ -1639,6 +1639,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Vertical Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, "Estimated Screen Framerate") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + "Set Display-Reported Refresh Rate") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, "Rotation") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, @@ -1759,6 +1761,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_HISTORY, "Display History Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_ADD, "Display Import content Tab") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_PLAYLISTS, + "Display Playlist Tabs") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_IMAGES, "Display Image Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_MUSIC, @@ -1769,6 +1773,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_VIDEO, "Display Video Tab") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_NETPLAY, "Display Netplay Tab") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + "Menu Layout") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, "Menu Icon Theme") MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, @@ -1780,7 +1786,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, "Enable or disable unofficial achievements and/or beta features for testing purposes.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, - "Enable or disable savestates, cheats, rewind, fast-forward, pause, and slow-motion for all games.") + "Enable or disable savestates, cheats, rewind, pause, and slow-motion for all games.") MSG_HASH(MENU_ENUM_SUBLABEL_DRIVER_SETTINGS, "Change drivers used by the system.") MSG_HASH(MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS, @@ -1869,6 +1875,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, "Chọn màn hình hiển thị để sử dụng.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, "The accurate estimated refresh rate of the screen in Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED, + "The refresh rate as reported by the display driver.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, "Điều chỉnh thiết lập cho video ra.") MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, @@ -2433,7 +2441,7 @@ MSG_HASH(MSG_NETPLAY_LAN_SCANNING, MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, "Pause gameplay when RetroArch is not the active window.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, - "Enable or disable composition (Windows only).") + "Enable or disable composition.") MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, "Enable or disable recent playlist for games, images, music, and videos.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, @@ -2903,6 +2911,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, + "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, @@ -2931,6 +2941,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Show the recent history tab inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Show the import content tab inside the main menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, + "Show playlist tabs inside the main menu.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Show startup screen in menu. This is automatically set to false after the program starts for the first time.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, @@ -3231,3 +3243,25 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Display Statistics") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Show onscreen technical statistics.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + "Enable border filler") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + "Enable border filler thickness") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + "Enable background filler thickness") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "For 15 kHz CRT displays only. Attempts to use exact core/game resolution and refresh rate.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") +MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "When CRT SwitchRes is enabled, force ultrawide horizontal resolution to minimize mode switching.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "CRT Super Resolution") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + "Show Rewind Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, + "Show/hide the Rewind options.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, + "Show/hide the Latency options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + "Show Latency Settings") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, + "Show/hide the Overlay options.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + "Show Overlay Settings") diff --git a/libretro-common/audio/audio_mix.c b/libretro-common/audio/audio_mix.c index 776a9f21e7..15879ab248 100644 --- a/libretro-common/audio/audio_mix.c +++ b/libretro-common/audio/audio_mix.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (audio_mix.c). @@ -111,7 +111,7 @@ void audio_mix_free_chunk(audio_chunk_t *chunk) audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate) { int sample_size; - ssize_t len = 0; + int64_t len = 0; void *buf = NULL; audio_chunk_t *chunk = (audio_chunk_t*)calloc(1, sizeof(*chunk)); diff --git a/libretro-common/audio/audio_mixer.c b/libretro-common/audio/audio_mixer.c index c781297309..d7a99a4dec 100644 --- a/libretro-common/audio/audio_mixer.c +++ b/libretro-common/audio/audio_mixer.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (audio_mixer.c). @@ -44,7 +44,18 @@ #define STB_VORBIS_NO_STDIO #define STB_VORBIS_NO_CRT -#include +#include +#endif + +#ifdef HAVE_DR_FLAC +#define DR_FLAC_IMPLEMENTATION +#include +#endif + + +#ifdef HAVE_DR_MP3 +#define DR_MP3_IMPLEMENTATION +#include #endif #ifdef HAVE_IBXM @@ -52,7 +63,7 @@ #endif #define AUDIO_MIXER_MAX_VOICES 8 -#define AUDIO_MIXER_TEMP_OGG_BUFFER 8192 +#define AUDIO_MIXER_TEMP_BUFFER 8192 struct audio_mixer_sound { @@ -75,6 +86,24 @@ struct audio_mixer_sound const void* data; } ogg; #endif + +#ifdef HAVE_DR_FLAC + struct + { + /* flac */ + unsigned size; + const void* data; + } flac; +#endif + +#ifdef HAVE_DR_MP3 + struct + { + /* mp */ + unsigned size; + const void* data; + } mp3; +#endif #ifdef HAVE_IBXM struct @@ -116,6 +145,34 @@ struct audio_mixer_voice } ogg; #endif +#ifdef HAVE_DR_FLAC + struct + { + unsigned position; + unsigned samples; + unsigned buf_samples; + float* buffer; + float ratio; + drflac *stream; + void *resampler_data; + const retro_resampler_t *resampler; + } flac; +#endif + +#ifdef HAVE_DR_MP3 + struct + { + unsigned position; + unsigned samples; + unsigned buf_samples; + float* buffer; + float ratio; + drmp3 stream; + void *resampler_data; + const retro_resampler_t *resampler; + } mp3; +#endif + #ifdef HAVE_IBXM struct { @@ -343,6 +400,43 @@ audio_mixer_sound_t* audio_mixer_load_ogg(void *buffer, int32_t size) #endif } + +audio_mixer_sound_t* audio_mixer_load_flac(void *buffer, int32_t size) +{ +#ifdef HAVE_DR_FLAC + audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound)); + + if (!sound) + return NULL; + + sound->type = AUDIO_MIXER_TYPE_FLAC; + sound->types.flac.size = size; + sound->types.flac.data = buffer; + + return sound; +#else + return NULL; +#endif +} + +audio_mixer_sound_t* audio_mixer_load_mp3(void *buffer, int32_t size) +{ +#ifdef HAVE_DR_MP3 + audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound)); + + if (!sound) + return NULL; + + sound->type = AUDIO_MIXER_TYPE_MP3; + sound->types.mp3.size = size; + sound->types.mp3.data = buffer; + + return sound; +#else + return NULL; +#endif +} + audio_mixer_sound_t* audio_mixer_load_mod(void *buffer, int32_t size) { #ifdef HAVE_IBXM @@ -386,6 +480,20 @@ void audio_mixer_destroy(audio_mixer_sound_t* sound) handle = (void*)sound->types.mod.data; if (handle) free(handle); +#endif + break; + case AUDIO_MIXER_TYPE_FLAC: +#ifdef HAVE_DR_FLAC + handle = (void*)sound->types.flac.data; + if (handle) + free(handle); +#endif + break; + case AUDIO_MIXER_TYPE_MP3: +#ifdef HAVE_DR_MP3 + handle = (void*)sound->types.mp3.data; + if (handle) + free(handle); #endif break; case AUDIO_MIXER_TYPE_NONE: @@ -412,7 +520,7 @@ static bool audio_mixer_play_ogg( { stb_vorbis_info info; int res = 0; - float ratio = 0.0f; + float ratio = 1.0f; unsigned samples = 0; void *ogg_buffer = NULL; void *resampler_data = NULL; @@ -436,7 +544,7 @@ static bool audio_mixer_play_ogg( goto error; } - samples = (unsigned)(AUDIO_MIXER_TEMP_OGG_BUFFER * ratio); + samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio); ogg_buffer = (float*)memalign_alloc(16, ((samples + 15) & ~15) * sizeof(float)); @@ -531,6 +639,113 @@ error: } #endif + +#ifdef HAVE_DR_FLAC +static bool audio_mixer_play_flac( + audio_mixer_sound_t* sound, + audio_mixer_voice_t* voice, + bool repeat, float volume, + audio_mixer_stop_cb_t stop_cb) +{ + float ratio = 1.0f; + unsigned samples = 0; + void *flac_buffer = NULL; + void *resampler_data = NULL; + const retro_resampler_t* resamp = NULL; + drflac *dr_flac = drflac_open_memory((const unsigned char*)sound->types.flac.data,sound->types.flac.size); + + + if (!dr_flac) + return false; + if (dr_flac->sampleRate != s_rate) + { + ratio = (double)s_rate / (double)(dr_flac->sampleRate); + + if (!retro_resampler_realloc(&resampler_data, + &resamp, NULL, RESAMPLER_QUALITY_DONTCARE, + ratio)) + goto error; + } + + samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio); + flac_buffer = (float*)memalign_alloc(16, + ((samples + 15) & ~15) * sizeof(float)); + + if (!flac_buffer) + { + resamp->free(resampler_data); + goto error; + } + + voice->types.flac.resampler = resamp; + voice->types.flac.resampler_data = resampler_data; + voice->types.flac.buffer = (float*)flac_buffer; + voice->types.flac.buf_samples = samples; + voice->types.flac.ratio = ratio; + voice->types.flac.stream = dr_flac; + voice->types.flac.position = 0; + voice->types.flac.samples = 0; + + return true; + +error: + drflac_close(dr_flac); + return false; +} +#endif + +#ifdef HAVE_DR_MP3 +static bool audio_mixer_play_mp3( + audio_mixer_sound_t* sound, + audio_mixer_voice_t* voice, + bool repeat, float volume, + audio_mixer_stop_cb_t stop_cb) +{ + float ratio = 1.0f; + unsigned samples = 0; + void *mp3_buffer = NULL; + void *resampler_data = NULL; + const retro_resampler_t* resamp = NULL; + bool res =drmp3_init_memory(&voice->types.mp3.stream,(const unsigned char*)sound->types.mp3.data,sound->types.mp3.size,NULL); + if (!res) + return false; + if (voice->types.mp3.stream.sampleRate != s_rate) + { + ratio = (double)s_rate / (double)(voice->types.mp3.stream.sampleRate); + + if (!retro_resampler_realloc(&resampler_data, + &resamp, NULL, RESAMPLER_QUALITY_DONTCARE, + ratio)) + goto error; + } + + samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio); + mp3_buffer = (float*)memalign_alloc(16, + ((samples + 15) & ~15) * sizeof(float)); + + if (!mp3_buffer) + { + resamp->free(resampler_data); + goto error; + } + + voice->types.mp3.resampler = resamp; + voice->types.mp3.resampler_data = resampler_data; + voice->types.mp3.buffer = (float*)mp3_buffer; + voice->types.mp3.buf_samples = samples; + voice->types.mp3.ratio = ratio; + voice->types.mp3.position = 0; + voice->types.mp3.samples = 0; + + return true; + +error: + drmp3_uninit(&voice->types.mp3.stream); + return false; +} +#endif + + audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat, float volume, audio_mixer_stop_cb_t stop_cb) { @@ -563,6 +778,16 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat, case AUDIO_MIXER_TYPE_MOD: #ifdef HAVE_IBXM res = audio_mixer_play_mod(sound, voice, repeat, volume, stop_cb); +#endif + break; + case AUDIO_MIXER_TYPE_FLAC: +#ifdef HAVE_DR_FLAC + res = audio_mixer_play_flac(sound, voice, repeat, volume, stop_cb); +#endif + break; + case AUDIO_MIXER_TYPE_MP3: +#ifdef HAVE_DR_MP3 + res = audio_mixer_play_mp3(sound, voice, repeat, volume, stop_cb); #endif break; case AUDIO_MIXER_TYPE_NONE: @@ -665,9 +890,9 @@ static void audio_mixer_mix_ogg(float* buffer, size_t num_frames, float volume) { int i; - struct resampler_data info; - float temp_buffer[AUDIO_MIXER_TEMP_OGG_BUFFER]; - unsigned buf_free = num_frames * 2; + struct resampler_data info = { 0 }; + float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 }; + unsigned buf_free = (unsigned)(num_frames * 2); unsigned temp_samples = 0; float* pcm = NULL; @@ -676,7 +901,7 @@ static void audio_mixer_mix_ogg(float* buffer, size_t num_frames, again: temp_samples = stb_vorbis_get_samples_float_interleaved( voice->types.ogg.stream, 2, temp_buffer, - AUDIO_MIXER_TEMP_OGG_BUFFER) * 2; + AUDIO_MIXER_TEMP_BUFFER) * 2; if (temp_samples == 0) { @@ -704,7 +929,10 @@ again: info.output_frames = 0; info.ratio = voice->types.ogg.ratio; - voice->types.ogg.resampler->process(voice->types.ogg.resampler_data, &info); + if (voice->types.ogg.resampler) + voice->types.ogg.resampler->process(voice->types.ogg.resampler_data, &info); + else + memcpy(voice->types.ogg.buffer, temp_buffer, temp_samples * sizeof(float)); voice->types.ogg.position = 0; voice->types.ogg.samples = voice->types.ogg.buf_samples; } @@ -740,7 +968,7 @@ static void audio_mixer_mix_mod(float* buffer, size_t num_frames, float samplef = 0.0f; int samplei = 0; unsigned temp_samples = 0; - unsigned buf_free = num_frames * 2; + unsigned buf_free = (unsigned)(num_frames * 2); int* pcm = NULL; if (voice->types.mod.position == voice->types.mod.samples) @@ -806,6 +1034,151 @@ again: } #endif +#ifdef HAVE_DR_FLAC +static void audio_mixer_mix_flac(float* buffer, size_t num_frames, + audio_mixer_voice_t* voice, + float volume) +{ + int i; + struct resampler_data info = { 0 }; + float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 }; + unsigned buf_free = (unsigned)(num_frames * 2); + unsigned temp_samples = 0; + float* pcm = NULL; + + if (voice->types.flac.position == voice->types.flac.samples) + { +again: + temp_samples = drflac_read_f32( voice->types.flac.stream, AUDIO_MIXER_TEMP_BUFFER, temp_buffer); + if (temp_samples == 0) + { + if (voice->repeat) + { + if (voice->stop_cb) + voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED); + + drflac_seek_to_sample(voice->types.flac.stream,0); + goto again; + } + else + { + if (voice->stop_cb) + voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED); + + voice->type = AUDIO_MIXER_TYPE_NONE; + return; + } + } + + info.data_in = temp_buffer; + info.data_out = voice->types.flac.buffer; + info.input_frames = temp_samples / 2; + info.output_frames = 0; + info.ratio = voice->types.flac.ratio; + + if (voice->types.flac.resampler) + voice->types.flac.resampler->process(voice->types.flac.resampler_data, &info); + else + memcpy(voice->types.flac.buffer, temp_buffer, temp_samples * sizeof(float)); + voice->types.flac.position = 0; + voice->types.flac.samples = voice->types.flac.buf_samples; + } + + pcm = voice->types.flac.buffer + voice->types.flac.position; + + if (voice->types.flac.samples < buf_free) + { + for (i = voice->types.flac.samples; i != 0; i--) + *buffer++ += *pcm++ * volume; + + buf_free -= voice->types.flac.samples; + goto again; + } + else + { + int i; + for (i = buf_free; i != 0; --i ) + *buffer++ += *pcm++ * volume; + + voice->types.flac.position += buf_free; + voice->types.flac.samples -= buf_free; + } +} +#endif + +#ifdef HAVE_DR_MP3 +static void audio_mixer_mix_mp3(float* buffer, size_t num_frames, + audio_mixer_voice_t* voice, + float volume) +{ + int i; + struct resampler_data info = { 0 }; + float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 }; + unsigned buf_free = (unsigned)(num_frames * 2); + unsigned temp_samples = 0; + float* pcm = NULL; + + if (voice->types.mp3.position == voice->types.mp3.samples) + { +again: + temp_samples = drmp3_read_f32(&voice->types.mp3.stream, AUDIO_MIXER_TEMP_BUFFER/2, temp_buffer) * 2; + + if (temp_samples == 0) + { + if (voice->repeat) + { + if (voice->stop_cb) + voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED); + + drmp3_seek_to_frame(&voice->types.mp3.stream,0); + goto again; + } + else + { + if (voice->stop_cb) + voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED); + + voice->type = AUDIO_MIXER_TYPE_NONE; + return; + } + } + + info.data_in = temp_buffer; + info.data_out = voice->types.mp3.buffer; + info.input_frames = temp_samples / 2; + info.output_frames = 0; + info.ratio = voice->types.mp3.ratio; + + if (voice->types.mp3.resampler) + voice->types.mp3.resampler->process(voice->types.mp3.resampler_data, &info); + else + memcpy(voice->types.mp3.buffer, temp_buffer, temp_samples * sizeof(float)); + voice->types.mp3.position = 0; + voice->types.mp3.samples = voice->types.mp3.buf_samples; + } + + pcm = voice->types.mp3.buffer + voice->types.mp3.position; + + if (voice->types.mp3.samples < buf_free) + { + for (i = voice->types.mp3.samples; i != 0; i--) + *buffer++ += *pcm++ * volume; + + buf_free -= voice->types.mp3.samples; + goto again; + } + else + { + int i; + for (i = buf_free; i != 0; --i ) + *buffer++ += *pcm++ * volume; + + voice->types.mp3.position += buf_free; + voice->types.mp3.samples -= buf_free; + } +} +#endif + void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bool override) { unsigned i; @@ -834,6 +1207,16 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo case AUDIO_MIXER_TYPE_MOD: #ifdef HAVE_IBXM audio_mixer_mix_mod(buffer, num_frames, voice, volume); +#endif + break; + case AUDIO_MIXER_TYPE_FLAC: +#ifdef HAVE_DR_FLAC + audio_mixer_mix_flac(buffer, num_frames, voice, volume); +#endif + break; + case AUDIO_MIXER_TYPE_MP3: +#ifdef HAVE_DR_MP3 + audio_mixer_mix_mp3(buffer, num_frames, voice, volume); #endif break; case AUDIO_MIXER_TYPE_NONE: diff --git a/libretro-common/audio/conversion/float_to_s16.c b/libretro-common/audio/conversion/float_to_s16.c index bb97945971..baf8b4fd01 100644 --- a/libretro-common/audio/conversion/float_to_s16.c +++ b/libretro-common/audio/conversion/float_to_s16.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (float_to_s16.c). diff --git a/libretro-common/audio/conversion/float_to_s16_neon.S b/libretro-common/audio/conversion/float_to_s16_neon.S index aa9e565671..352c4d3dc7 100644 --- a/libretro-common/audio/conversion/float_to_s16_neon.S +++ b/libretro-common/audio/conversion/float_to_s16_neon.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (float_to_s16_neon.S). diff --git a/libretro-common/audio/conversion/float_to_s16_neon.c b/libretro-common/audio/conversion/float_to_s16_neon.c index 342f4978e1..a5d10e0a68 100644 --- a/libretro-common/audio/conversion/float_to_s16_neon.c +++ b/libretro-common/audio/conversion/float_to_s16_neon.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (float_to_s16_neon.S). diff --git a/libretro-common/audio/conversion/s16_to_float.c b/libretro-common/audio/conversion/s16_to_float.c index 814ddd8261..c8042ea817 100644 --- a/libretro-common/audio/conversion/s16_to_float.c +++ b/libretro-common/audio/conversion/s16_to_float.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (s16_to_float.c). diff --git a/libretro-common/audio/conversion/s16_to_float_neon.S b/libretro-common/audio/conversion/s16_to_float_neon.S index b744924400..3cc47e9f8f 100644 --- a/libretro-common/audio/conversion/s16_to_float_neon.S +++ b/libretro-common/audio/conversion/s16_to_float_neon.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (s16_to_float_neon.S). diff --git a/libretro-common/audio/conversion/s16_to_float_neon.c b/libretro-common/audio/conversion/s16_to_float_neon.c index 464e40fbc9..9912c0d50b 100644 --- a/libretro-common/audio/conversion/s16_to_float_neon.c +++ b/libretro-common/audio/conversion/s16_to_float_neon.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (s16_to_float_neon.S). diff --git a/libretro-common/audio/dsp_filter.c b/libretro-common/audio/dsp_filter.c index 7f428eee12..c7bb2dc9c9 100644 --- a/libretro-common/audio/dsp_filter.c +++ b/libretro-common/audio/dsp_filter.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dsp_filter.c). diff --git a/libretro-common/audio/dsp_filters/Tremolo.dsp b/libretro-common/audio/dsp_filters/Tremolo.dsp new file mode 100644 index 0000000000..50523333ac --- /dev/null +++ b/libretro-common/audio/dsp_filters/Tremolo.dsp @@ -0,0 +1,7 @@ +filters = 1 +filter0 = tremolo + +# Defaults. +#tremolo_frequency = 4.0 +#tremolo_depth = 0.9 + diff --git a/libretro-common/audio/dsp_filters/Vibrato.dsp b/libretro-common/audio/dsp_filters/Vibrato.dsp new file mode 100644 index 0000000000..b1ea8e1107 --- /dev/null +++ b/libretro-common/audio/dsp_filters/Vibrato.dsp @@ -0,0 +1,7 @@ +filters = 1 +filter0 = vibrato + +# Defaults. +#vibrato_frequency = 5.0 +#vibrato_depth = 0.5 + diff --git a/libretro-common/audio/dsp_filters/fft/fft.c b/libretro-common/audio/dsp_filters/fft/fft.c index e8c80f4f9d..7bafefad1e 100644 --- a/libretro-common/audio/dsp_filters/fft/fft.c +++ b/libretro-common/audio/dsp_filters/fft/fft.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fft.c). diff --git a/libretro-common/audio/dsp_filters/fft/fft.h b/libretro-common/audio/dsp_filters/fft/fft.h index 8a16c6cb83..e5bcdf7176 100644 --- a/libretro-common/audio/dsp_filters/fft/fft.h +++ b/libretro-common/audio/dsp_filters/fft/fft.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fft.h). diff --git a/libretro-common/audio/dsp_filters/reverb.c b/libretro-common/audio/dsp_filters/reverb.c index e81d85980d..e9bc8170e1 100644 --- a/libretro-common/audio/dsp_filters/reverb.c +++ b/libretro-common/audio/dsp_filters/reverb.c @@ -91,37 +91,13 @@ static const float initialwidth = 1; static const float initialmode = 0; static const float freezemode = 0.5f; -#define combtuningL1 1116 -#define combtuningL2 1188 -#define combtuningL3 1277 -#define combtuningL4 1356 -#define combtuningL5 1422 -#define combtuningL6 1491 -#define combtuningL7 1557 -#define combtuningL8 1617 -#define allpasstuningL1 556 -#define allpasstuningL2 441 -#define allpasstuningL3 341 -#define allpasstuningL4 225 - struct revmodel { struct comb combL[numcombs]; struct allpass allpassL[numallpasses]; - float bufcombL1[combtuningL1]; - float bufcombL2[combtuningL2]; - float bufcombL3[combtuningL3]; - float bufcombL4[combtuningL4]; - float bufcombL5[combtuningL5]; - float bufcombL6[combtuningL6]; - float bufcombL7[combtuningL7]; - float bufcombL8[combtuningL8]; - - float bufallpassL1[allpasstuningL1]; - float bufallpassL2[allpasstuningL2]; - float bufallpassL3[allpasstuningL3]; - float bufallpassL4[allpasstuningL4]; + float **bufcomb; + float **bufallpass; float gain; float roomsize, roomsize1; @@ -210,21 +186,29 @@ static void revmodel_setmode(struct revmodel *rev, float value) revmodel_update(rev); } -static void revmodel_init(struct revmodel *rev) +static void revmodel_init(struct revmodel *rev,int srate) { - rev->combL[0].buffer = rev->bufcombL1; rev->combL[0].bufsize = combtuningL1; - rev->combL[1].buffer = rev->bufcombL2; rev->combL[1].bufsize = combtuningL2; - rev->combL[2].buffer = rev->bufcombL3; rev->combL[2].bufsize = combtuningL3; - rev->combL[3].buffer = rev->bufcombL4; rev->combL[3].bufsize = combtuningL4; - rev->combL[4].buffer = rev->bufcombL5; rev->combL[4].bufsize = combtuningL5; - rev->combL[5].buffer = rev->bufcombL6; rev->combL[5].bufsize = combtuningL6; - rev->combL[6].buffer = rev->bufcombL7; rev->combL[6].bufsize = combtuningL7; - rev->combL[7].buffer = rev->bufcombL8; rev->combL[7].bufsize = combtuningL8; - rev->allpassL[0].buffer = rev->bufallpassL1; rev->allpassL[0].bufsize = allpasstuningL1; - rev->allpassL[1].buffer = rev->bufallpassL2; rev->allpassL[1].bufsize = allpasstuningL2; - rev->allpassL[2].buffer = rev->bufallpassL3; rev->allpassL[2].bufsize = allpasstuningL3; - rev->allpassL[3].buffer = rev->bufallpassL4; rev->allpassL[3].bufsize = allpasstuningL4; + static const int comb_lengths[8] = { 1116,1188,1277,1356,1422,1491,1557,1617 }; + static const int allpass_lengths[4] = { 225,341,441,556 }; + double r = srate * (1 / 44100.0); + unsigned c; + + rev->bufcomb=malloc(numcombs*sizeof(float*)); + for (c = 0; c < numcombs; ++c) + { + rev->bufcomb[c] = malloc(r*comb_lengths[c]*sizeof(float)); + rev->combL[c].buffer = rev->bufcomb[c]; + rev->combL[c].bufsize=r*comb_lengths[c]; + } + + rev->bufallpass=malloc(numallpasses*sizeof(float*)); + for (c = 0; c < numallpasses; ++c) + { + rev->bufallpass[c] = malloc(r*allpass_lengths[c]*sizeof(float)); + rev->allpassL[c].buffer = rev->bufallpass[c]; + rev->allpassL[c].bufsize=r*allpass_lengths[c]; + } rev->allpassL[0].feedback = 0.5f; rev->allpassL[1].feedback = 0.5f; @@ -246,6 +230,22 @@ struct reverb_data static void reverb_free(void *data) { + struct reverb_data *rev = (struct reverb_data*)data; + unsigned i; + + for (i = 0; i < numcombs; i++) { + free(rev->left.bufcomb[i]); + free(rev->right.bufcomb[i]); + } + free(rev->left.bufcomb); + free(rev->right.bufcomb); + + for (i = 0; i < numallpasses; i++) { + free(rev->left.bufallpass[i]); + free(rev->right.bufallpass[i]); + } + free(rev->left.bufallpass); + free(rev->right.bufallpass); free(data); } @@ -284,8 +284,8 @@ static void *reverb_init(const struct dspfilter_info *info, config->get_float(userdata, "roomwidth", &roomwidth, 0.56f); config->get_float(userdata, "roomsize", &roomsize, 0.56f); - revmodel_init(&rev->left); - revmodel_init(&rev->right); + revmodel_init(&rev->left,info->input_rate); + revmodel_init(&rev->right,info->input_rate); revmodel_setdamp(&rev->left, damping); revmodel_setdry(&rev->left, drytime); diff --git a/libretro-common/audio/dsp_filters/tremolo.c b/libretro-common/audio/dsp_filters/tremolo.c new file mode 100644 index 0000000000..38b535742c --- /dev/null +++ b/libretro-common/audio/dsp_filters/tremolo.c @@ -0,0 +1,133 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (tremolo.c). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +#define sqr(a) ((a) * (a)) + +struct tremolo_core +{ + float freq; + float depth; + float* wavetable; + int index; + int maxindex; +}; + +struct tremolo +{ + struct tremolo_core left, right; +}; + +static void tremolo_free(void *data) +{ + struct tremolo *tre = (struct tremolo*)data; + free(tre->left.wavetable); + free(tre->right.wavetable); + free(data); +} + +static void tremolocore_init(struct tremolo_core *core,float depth,int samplerate,float freq) +{ + const double offset = 1. - depth / 2.; + unsigned i; + double env; + core->index = 0; + core->maxindex = samplerate/freq; + core->wavetable = malloc(core->maxindex*sizeof(float)); + memset(core->wavetable, 0, core->maxindex * sizeof(float)); + for (i = 0; i < core->maxindex; i++) { + env = freq * i / samplerate; + env = sin((M_PI*2) * fmod(env + 0.25, 1.0)); + core->wavetable[i] = env * (1 - fabs(offset)) + offset; + } +} + +float tremolocore_core(struct tremolo_core *core,float in) +{ + core->index = core->index % core->maxindex; + return in * core->wavetable[core->index++]; +} + +static void tremolo_process(void *data, struct dspfilter_output *output, + const struct dspfilter_input *input) +{ + unsigned i; + float *out; + struct tremolo *tre = (struct tremolo*)data; + + output->samples = input->samples; + output->frames = input->frames; + out = output->samples; + + for (i = 0; i < input->frames; i++, out += 2) + { + float in[2] = { out[0], out[1] }; + + out[0] = tremolocore_core(&tre->left, in[0]); + out[1] = tremolocore_core(&tre->right, in[1]); + } +} + +static void *tremolo_init(const struct dspfilter_info *info, + const struct dspfilter_config *config, void *userdata) +{ + float freq, depth; + struct tremolo *tre = (struct tremolo*)calloc(1, sizeof(*tre)); + if (!tre) + return NULL; + + config->get_float(userdata, "freq", &freq,4.0f); + config->get_float(userdata, "depth", &depth, 0.9f); + tremolocore_init(&tre->left,depth,info->input_rate,freq); + tremolocore_init(&tre->right,depth,info->input_rate,freq); + return tre; +} + +static const struct dspfilter_implementation tremolo_plug = { + tremolo_init, + tremolo_process, + tremolo_free, + + DSPFILTER_API_VERSION, + "Tremolo", + "tremolo", +}; + +#ifdef HAVE_FILTERS_BUILTIN +#define dspfilter_get_implementation tremolo_dspfilter_get_implementation +#endif + +const struct dspfilter_implementation *dspfilter_get_implementation(dspfilter_simd_mask_t mask) +{ + (void)mask; + return &tremolo_plug; +} + +#undef dspfilter_get_implementation + diff --git a/libretro-common/audio/dsp_filters/vibrato.c b/libretro-common/audio/dsp_filters/vibrato.c new file mode 100644 index 0000000000..6e79d2f0fb --- /dev/null +++ b/libretro-common/audio/dsp_filters/vibrato.c @@ -0,0 +1,169 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (vibrato.c). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +#define sqr(a) ((a) * (a)) + + +const float BASE_DELAY_SEC = 0.002; // 2 ms +const float VIBRATO_FREQUENCY_DEFAULT_HZ = 2; +const float VIBRATO_FREQUENCY_MAX_HZ = 14; +const float VIBRATO_DEPTH_DEFAULT_PERCENT = 50; +const int add_delay = 3; + +float hermite_interp(float x, float *y) +{ + float c0, c1, c2, c3; + c0 = y[1]; + c1 = (1.0 / 2.0)*(y[2] - y[0]); + c2 = (y[0] - (5.0 / 2.0)*y[1]) + (2.0*y[2] - (1.0 / 2.0)*y[3]); + c3 = (1.0 / 2.0)*(y[3] - y[0]) + (3.0 / 2.0)*(y[1] - y[2]); + return ((c3*x + c2)*x + c1)*x + c0; +} + +struct vibrato_core +{ + float freq; + float samplerate; + int phase; + float depth; + float* buffer; + int writeindex; + int size; +}; + +struct vibrato +{ + struct vibrato_core left, right; +}; + +static void vibrato_free(void *data) +{ + struct vibrato *vib = (struct vibrato*)data; + free(vib->left.buffer); + free(vib->right.buffer); + free(data); +} + +static void vibratocore_init(struct vibrato_core *core,float depth,int samplerate,float freq) +{ + core->size = BASE_DELAY_SEC * samplerate * 2; + core->buffer = malloc((core->size + add_delay)*sizeof(float)); + memset(core->buffer, 0, (core->size + add_delay) * sizeof(float)); + core->samplerate = samplerate; + core->freq = freq; + core->depth = depth; + core->phase = 0; + core->writeindex = 0; +} + +float vibratocore_core(struct vibrato_core *core,float in) +{ + float M = core->freq / core->samplerate; + int maxphase = core->samplerate / core->freq; + float lfo = sin(M * 2. * M_PI * core->phase++); + core->phase = core->phase % maxphase; + lfo = (lfo + 1) * 1.; // transform from [-1; 1] to [0; 1] + int maxdelay = BASE_DELAY_SEC * core->samplerate; + float delay = lfo * core->depth * maxdelay; + delay += add_delay; + float readindex = core->writeindex - 1 - delay; + while (readindex < 0)readindex += core->size; + while (readindex >= core->size)readindex -= core->size; + int ipart = (int)readindex; // integer part of the delay + float fpart = readindex - ipart; // fractional part of the delay + float value = hermite_interp(fpart, &(core->buffer[ipart])); + core->buffer[core->writeindex] = in; + if (core->writeindex < add_delay){ + core->buffer[core->size + core->writeindex] = in; + } + core->writeindex++; + if (core->writeindex == core->size) { + core->writeindex = 0; + } + return value; +} + +static void vibrato_process(void *data, struct dspfilter_output *output, + const struct dspfilter_input *input) +{ + unsigned i; + float *out; + struct vibrato *vib = (struct vibrato*)data; + + output->samples = input->samples; + output->frames = input->frames; + out = output->samples; + + for (i = 0; i < input->frames; i++, out += 2) + { + float in[2] = { out[0], out[1] }; + + out[0] = vibratocore_core(&vib->left, in[0]); + out[1] = vibratocore_core(&vib->right, in[1]); + } +} + +static void *vibrato_init(const struct dspfilter_info *info, + const struct dspfilter_config *config, void *userdata) +{ + float freq, depth; + struct vibrato *vib = (struct vibrato*)calloc(1, sizeof(*vib)); + if (!vib) + return NULL; + + config->get_float(userdata, "freq", &freq,5.0f); + config->get_float(userdata, "depth", &depth, 0.5f); + vibratocore_init(&vib->left,depth,info->input_rate,freq); + vibratocore_init(&vib->right,depth,info->input_rate,freq); + return vib; +} + +static const struct dspfilter_implementation vibrato_plug = { + vibrato_init, + vibrato_process, + vibrato_free, + + DSPFILTER_API_VERSION, + "Vibrato", + "vibrato", +}; + +#ifdef HAVE_FILTERS_BUILTIN +#define dspfilter_get_implementation vibrato_dspfilter_get_implementation +#endif + +const struct dspfilter_implementation *dspfilter_get_implementation(dspfilter_simd_mask_t mask) +{ + (void)mask; + return &vibrato_plug; +} + +#undef dspfilter_get_implementation + diff --git a/libretro-common/audio/resampler/audio_resampler.c b/libretro-common/audio/resampler/audio_resampler.c index 3cf4660f47..8d27f06932 100644 --- a/libretro-common/audio/resampler/audio_resampler.c +++ b/libretro-common/audio/resampler/audio_resampler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (audio_resampler.c). diff --git a/libretro-common/audio/resampler/drivers/nearest_resampler.c b/libretro-common/audio/resampler/drivers/nearest_resampler.c index 1083c85836..982d4fe67d 100644 --- a/libretro-common/audio/resampler/drivers/nearest_resampler.c +++ b/libretro-common/audio/resampler/drivers/nearest_resampler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (nearest_resampler.c). diff --git a/libretro-common/audio/resampler/drivers/null_resampler.c b/libretro-common/audio/resampler/drivers/null_resampler.c index e75026944f..b970dfe0f5 100644 --- a/libretro-common/audio/resampler/drivers/null_resampler.c +++ b/libretro-common/audio/resampler/drivers/null_resampler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (null_resampler.c). diff --git a/libretro-common/audio/resampler/drivers/sinc_resampler.c b/libretro-common/audio/resampler/drivers/sinc_resampler.c index b5754f6632..c400ab1b23 100644 --- a/libretro-common/audio/resampler/drivers/sinc_resampler.c +++ b/libretro-common/audio/resampler/drivers/sinc_resampler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (sinc_resampler.c). diff --git a/libretro-common/audio/resampler/drivers/sinc_resampler_neon.S b/libretro-common/audio/resampler/drivers/sinc_resampler_neon.S index 033104e064..15a3773414 100644 --- a/libretro-common/audio/resampler/drivers/sinc_resampler_neon.S +++ b/libretro-common/audio/resampler/drivers/sinc_resampler_neon.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (sinc_resampler_neon.S). diff --git a/libretro-common/compat/compat_fnmatch.c b/libretro-common/compat/compat_fnmatch.c index 81beb3e06b..19f87cc76a 100644 --- a/libretro-common/compat/compat_fnmatch.c +++ b/libretro-common/compat/compat_fnmatch.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_fnmatch.c). diff --git a/libretro-common/compat/compat_getopt.c b/libretro-common/compat/compat_getopt.c index 632f67e9f4..81978b86c2 100644 --- a/libretro-common/compat/compat_getopt.c +++ b/libretro-common/compat/compat_getopt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_getopt.c). diff --git a/libretro-common/compat/compat_posix_string.c b/libretro-common/compat/compat_posix_string.c index 4bddf11f8f..33a30e5772 100644 --- a/libretro-common/compat/compat_posix_string.c +++ b/libretro-common/compat/compat_posix_string.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_posix_string.c). diff --git a/libretro-common/compat/compat_snprintf.c b/libretro-common/compat/compat_snprintf.c index 03bfba64da..7cfd2d7682 100644 --- a/libretro-common/compat/compat_snprintf.c +++ b/libretro-common/compat/compat_snprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_snprintf.c). @@ -24,8 +24,9 @@ #ifdef _MSC_VER #include - -#include +#if _MSC_VER >= 1800 +#include /* added for _vsnprintf_s and _vscprintf on VS2015 and VS2017 */ +#endif #include #if _MSC_VER < 1800 diff --git a/libretro-common/compat/compat_strcasestr.c b/libretro-common/compat/compat_strcasestr.c index 82ce5acb7b..54c93a48d0 100644 --- a/libretro-common/compat/compat_strcasestr.c +++ b/libretro-common/compat/compat_strcasestr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_strcasestr.c). diff --git a/libretro-common/compat/compat_strl.c b/libretro-common/compat/compat_strl.c index d42fca3655..94cb39b62b 100644 --- a/libretro-common/compat/compat_strl.c +++ b/libretro-common/compat/compat_strl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_strl.c). diff --git a/libretro-common/compat/compat_vscprintf.c b/libretro-common/compat/compat_vscprintf.c new file mode 100644 index 0000000000..ddffeb7e77 --- /dev/null +++ b/libretro-common/compat/compat_vscprintf.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (compat_snprintf.c). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* THIS FILE HAS NOT BEEN VALIDATED ON PLATFORMS BESIDES MSVC */ +#ifdef _MSC_VER + +#include + +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +#define va_copy(dst, src) ((dst) = (src)) +#endif + +int c89_vscprintf_retro__(const char *format, va_list pargs) +{ + int retval; + va_list argcopy; + va_copy(argcopy, pargs); + retval = vsnprintf(NULL, 0, format, argcopy); + va_end(argcopy); + return retval; +} +#endif diff --git a/libretro-common/compat/fopen_utf8.c b/libretro-common/compat/fopen_utf8.c index abd50cf275..52b481e7e7 100644 --- a/libretro-common/compat/fopen_utf8.c +++ b/libretro-common/compat/fopen_utf8.c @@ -1,5 +1,28 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (fopen_utf8.c). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + #include #include +#include #include #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX) @@ -11,7 +34,7 @@ #ifdef _WIN32 #undef fopen -FILE* fopen_utf8(const char * filename, const char * mode) +void *fopen_utf8(const char * filename, const char * mode) { #if defined(_XBOX) return fopen(filename, mode); diff --git a/libretro-common/dynamic/dylib.c b/libretro-common/dynamic/dylib.c index d4864a7057..bc6be9fc40 100644 --- a/libretro-common/dynamic/dylib.c +++ b/libretro-common/dynamic/dylib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dylib.c). diff --git a/libretro-common/encodings/encoding_crc32.c b/libretro-common/encodings/encoding_crc32.c index 0c1895a98f..4775e76357 100644 --- a/libretro-common/encodings/encoding_crc32.c +++ b/libretro-common/encodings/encoding_crc32.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (encoding_crc32.c). diff --git a/libretro-common/encodings/encoding_utf.c b/libretro-common/encodings/encoding_utf.c index d6c4ff4650..f7c533f144 100644 --- a/libretro-common/encodings/encoding_utf.c +++ b/libretro-common/encodings/encoding_utf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (encoding_utf.c). diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c index dc3872043f..3a32a46c64 100644 --- a/libretro-common/features/features_cpu.c +++ b/libretro-common/features/features_cpu.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (features_cpu.c). diff --git a/libretro-common/file/archive_file.c b/libretro-common/file/archive_file.c index ca39050746..b2f35518f4 100644 --- a/libretro-common/file/archive_file.c +++ b/libretro-common/file/archive_file.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (archive_file.c). @@ -129,7 +129,7 @@ static void file_archive_free(file_archive_file_data_t *data) static file_archive_file_data_t* file_archive_open(const char *path) { - ssize_t ret = -1; + int64_t ret = -1; bool read_from_file = false; file_archive_file_data_t *data = (file_archive_file_data_t*) calloc(1, sizeof(*data)); @@ -722,7 +722,7 @@ error: */ int file_archive_compressed_read( const char * path, void **buf, - const char* optional_filename, ssize_t *length) + const char* optional_filename, int64_t *length) { const struct file_archive_file_backend *backend = NULL; int ret = 0; diff --git a/libretro-common/file/archive_file_7z.c b/libretro-common/file/archive_file_7z.c index 1afd5d4b83..0f00c0723d 100644 --- a/libretro-common/file/archive_file_7z.c +++ b/libretro-common/file/archive_file_7z.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (archive_file_sevenzip.c). diff --git a/libretro-common/file/archive_file_zlib.c b/libretro-common/file/archive_file_zlib.c index 4716ba95a3..07fec55fd4 100644 --- a/libretro-common/file/archive_file_zlib.c +++ b/libretro-common/file/archive_file_zlib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (archive_file_zlib.c). @@ -240,22 +240,22 @@ static int zip_file_read( const char *needle, void **buf, const char *optional_outfile) { - file_archive_transfer_t zlib; + file_archive_transfer_t zlib = {0}; struct archive_extract_userdata userdata = {{0}}; - bool returnerr = true; - int ret = 0; + bool returnerr = true; + int ret = 0; - zlib.type = ARCHIVE_TRANSFER_INIT; + zlib.type = ARCHIVE_TRANSFER_INIT; - userdata.decomp_state.needle = NULL; - userdata.decomp_state.opt_file = NULL; - userdata.decomp_state.found = false; - userdata.decomp_state.buf = buf; + userdata.decomp_state.needle = NULL; + userdata.decomp_state.opt_file = NULL; + userdata.decomp_state.found = false; + userdata.decomp_state.buf = buf; if (needle) - userdata.decomp_state.needle = strdup(needle); + userdata.decomp_state.needle = strdup(needle); if (optional_outfile) - userdata.decomp_state.opt_file = strdup(optional_outfile); + userdata.decomp_state.opt_file = strdup(optional_outfile); do { diff --git a/libretro-common/file/config_file.c b/libretro-common/file/config_file.c index 455d3aa513..a8f8cfa808 100644 --- a/libretro-common/file/config_file.c +++ b/libretro-common/file/config_file.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (config_file.c). @@ -862,7 +862,7 @@ bool config_file_write(config_file_t *conf, const char *path) if (!string_is_empty(path)) { void* buf = NULL; - FILE *file = fopen_utf8(path, "wb"); + FILE *file = (FILE*)fopen_utf8(path, "wb"); if (!file) return false; diff --git a/libretro-common/file/config_file_userdata.c b/libretro-common/file/config_file_userdata.c index 8490fda4ad..e91fb8b04e 100644 --- a/libretro-common/file/config_file_userdata.c +++ b/libretro-common/file/config_file_userdata.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (config_file_userdata.c). diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index 4830898775..7c79b0b44f 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.c). @@ -392,7 +392,7 @@ char *path_remove_extension(char *path) return NULL; if (*last) *last = '\0'; - return last; + return path; } /** @@ -793,7 +793,7 @@ bool path_is_absolute(const char *path) **/ void path_resolve_realpath(char *buf, size_t size) { -#ifndef RARCH_CONSOLE +#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL) char tmp[PATH_MAX_LENGTH]; tmp[0] = '\0'; @@ -971,7 +971,7 @@ void fill_short_pathname_representation_noext(char* out_rep, void fill_pathname_expand_special(char *out_path, const char *in_path, size_t size) { -#if !defined(RARCH_CONSOLE) +#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL) if (*in_path == '~') { const char *home = getenv("HOME"); @@ -1020,7 +1020,7 @@ void fill_pathname_expand_special(char *out_path, void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size) { -#if !defined(RARCH_CONSOLE) +#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL) unsigned i; const char *candidates[3]; const char *notations[3]; @@ -1107,7 +1107,7 @@ void path_basedir_wrapper(char *path) snprintf(path, 3, ".%s", path_default_slash()); } -#if !defined(RARCH_CONSOLE) +#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL) void fill_pathname_application_path(char *s, size_t len) { size_t i; diff --git a/libretro-common/file/nbio/nbio_intf.c b/libretro-common/file/nbio/nbio_intf.c index cfcef60d2b..d6254ef08e 100644 --- a/libretro-common/file/nbio/nbio_intf.c +++ b/libretro-common/file/nbio/nbio_intf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (nbio_intf.c). diff --git a/libretro-common/file/nbio/nbio_linux.c b/libretro-common/file/nbio/nbio_linux.c index 8ef3f2bacb..8644bb94cb 100644 --- a/libretro-common/file/nbio/nbio_linux.c +++ b/libretro-common/file/nbio/nbio_linux.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (nbio_linux.c). diff --git a/libretro-common/file/nbio/nbio_stdio.c b/libretro-common/file/nbio/nbio_stdio.c index aa9d3cc522..f80e91a27b 100644 --- a/libretro-common/file/nbio/nbio_stdio.c +++ b/libretro-common/file/nbio/nbio_stdio.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (nbio_stdio.c). diff --git a/libretro-common/file/nbio/nbio_unixmmap.c b/libretro-common/file/nbio/nbio_unixmmap.c index 672b556663..29b574738d 100644 --- a/libretro-common/file/nbio/nbio_unixmmap.c +++ b/libretro-common/file/nbio/nbio_unixmmap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (nbio_unixmmap.c). diff --git a/libretro-common/file/nbio/nbio_windowsmmap.c b/libretro-common/file/nbio/nbio_windowsmmap.c index ff9d9d46e4..2bfd834a71 100644 --- a/libretro-common/file/nbio/nbio_windowsmmap.c +++ b/libretro-common/file/nbio/nbio_windowsmmap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (nbio_windowsmmap.c). diff --git a/libretro-common/file/retro_dirent.c b/libretro-common/file/retro_dirent.c index 9c53504732..0b6ecad246 100644 --- a/libretro-common/file/retro_dirent.c +++ b/libretro-common/file/retro_dirent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_dirent.c). @@ -106,8 +106,14 @@ struct RDIR *retro_opendir(const char *name) wchar_t *path_wide = NULL; unsigned path_len; #endif - struct RDIR *rdir = (struct RDIR*)calloc(1, sizeof(*rdir)); + struct RDIR *rdir; + /*Reject null or empty string paths*/ + if (!name||(*name==0)) + return NULL; + + /*Allocate RDIR struct. Tidied later with retro_closedir*/ + rdir = (struct RDIR*)calloc(1, sizeof(*rdir)); if (!rdir) return NULL; diff --git a/libretro-common/formats/bmp/rbmp.c b/libretro-common/formats/bmp/rbmp.c index ee2b06f01d..1e7eaa9349 100644 --- a/libretro-common/formats/bmp/rbmp.c +++ b/libretro-common/formats/bmp/rbmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rbmp.c). diff --git a/libretro-common/formats/bmp/rbmp_encode.c b/libretro-common/formats/bmp/rbmp_encode.c index 8b22f5ce31..50798b080f 100644 --- a/libretro-common/formats/bmp/rbmp_encode.c +++ b/libretro-common/formats/bmp/rbmp_encode.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rbmp_encode.c). diff --git a/libretro-common/formats/image_texture.c b/libretro-common/formats/image_texture.c index c531335e7b..e2f3c3d162 100644 --- a/libretro-common/formats/image_texture.c +++ b/libretro-common/formats/image_texture.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (image_texture.c). diff --git a/libretro-common/formats/image_transfer.c b/libretro-common/formats/image_transfer.c index 4c2bb5dd15..3f78b5356a 100644 --- a/libretro-common/formats/image_transfer.c +++ b/libretro-common/formats/image_transfer.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (image_transfer.c). diff --git a/libretro-common/formats/jpeg/rjpeg.c b/libretro-common/formats/jpeg/rjpeg.c index 49490e82eb..0b1f7ea2c6 100644 --- a/libretro-common/formats/jpeg/rjpeg.c +++ b/libretro-common/formats/jpeg/rjpeg.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rjpeg.c). diff --git a/libretro-common/formats/json/jsonsax.c b/libretro-common/formats/json/jsonsax.c index fec8a7df8a..ec57c004da 100644 --- a/libretro-common/formats/json/jsonsax.c +++ b/libretro-common/formats/json/jsonsax.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (jsonsax.c). diff --git a/libretro-common/formats/libchdr/bitstream.c b/libretro-common/formats/libchdr/libchdr_bitstream.c similarity index 100% rename from libretro-common/formats/libchdr/bitstream.c rename to libretro-common/formats/libchdr/libchdr_bitstream.c diff --git a/libretro-common/formats/libchdr/cdrom.c b/libretro-common/formats/libchdr/libchdr_cdrom.c similarity index 100% rename from libretro-common/formats/libchdr/cdrom.c rename to libretro-common/formats/libchdr/libchdr_cdrom.c diff --git a/libretro-common/formats/libchdr/chd.c b/libretro-common/formats/libchdr/libchdr_chd.c similarity index 66% rename from libretro-common/formats/libchdr/chd.c rename to libretro-common/formats/libchdr/libchdr_chd.c index 78cac091bb..79a50aac2f 100644 --- a/libretro-common/formats/libchdr/chd.c +++ b/libretro-common/formats/libchdr/libchdr_chd.c @@ -38,18 +38,29 @@ ***************************************************************************/ #include +#include #include #include #include #include #include #include -#include #include -#include -#include -#include + +#ifdef HAVE_FLAC +#include +#endif + +#ifdef HAVE_7ZIP +#include +#endif + +#ifdef HAVE_ZLIB +#include +#endif + #include +#include #define TRUE 1 #define FALSE 0 @@ -71,33 +82,30 @@ #define OLD_MAP_ENTRY_SIZE 8 /* V1-V2 */ #define METADATA_HEADER_SIZE 16 /* metadata header size */ +#define CRCMAP_HASH_SIZE 4095 /* number of CRC hashtable entries */ + #define MAP_ENTRY_FLAG_TYPE_MASK 0x0f /* what type of hunk */ #define MAP_ENTRY_FLAG_NO_CRC 0x10 /* no CRC is present */ #define CHD_V1_SECTOR_SIZE 512 /* size of a "sector" in the V1 header */ #define COOKIE_VALUE 0xbaadf00d -#define MAX_ZLIB_ALLOCS 64 #define END_OF_LIST_COOKIE "EndOfListCookie" #define NO_MATCH (~0) -#ifdef WANT_RAW_DATA_SECTOR -static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 }; -#endif +#define MAP_ENTRY_TYPE_INVALID 0x0000 /* invalid type */ +#define MAP_ENTRY_TYPE_COMPRESSED 0x0001 /* standard compression */ +#define MAP_ENTRY_TYPE_UNCOMPRESSED 0x0002 /* uncompressed data */ +#define MAP_ENTRY_TYPE_MINI 0x0003 /* mini: use offset as raw data */ +#define MAP_ENTRY_TYPE_SELF_HUNK 0x0004 /* same as another hunk in this file */ +#define MAP_ENTRY_TYPE_PARENT_HUNK 0x0005 /* same as a hunk in the parent file */ +#define MAP_ENTRY_TYPE_2ND_COMPRESSED 0x0006 /* compressed with secondary algorithm (usually FLAC CDDA) */ -/* V3-V4 entry types */ -enum -{ - V34_MAP_ENTRY_TYPE_INVALID = 0, /* invalid type */ - V34_MAP_ENTRY_TYPE_COMPRESSED = 1, /* standard compression */ - V34_MAP_ENTRY_TYPE_UNCOMPRESSED = 2, /* uncompressed data */ - V34_MAP_ENTRY_TYPE_MINI = 3, /* mini: use offset as raw data */ - V34_MAP_ENTRY_TYPE_SELF_HUNK = 4, /* same as another hunk in this file */ - V34_MAP_ENTRY_TYPE_PARENT_HUNK = 5, /* same as a hunk in the parent file */ - V34_MAP_ENTRY_TYPE_2ND_COMPRESSED = 6 /* compressed with secondary algorithm (usually FLAC CDDA) */ -}; +#ifdef WANT_RAW_DATA_SECTOR +const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 }; +#endif /* V5 compression types */ enum @@ -139,6 +147,8 @@ enum MACROS ***************************************************************************/ +#define SET_ERROR_AND_CLEANUP(err) do { last_error = (err); goto cleanup; } while (0) + #define EARLY_EXIT(x) do { (void)(x); goto cleanup; } while (0) /*************************************************************************** @@ -180,80 +190,12 @@ struct _metadata_entry UINT8 flags; /* flag bits */ }; -/* codec-private data for the ZLIB codec */ - -typedef struct _zlib_allocator zlib_allocator; -struct _zlib_allocator -{ - UINT32 * allocptr[MAX_ZLIB_ALLOCS]; -}; - -typedef struct _zlib_codec_data zlib_codec_data; -struct _zlib_codec_data -{ - z_stream inflater; - zlib_allocator allocator; -}; - -/* codec-private data for the LZMA codec */ -#define MAX_LZMA_ALLOCS 64 - -typedef struct _lzma_allocator lzma_allocator; -struct _lzma_allocator -{ - void *(*Alloc)(void *p, size_t size); - void (*Free)(void *p, void *address); /* address can be 0 */ - void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */ - uint32_t* allocptr[MAX_LZMA_ALLOCS]; -}; - -typedef struct _lzma_codec_data lzma_codec_data; -struct _lzma_codec_data -{ - CLzmaDec decoder; - lzma_allocator allocator; -}; - -/* codec-private data for the CDZL codec */ -typedef struct _cdzl_codec_data cdzl_codec_data; -struct _cdzl_codec_data { - /* internal state */ - zlib_codec_data base_decompressor; -#ifdef WANT_SUBCODE - zlib_codec_data subcode_decompressor; -#endif - uint8_t* buffer; -}; - -/* codec-private data for the CDLZ codec */ -typedef struct _cdlz_codec_data cdlz_codec_data; -struct _cdlz_codec_data { - /* internal state */ - lzma_codec_data base_decompressor; -#ifdef WANT_SUBCODE - zlib_codec_data subcode_decompressor; -#endif - uint8_t* buffer; -}; - -/* codec-private data for the CDFL codec */ -typedef struct _cdfl_codec_data cdfl_codec_data; -struct _cdfl_codec_data { - /* internal state */ - int swap_endian; - flac_decoder decoder; -#ifdef WANT_SUBCODE - zlib_codec_data subcode_decompressor; -#endif - uint8_t* buffer; -}; - /* internal representation of an open CHD file */ struct _chd_file { UINT32 cookie; /* cookie, should equal COOKIE_VALUE */ - core_file * file; /* handle to the open core file */ + RFILE * file; /* handle to the open core file */ UINT8 owns_file; /* flag indicating if this file should be closed on chd_close() */ chd_header header; /* header, extracted from file */ @@ -272,14 +214,21 @@ struct _chd_file UINT8 * compressed; /* pointer to buffer for compressed data */ const codec_interface * codecintf[4]; /* interface to the codec */ +#ifdef HAVE_ZLIB zlib_codec_data zlib_codec_data; /* zlib codec data */ cdzl_codec_data cdzl_codec_data; /* cdzl codec data */ +#endif +#ifdef HAVE_7ZIP cdlz_codec_data cdlz_codec_data; /* cdlz codec data */ +#endif +#ifdef HAVE_FLAC cdfl_codec_data cdfl_codec_data; /* cdfl codec data */ +#endif #ifdef NEED_CACHE_HUNK UINT32 maxhunk; /* maximum hunk accessed */ #endif + UINT8 * file_cache; /* cache of underlying file */ }; /*************************************************************************** @@ -309,523 +258,6 @@ static chd_error map_read(chd_file *chd); /* metadata management */ static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry); -/* zlib compression codec */ -static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes); -static void zlib_codec_free(void *codec); -static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); -static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size); -static void zlib_fast_free(voidpf opaque, voidpf address); - -/* lzma compression codec */ -static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes); -static void lzma_codec_free(void *codec); -static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); - -/* cdzl compression codec */ -static chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes); -static void cdzl_codec_free(void* codec); -static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); - -/* cdlz compression codec */ -static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes); -static void cdlz_codec_free(void* codec); -static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); - -/* cdfl compression codec */ -static chd_error cdfl_codec_init(void* codec, uint32_t hunkbytes); -static void cdfl_codec_free(void* codec); -static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); - -/*************************************************************************** - * LZMA ALLOCATOR HELPER - *************************************************************************** - */ - -void *lzma_fast_alloc(void *p, size_t size); -void lzma_fast_free(void *p, void *address); - -/*------------------------------------------------- - * lzma_allocator_init - *------------------------------------------------- - */ - -void lzma_allocator_init(void* p) -{ - lzma_allocator *codec = (lzma_allocator *)(p); - - /* reset pointer list */ - memset(codec->allocptr, 0, sizeof(codec->allocptr)); - codec->Alloc = lzma_fast_alloc; - codec->Free = lzma_fast_free; -} - -/*------------------------------------------------- - * lzma_allocator_free - *------------------------------------------------- - */ - -void lzma_allocator_free(void* p ) -{ - lzma_allocator *codec = (lzma_allocator *)(p); - - /* free our memory */ - int i; - for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++) - { - if (codec->allocptr[i] != NULL) - free(codec->allocptr[i]); - } -} - -/*------------------------------------------------- - * lzma_fast_alloc - fast malloc for lzma, which - * allocates and frees memory frequently - *------------------------------------------------- - */ - -void *lzma_fast_alloc(void *p, size_t size) -{ - int scan; - uint32_t *addr = NULL; - lzma_allocator *codec = (lzma_allocator *)(p); - - /* compute the size, rounding to the nearest 1k */ - size = (size + 0x3ff) & ~0x3ff; - - /* reuse a hunk if we can */ - for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++) - { - uint32_t *ptr = codec->allocptr[scan]; - if (ptr != NULL && size == *ptr) - { - /* set the low bit of the size so we don't match next time */ - *ptr |= 1; - return ptr + 1; - } - } - - /* alloc a new one and put it into the list */ - addr = (uint32_t *)malloc(sizeof(uint8_t) * (size + sizeof(uint32_t))); - if (addr==NULL) - return NULL; - for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++) - { - if (codec->allocptr[scan] == NULL) - { - codec->allocptr[scan] = addr; - break; - } - } - - /* set the low bit of the size so we don't match next time */ - *addr = size | 1; - return addr + 1; -} - -/*------------------------------------------------- - * lzma_fast_free - fast free for lzma, which - * allocates and frees memory frequently - *------------------------------------------------- - */ - -void lzma_fast_free(void *p, void *address) -{ - int scan; - uint32_t *ptr; - lzma_allocator *codec; - if (address == NULL) - return; - - codec = (lzma_allocator *)(p); - - /* find the hunk */ - ptr = (uint32_t *)(address) - 1; - for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++) - { - if (ptr == codec->allocptr[scan]) - { - /* clear the low bit of the size to allow matches */ - *ptr &= ~1; - return; - } - } -} - -/*************************************************************************** - * LZMA DECOMPRESSOR - *************************************************************************** - */ - -/*------------------------------------------------- - * lzma_codec_init - constructor - *------------------------------------------------- - */ - -chd_error lzma_codec_init(void* codec, uint32_t hunkbytes) -{ - CLzmaEncProps encoder_props; - CLzmaEncHandle enc; - Byte decoder_props[LZMA_PROPS_SIZE]; - lzma_allocator* alloc; - size_t props_size; - lzma_codec_data* lzma_codec = (lzma_codec_data*) codec; - - /* construct the decoder */ - LzmaDec_Construct(&lzma_codec->decoder); - - /* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK - * This code assumes that the current version of the encoder imposes the same requirements on the - * decoder as the encoder used to produce the file. This is not necessarily true. The format - * needs to be changed so the encoder properties are written to the file. - - * configure the properties like the compressor did */ - LzmaEncProps_Init(&encoder_props); - encoder_props.level = 9; - encoder_props.reduceSize = hunkbytes; - LzmaEncProps_Normalize(&encoder_props); - - /* convert to decoder properties */ - alloc = &lzma_codec->allocator; - lzma_allocator_init(alloc); - enc = LzmaEnc_Create((ISzAlloc*)alloc); - if (!enc) - return CHDERR_DECOMPRESSION_ERROR; - if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK) - { - LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc); - return CHDERR_DECOMPRESSION_ERROR; - } - props_size = sizeof(decoder_props); - if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK) - { - LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc); - return CHDERR_DECOMPRESSION_ERROR; - } - LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc); - - /* do memory allocations */ - if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK) - return CHDERR_DECOMPRESSION_ERROR; - - /* Okay */ - return CHDERR_NONE; -} - -/*------------------------------------------------- - * lzma_codec_free - *------------------------------------------------- - */ - -void lzma_codec_free(void* codec) -{ - lzma_codec_data* lzma_codec = (lzma_codec_data*) codec; - lzma_allocator* alloc = &lzma_codec->allocator; - - /* free memory */ - lzma_allocator_free(alloc); - LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator); -} - -/*------------------------------------------------- - * decompress - decompress data using the LZMA - * codec - *------------------------------------------------- - */ - -chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) -{ - ELzmaStatus status; - SRes res; - size_t consumedlen, decodedlen; - /* initialize */ - lzma_codec_data* lzma_codec = (lzma_codec_data*) codec; - LzmaDec_Init(&lzma_codec->decoder); - - /* decode */ - consumedlen = complen; - decodedlen = destlen; - res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status); - if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen) - return CHDERR_DECOMPRESSION_ERROR; - return CHDERR_NONE; -} - -/* cdlz */ -chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes) -{ - chd_error ret; - cdlz_codec_data* cdlz = (cdlz_codec_data*) codec; - - /* allocate buffer */ - cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes); - if (cdlz->buffer == NULL) - return CHDERR_OUT_OF_MEMORY; - - ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); - if (ret != CHDERR_NONE) - return ret; - -#ifdef WANT_SUBCODE - ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); - if (ret != CHDERR_NONE) - return ret; -#endif - - return CHDERR_NONE; -} - -void cdlz_codec_free(void* codec) -{ - cdlz_codec_data* cdlz = (cdlz_codec_data*) codec; - - lzma_codec_free(&cdlz->base_decompressor); -#ifdef WANT_SUBCODE - zlib_codec_free(&cdlz->subcode_decompressor); -#endif - if (cdlz->buffer) - free(cdlz->buffer); -} - -chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) -{ -#ifdef WANT_RAW_DATA_SECTOR - uint8_t *sector; -#endif - uint32_t framenum; - cdlz_codec_data* cdlz = (cdlz_codec_data*)codec; - - /* determine header bytes */ - uint32_t frames = destlen / CD_FRAME_SIZE; - uint32_t complen_bytes = (destlen < 65536) ? 2 : 3; - uint32_t ecc_bytes = (frames + 7) / 8; - uint32_t header_bytes = ecc_bytes + complen_bytes; - - /* extract compressed length of base */ - uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1]; - if (complen_bytes > 2) - complen_base = (complen_base << 8) | src[ecc_bytes + 2]; - - /* reset and decode */ - lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA); -#ifdef WANT_SUBCODE - if (header_bytes + complen_base >= complen) - return CHDERR_DECOMPRESSION_ERROR; - zlib_codec_decompress(&cdlz->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdlz->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA); -#endif - - /* reassemble the data */ - for (framenum = 0; framenum < frames; framenum++) - { - memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA); -#ifdef WANT_SUBCODE - memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdlz->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA); -#endif - -#ifdef WANT_RAW_DATA_SECTOR - /* reconstitute the ECC data and sync header */ - sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE]; - if ((src[framenum / 8] & (1 << (framenum % 8))) != 0) - { - memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header)); - ecc_generate(sector); - } -#endif - } - return CHDERR_NONE; -} - -/* cdzl */ - -chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes) -{ - chd_error ret; - cdzl_codec_data* cdzl = (cdzl_codec_data*)codec; - - /* make sure the CHD's hunk size is an even multiple of the frame size */ - if (hunkbytes % CD_FRAME_SIZE != 0) - return CHDERR_CODEC_ERROR; - - cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes); - if (cdzl->buffer == NULL) - return CHDERR_OUT_OF_MEMORY; - - ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); - if (ret != CHDERR_NONE) - return ret; - -#ifdef WANT_SUBCODE - ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); - if (ret != CHDERR_NONE) - return ret; -#endif - - return CHDERR_NONE; -} - -void cdzl_codec_free(void *codec) -{ - cdzl_codec_data* cdzl = (cdzl_codec_data*)codec; - - zlib_codec_free(&cdzl->base_decompressor); -#ifdef WANT_SUBCODE - zlib_codec_free(&cdzl->subcode_decompressor); -#endif - if (cdzl->buffer) - free(cdzl->buffer); -} - -chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) -{ -#ifdef WANT_RAW_DATA_SECTOR - uint8_t *sector; -#endif - uint32_t framenum; - cdzl_codec_data* cdzl = (cdzl_codec_data*)codec; - - /* determine header bytes */ - uint32_t frames = destlen / CD_FRAME_SIZE; - uint32_t complen_bytes = (destlen < 65536) ? 2 : 3; - uint32_t ecc_bytes = (frames + 7) / 8; - uint32_t header_bytes = ecc_bytes + complen_bytes; - - /* extract compressed length of base */ - uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1]; - if (complen_bytes > 2) - complen_base = (complen_base << 8) | src[ecc_bytes + 2]; - - /* reset and decode */ - zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA); -#ifdef WANT_SUBCODE - zlib_codec_decompress(&cdzl->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA); -#endif - - /* reassemble the data */ - for (framenum = 0; framenum < frames; framenum++) - { - memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA); -#ifdef WANT_SUBCODE - memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA); -#endif - -#ifdef WANT_RAW_DATA_SECTOR - /* reconstitute the ECC data and sync header */ - sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE]; - if ((src[framenum / 8] & (1 << (framenum % 8))) != 0) - { - memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header)); - ecc_generate(sector); - } -#endif - } - return CHDERR_NONE; -} - -/*************************************************************************** - * CD FLAC DECOMPRESSOR - *************************************************************************** - */ - -/*------------------------------------------------------ - * cdfl_codec_blocksize - return the optimal block size - *------------------------------------------------------ - */ - -static uint32_t cdfl_codec_blocksize(uint32_t bytes) -{ - /* determine FLAC block size, which must be 16-65535 - * clamp to 2k since that's supposed to be the sweet spot */ - uint32_t hunkbytes = bytes / 4; - while (hunkbytes > 2048) - hunkbytes /= 2; - return hunkbytes; -} - -chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes) -{ -#ifdef WANT_SUBCODE - chd_error ret; -#endif - uint16_t native_endian = 0; - cdfl_codec_data *cdfl = (cdfl_codec_data*)codec; - - /* make sure the CHD's hunk size is an even multiple of the frame size */ - if (hunkbytes % CD_FRAME_SIZE != 0) - return CHDERR_CODEC_ERROR; - - cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes); - if (cdfl->buffer == NULL) - return CHDERR_OUT_OF_MEMORY; - - /* determine whether we want native or swapped samples */ - *(uint8_t *)(&native_endian) = 1; - cdfl->swap_endian = (native_endian & 1); - -#ifdef WANT_SUBCODE - /* init zlib inflater */ - ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); - if (ret != CHDERR_NONE) - return ret; -#endif - - /* flac decoder init */ - flac_decoder_init(&cdfl->decoder); - if (cdfl->decoder.decoder == NULL) - return CHDERR_OUT_OF_MEMORY; - - return CHDERR_NONE; -} - -void cdfl_codec_free(void *codec) -{ - cdfl_codec_data *cdfl = (cdfl_codec_data*)codec; - flac_decoder_free(&cdfl->decoder); -#ifdef WANT_SUBCODE - zlib_codec_free(&cdfl->subcode_decompressor); -#endif - if (cdfl->buffer) - free(cdfl->buffer); -} - -chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) -{ - uint32_t framenum; - uint8_t *buffer; -#ifdef WANT_SUBCODE - uint32_t offset; - chd_error ret; -#endif - cdfl_codec_data *cdfl = (cdfl_codec_data*)codec; - - /* reset and decode */ - uint32_t frames = destlen / CD_FRAME_SIZE; - - if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen)) - return CHDERR_DECOMPRESSION_ERROR; - buffer = &cdfl->buffer[0]; - if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian)) - return CHDERR_DECOMPRESSION_ERROR; - -#ifdef WANT_SUBCODE - /* inflate the subcode data */ - offset = flac_decoder_finish(&cdfl->decoder); - ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA); - if (ret != CHDERR_NONE) - return ret; -#else - flac_decoder_finish(&cdfl->decoder); -#endif - - /* reassemble the data */ - for (framenum = 0; framenum < frames; framenum++) - { - memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA); -#ifdef WANT_SUBCODE - memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdfl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA); -#endif - } - - return CHDERR_NONE; -} /*************************************************************************** CODEC INTERFACES ***************************************************************************/ @@ -850,6 +282,7 @@ static const codec_interface codec_interfaces[] = NULL }, +#ifdef HAVE_ZLIB /* standard zlib compression */ { CHDCOMPRESSION_ZLIB, @@ -882,7 +315,9 @@ static const codec_interface codec_interfaces[] = cdzl_codec_decompress, NULL }, +#endif +#ifdef HAVE_7ZIP /* V5 CD lzma compression */ { CHD_CODEC_CD_LZMA, @@ -893,7 +328,9 @@ static const codec_interface codec_interfaces[] = cdlz_codec_decompress, NULL }, +#endif +#ifdef HAVE_FLAC /* V5 CD flac compression */ { CHD_CODEC_CD_FLAC, @@ -904,6 +341,7 @@ static const codec_interface codec_interfaces[] = cdfl_codec_decompress, NULL }, +#endif }; /*************************************************************************** @@ -1146,8 +584,8 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header) } /* read the reader */ - core_fseek(chd->file, header->mapoffset, SEEK_SET); - core_fread(chd->file, rawbuf, sizeof(rawbuf)); + filestream_seek(chd->file, header->mapoffset, SEEK_SET); + filestream_read(chd->file, rawbuf, sizeof(rawbuf)); mapbytes = get_bigendian_uint32(&rawbuf[0]); firstoffs = get_bigendian_uint48(&rawbuf[4]); mapcrc = get_bigendian_uint16(&rawbuf[10]); @@ -1160,8 +598,8 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header) if (compressed == NULL) return CHDERR_OUT_OF_MEMORY; - core_fseek(chd->file, header->mapoffset + 16, SEEK_SET); - core_fread(chd->file, compressed, mapbytes); + filestream_seek(chd->file, header->mapoffset + 16, SEEK_SET); + filestream_read(chd->file, compressed, mapbytes); bitbuf = create_bitstream(compressed, sizeof(uint8_t) * mapbytes); if (bitbuf == NULL) { @@ -1297,7 +735,7 @@ static INLINE void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 h entry->offset = get_bigendian_uint64(&base[0]); entry->crc = 0; entry->length = entry->offset >> 44; - entry->flags = MAP_ENTRY_FLAG_NO_CRC | ((entry->length == hunkbytes) ? V34_MAP_ENTRY_TYPE_UNCOMPRESSED : V34_MAP_ENTRY_TYPE_COMPRESSED); + entry->flags = MAP_ENTRY_FLAG_NO_CRC | ((entry->length == hunkbytes) ? MAP_ENTRY_TYPE_UNCOMPRESSED : MAP_ENTRY_TYPE_COMPRESSED); #ifdef __MWERKS__ entry->offset = entry->offset & 0x00000FFFFFFFFFFFLL; #else @@ -1313,7 +751,7 @@ static INLINE void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 h chd_open_file - open a CHD file for access -------------------------------------------------*/ -chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd) +chd_error chd_open_file(RFILE *file, int mode, chd_file *parent, chd_file **chd) { chd_file *newchd = NULL; chd_error err; @@ -1405,29 +843,31 @@ chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file ** /* find the codec interface */ if (newchd->header.version < 5) { - for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++) + for (intfnum = 0; intfnum < ARRAY_SIZE(codec_interfaces); intfnum++) if (codec_interfaces[intfnum].compression == newchd->header.compression[0]) { newchd->codecintf[0] = &codec_interfaces[intfnum]; break; } - if (intfnum == ARRAY_LENGTH(codec_interfaces)) + if (intfnum == ARRAY_SIZE(codec_interfaces)) EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT); +#ifdef HAVE_ZLIB /* initialize the codec */ if (newchd->codecintf[0]->init != NULL) - { - err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes); - (void)err; - } + { + err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes); + (void)err; + } +#endif } else { int i, decompnum; /* verify the compression types and initialize the codecs */ - for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++) + for (decompnum = 0; decompnum < ARRAY_SIZE(newchd->header.compression); decompnum++) { - for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++) + for (i = 0 ; i < ARRAY_SIZE(codec_interfaces) ; i++) { if (codec_interfaces[i].compression == newchd->header.compression[decompnum]) { @@ -1445,15 +885,21 @@ chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file ** switch (newchd->header.compression[decompnum]) { case CHD_CODEC_CD_ZLIB: +#ifdef HAVE_ZLIB codec = &newchd->cdzl_codec_data; +#endif break; case CHD_CODEC_CD_LZMA: +#ifdef HAVE_7ZIP codec = &newchd->cdlz_codec_data; +#endif break; case CHD_CODEC_CD_FLAC: +#ifdef HAVE_FLAC codec = &newchd->cdfl_codec_data; +#endif break; } if (codec != NULL) @@ -1492,7 +938,7 @@ cleanup: chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd) { chd_error err; - core_file *file = NULL; + RFILE *file = NULL; /* choose the proper mode */ switch(mode) @@ -1506,8 +952,11 @@ chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file ** } /* open the file */ - file = core_fopen(filename); - if (file == 0) + file = filestream_open(filename, + RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + + if (!file) { err = CHDERR_FILE_NOT_FOUND; goto cleanup; @@ -1523,10 +972,36 @@ chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file ** cleanup: if ((err != CHDERR_NONE) && (file != NULL)) - core_fclose(file); + filestream_close(file); return err; } +chd_error chd_precache(chd_file *chd) +{ + int64_t size, count; + + if (!chd->file_cache) + { + filestream_seek(chd->file, 0, SEEK_END); + size = filestream_tell(chd->file); + if (size <= 0) + return CHDERR_INVALID_DATA; + chd->file_cache = malloc(size); + if (chd->file_cache == NULL) + return CHDERR_OUT_OF_MEMORY; + filestream_seek(chd->file, 0, SEEK_SET); + count = filestream_read(chd->file, chd->file_cache, size); + if (count != size) + { + free(chd->file_cache); + chd->file_cache = NULL; + return CHDERR_READ_ERROR; + } + } + + return CHDERR_NONE; +} + /*------------------------------------------------- chd_close - close a CHD file for access -------------------------------------------------*/ @@ -1540,35 +1015,41 @@ void chd_close(chd_file *chd) /* deinit the codec */ if (chd->header.version < 5) { +#ifdef HAVE_ZLIB if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL) (*chd->codecintf[0]->free)(&chd->zlib_codec_data); +#endif } else { int i; /* Free the codecs */ for (i = 0 ; i < 4 ; i++) - { - void* codec = NULL; - switch (chd->codecintf[i]->compression) - { - case CHD_CODEC_CD_LZMA: - codec = &chd->cdlz_codec_data; - break; + { + void* codec = NULL; + switch (chd->codecintf[i]->compression) + { + case CHD_CODEC_CD_LZMA: +#ifdef HAVE_7ZIP + codec = &chd->cdlz_codec_data; +#endif + break; - case CHD_CODEC_CD_ZLIB: - codec = &chd->cdzl_codec_data; - break; + case CHD_CODEC_CD_ZLIB: +#ifdef HAVE_ZLIB + codec = &chd->cdzl_codec_data; +#endif + break; - case CHD_CODEC_CD_FLAC: - codec = &chd->cdfl_codec_data; - break; - } - if (codec) - { - (*chd->codecintf[i]->free)(codec); - } - } + case CHD_CODEC_CD_FLAC: +#ifdef HAVE_FLAC + codec = &chd->cdfl_codec_data; +#endif + break; + } + if (codec) + (*chd->codecintf[i]->free)(codec); + } /* Free the raw map */ if (chd->header.rawmap != NULL) @@ -1593,12 +1074,15 @@ void chd_close(chd_file *chd) /* close the file */ if (chd->owns_file && chd->file != NULL) - core_fclose(chd->file); + filestream_close(chd->file); #ifdef NEED_CACHE_HUNK if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks); #endif + if (chd->file_cache) + free(chd->file_cache); + /* free our memory */ free(chd); } @@ -1608,7 +1092,7 @@ void chd_close(chd_file *chd) core_file -------------------------------------------------*/ -core_file *chd_core_file(chd_file *chd) +RFILE *chd_core_file(chd_file *chd) { return chd->file; } @@ -1704,7 +1188,7 @@ chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, { metadata_entry metaentry; chd_error err; - UINT32 count; + int64_t count; /* if we didn't find it, just return */ err = metadata_find_entry(chd, searchtag, searchindex, &metaentry); @@ -1735,8 +1219,8 @@ chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, /* read the metadata */ outputlen = MIN(outputlen, metaentry.length); - core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET); - count = core_fread(chd->file, output, outputlen); + filestream_seek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET); + count = filestream_read(chd->file, output, outputlen); if (count != outputlen) return CHDERR_READ_ERROR; @@ -1807,11 +1291,11 @@ static chd_error header_validate(const chd_header *header) return CHDERR_INVALID_PARAMETER; /* require a supported compression mechanism */ - for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++) + for (intfnum = 0; intfnum < ARRAY_SIZE(codec_interfaces); intfnum++) if (codec_interfaces[intfnum].compression == header->compression[0]) break; - if (intfnum == ARRAY_LENGTH(codec_interfaces)) + if (intfnum == ARRAY_SIZE(codec_interfaces)) return CHDERR_INVALID_PARAMETER; /* require a valid hunksize */ @@ -1875,7 +1359,7 @@ static UINT32 header_guess_unitbytes(chd_file *chd) static chd_error header_read(chd_file *chd, chd_header *header) { UINT8 rawheader[CHD_MAX_HEADER_SIZE]; - UINT32 count; + int64_t count; /* punt if NULL */ if (header == NULL) @@ -1886,8 +1370,8 @@ static chd_error header_read(chd_file *chd, chd_header *header) return CHDERR_INVALID_FILE; /* seek and read */ - core_fseek(chd->file, 0, SEEK_SET); - count = core_fread(chd->file, rawheader, sizeof(rawheader)); + filestream_seek(chd->file, 0, SEEK_SET); + count = filestream_read(chd->file, rawheader, sizeof(rawheader)); if (count != sizeof(rawheader)) return CHDERR_READ_ERROR; @@ -2034,6 +1518,35 @@ static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum) } #endif +static UINT8* read_compressed(chd_file *chd, UINT64 offset, size_t size) +{ + int64_t bytes; + if (chd->file_cache) + return chd->file_cache + offset; + filestream_seek(chd->file, offset, SEEK_SET); + bytes = filestream_read(chd->file, chd->compressed, size); + if (bytes != size) + return NULL; + return chd->compressed; +} + +static chd_error read_uncompressed(chd_file *chd, UINT64 offset, size_t size, UINT8 *dest) +{ + int64_t bytes; + if (chd->file_cache) + { + memcpy(dest, chd->file_cache + offset, size); + return CHDERR_NONE; + } + filestream_seek(chd->file, offset, SEEK_SET); + bytes = filestream_read(chd->file, dest, size); + if (bytes != size) + return CHDERR_READ_ERROR; + return CHDERR_NONE; +} + + + /*------------------------------------------------- hunk_read_into_memory - read a hunk into memory at the given location @@ -2056,7 +1569,6 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des if (chd->header.version < 5) { - void* codec; map_entry *entry = &chd->map[hunknum]; UINT32 bytes; @@ -2064,42 +1576,42 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK) { /* compressed data */ - case V34_MAP_ENTRY_TYPE_COMPRESSED: + case MAP_ENTRY_TYPE_COMPRESSED: + { + void *codec; + UINT8 *bytes = read_compressed(chd, entry->offset, + entry->length); + if (bytes == NULL) + return CHDERR_READ_ERROR; - /* read it into the decompression buffer */ - if (core_fseek(chd->file, entry->offset, SEEK_SET) != 0) - return CHDERR_READ_ERROR; - bytes = core_fread(chd->file, chd->compressed, entry->length); - if (bytes != entry->length) - return CHDERR_READ_ERROR; - - /* now decompress using the codec */ - err = CHDERR_NONE; - codec = &chd->zlib_codec_data; - if (chd->codecintf[0]->decompress != NULL) - err = (*chd->codecintf[0]->decompress)(codec, chd->compressed, entry->length, dest, chd->header.hunkbytes); - if (err != CHDERR_NONE) - return err; +#ifdef HAVE_ZLIB + /* now decompress using the codec */ + err = CHDERR_NONE; + codec = &chd->zlib_codec_data; + if (chd->codecintf[0]->decompress != NULL) + err = (*chd->codecintf[0]->decompress)(codec, chd->compressed, entry->length, dest, chd->header.hunkbytes); + if (err != CHDERR_NONE) + return err; +#endif + } break; /* uncompressed data */ - case V34_MAP_ENTRY_TYPE_UNCOMPRESSED: - if (core_fseek(chd->file, entry->offset, SEEK_SET) != 0) - return CHDERR_READ_ERROR; - bytes = core_fread(chd->file, dest, chd->header.hunkbytes); - if (bytes != chd->header.hunkbytes) - return CHDERR_READ_ERROR; + case MAP_ENTRY_TYPE_UNCOMPRESSED: + err = read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest); + if (err != CHDERR_NONE) + return err; break; /* mini-compressed data */ - case V34_MAP_ENTRY_TYPE_MINI: + case MAP_ENTRY_TYPE_MINI: put_bigendian_uint64(&dest[0], entry->offset); for (bytes = 8; bytes < chd->header.hunkbytes; bytes++) dest[bytes] = dest[bytes - 8]; break; /* self-referenced data */ - case V34_MAP_ENTRY_TYPE_SELF_HUNK: + case MAP_ENTRY_TYPE_SELF_HUNK: #ifdef NEED_CACHE_HUNK if (chd->cachehunk == entry->offset && dest == chd->cache) break; @@ -2107,7 +1619,7 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des return hunk_read_into_memory(chd, entry->offset, dest); /* parent-referenced data */ - case V34_MAP_ENTRY_TYPE_PARENT_HUNK: + case MAP_ENTRY_TYPE_PARENT_HUNK: err = hunk_read_into_memory(chd->parent, entry->offset, dest); if (err != CHDERR_NONE) return err; @@ -2125,6 +1637,7 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des uint16_t blockcrc; #endif uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum]; + UINT8 *bytes; #if 0 /* uncompressed case - TODO */ @@ -2155,23 +1668,27 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des case COMPRESSION_TYPE_1: case COMPRESSION_TYPE_2: case COMPRESSION_TYPE_3: - if (core_fseek(chd->file, blockoffs, SEEK_SET) != 0) - return CHDERR_READ_ERROR; - if(core_fread(chd->file, chd->compressed, blocklen) != blocklen) - return CHDERR_READ_ERROR; - + bytes = read_compressed(chd, blockoffs, blocklen); + if (bytes == NULL) + return CHDERR_READ_ERROR; switch (chd->codecintf[rawmap[0]]->compression) { case CHD_CODEC_CD_LZMA: +#ifdef HAVE_7ZIP codec = &chd->cdlz_codec_data; +#endif break; case CHD_CODEC_CD_ZLIB: +#ifdef HAVE_ZLIB codec = &chd->cdzl_codec_data; +#endif break; case CHD_CODEC_CD_FLAC: +#ifdef HAVE_FLAC codec = &chd->cdfl_codec_data; +#endif break; } if (codec==NULL) @@ -2186,13 +1703,12 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des return CHDERR_NONE; case COMPRESSION_NONE: - if (core_fseek(chd->file, blockoffs, SEEK_SET) != 0) - return CHDERR_READ_ERROR; - if (core_fread(chd->file, dest, chd->header.hunkbytes) != chd->header.hunkbytes) - return CHDERR_READ_ERROR; + err = read_uncompressed(chd, blockoffs, blocklen, dest); + if (err != CHDERR_NONE) + return err; #ifdef VERIFY_BLOCK_CRC - if (crc16(dest, chd->header.hunkbytes) != blockcrc) - return CHDERR_DECOMPRESSION_ERROR; + if (crc16(dest, chd->header.hunkbytes) != blockcrc) + return CHDERR_DECOMPRESSION_ERROR; #endif return CHDERR_NONE; @@ -2219,12 +1735,12 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des INTERNAL MAP ACCESS ***************************************************************************/ -static size_t core_fsize(core_file *f) +static size_t core_fsize(RFILE *f) { - long rv,p = ftell(f); - fseek(f, 0, SEEK_END); - rv = ftell(f); - fseek(f, p, SEEK_SET); + int64_t rv, p = filestream_tell(f); + filestream_seek(f, 0, SEEK_END); + rv = filestream_tell(f); + filestream_seek(f, p, SEEK_SET); return rv; } @@ -2238,7 +1754,7 @@ static chd_error map_read(chd_file *chd) UINT8 raw_map_entries[MAP_STACK_ENTRIES * MAP_ENTRY_SIZE]; UINT64 fileoffset, maxoffset = 0; UINT8 cookie[MAP_ENTRY_SIZE]; - UINT32 count; + int64_t count; chd_error err; int i; @@ -2257,8 +1773,8 @@ static chd_error map_read(chd_file *chd) entries = MAP_STACK_ENTRIES; /* read that many */ - core_fseek(chd->file, fileoffset, SEEK_SET); - count = core_fread(chd->file, raw_map_entries, entries * entrysize); + filestream_seek(chd->file, fileoffset, SEEK_SET); + count = filestream_read(chd->file, raw_map_entries, entries * entrysize); if (count != entries * entrysize) { err = CHDERR_READ_ERROR; @@ -2280,14 +1796,14 @@ static chd_error map_read(chd_file *chd) /* track the maximum offset */ for (j = 0; j < entries; j++) - if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_COMPRESSED || - (chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_UNCOMPRESSED) + if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == MAP_ENTRY_TYPE_COMPRESSED || + (chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == MAP_ENTRY_TYPE_UNCOMPRESSED) maxoffset = MAX(maxoffset, chd->map[i + j].offset + chd->map[i + j].length); } /* verify the cookie */ - core_fseek(chd->file, fileoffset, SEEK_SET); - count = core_fread(chd->file, &cookie, entrysize); + filestream_seek(chd->file, fileoffset, SEEK_SET); + count = filestream_read(chd->file, &cookie, entrysize); if (count != entrysize || memcmp(&cookie, END_OF_LIST_COOKIE, entrysize)) { err = CHDERR_INVALID_FILE; @@ -2327,11 +1843,11 @@ static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metai while (metaentry->offset != 0) { UINT8 raw_meta_header[METADATA_HEADER_SIZE]; - UINT32 count; + int64_t count; /* read the raw header */ - core_fseek(chd->file, metaentry->offset, SEEK_SET); - count = core_fread(chd->file, raw_meta_header, sizeof(raw_meta_header)); + filestream_seek(chd->file, metaentry->offset, SEEK_SET); + count = filestream_read(chd->file, raw_meta_header, sizeof(raw_meta_header)); if (count != sizeof(raw_meta_header)) break; @@ -2357,159 +1873,3 @@ static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metai /* if we get here, we didn't find it */ return CHDERR_METADATA_NOT_FOUND; } - -/*************************************************************************** - ZLIB COMPRESSION CODEC -***************************************************************************/ - -/*------------------------------------------------- - zlib_codec_init - initialize the ZLIB codec --------------------------------------------------*/ - -static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes) -{ - int zerr; - chd_error err; - zlib_codec_data *data = (zlib_codec_data*)codec; - - /* clear the buffers */ - memset(data, 0, sizeof(zlib_codec_data)); - - /* init the inflater first */ - data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */ - data->inflater.avail_in = 0; - data->inflater.zalloc = zlib_fast_alloc; - data->inflater.zfree = zlib_fast_free; - data->inflater.opaque = &data->allocator; - zerr = inflateInit2(&data->inflater, -MAX_WBITS); - - /* convert errors */ - if (zerr == Z_MEM_ERROR) - err = CHDERR_OUT_OF_MEMORY; - else if (zerr != Z_OK) - err = CHDERR_CODEC_ERROR; - else - err = CHDERR_NONE; - - return err; -} - -/*------------------------------------------------- - zlib_codec_free - free data for the ZLIB - codec --------------------------------------------------*/ - -static void zlib_codec_free(void *codec) -{ - zlib_codec_data *data = (zlib_codec_data *)codec; - - /* deinit the streams */ - if (data != NULL) - { - int i; - zlib_allocator alloc; - - inflateEnd(&data->inflater); - - /* free our fast memory */ - alloc = data->allocator; - for (i = 0; i < MAX_ZLIB_ALLOCS; i++) - if (alloc.allocptr[i]) - free(alloc.allocptr[i]); - } -} - -/*------------------------------------------------- - zlib_codec_decompress - decomrpess data using - the ZLIB codec --------------------------------------------------*/ - -static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) -{ - zlib_codec_data *data = (zlib_codec_data *)codec; - int zerr; - - /* reset the decompressor */ - data->inflater.next_in = (Bytef *)src; - data->inflater.avail_in = complen; - data->inflater.total_in = 0; - data->inflater.next_out = (Bytef *)dest; - data->inflater.avail_out = destlen; - data->inflater.total_out = 0; - zerr = inflateReset(&data->inflater); - if (zerr != Z_OK) - return CHDERR_DECOMPRESSION_ERROR; - - /* do it */ - zerr = inflate(&data->inflater, Z_FINISH); - (void)zerr; - if (data->inflater.total_out != destlen) - return CHDERR_DECOMPRESSION_ERROR; - - return CHDERR_NONE; -} - -/*------------------------------------------------- - zlib_fast_alloc - fast malloc for ZLIB, which - allocates and frees memory frequently --------------------------------------------------*/ - -static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size) -{ - zlib_allocator *alloc = (zlib_allocator *)opaque; - UINT32 *ptr; - int i; - - /* compute the size, rounding to the nearest 1k */ - size = (size * items + 0x3ff) & ~0x3ff; - - /* reuse a hunk if we can */ - for (i = 0; i < MAX_ZLIB_ALLOCS; i++) - { - ptr = alloc->allocptr[i]; - if (ptr && size == *ptr) - { - /* set the low bit of the size so we don't match next time */ - *ptr |= 1; - return ptr + 1; - } - } - - /* alloc a new one */ - ptr = (UINT32 *)malloc(size + sizeof(UINT32)); - if (!ptr) - return NULL; - - /* put it into the list */ - for (i = 0; i < MAX_ZLIB_ALLOCS; i++) - if (!alloc->allocptr[i]) - { - alloc->allocptr[i] = ptr; - break; - } - - /* set the low bit of the size so we don't match next time */ - *ptr = size | 1; - return ptr + 1; -} - -/*------------------------------------------------- - zlib_fast_free - fast free for ZLIB, which - allocates and frees memory frequently --------------------------------------------------*/ - -static void zlib_fast_free(voidpf opaque, voidpf address) -{ - zlib_allocator *alloc = (zlib_allocator *)opaque; - UINT32 *ptr = (UINT32 *)address - 1; - int i; - - /* find the hunk */ - for (i = 0; i < MAX_ZLIB_ALLOCS; i++) - if (ptr == alloc->allocptr[i]) - { - /* clear the low bit of the size to allow matches */ - *ptr &= ~1; - return; - } -} diff --git a/libretro-common/formats/libchdr/flac.c b/libretro-common/formats/libchdr/libchdr_flac.c similarity index 99% rename from libretro-common/formats/libchdr/flac.c rename to libretro-common/formats/libchdr/libchdr_flac.c index 8fe0cf7752..4cc5dc20a4 100644 --- a/libretro-common/formats/libchdr/flac.c +++ b/libretro-common/formats/libchdr/libchdr_flac.c @@ -12,6 +12,7 @@ #include #include #include +#include /*************************************************************************** * FLAC DECODER @@ -153,7 +154,7 @@ bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_end { /* make sure we don't have too many channels */ int chans = channels(); - if (chans > ARRAY_LENGTH(m_uncompressed_start)) + if (chans > ARRAY_SIZE(m_uncompressed_start)) return false; /* configure the uncompressed buffer */ diff --git a/libretro-common/formats/libchdr/libchdr_flac_codec.c b/libretro-common/formats/libchdr/libchdr_flac_codec.c new file mode 100644 index 0000000000..83abadd3f2 --- /dev/null +++ b/libretro-common/formats/libchdr/libchdr_flac_codec.c @@ -0,0 +1,163 @@ +/*************************************************************************** + + libchdr_flac_codec.c + + MAME Compressed Hunks of Data file format + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TRUE 1 +#define FALSE 0 + +/*************************************************************************** + * CD FLAC DECOMPRESSOR + *************************************************************************** + */ + +/*------------------------------------------------------ + * cdfl_codec_blocksize - return the optimal block size + *------------------------------------------------------ + */ + +static uint32_t cdfl_codec_blocksize(uint32_t bytes) +{ + /* determine FLAC block size, which must be 16-65535 + * clamp to 2k since that's supposed to be the sweet spot */ + uint32_t hunkbytes = bytes / 4; + while (hunkbytes > 2048) + hunkbytes /= 2; + return hunkbytes; +} + +chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes) +{ +#ifdef WANT_SUBCODE + chd_error ret; +#endif + uint16_t native_endian = 0; + cdfl_codec_data *cdfl = (cdfl_codec_data*)codec; + + /* make sure the CHD's hunk size is an even multiple of the frame size */ + if (hunkbytes % CD_FRAME_SIZE != 0) + return CHDERR_CODEC_ERROR; + + cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes); + if (cdfl->buffer == NULL) + return CHDERR_OUT_OF_MEMORY; + + /* determine whether we want native or swapped samples */ + *(uint8_t *)(&native_endian) = 1; + cdfl->swap_endian = (native_endian & 1); + +#ifdef WANT_SUBCODE + /* init zlib inflater */ + ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); + if (ret != CHDERR_NONE) + return ret; +#endif + + /* flac decoder init */ + flac_decoder_init(&cdfl->decoder); + if (cdfl->decoder.decoder == NULL) + return CHDERR_OUT_OF_MEMORY; + + return CHDERR_NONE; +} + +void cdfl_codec_free(void *codec) +{ + cdfl_codec_data *cdfl = (cdfl_codec_data*)codec; + flac_decoder_free(&cdfl->decoder); +#ifdef WANT_SUBCODE + zlib_codec_free(&cdfl->subcode_decompressor); +#endif + if (cdfl->buffer) + free(cdfl->buffer); +} + +chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) +{ + uint32_t framenum; + uint8_t *buffer; +#ifdef WANT_SUBCODE + uint32_t offset; + chd_error ret; +#endif + cdfl_codec_data *cdfl = (cdfl_codec_data*)codec; + + /* reset and decode */ + uint32_t frames = destlen / CD_FRAME_SIZE; + + if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen)) + return CHDERR_DECOMPRESSION_ERROR; + buffer = &cdfl->buffer[0]; + if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian)) + return CHDERR_DECOMPRESSION_ERROR; + +#ifdef WANT_SUBCODE + /* inflate the subcode data */ + offset = flac_decoder_finish(&cdfl->decoder); + ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA); + if (ret != CHDERR_NONE) + return ret; +#else + flac_decoder_finish(&cdfl->decoder); +#endif + + /* reassemble the data */ + for (framenum = 0; framenum < frames; framenum++) + { + memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA); +#ifdef WANT_SUBCODE + memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdfl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA); +#endif + } + + return CHDERR_NONE; +} diff --git a/libretro-common/formats/libchdr/huffman.c b/libretro-common/formats/libchdr/libchdr_huffman.c similarity index 99% rename from libretro-common/formats/libchdr/huffman.c rename to libretro-common/formats/libchdr/libchdr_huffman.c index 04b0300dd0..dd041a76c9 100644 --- a/libretro-common/formats/libchdr/huffman.c +++ b/libretro-common/formats/libchdr/libchdr_huffman.c @@ -294,7 +294,10 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, /* make sure we ended up with the right number */ if (curcode != decoder->numcodes) + { + delete_huffman_decoder(smallhuff); return HUFFERR_INVALID_DATA; + } /* assign canonical codes for all nodes based on their code lengths */ error = huffman_assign_canonical_codes(decoder); diff --git a/libretro-common/formats/libchdr/libchdr_lzma.c b/libretro-common/formats/libchdr/libchdr_lzma.c new file mode 100644 index 0000000000..096c6efb0f --- /dev/null +++ b/libretro-common/formats/libchdr/libchdr_lzma.c @@ -0,0 +1,355 @@ +/*************************************************************************** + + libchdr_lzma_codec.c + + MAME Compressed Hunks of Data file format + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TRUE 1 +#define FALSE 0 + +/*************************************************************************** + * LZMA ALLOCATOR HELPER + *************************************************************************** + */ + +/*------------------------------------------------- + * lzma_fast_alloc - fast malloc for lzma, which + * allocates and frees memory frequently + *------------------------------------------------- + */ + +static void *lzma_fast_alloc(void *p, size_t size) +{ + int scan; + uint32_t *addr = NULL; + lzma_allocator *codec = (lzma_allocator *)(p); + + /* compute the size, rounding to the nearest 1k */ + size = (size + 0x3ff) & ~0x3ff; + + /* reuse a hunk if we can */ + for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++) + { + uint32_t *ptr = codec->allocptr[scan]; + if (ptr != NULL && size == *ptr) + { + /* set the low bit of the size so we don't match next time */ + *ptr |= 1; + return ptr + 1; + } + } + + /* alloc a new one and put it into the list */ + addr = (uint32_t *)malloc(sizeof(uint32_t) * (size + sizeof(uint32_t))); + if (!addr) + return NULL; + + for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++) + { + if (codec->allocptr[scan] == NULL) + { + codec->allocptr[scan] = addr; + break; + } + } + + /* set the low bit of the size so we don't match next time */ + *addr = size | 1; + return addr + 1; +} + +/*------------------------------------------------- + * lzma_fast_free - fast free for lzma, which + * allocates and frees memory frequently + *------------------------------------------------- + */ +static void lzma_fast_free(void *p, void *address) +{ + int scan; + uint32_t *ptr; + lzma_allocator *codec; + if (address == NULL) + return; + + codec = (lzma_allocator *)(p); + + /* find the hunk */ + ptr = (uint32_t *)(address) - 1; + for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++) + { + if (ptr == codec->allocptr[scan]) + { + /* clear the low bit of the size to allow matches */ + *ptr &= ~1; + return; + } + } +} + + +/*------------------------------------------------- + * lzma_allocator_init + *------------------------------------------------- + */ + +void lzma_allocator_init(void* p) +{ + lzma_allocator *codec = (lzma_allocator *)(p); + + /* reset pointer list */ + memset(codec->allocptr, 0, sizeof(codec->allocptr)); + codec->Alloc = lzma_fast_alloc; + codec->Free = lzma_fast_free; +} + +/*------------------------------------------------- + * lzma_allocator_free + *------------------------------------------------- + */ + +void lzma_allocator_free(void* p ) +{ + lzma_allocator *codec = (lzma_allocator *)(p); + + /* free our memory */ + int i; + for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++) + { + if (codec->allocptr[i] != NULL) + free(codec->allocptr[i]); + } +} + + + +/*************************************************************************** + * LZMA DECOMPRESSOR + *************************************************************************** + */ + +/*------------------------------------------------- + * lzma_codec_init - constructor + *------------------------------------------------- + */ + +chd_error lzma_codec_init(void* codec, uint32_t hunkbytes) +{ + CLzmaEncProps encoder_props; + CLzmaEncHandle enc; + uint8_t decoder_props[LZMA_PROPS_SIZE]; + lzma_allocator* alloc; + size_t props_size; + lzma_codec_data* lzma_codec = (lzma_codec_data*) codec; + + /* construct the decoder */ + LzmaDec_Construct(&lzma_codec->decoder); + + /* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK + * This code assumes that the current version of the encoder imposes the same requirements on the + * decoder as the encoder used to produce the file. This is not necessarily true. The format + * needs to be changed so the encoder properties are written to the file. + + * configure the properties like the compressor did */ + LzmaEncProps_Init(&encoder_props); + encoder_props.level = 9; + encoder_props.reduceSize = hunkbytes; + LzmaEncProps_Normalize(&encoder_props); + + /* convert to decoder properties */ + alloc = &lzma_codec->allocator; + lzma_allocator_init(alloc); + enc = LzmaEnc_Create((ISzAlloc*)alloc); + if (!enc) + return CHDERR_DECOMPRESSION_ERROR; + if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK) + { + LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc); + return CHDERR_DECOMPRESSION_ERROR; + } + props_size = sizeof(decoder_props); + if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK) + { + LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc); + return CHDERR_DECOMPRESSION_ERROR; + } + LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc); + + /* do memory allocations */ + if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK) + return CHDERR_DECOMPRESSION_ERROR; + + /* Okay */ + return CHDERR_NONE; +} + +/*------------------------------------------------- + * lzma_codec_free + *------------------------------------------------- + */ + +void lzma_codec_free(void* codec) +{ + lzma_codec_data* lzma_codec = (lzma_codec_data*) codec; + lzma_allocator* alloc = &lzma_codec->allocator; + + /* free memory */ + lzma_allocator_free(alloc); + LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator); +} + +/*------------------------------------------------- + * decompress - decompress data using the LZMA + * codec + *------------------------------------------------- + */ + +chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) +{ + ELzmaStatus status; + SRes res; + size_t consumedlen, decodedlen; + /* initialize */ + lzma_codec_data* lzma_codec = (lzma_codec_data*) codec; + LzmaDec_Init(&lzma_codec->decoder); + + /* decode */ + consumedlen = complen; + decodedlen = destlen; + res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status); + if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen) + return CHDERR_DECOMPRESSION_ERROR; + return CHDERR_NONE; +} + +/* cdlz */ +chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes) +{ + chd_error ret; + cdlz_codec_data* cdlz = (cdlz_codec_data*) codec; + + /* allocate buffer */ + cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes); + if (cdlz->buffer == NULL) + return CHDERR_OUT_OF_MEMORY; + + ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); + if (ret != CHDERR_NONE) + return ret; + +#ifdef WANT_SUBCODE + ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); + if (ret != CHDERR_NONE) + return ret; +#endif + + return CHDERR_NONE; +} + +void cdlz_codec_free(void* codec) +{ + cdlz_codec_data* cdlz = (cdlz_codec_data*) codec; + + lzma_codec_free(&cdlz->base_decompressor); +#ifdef WANT_SUBCODE + zlib_codec_free(&cdlz->subcode_decompressor); +#endif + if (cdlz->buffer) + free(cdlz->buffer); +} + +chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) +{ +#ifdef WANT_RAW_DATA_SECTOR + uint8_t *sector; +#endif + uint32_t framenum; + cdlz_codec_data* cdlz = (cdlz_codec_data*)codec; + + /* determine header bytes */ + uint32_t frames = destlen / CD_FRAME_SIZE; + uint32_t complen_bytes = (destlen < 65536) ? 2 : 3; + uint32_t ecc_bytes = (frames + 7) / 8; + uint32_t header_bytes = ecc_bytes + complen_bytes; + + /* extract compressed length of base */ + uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1]; + if (complen_bytes > 2) + complen_base = (complen_base << 8) | src[ecc_bytes + 2]; + + /* reset and decode */ + lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA); +#ifdef WANT_SUBCODE + if (header_bytes + complen_base >= complen) + return CHDERR_DECOMPRESSION_ERROR; + zlib_codec_decompress(&cdlz->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdlz->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA); +#endif + + /* reassemble the data */ + for (framenum = 0; framenum < frames; framenum++) + { + memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA); +#ifdef WANT_SUBCODE + memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdlz->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA); +#endif + +#ifdef WANT_RAW_DATA_SECTOR + /* reconstitute the ECC data and sync header */ + sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE]; + if ((src[framenum / 8] & (1 << (framenum % 8))) != 0) + { + memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header)); + ecc_generate(sector); + } +#endif + } + return CHDERR_NONE; +} + diff --git a/libretro-common/formats/libchdr/libchdr_zlib.c b/libretro-common/formats/libchdr/libchdr_zlib.c new file mode 100644 index 0000000000..44c642f81e --- /dev/null +++ b/libretro-common/formats/libchdr/libchdr_zlib.c @@ -0,0 +1,298 @@ +/*************************************************************************** + + libchdr_zlib.c + + MAME Compressed Hunks of Data file format + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TRUE 1 +#define FALSE 0 + +/* cdzl */ + +chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes) +{ + chd_error ret; + cdzl_codec_data* cdzl = (cdzl_codec_data*)codec; + + /* make sure the CHD's hunk size is an even multiple of the frame size */ + if (hunkbytes % CD_FRAME_SIZE != 0) + return CHDERR_CODEC_ERROR; + + cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes); + if (cdzl->buffer == NULL) + return CHDERR_OUT_OF_MEMORY; + + ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); + if (ret != CHDERR_NONE) + return ret; + +#ifdef WANT_SUBCODE + ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); + if (ret != CHDERR_NONE) + return ret; +#endif + + return CHDERR_NONE; +} + +void cdzl_codec_free(void *codec) +{ + cdzl_codec_data* cdzl = (cdzl_codec_data*)codec; + + zlib_codec_free(&cdzl->base_decompressor); +#ifdef WANT_SUBCODE + zlib_codec_free(&cdzl->subcode_decompressor); +#endif + if (cdzl->buffer) + free(cdzl->buffer); +} + +chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) +{ +#ifdef WANT_RAW_DATA_SECTOR + uint8_t *sector; +#endif + uint32_t framenum; + cdzl_codec_data* cdzl = (cdzl_codec_data*)codec; + + /* determine header bytes */ + uint32_t frames = destlen / CD_FRAME_SIZE; + uint32_t complen_bytes = (destlen < 65536) ? 2 : 3; + uint32_t ecc_bytes = (frames + 7) / 8; + uint32_t header_bytes = ecc_bytes + complen_bytes; + + /* extract compressed length of base */ + uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1]; + if (complen_bytes > 2) + complen_base = (complen_base << 8) | src[ecc_bytes + 2]; + + /* reset and decode */ + zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA); +#ifdef WANT_SUBCODE + zlib_codec_decompress(&cdzl->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA); +#endif + + /* reassemble the data */ + for (framenum = 0; framenum < frames; framenum++) + { + memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA); +#ifdef WANT_SUBCODE + memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA); +#endif + +#ifdef WANT_RAW_DATA_SECTOR + /* reconstitute the ECC data and sync header */ + sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE]; + if ((src[framenum / 8] & (1 << (framenum % 8))) != 0) + { + memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header)); + ecc_generate(sector); + } +#endif + } + return CHDERR_NONE; +} + +/*************************************************************************** + ZLIB COMPRESSION CODEC +***************************************************************************/ + +/*------------------------------------------------- + zlib_codec_init - initialize the ZLIB codec +-------------------------------------------------*/ + +chd_error zlib_codec_init(void *codec, uint32_t hunkbytes) +{ + int zerr; + chd_error err; + zlib_codec_data *data = (zlib_codec_data*)codec; + + /* clear the buffers */ + memset(data, 0, sizeof(zlib_codec_data)); + + /* init the inflater first */ + data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */ + data->inflater.avail_in = 0; + data->inflater.zalloc = zlib_fast_alloc; + data->inflater.zfree = zlib_fast_free; + data->inflater.opaque = &data->allocator; + zerr = inflateInit2(&data->inflater, -MAX_WBITS); + + /* convert errors */ + if (zerr == Z_MEM_ERROR) + err = CHDERR_OUT_OF_MEMORY; + else if (zerr != Z_OK) + err = CHDERR_CODEC_ERROR; + else + err = CHDERR_NONE; + + return err; +} + +/*------------------------------------------------- + zlib_codec_free - free data for the ZLIB + codec +-------------------------------------------------*/ + +void zlib_codec_free(void *codec) +{ + zlib_codec_data *data = (zlib_codec_data *)codec; + + /* deinit the streams */ + if (data != NULL) + { + int i; + zlib_allocator alloc; + + inflateEnd(&data->inflater); + + /* free our fast memory */ + alloc = data->allocator; + for (i = 0; i < MAX_ZLIB_ALLOCS; i++) + if (alloc.allocptr[i]) + free(alloc.allocptr[i]); + } +} + +/*------------------------------------------------- + zlib_codec_decompress - decomrpess data using + the ZLIB codec +-------------------------------------------------*/ + +chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) +{ + zlib_codec_data *data = (zlib_codec_data *)codec; + int zerr; + + /* reset the decompressor */ + data->inflater.next_in = (Bytef *)src; + data->inflater.avail_in = complen; + data->inflater.total_in = 0; + data->inflater.next_out = (Bytef *)dest; + data->inflater.avail_out = destlen; + data->inflater.total_out = 0; + zerr = inflateReset(&data->inflater); + if (zerr != Z_OK) + return CHDERR_DECOMPRESSION_ERROR; + + /* do it */ + zerr = inflate(&data->inflater, Z_FINISH); + (void)zerr; + if (data->inflater.total_out != destlen) + return CHDERR_DECOMPRESSION_ERROR; + + return CHDERR_NONE; +} + +/*------------------------------------------------- + zlib_fast_alloc - fast malloc for ZLIB, which + allocates and frees memory frequently +-------------------------------------------------*/ + +voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size) +{ + zlib_allocator *alloc = (zlib_allocator *)opaque; + UINT32 *ptr; + int i; + + /* compute the size, rounding to the nearest 1k */ + size = (size * items + 0x3ff) & ~0x3ff; + + /* reuse a hunk if we can */ + for (i = 0; i < MAX_ZLIB_ALLOCS; i++) + { + ptr = alloc->allocptr[i]; + if (ptr && size == *ptr) + { + /* set the low bit of the size so we don't match next time */ + *ptr |= 1; + return ptr + 1; + } + } + + /* alloc a new one */ + ptr = (UINT32 *)malloc(size + sizeof(UINT32)); + if (!ptr) + return NULL; + + /* put it into the list */ + for (i = 0; i < MAX_ZLIB_ALLOCS; i++) + if (!alloc->allocptr[i]) + { + alloc->allocptr[i] = ptr; + break; + } + + /* set the low bit of the size so we don't match next time */ + *ptr = size | 1; + return ptr + 1; +} + +/*------------------------------------------------- + zlib_fast_free - fast free for ZLIB, which + allocates and frees memory frequently +-------------------------------------------------*/ + +void zlib_fast_free(voidpf opaque, voidpf address) +{ + zlib_allocator *alloc = (zlib_allocator *)opaque; + UINT32 *ptr = (UINT32 *)address - 1; + int i; + + /* find the hunk */ + for (i = 0; i < MAX_ZLIB_ALLOCS; i++) + if (ptr == alloc->allocptr[i]) + { + /* clear the low bit of the size to allow matches */ + *ptr &= ~1; + return; + } +} diff --git a/libretro-common/formats/png/rpng.c b/libretro-common/formats/png/rpng.c index b4b9c6c675..e28272124c 100644 --- a/libretro-common/formats/png/rpng.c +++ b/libretro-common/formats/png/rpng.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng.c). diff --git a/libretro-common/formats/png/rpng_encode.c b/libretro-common/formats/png/rpng_encode.c index 92e25e16f4..3500c3aaf4 100644 --- a/libretro-common/formats/png/rpng_encode.c +++ b/libretro-common/formats/png/rpng_encode.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng_encode.c). diff --git a/libretro-common/formats/png/rpng_internal.h b/libretro-common/formats/png/rpng_internal.h index 440bd3d587..62dcfbc9e0 100644 --- a/libretro-common/formats/png/rpng_internal.h +++ b/libretro-common/formats/png/rpng_internal.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng_internal.h). diff --git a/libretro-common/formats/tga/rtga.c b/libretro-common/formats/tga/rtga.c index 7e4e62e306..c96e7ba8f4 100644 --- a/libretro-common/formats/tga/rtga.c +++ b/libretro-common/formats/tga/rtga.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rtga.c). diff --git a/libretro-common/formats/wav/rwav.c b/libretro-common/formats/wav/rwav.c index 7e43ade3ea..e012005ae8 100644 --- a/libretro-common/formats/wav/rwav.c +++ b/libretro-common/formats/wav/rwav.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rwav.c). diff --git a/libretro-common/formats/xml/rxml.c b/libretro-common/formats/xml/rxml.c index b7129653c4..e2a02a77c5 100644 --- a/libretro-common/formats/xml/rxml.c +++ b/libretro-common/formats/xml/rxml.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rxml.c). diff --git a/libretro-common/formats/xml/test/rxml_test.c b/libretro-common/formats/xml/test/rxml_test.c index e966b1d60e..36e794eefc 100644 --- a/libretro-common/formats/xml/test/rxml_test.c +++ b/libretro-common/formats/xml/test/rxml_test.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rxml_test.c). diff --git a/libretro-common/gfx/gl_capabilities.c b/libretro-common/gfx/gl_capabilities.c index d9c8d147b2..d7ec069e4b 100644 --- a/libretro-common/gfx/gl_capabilities.c +++ b/libretro-common/gfx/gl_capabilities.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (gl_capabilities.c). diff --git a/libretro-common/gfx/scaler/pixconv.c b/libretro-common/gfx/scaler/pixconv.c index 604479e404..64f5d89d0d 100644 --- a/libretro-common/gfx/scaler/pixconv.c +++ b/libretro-common/gfx/scaler/pixconv.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (pixconv.c). diff --git a/libretro-common/gfx/scaler/scaler.c b/libretro-common/gfx/scaler/scaler.c index 24b2d0c919..803fecb1aa 100644 --- a/libretro-common/gfx/scaler/scaler.c +++ b/libretro-common/gfx/scaler/scaler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler.c). diff --git a/libretro-common/gfx/scaler/scaler_filter.c b/libretro-common/gfx/scaler/scaler_filter.c index 6134e99f71..498f80d8f3 100644 --- a/libretro-common/gfx/scaler/scaler_filter.c +++ b/libretro-common/gfx/scaler/scaler_filter.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler_filter.c). diff --git a/libretro-common/gfx/scaler/scaler_int.c b/libretro-common/gfx/scaler/scaler_int.c index 42c8ab58bf..9aa583cef8 100644 --- a/libretro-common/gfx/scaler/scaler_int.c +++ b/libretro-common/gfx/scaler/scaler_int.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler_int.c). diff --git a/libretro-common/glsm/glsm.c b/libretro-common/glsm/glsm.c index ab8c5624e6..85a7ced78a 100644 --- a/libretro-common/glsm/glsm.c +++ b/libretro-common/glsm/glsm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsm). @@ -2207,7 +2207,7 @@ static bool glsm_state_ctx_init(void *data) #ifdef CORE hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE; hw_render.version_major = 3; - hw_render.version_minor = 1; + hw_render.version_minor = 3; #else hw_render.context_type = RETRO_HW_CONTEXT_OPENGL; #endif diff --git a/libretro-common/glsym/glsym_gl.c b/libretro-common/glsym/glsym_gl.c index 5aa92fdca2..d89992c919 100644 --- a/libretro-common/glsym/glsym_gl.c +++ b/libretro-common/glsym/glsym_gl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). diff --git a/libretro-common/glsym/rglgen.c b/libretro-common/glsym/rglgen.c index 0ea1fdc99c..6306eaef47 100644 --- a/libretro-common/glsym/rglgen.c +++ b/libretro-common/glsym/rglgen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). diff --git a/libretro-common/hash/rhash.c b/libretro-common/hash/rhash.c index 616e85990c..b123d4d09b 100644 --- a/libretro-common/hash/rhash.c +++ b/libretro-common/hash/rhash.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rhash.c). diff --git a/libretro-common/include/audio/audio_mix.h b/libretro-common/include/audio/audio_mix.h index 3b59dff689..937c4b28e8 100644 --- a/libretro-common/include/audio/audio_mix.h +++ b/libretro-common/include/audio/audio_mix.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (audio_mix.h). diff --git a/libretro-common/include/audio/audio_mixer.h b/libretro-common/include/audio/audio_mixer.h index 3df9c64931..a9c588372e 100644 --- a/libretro-common/include/audio/audio_mixer.h +++ b/libretro-common/include/audio/audio_mixer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (audio_mixer.h). @@ -41,7 +41,9 @@ enum audio_mixer_type AUDIO_MIXER_TYPE_NONE = 0, AUDIO_MIXER_TYPE_WAV, AUDIO_MIXER_TYPE_OGG, - AUDIO_MIXER_TYPE_MOD + AUDIO_MIXER_TYPE_MOD, + AUDIO_MIXER_TYPE_FLAC, + AUDIO_MIXER_TYPE_MP3 }; typedef struct audio_mixer_sound audio_mixer_sound_t; @@ -61,6 +63,8 @@ void audio_mixer_done(void); audio_mixer_sound_t* audio_mixer_load_wav(void *buffer, int32_t size); audio_mixer_sound_t* audio_mixer_load_ogg(void *buffer, int32_t size); audio_mixer_sound_t* audio_mixer_load_mod(void *buffer, int32_t size); +audio_mixer_sound_t* audio_mixer_load_flac(void *buffer, int32_t size); +audio_mixer_sound_t* audio_mixer_load_mp3(void *buffer, int32_t size); void audio_mixer_destroy(audio_mixer_sound_t* sound); diff --git a/libretro-common/include/audio/audio_resampler.h b/libretro-common/include/audio/audio_resampler.h index d950586aea..46eb426a20 100644 --- a/libretro-common/include/audio/audio_resampler.h +++ b/libretro-common/include/audio/audio_resampler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (audio_resampler.h). diff --git a/libretro-common/include/audio/conversion/float_to_s16.h b/libretro-common/include/audio/conversion/float_to_s16.h index 30903cfd4c..2ddf65e75d 100644 --- a/libretro-common/include/audio/conversion/float_to_s16.h +++ b/libretro-common/include/audio/conversion/float_to_s16.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (float_to_s16.h). diff --git a/libretro-common/include/audio/conversion/s16_to_float.h b/libretro-common/include/audio/conversion/s16_to_float.h index ebe43ac4f4..4f705b8b80 100644 --- a/libretro-common/include/audio/conversion/s16_to_float.h +++ b/libretro-common/include/audio/conversion/s16_to_float.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (s16_to_float.h). diff --git a/libretro-common/include/audio/dsp_filter.h b/libretro-common/include/audio/dsp_filter.h index 2055235f6f..82af77135c 100644 --- a/libretro-common/include/audio/dsp_filter.h +++ b/libretro-common/include/audio/dsp_filter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dsp_filter.h). diff --git a/libretro-common/include/boolean.h b/libretro-common/include/boolean.h index 8a5482cde5..f06ac5a742 100644 --- a/libretro-common/include/boolean.h +++ b/libretro-common/include/boolean.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (boolean.h). diff --git a/libretro-common/include/clamping.h b/libretro-common/include/clamping.h index 7919332b95..ec29bf9a38 100644 --- a/libretro-common/include/clamping.h +++ b/libretro-common/include/clamping.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (clamping.h). diff --git a/libretro-common/include/compat/apple_compat.h b/libretro-common/include/compat/apple_compat.h index f656546302..819b39ecf6 100644 --- a/libretro-common/include/compat/apple_compat.h +++ b/libretro-common/include/compat/apple_compat.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (apple_compat.h). diff --git a/libretro-common/include/compat/fnmatch.h b/libretro-common/include/compat/fnmatch.h index 3f3c0254bc..cede1ca6c7 100644 --- a/libretro-common/include/compat/fnmatch.h +++ b/libretro-common/include/compat/fnmatch.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fnmatch.h). diff --git a/libretro-common/include/compat/fopen_utf8.h b/libretro-common/include/compat/fopen_utf8.h index 67cc289aa6..f59822a5ca 100644 --- a/libretro-common/include/compat/fopen_utf8.h +++ b/libretro-common/include/compat/fopen_utf8.h @@ -1,13 +1,33 @@ -#ifndef __FOPEN_UTF8_H -#define __FOPEN_UTF8_H +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (fopen_utf8.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ -#include +#ifndef __LIBRETRO_SDK_COMPAT_FOPEN_UTF8_H +#define __LIBRETRO_SDK_COMPAT_FOPEN_UTF8_H #ifdef _WIN32 -/* defined to error rather than fopen_utf8, to make it clear to everyone reading the code that not worrying about utf16 is fine */ +/* Defined to error rather than fopen_utf8, to make it clear to everyone reading the code that not worrying about utf16 is fine */ /* TODO: enable */ /* #define fopen (use fopen_utf8 instead) */ -FILE* fopen_utf8(const char * filename, const char * mode); +void *fopen_utf8(const char * filename, const char * mode); #else #define fopen_utf8 fopen #endif diff --git a/libretro-common/include/compat/getopt.h b/libretro-common/include/compat/getopt.h index f685681559..74287b64f5 100644 --- a/libretro-common/include/compat/getopt.h +++ b/libretro-common/include/compat/getopt.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (getopt.h). diff --git a/libretro-common/include/compat/intrinsics.h b/libretro-common/include/compat/intrinsics.h index 5d6e8a5b60..3fc7d92918 100644 --- a/libretro-common/include/compat/intrinsics.h +++ b/libretro-common/include/compat/intrinsics.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (intrinsics.h). diff --git a/libretro-common/include/compat/msvc.h b/libretro-common/include/compat/msvc.h index fea4b53660..822c97339a 100644 --- a/libretro-common/include/compat/msvc.h +++ b/libretro-common/include/compat/msvc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (msvc.h). diff --git a/libretro-common/include/compat/posix_string.h b/libretro-common/include/compat/posix_string.h index 380e1a121f..9f56322ab9 100644 --- a/libretro-common/include/compat/posix_string.h +++ b/libretro-common/include/compat/posix_string.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (posix_string.h). diff --git a/libretro-common/include/compat/strcasestr.h b/libretro-common/include/compat/strcasestr.h index 376f1003fd..f849593b0f 100644 --- a/libretro-common/include/compat/strcasestr.h +++ b/libretro-common/include/compat/strcasestr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (strcasestr.h). diff --git a/libretro-common/include/compat/strl.h b/libretro-common/include/compat/strl.h index 853aceffcc..290498d9a6 100644 --- a/libretro-common/include/compat/strl.h +++ b/libretro-common/include/compat/strl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (strl.h). diff --git a/libretro-common/include/dynamic/dylib.h b/libretro-common/include/dynamic/dylib.h index b8ee171cf3..f6951273bd 100644 --- a/libretro-common/include/dynamic/dylib.h +++ b/libretro-common/include/dynamic/dylib.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dylib.h). diff --git a/libretro-common/include/encodings/crc32.h b/libretro-common/include/encodings/crc32.h index 0c9947629d..76fbb5475e 100644 --- a/libretro-common/include/encodings/crc32.h +++ b/libretro-common/include/encodings/crc32.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (crc32.h). diff --git a/libretro-common/include/encodings/utf.h b/libretro-common/include/encodings/utf.h index bad9458966..b513f28a18 100644 --- a/libretro-common/include/encodings/utf.h +++ b/libretro-common/include/encodings/utf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (utf.h). diff --git a/libretro-common/include/encodings/win32.h b/libretro-common/include/encodings/win32.h index 7d8057e8b8..d4221bd9b7 100644 --- a/libretro-common/include/encodings/win32.h +++ b/libretro-common/include/encodings/win32.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2016 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (utf.h). diff --git a/libretro-common/include/fastcpy.h b/libretro-common/include/fastcpy.h index 13b94d97bd..9d40702bf3 100644 --- a/libretro-common/include/fastcpy.h +++ b/libretro-common/include/fastcpy.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fastcpy.h). diff --git a/libretro-common/include/features/features_cpu.h b/libretro-common/include/features/features_cpu.h index fd8f5f62b6..0aa043dad0 100644 --- a/libretro-common/include/features/features_cpu.h +++ b/libretro-common/include/features/features_cpu.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (features_cpu.h). diff --git a/libretro-common/include/file/archive_file.h b/libretro-common/include/file/archive_file.h index b2b5971931..6cc7d4725b 100644 --- a/libretro-common/include/file/archive_file.h +++ b/libretro-common/include/file/archive_file.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (archive_file.h). @@ -187,7 +187,7 @@ bool file_archive_perform_mode(const char *name, const char *valid_exts, int file_archive_compressed_read( const char* path, void **buf, - const char* optional_filename, ssize_t *length); + const char* optional_filename, int64_t *length); const struct file_archive_file_backend* file_archive_get_zlib_file_backend(void); const struct file_archive_file_backend* file_archive_get_7z_file_backend(void); diff --git a/libretro-common/include/file/config_file.h b/libretro-common/include/file/config_file.h index 3c0d99987a..6b4dde77e7 100644 --- a/libretro-common/include/file/config_file.h +++ b/libretro-common/include/file/config_file.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (config_file.h). diff --git a/libretro-common/include/file/config_file_userdata.h b/libretro-common/include/file/config_file_userdata.h index 0c433ed361..ca6f691785 100644 --- a/libretro-common/include/file/config_file_userdata.h +++ b/libretro-common/include/file/config_file_userdata.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (config_file_userdata.h). diff --git a/libretro-common/include/file/file_path.h b/libretro-common/include/file/file_path.h index 85f190c6ad..89321c8f80 100644 --- a/libretro-common/include/file/file_path.h +++ b/libretro-common/include/file/file_path.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.h). @@ -432,7 +432,7 @@ void path_basedir_wrapper(char *path); #endif /** - * path_default_slash: + * path_default_slash and path_default_slash_c: * * Gets the default slash separator. * @@ -440,8 +440,10 @@ void path_basedir_wrapper(char *path); */ #ifdef _WIN32 #define path_default_slash() "\\" +#define path_default_slash_c() '\\' #else #define path_default_slash() "/" +#define path_default_slash_c() '/' #endif /** @@ -454,7 +456,7 @@ void path_basedir_wrapper(char *path); **/ void fill_pathname_slash(char *path, size_t size); -#ifndef RARCH_CONSOLE +#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL) void fill_pathname_application_path(char *buf, size_t size); #endif diff --git a/libretro-common/include/file/nbio.h b/libretro-common/include/file/nbio.h index 554bd1103d..4b5e5a41bc 100644 --- a/libretro-common/include/file/nbio.h +++ b/libretro-common/include/file/nbio.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (nbio.h). diff --git a/libretro-common/include/filters.h b/libretro-common/include/filters.h index 53743bba7f..69048efd90 100644 --- a/libretro-common/include/filters.h +++ b/libretro-common/include/filters.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (filters.h). diff --git a/libretro-common/include/formats/image.h b/libretro-common/include/formats/image.h index bba886642d..20a3c8058a 100644 --- a/libretro-common/include/formats/image.h +++ b/libretro-common/include/formats/image.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (image.h). diff --git a/libretro-common/include/formats/jsonsax.h b/libretro-common/include/formats/jsonsax.h index d8b18e6b8d..c98331fb39 100644 --- a/libretro-common/include/formats/jsonsax.h +++ b/libretro-common/include/formats/jsonsax.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (jsonsax.h). diff --git a/libretro-common/include/formats/rbmp.h b/libretro-common/include/formats/rbmp.h index 622d8c94d7..9b3a908733 100644 --- a/libretro-common/include/formats/rbmp.h +++ b/libretro-common/include/formats/rbmp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rbmp.h). diff --git a/libretro-common/include/formats/rjpeg.h b/libretro-common/include/formats/rjpeg.h index a999516df0..ed4ee3eea1 100644 --- a/libretro-common/include/formats/rjpeg.h +++ b/libretro-common/include/formats/rjpeg.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rjpeg.h). diff --git a/libretro-common/include/formats/rpng.h b/libretro-common/include/formats/rpng.h index b16a8307fa..aeae7af49a 100644 --- a/libretro-common/include/formats/rpng.h +++ b/libretro-common/include/formats/rpng.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng.h). diff --git a/libretro-common/include/formats/rtga.h b/libretro-common/include/formats/rtga.h index a66f4a0ab6..1b9409c365 100644 --- a/libretro-common/include/formats/rtga.h +++ b/libretro-common/include/formats/rtga.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rtga.h). diff --git a/libretro-common/include/formats/rwav.h b/libretro-common/include/formats/rwav.h index 3f4ed170e3..198d24b5b5 100644 --- a/libretro-common/include/formats/rwav.h +++ b/libretro-common/include/formats/rwav.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rwav.h). diff --git a/libretro-common/include/formats/rxml.h b/libretro-common/include/formats/rxml.h index 13bcebac1f..78d01a2972 100644 --- a/libretro-common/include/formats/rxml.h +++ b/libretro-common/include/formats/rxml.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rxml.h). diff --git a/libretro-common/include/gfx/gl_capabilities.h b/libretro-common/include/gfx/gl_capabilities.h index 4e7c97a0a7..c71352efaa 100644 --- a/libretro-common/include/gfx/gl_capabilities.h +++ b/libretro-common/include/gfx/gl_capabilities.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (gl_capabilities.h). diff --git a/libretro-common/include/gfx/math/matrix_3x3.h b/libretro-common/include/gfx/math/matrix_3x3.h index 9bdd886945..791f1dae06 100644 --- a/libretro-common/include/gfx/math/matrix_3x3.h +++ b/libretro-common/include/gfx/math/matrix_3x3.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (matrix_3x3.h). diff --git a/libretro-common/include/gfx/math/matrix_4x4.h b/libretro-common/include/gfx/math/matrix_4x4.h index de5244ef26..dacb37c31c 100644 --- a/libretro-common/include/gfx/math/matrix_4x4.h +++ b/libretro-common/include/gfx/math/matrix_4x4.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (matrix_4x4.h). diff --git a/libretro-common/include/gfx/math/vector_2.h b/libretro-common/include/gfx/math/vector_2.h index 1265c6de45..a38153ea2c 100644 --- a/libretro-common/include/gfx/math/vector_2.h +++ b/libretro-common/include/gfx/math/vector_2.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vector_2.h). diff --git a/libretro-common/include/gfx/math/vector_3.h b/libretro-common/include/gfx/math/vector_3.h index 67256172f0..40c9f7f49c 100644 --- a/libretro-common/include/gfx/math/vector_3.h +++ b/libretro-common/include/gfx/math/vector_3.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vector_3.h). diff --git a/libretro-common/include/gfx/math/vector_4.h b/libretro-common/include/gfx/math/vector_4.h index 3b9510c511..e985649206 100644 --- a/libretro-common/include/gfx/math/vector_4.h +++ b/libretro-common/include/gfx/math/vector_4.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vector_4.h). diff --git a/libretro-common/include/gfx/scaler/filter.h b/libretro-common/include/gfx/scaler/filter.h index ba5ae93907..27f677a6c3 100644 --- a/libretro-common/include/gfx/scaler/filter.h +++ b/libretro-common/include/gfx/scaler/filter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (filter.h). diff --git a/libretro-common/include/gfx/scaler/pixconv.h b/libretro-common/include/gfx/scaler/pixconv.h index 6dfab47a9a..100864de68 100644 --- a/libretro-common/include/gfx/scaler/pixconv.h +++ b/libretro-common/include/gfx/scaler/pixconv.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (pixconv.h). diff --git a/libretro-common/include/gfx/scaler/scaler.h b/libretro-common/include/gfx/scaler/scaler.h index 8d97515616..97854d45b3 100644 --- a/libretro-common/include/gfx/scaler/scaler.h +++ b/libretro-common/include/gfx/scaler/scaler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler.h). diff --git a/libretro-common/include/gfx/scaler/scaler_int.h b/libretro-common/include/gfx/scaler/scaler_int.h index 87ef68eda2..2cb203a3ba 100644 --- a/libretro-common/include/gfx/scaler/scaler_int.h +++ b/libretro-common/include/gfx/scaler/scaler_int.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler_int.h). diff --git a/libretro-common/include/gfx/video_frame.h b/libretro-common/include/gfx/video_frame.h index e5c0540d9c..c00dc81d57 100644 --- a/libretro-common/include/gfx/video_frame.h +++ b/libretro-common/include/gfx/video_frame.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (video_frame.h). diff --git a/libretro-common/include/glsm/glsm.h b/libretro-common/include/glsm/glsm.h index 8e30acdc04..d422267d11 100644 --- a/libretro-common/include/glsm/glsm.h +++ b/libretro-common/include/glsm/glsm.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsm.h). diff --git a/libretro-common/include/glsm/glsmsym.h b/libretro-common/include/glsm/glsmsym.h index 215f3ecb51..3611441919 100644 --- a/libretro-common/include/glsm/glsmsym.h +++ b/libretro-common/include/glsm/glsmsym.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsmsym.h). diff --git a/libretro-common/include/glsym/glsym.h b/libretro-common/include/glsym/glsym.h index c1c13e2a56..24f4584bb6 100644 --- a/libretro-common/include/glsym/glsym.h +++ b/libretro-common/include/glsym/glsym.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). diff --git a/libretro-common/include/glsym/glsym_gl.h b/libretro-common/include/glsym/glsym_gl.h index 9720c2e1cf..1934287f2a 100644 --- a/libretro-common/include/glsym/glsym_gl.h +++ b/libretro-common/include/glsym/glsym_gl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). diff --git a/libretro-common/include/glsym/rglgen.h b/libretro-common/include/glsym/rglgen.h index 54dcb62a84..b8a1a0c877 100644 --- a/libretro-common/include/glsym/rglgen.h +++ b/libretro-common/include/glsym/rglgen.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). diff --git a/libretro-common/include/glsym/rglgen_headers.h b/libretro-common/include/glsym/rglgen_headers.h index 06d8530b27..766efb6361 100644 --- a/libretro-common/include/glsym/rglgen_headers.h +++ b/libretro-common/include/glsym/rglgen_headers.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). diff --git a/libretro-common/include/libchdr/chd.h b/libretro-common/include/libchdr/chd.h index 1a33e0cc32..9b4df95349 100644 --- a/libretro-common/include/libchdr/chd.h +++ b/libretro-common/include/libchdr/chd.h @@ -47,6 +47,7 @@ extern "C" { #endif #include "coretypes.h" +#include /*************************************************************************** @@ -347,15 +348,18 @@ struct _chd_verify_result /* chd_error chd_create_file(core_file *file, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */ /* open an existing CHD file */ -chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd); +chd_error chd_open_file(RFILE *file, int mode, chd_file *parent, chd_file **chd); + chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd); +/* precache underlying file */ +chd_error chd_precache(chd_file *chd); /* close a CHD file */ void chd_close(chd_file *chd); /* return the associated core_file */ -core_file *chd_core_file(chd_file *chd); +RFILE *chd_core_file(chd_file *chd); /* return an error string for the given CHD error */ const char *chd_error_string(chd_error err); @@ -393,6 +397,8 @@ chd_error chd_codec_config(chd_file *chd, int param, void *config); /* return a string description of a codec */ const char *chd_get_codec_name(UINT32 codec); +extern const uint8_t s_cd_sync_header[12]; + #ifdef __cplusplus } #endif diff --git a/libretro-common/include/libchdr/coretypes.h b/libretro-common/include/libchdr/coretypes.h index 5a769f6a86..2a68a8a4c3 100644 --- a/libretro-common/include/libchdr/coretypes.h +++ b/libretro-common/include/libchdr/coretypes.h @@ -3,8 +3,7 @@ #include #include - -#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0])) +#include typedef uint64_t UINT64; #ifndef OSD_CPU_H @@ -20,11 +19,4 @@ typedef int16_t INT16; typedef int8_t INT8; #endif -#define core_file FILE -#define core_fopen(file) fopen(file, "rb") -#define core_fseek fseek -#define core_fread(fc, buff, len) fread(buff, 1, len, fc) -#define core_fclose fclose -#define core_ftell ftell - #endif diff --git a/libretro-common/include/libchdr/flac.h b/libretro-common/include/libchdr/flac.h index a9f84962af..2ce112d27a 100644 --- a/libretro-common/include/libchdr/flac.h +++ b/libretro-common/include/libchdr/flac.h @@ -14,6 +14,7 @@ #define __FLAC_H__ #include +#include "libchdr_zlib.h" #include "FLAC/ordinals.h" #include "FLAC/stream_decoder.h" @@ -49,4 +50,21 @@ int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t nu int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian); uint32_t flac_decoder_finish(flac_decoder* decoder); +/* codec-private data for the CDFL codec */ +typedef struct _cdfl_codec_data cdfl_codec_data; +struct _cdfl_codec_data { + /* internal state */ + int swap_endian; + flac_decoder decoder; +#ifdef WANT_SUBCODE + zlib_codec_data subcode_decompressor; +#endif + uint8_t* buffer; +}; + +/* cdfl compression codec */ +chd_error cdfl_codec_init(void* codec, uint32_t hunkbytes); +void cdfl_codec_free(void* codec); +chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); + #endif /* __FLAC_H__ */ diff --git a/libretro-common/include/libchdr/libchdr_zlib.h b/libretro-common/include/libchdr/libchdr_zlib.h new file mode 100644 index 0000000000..4f3f141050 --- /dev/null +++ b/libretro-common/include/libchdr/libchdr_zlib.h @@ -0,0 +1,69 @@ +/* license:BSD-3-Clause + * copyright-holders:Aaron Giles + *************************************************************************** + + libchr_zlib.h + + Zlib compression wrappers + +***************************************************************************/ + +#pragma once + +#ifndef __LIBCHDR_ZLIB_H__ +#define __LIBCHDR_ZLIB_H__ + +#include + +#include +#include "coretypes.h" +#include "chd.h" + +#define MAX_ZLIB_ALLOCS 64 + +/* codec-private data for the ZLIB codec */ + +typedef struct _zlib_allocator zlib_allocator; +struct _zlib_allocator +{ + UINT32 * allocptr[MAX_ZLIB_ALLOCS]; +}; + +typedef struct _zlib_codec_data zlib_codec_data; +struct _zlib_codec_data +{ + z_stream inflater; + zlib_allocator allocator; +}; + + +/* codec-private data for the CDZL codec */ +typedef struct _cdzl_codec_data cdzl_codec_data; +struct _cdzl_codec_data { + /* internal state */ + zlib_codec_data base_decompressor; +#ifdef WANT_SUBCODE + zlib_codec_data subcode_decompressor; +#endif + uint8_t* buffer; +}; + +/* zlib compression codec */ +chd_error zlib_codec_init(void *codec, uint32_t hunkbytes); + +void zlib_codec_free(void *codec); + +chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); + +voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size); + +void zlib_fast_free(voidpf opaque, voidpf address); + +/* cdzl compression codec */ +chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes); + +void cdzl_codec_free(void* codec); + +chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); + +#endif /* __LIBCHDR_ZLIB_H__ */ diff --git a/libretro-common/include/libchdr/lzma.h b/libretro-common/include/libchdr/lzma.h new file mode 100644 index 0000000000..e3cccbc196 --- /dev/null +++ b/libretro-common/include/libchdr/lzma.h @@ -0,0 +1,72 @@ +/* license:BSD-3-Clause + * copyright-holders:Aaron Giles + *************************************************************************** + + lzma.h + + LZMA compression wrappers + +***************************************************************************/ + +#pragma once + +#ifndef __LIBCHDR_LZMA_H__ +#define __LIBCHDR_LZMA_H__ + +#include + +#include +#include + +#include + +/* codec-private data for the LZMA codec */ +#define MAX_LZMA_ALLOCS 64 + +typedef struct _lzma_allocator lzma_allocator; +struct _lzma_allocator +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ + void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */ + uint32_t* allocptr[MAX_LZMA_ALLOCS]; +}; + +typedef struct _lzma_codec_data lzma_codec_data; +struct _lzma_codec_data +{ + CLzmaDec decoder; + lzma_allocator allocator; +}; + +/* codec-private data for the CDLZ codec */ +typedef struct _cdlz_codec_data cdlz_codec_data; +struct _cdlz_codec_data { + /* internal state */ + lzma_codec_data base_decompressor; +#ifdef WANT_SUBCODE + zlib_codec_data subcode_decompressor; +#endif + uint8_t* buffer; +}; + +chd_error lzma_codec_init(void* codec, uint32_t hunkbytes); + +void lzma_codec_free(void* codec); + +/*------------------------------------------------- + * decompress - decompress data using the LZMA + * codec + *------------------------------------------------- + */ + +chd_error lzma_codec_decompress(void* codec, const uint8_t *src, + uint32_t complen, uint8_t *dest, uint32_t destlen); + +chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes); + +void cdlz_codec_free(void* codec); + +chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); + +#endif /* __LIBCHDR_LZMA_H__ */ diff --git a/libretro-common/include/libco.h b/libretro-common/include/libco.h index 1599cb2ca0..851b29cc43 100644 --- a/libretro-common/include/libco.h +++ b/libretro-common/include/libco.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (libco.h). diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index bfe832c202..654c799828 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro.h). @@ -599,9 +599,12 @@ enum retro_mod * GET_VARIABLE. * This allows the frontend to present these variables to * a user dynamically. - * This should be called as early as possible (ideally in - * retro_set_environment). - * + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterward it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * * 'data' points to an array of retro_variable structs * terminated by a { NULL, NULL } element. * retro_variable::key should be namespaced to not collide @@ -1119,12 +1122,44 @@ struct retro_led_interface #define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* int * -- - * Queries the frontend if audio and video are enabled or not. - * If not enabled, the frontend will discard the audio or video, - * so the core may decide to skip producing audio or video. - * Bit 0 (value 1) is set if Video is enabled, - * Bit 1 (value 2) is set if Audio is enabled. - * Other bits are reserved for future use. + * Tells the core if the frontend wants audio or video. + * If disabled, the frontend will discard the audio or video, + * so the core may decide to skip generating a frame or generating audio. + * This is mainly used for increasing performance. + * Bit 0 (value 1): Enable Video + * Bit 1 (value 2): Enable Audio + * Bit 2 (value 4): Use Fast Savestates. + * Bit 3 (value 8): Hard Disable Audio + * Other bits are reserved for future use and will default to zero. + * If video is disabled: + * * The frontend wants the core to not generate any video, + * including presenting frames via hardware acceleration. + * * The frontend's video frame callback will do nothing. + * * After running the frame, the video output of the next frame should be + * no different than if video was enabled, and saving and loading state + * should have no issues. + * If audio is disabled: + * * The frontend wants the core to not generate any audio. + * * The frontend's audio callbacks will do nothing. + * * After running the frame, the audio output of the next frame should be + * no different than if audio was enabled, and saving and loading state + * should have no issues. + * Fast Savestates: + * * Guaranteed to be created by the same binary that will load them. + * * Will not be written to or read from the disk. + * * Suggest that the core assumes loading state will succeed. + * * Suggest that the core updates its memory buffers in-place if possible. + * * Suggest that the core skips clearing memory. + * * Suggest that the core skips resetting the system. + * * Suggest that the core may skip validation steps. + * Hard Disable Audio: + * * Used for a secondary core when running ahead. + * * Indicates that the frontend will never need audio from the core. + * * Suggests that the core may stop synthesizing audio, but this should not + * compromise emulation accuracy. + * * Audio output for the next frame does not matter, and the frontend will + * never need an accurate audio state in the future. + * * State will never be saved when using Hard Disable Audio. */ #define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) diff --git a/libretro-common/include/libretro_d3d.h b/libretro-common/include/libretro_d3d.h index 2ed71aa7c0..d95931b3e9 100644 --- a/libretro-common/include/libretro_d3d.h +++ b/libretro-common/include/libretro_d3d.h @@ -1,7 +1,7 @@ -/* Copyright (C) 2010-2016 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------------- - * The following license statement only applies to this libretro API header (libretro_vulkan.h) + * The following license statement only applies to this libretro API header (libretro_d3d.h) * --------------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, diff --git a/libretro-common/include/libretro_dspfilter.h b/libretro-common/include/libretro_dspfilter.h index 4de515d01b..36bfd88d5f 100644 --- a/libretro-common/include/libretro_dspfilter.h +++ b/libretro-common/include/libretro_dspfilter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro_dspfilter.h). diff --git a/libretro-common/include/libretro_vulkan.h b/libretro-common/include/libretro_vulkan.h index e1005a163b..5ae7187b7d 100644 --- a/libretro-common/include/libretro_vulkan.h +++ b/libretro-common/include/libretro_vulkan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro_vulkan.h) diff --git a/libretro-common/include/lists/dir_list.h b/libretro-common/include/lists/dir_list.h index 3b4a9c573d..4babb02d39 100644 --- a/libretro-common/include/lists/dir_list.h +++ b/libretro-common/include/lists/dir_list.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dir_list.h). diff --git a/libretro-common/include/lists/file_list.h b/libretro-common/include/lists/file_list.h index f6715a3572..208bf15a59 100644 --- a/libretro-common/include/lists/file_list.h +++ b/libretro-common/include/lists/file_list.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_list.h). diff --git a/libretro-common/include/lists/string_list.h b/libretro-common/include/lists/string_list.h index c15cd0eca7..513876e6d1 100644 --- a/libretro-common/include/lists/string_list.h +++ b/libretro-common/include/lists/string_list.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (string_list.h). diff --git a/libretro-common/include/math/complex.h b/libretro-common/include/math/complex.h index d7695c2d22..abfbfa60f5 100644 --- a/libretro-common/include/math/complex.h +++ b/libretro-common/include/math/complex.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (complex.h). diff --git a/libretro-common/include/math/float_minmax.h b/libretro-common/include/math/float_minmax.h index d917ef8ef6..2164dde0f7 100644 --- a/libretro-common/include/math/float_minmax.h +++ b/libretro-common/include/math/float_minmax.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (float_minmax.h). diff --git a/libretro-common/include/math/fxp.h b/libretro-common/include/math/fxp.h index 56b036cd72..46f58bae91 100644 --- a/libretro-common/include/math/fxp.h +++ b/libretro-common/include/math/fxp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fxp.h). diff --git a/libretro-common/include/memalign.h b/libretro-common/include/memalign.h index ca809f80c3..2c07a7c053 100644 --- a/libretro-common/include/memalign.h +++ b/libretro-common/include/memalign.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memalign.h). diff --git a/libretro-common/include/memmap.h b/libretro-common/include/memmap.h index 8d939c4351..2bedd5c926 100644 --- a/libretro-common/include/memmap.h +++ b/libretro-common/include/memmap.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memmap.h). diff --git a/libretro-common/include/net/net_compat.h b/libretro-common/include/net/net_compat.h index 7a182af2af..789f944e71 100644 --- a/libretro-common/include/net/net_compat.h +++ b/libretro-common/include/net/net_compat.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_compat.h). diff --git a/libretro-common/include/net/net_http.h b/libretro-common/include/net/net_http.h index 8a9f2c5e0b..f98462764d 100644 --- a/libretro-common/include/net/net_http.h +++ b/libretro-common/include/net/net_http.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_http.h). diff --git a/libretro-common/include/net/net_http_parse.h b/libretro-common/include/net/net_http_parse.h index 4fc4845cd0..6e957d3975 100644 --- a/libretro-common/include/net/net_http_parse.h +++ b/libretro-common/include/net/net_http_parse.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_http.h). diff --git a/libretro-common/include/net/net_ifinfo.h b/libretro-common/include/net/net_ifinfo.h index 9949da2f05..b1d2535500 100644 --- a/libretro-common/include/net/net_ifinfo.h +++ b/libretro-common/include/net/net_ifinfo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_ifinfo.h). diff --git a/libretro-common/include/net/net_natt.h b/libretro-common/include/net/net_natt.h index 9c8b3d7d7d..66c3ff355a 100644 --- a/libretro-common/include/net/net_natt.h +++ b/libretro-common/include/net/net_natt.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_natt.h). @@ -30,7 +30,8 @@ RETRO_BEGIN_DECLS -struct natt_status { +struct natt_status +{ /** nfds for select when checking for input */ int nfds; diff --git a/libretro-common/include/net/net_socket.h b/libretro-common/include/net/net_socket.h index 5d6dd8784e..098854e658 100644 --- a/libretro-common/include/net/net_socket.h +++ b/libretro-common/include/net/net_socket.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_socket.h). diff --git a/libretro-common/include/net/net_socket_ssl.h b/libretro-common/include/net/net_socket_ssl.h index c9ca75dad0..2691a2d12d 100644 --- a/libretro-common/include/net/net_socket_ssl.h +++ b/libretro-common/include/net/net_socket_ssl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_socket.h). diff --git a/libretro-common/include/queues/fifo_queue.h b/libretro-common/include/queues/fifo_queue.h index f1a3cae13c..b9c22e7ece 100644 --- a/libretro-common/include/queues/fifo_queue.h +++ b/libretro-common/include/queues/fifo_queue.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fifo_queue.h). diff --git a/libretro-common/include/queues/message_queue.h b/libretro-common/include/queues/message_queue.h index 2339e93578..760ba279d8 100644 --- a/libretro-common/include/queues/message_queue.h +++ b/libretro-common/include/queues/message_queue.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (message_queue.h). diff --git a/libretro-common/include/queues/task_queue.h b/libretro-common/include/queues/task_queue.h index 8e25cc43ac..40c35ddfdb 100644 --- a/libretro-common/include/queues/task_queue.h +++ b/libretro-common/include/queues/task_queue.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (task_queue.h). diff --git a/libretro-common/include/retro_assert.h b/libretro-common/include/retro_assert.h index 3ef0300ec6..9f3abdeafb 100644 --- a/libretro-common/include/retro_assert.h +++ b/libretro-common/include/retro_assert.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_assert.h). diff --git a/libretro-common/include/retro_common.h b/libretro-common/include/retro_common.h index 5938bea1b5..e4804fae08 100644 --- a/libretro-common/include/retro_common.h +++ b/libretro-common/include/retro_common.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common.h). diff --git a/libretro-common/include/retro_common_api.h b/libretro-common/include/retro_common_api.h index ff38f9837c..c3b3f4927f 100644 --- a/libretro-common/include/retro_common_api.h +++ b/libretro-common/include/retro_common_api.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common_api.h). diff --git a/libretro-common/include/retro_dirent.h b/libretro-common/include/retro_dirent.h index 090076ec64..c3450732c5 100644 --- a/libretro-common/include/retro_dirent.h +++ b/libretro-common/include/retro_dirent.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_dirent.h). @@ -32,6 +32,16 @@ RETRO_BEGIN_DECLS typedef struct RDIR RDIR; +/** + * + * retro_opendir: + * @name : path to the directory to open. + * + * Opens a directory for reading. Tidy up with retro_closedir. + * + * Returns: RDIR pointer on success, NULL if name is not a + * valid directory, null itself or the empty string. + */ struct RDIR *retro_opendir(const char *name); int retro_readdir(struct RDIR *rdir); diff --git a/libretro-common/include/retro_endianness.h b/libretro-common/include/retro_endianness.h index fc9299e178..e721ec9d4d 100644 --- a/libretro-common/include/retro_endianness.h +++ b/libretro-common/include/retro_endianness.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_endianness.h). diff --git a/libretro-common/include/retro_environment.h b/libretro-common/include/retro_environment.h index 12ee429de8..1a18cd6f8c 100644 --- a/libretro-common/include/retro_environment.h +++ b/libretro-common/include/retro_environment.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_environment.h). diff --git a/libretro-common/include/retro_inline.h b/libretro-common/include/retro_inline.h index ffdaa4a3ab..e4a21f6c41 100644 --- a/libretro-common/include/retro_inline.h +++ b/libretro-common/include/retro_inline.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_inline.h). diff --git a/libretro-common/include/retro_math.h b/libretro-common/include/retro_math.h index c0efb23bd9..03d31dd546 100644 --- a/libretro-common/include/retro_math.h +++ b/libretro-common/include/retro_math.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_math.h). diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h index 23f9ef02ac..afcb885cf7 100644 --- a/libretro-common/include/retro_miscellaneous.h +++ b/libretro-common/include/retro_miscellaneous.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_miscellaneous.h). diff --git a/libretro-common/include/retro_timers.h b/libretro-common/include/retro_timers.h index 0cd4b4c48b..e56e18fc38 100644 --- a/libretro-common/include/retro_timers.h +++ b/libretro-common/include/retro_timers.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_timers.h). diff --git a/libretro-common/include/rhash.h b/libretro-common/include/rhash.h index d7394885bd..6ed9149f4d 100644 --- a/libretro-common/include/rhash.h +++ b/libretro-common/include/rhash.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rhash.h). diff --git a/libretro-common/include/rthreads/rthreads.h b/libretro-common/include/rthreads/rthreads.h index c9448ec702..6e248f3d94 100644 --- a/libretro-common/include/rthreads/rthreads.h +++ b/libretro-common/include/rthreads/rthreads.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rthreads.h). diff --git a/libretro-common/include/streams/chd_stream.h b/libretro-common/include/streams/chd_stream.h index 86f0ccbcd0..246a2dcfc9 100644 --- a/libretro-common/include/streams/chd_stream.h +++ b/libretro-common/include/streams/chd_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (chd_stream.h). @@ -49,11 +49,11 @@ int chdstream_getc(chdstream_t *stream); char *chdstream_gets(chdstream_t *stream, char *buffer, size_t len); -size_t chdstream_tell(chdstream_t *stream); +uint64_t chdstream_tell(chdstream_t *stream); void chdstream_rewind(chdstream_t *stream); -int chdstream_seek(chdstream_t *stream, ssize_t offset, int whence); +int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence); ssize_t chdstream_get_size(chdstream_t *stream); diff --git a/libretro-common/include/streams/file_stream.h b/libretro-common/include/streams/file_stream.h index 79fd92ed2e..546fd12697 100644 --- a/libretro-common/include/streams/file_stream.h +++ b/libretro-common/include/streams/file_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream.h). @@ -47,7 +47,7 @@ typedef struct RFILE RFILE; void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info); -ssize_t filestream_get_size(RFILE *stream); +int64_t filestream_get_size(RFILE *stream); /** * filestream_open: @@ -60,19 +60,19 @@ ssize_t filestream_get_size(RFILE *stream); **/ RFILE *filestream_open(const char *path, unsigned mode, unsigned hints); -ssize_t filestream_seek(RFILE *stream, ssize_t offset, int seek_position); +int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position); -ssize_t filestream_read(RFILE *stream, void *data, int64_t len); +int64_t filestream_read(RFILE *stream, void *data, int64_t len); -ssize_t filestream_write(RFILE *stream, const void *data, int64_t len); +int64_t filestream_write(RFILE *stream, const void *data, int64_t len); -ssize_t filestream_tell(RFILE *stream); +int64_t filestream_tell(RFILE *stream); void filestream_rewind(RFILE *stream); int filestream_close(RFILE *stream); -int filestream_read_file(const char *path, void **buf, ssize_t *len); +int64_t filestream_read_file(const char *path, void **buf, int64_t *len); char *filestream_gets(RFILE *stream, char *s, size_t len); @@ -80,7 +80,7 @@ int filestream_getc(RFILE *stream); int filestream_eof(RFILE *stream); -bool filestream_write_file(const char *path, const void *data, ssize_t size); +bool filestream_write_file(const char *path, const void *data, int64_t size); int filestream_putc(RFILE *stream, int c); diff --git a/libretro-common/include/streams/file_stream_transforms.h b/libretro-common/include/streams/file_stream_transforms.h index 0cd565b61c..c1690fa6d6 100644 --- a/libretro-common/include/streams/file_stream_transforms.h +++ b/libretro-common/include/streams/file_stream_transforms.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream_transforms.h). @@ -23,9 +23,10 @@ #ifndef __LIBRETRO_SDK_FILE_STREAM_TRANSFORMS_H #define __LIBRETRO_SDK_FILE_STREAM_TRANSFORMS_H +#include +#include #include #include -#include RETRO_BEGIN_DECLS @@ -61,19 +62,19 @@ RFILE* rfopen(const char *path, const char *mode); int rfclose(RFILE* stream); -long rftell(RFILE* stream); +int64_t rftell(RFILE* stream); -int rfseek(RFILE* stream, long offset, int origin); +int64_t rfseek(RFILE* stream, int64_t offset, int origin); -size_t rfread(void* buffer, - size_t elementSize, size_t elementCount, RFILE* stream); +int64_t rfread(void* buffer, + size_t elem_size, size_t elem_count, RFILE* stream); char *rfgets(char *buffer, int maxCount, RFILE* stream); int rfgetc(RFILE* stream); -size_t rfwrite(void const* buffer, - size_t elementSize, size_t elementCount, RFILE* stream); +int64_t rfwrite(void const* buffer, + size_t elem_size, size_t elem_count, RFILE* stream); int rfputc(int character, RFILE * stream); diff --git a/libretro-common/include/streams/interface_stream.h b/libretro-common/include/streams/interface_stream.h index 468d35eff3..71d5c97fd4 100644 --- a/libretro-common/include/streams/interface_stream.h +++ b/libretro-common/include/streams/interface_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (interface_stream.h). @@ -48,7 +48,7 @@ typedef struct intfstream_info struct { uint8_t *data; - unsigned size; + uint64_t size; } buf; bool writable; } memory; @@ -68,29 +68,29 @@ bool intfstream_resize(intfstream_internal_t *intf, bool intfstream_open(intfstream_internal_t *intf, const char *path, unsigned mode, unsigned hints); -ssize_t intfstream_read(intfstream_internal_t *intf, - void *s, size_t len); +int64_t intfstream_read(intfstream_internal_t *intf, + void *s, uint64_t len); -ssize_t intfstream_write(intfstream_internal_t *intf, - const void *s, size_t len); +int64_t intfstream_write(intfstream_internal_t *intf, + const void *s, uint64_t len); char *intfstream_gets(intfstream_internal_t *intf, - char *buffer, size_t len); + char *buffer, uint64_t len); int intfstream_getc(intfstream_internal_t *intf); -int intfstream_seek(intfstream_internal_t *intf, - int offset, int whence); +int64_t intfstream_seek(intfstream_internal_t *intf, + int64_t offset, int whence); void intfstream_rewind(intfstream_internal_t *intf); -int intfstream_tell(intfstream_internal_t *intf); +int64_t intfstream_tell(intfstream_internal_t *intf); void intfstream_putc(intfstream_internal_t *intf, int c); int intfstream_close(intfstream_internal_t *intf); -ssize_t intfstream_get_size(intfstream_internal_t *intf); +int64_t intfstream_get_size(intfstream_internal_t *intf); int intfstream_flush(intfstream_internal_t *intf); @@ -98,7 +98,7 @@ intfstream_t* intfstream_open_file(const char *path, unsigned mode, unsigned hints); intfstream_t *intfstream_open_memory(void *data, - unsigned mode, unsigned hints, size_t size); + unsigned mode, unsigned hints, uint64_t size); intfstream_t *intfstream_open_chd_track(const char *path, unsigned mode, unsigned hints, int32_t track); diff --git a/libretro-common/include/streams/memory_stream.h b/libretro-common/include/streams/memory_stream.h index dca8e7a6ed..c594808772 100644 --- a/libretro-common/include/streams/memory_stream.h +++ b/libretro-common/include/streams/memory_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.h). @@ -36,9 +36,9 @@ memstream_t *memstream_open(unsigned writing); void memstream_close(memstream_t *stream); -size_t memstream_read(memstream_t *stream, void *data, size_t bytes); +uint64_t memstream_read(memstream_t *stream, void *data, uint64_t bytes); -size_t memstream_write(memstream_t *stream, const void *data, size_t bytes); +uint64_t memstream_write(memstream_t *stream, const void *data, uint64_t bytes); int memstream_getc(memstream_t *stream); @@ -46,15 +46,15 @@ void memstream_putc(memstream_t *stream, int c); char *memstream_gets(memstream_t *stream, char *buffer, size_t len); -size_t memstream_pos(memstream_t *stream); +uint64_t memstream_pos(memstream_t *stream); void memstream_rewind(memstream_t *stream); -int memstream_seek(memstream_t *stream, int offset, int whence); +int64_t memstream_seek(memstream_t *stream, int64_t offset, int whence); -void memstream_set_buffer(uint8_t *buffer, size_t size); +void memstream_set_buffer(uint8_t *buffer, uint64_t size); -size_t memstream_get_last_size(void); +uint64_t memstream_get_last_size(void); RETRO_END_DECLS diff --git a/libretro-common/include/streams/stdin_stream.h b/libretro-common/include/streams/stdin_stream.h index ce5ebe55df..dda02963e4 100644 --- a/libretro-common/include/streams/stdin_stream.h +++ b/libretro-common/include/streams/stdin_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (stdin_stream.h). diff --git a/libretro-common/include/streams/trans_stream.h b/libretro-common/include/streams/trans_stream.h index 4023103e8a..0a10368e73 100644 --- a/libretro-common/include/streams/trans_stream.h +++ b/libretro-common/include/streams/trans_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (trans_stream.h). diff --git a/libretro-common/include/string/stdstring.h b/libretro-common/include/string/stdstring.h index 17e7209529..eb2954b825 100644 --- a/libretro-common/include/string/stdstring.h +++ b/libretro-common/include/string/stdstring.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (stdstring.h). diff --git a/libretro-common/include/vfs/vfs_implementation.h b/libretro-common/include/vfs/vfs_implementation.h index 5ceae39b6f..047b170354 100644 --- a/libretro-common/include/vfs/vfs_implementation.h +++ b/libretro-common/include/vfs/vfs_implementation.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vfs_implementation.h). diff --git a/libretro-common/lists/dir_list.c b/libretro-common/lists/dir_list.c index 73148c83e3..fc360f748b 100644 --- a/libretro-common/lists/dir_list.c +++ b/libretro-common/lists/dir_list.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dir_list.c). @@ -185,13 +185,16 @@ static int dir_list_read(const char *dir, bool is_dir = false; int ret = 0; const char *name = retro_dirent_get_name(entry); - const char *file_ext = path_get_extension(name); + const char *file_ext = ""; file_path[0] = '\0'; fill_pathname_join(file_path, dir, name, sizeof(file_path)); is_dir = retro_dirent_is_dir(entry, file_path); + if(!is_dir) + file_ext = path_get_extension(name); + if (!include_hidden) { if (*name == '.') @@ -200,7 +203,7 @@ static int dir_list_read(const char *dir, if(is_dir && recursive) { - if(strstr(name, ".") || strstr(name, "..")) + if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue; dir_list_read(file_path, list, ext_list, include_dirs, diff --git a/libretro-common/lists/file_list.c b/libretro-common/lists/file_list.c index c52523e193..1525d8879e 100644 --- a/libretro-common/lists/file_list.c +++ b/libretro-common/lists/file_list.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_list.c). diff --git a/libretro-common/lists/string_list.c b/libretro-common/lists/string_list.c index a5cb4be298..3a5fb96fef 100644 --- a/libretro-common/lists/string_list.c +++ b/libretro-common/lists/string_list.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (string_list.c). diff --git a/libretro-common/lists/vector_list.c b/libretro-common/lists/vector_list.c index 4b8c2314e6..b8493c5675 100644 --- a/libretro-common/lists/vector_list.c +++ b/libretro-common/lists/vector_list.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vector_list.c). diff --git a/libretro-common/memmap/memalign.c b/libretro-common/memmap/memalign.c index 56d0c94669..449d8471b8 100644 --- a/libretro-common/memmap/memalign.c +++ b/libretro-common/memmap/memalign.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memalign.c). diff --git a/libretro-common/memmap/memmap.c b/libretro-common/memmap/memmap.c index cda86ff01e..26d9ce031f 100644 --- a/libretro-common/memmap/memmap.c +++ b/libretro-common/memmap/memmap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memmap.c). diff --git a/libretro-common/net/net_compat.c b/libretro-common/net/net_compat.c index a2950a8586..86c1381221 100644 --- a/libretro-common/net/net_compat.c +++ b/libretro-common/net/net_compat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_compat.c). diff --git a/libretro-common/net/net_http.c b/libretro-common/net/net_http.c index 3b25f340d9..9e916f7942 100644 --- a/libretro-common/net/net_http.c +++ b/libretro-common/net/net_http.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_http.c). @@ -138,7 +138,6 @@ void net_http_urlencode_full(char *dest, char *tmp = NULL; char url_domain[PATH_MAX_LENGTH] = {0}; char url_path[PATH_MAX_LENGTH] = {0}; - char url_encoded[PATH_MAX_LENGTH] = {0}; int count = 0; strlcpy (url_path, source, sizeof(url_path)); diff --git a/libretro-common/net/net_http_parse.c b/libretro-common/net/net_http_parse.c index 69b80f6e37..113eeaa00a 100644 --- a/libretro-common/net/net_http_parse.c +++ b/libretro-common/net/net_http_parse.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_http_parse.c). diff --git a/libretro-common/net/net_ifinfo.c b/libretro-common/net/net_ifinfo.c index e226dda325..77c5971171 100644 --- a/libretro-common/net/net_ifinfo.c +++ b/libretro-common/net/net_ifinfo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_ifinfo.c). diff --git a/libretro-common/net/net_natt.c b/libretro-common/net/net_natt.c index 34c6f1d648..33d0865208 100644 --- a/libretro-common/net/net_natt.c +++ b/libretro-common/net/net_natt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2016-2017 The RetroArch team +/* Copyright (C) 2016-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_natt.c). @@ -74,8 +74,9 @@ void natt_init(void) descXML = (char *) miniwget(dev->descURL, &descXMLsize, 0, NULL); if (descXML) { - parserootdesc (descXML, descXMLsize, &data); - free (descXML); descXML = 0; + parserootdesc(descXML, descXMLsize, &data); + free (descXML); + descXML = 0; GetUPNPUrls (&urls, &data, dev->descURL, 0); } freeUPNPDevlist(devlist); @@ -112,44 +113,55 @@ static bool natt_open_port(struct natt_status *status, return false; /* figure out the internal info */ - if (getnameinfo(addr, addrlen, host, PATH_MAX_LENGTH, port_str, 6, NI_NUMERICHOST|NI_NUMERICSERV) != 0) + if (getnameinfo(addr, addrlen, host, PATH_MAX_LENGTH, + port_str, 6, NI_NUMERICHOST|NI_NUMERICSERV) != 0) return false; + proto_str = (proto == SOCKET_PROTOCOL_UDP) ? "UDP" : "TCP"; /* add the port mapping */ - r = UPNP_AddAnyPortMapping(urls.controlURL, data.first.servicetype, port_str, - port_str, host, "retroarch", proto_str, NULL, "3600", ext_port_str); + r = UPNP_AddAnyPortMapping(urls.controlURL, + data.first.servicetype, port_str, + port_str, host, "retroarch", + proto_str, NULL, "3600", ext_port_str); + if (r != 0) { /* try the older AddPortMapping */ memcpy(ext_port_str, port_str, 6); - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port_str, - port_str, host, "retroarch", proto_str, NULL, "3600"); + r = UPNP_AddPortMapping(urls.controlURL, + data.first.servicetype, port_str, + port_str, host, "retroarch", + proto_str, NULL, "3600"); } if (r != 0) return false; /* get the external IP */ - r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, ext_host); + r = UPNP_GetExternalIPAddress(urls.controlURL, + data.first.servicetype, ext_host); if (r != 0) return false; /* update the status */ - if (getaddrinfo_retro(ext_host, ext_port_str, &hints, &ext_addrinfo) != 0) + if (getaddrinfo_retro(ext_host, + ext_port_str, &hints, &ext_addrinfo) != 0) return false; if (ext_addrinfo->ai_family == AF_INET && ext_addrinfo->ai_addrlen >= sizeof(struct sockaddr_in)) { - status->have_inet4 = true; - status->ext_inet4_addr = *((struct sockaddr_in *) ext_addrinfo->ai_addr); + status->have_inet4 = true; + status->ext_inet4_addr = *((struct sockaddr_in *) + ext_addrinfo->ai_addr); } #if defined(AF_INET6) && !defined(HAVE_SOCKET_LEGACY) else if (ext_addrinfo->ai_family == AF_INET6 && ext_addrinfo->ai_addrlen >= sizeof(struct sockaddr_in6)) { - status->have_inet6 = true; - status->ext_inet6_addr = *((struct sockaddr_in6 *) ext_addrinfo->ai_addr); + status->have_inet6 = true; + status->ext_inet6_addr = *((struct sockaddr_in6 *) + ext_addrinfo->ai_addr); } #endif else @@ -169,16 +181,17 @@ static bool natt_open_port(struct natt_status *status, #endif } -bool natt_open_port_any(struct natt_status *status, uint16_t port, enum socket_protocol proto) +bool natt_open_port_any(struct natt_status *status, + uint16_t port, enum socket_protocol proto) { #if !defined(HAVE_SOCKET_LEGACY) && !defined(WIIU) - struct net_ifinfo list; - bool ret = false; size_t i; - struct addrinfo hints = {0}, *addr; char port_str[6]; + struct net_ifinfo list; + struct addrinfo hints = {0}, *addr; + bool ret = false; - sprintf(port_str, "%hu", port); + snprintf(port_str, sizeof(port_str), "%hu", port); /* get our interfaces */ if (!net_ifinfo_new(&list)) @@ -190,13 +203,15 @@ bool natt_open_port_any(struct natt_status *status, uint16_t port, enum socket_p struct net_ifinfo_entry *entry = list.entries + i; /* ignore localhost */ - if (string_is_equal(entry->host, "127.0.0.1") || string_is_equal(entry->host, "::1")) + if ( string_is_equal(entry->host, "127.0.0.1") || + string_is_equal(entry->host, "::1")) continue; /* make a request for this host */ if (getaddrinfo_retro(entry->host, port_str, &hints, &addr) == 0) { - ret = natt_open_port(status, addr->ai_addr, addr->ai_addrlen, proto) || ret; + ret = natt_open_port(status, addr->ai_addr, + addr->ai_addrlen, proto) || ret; freeaddrinfo_retro(addr); } } @@ -218,19 +233,24 @@ bool natt_read(struct natt_status *status) } #if 0 -/* If we want to remove redirects in the future, this is a sample of how to do - * that */ +/* If we want to remove redirects in the future, this is a + * sample of how to do that. */ + void upnp_rem_redir (int port) { - char port_str[16]; int t; + char port_str[16]; + printf("TB : upnp_rem_redir (%d)\n", port); + if(urls.controlURL[0] == '\0') { printf("TB : the init was not done !\n"); return; } - sprintf(port_str, "%d", port); - UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port_str, "TCP", NULL); + + snprintf(port_str, sizeof(port_str), "%d", port); + UPNP_DeletePortMapping(urls.controlURL, + data.first.servicetype, port_str, "TCP", NULL); } #endif diff --git a/libretro-common/net/net_socket.c b/libretro-common/net/net_socket.c index 0c960360bc..e2213c9bac 100644 --- a/libretro-common/net/net_socket.c +++ b/libretro-common/net/net_socket.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_socket.c). diff --git a/libretro-common/net/net_socket_ssl.c b/libretro-common/net/net_socket_ssl.c index 4b9da1206b..04e0babad1 100644 --- a/libretro-common/net/net_socket_ssl.c +++ b/libretro-common/net/net_socket_ssl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_socket.c). diff --git a/libretro-common/queues/fifo_queue.c b/libretro-common/queues/fifo_queue.c index 85d0268011..d6b21aca48 100644 --- a/libretro-common/queues/fifo_queue.c +++ b/libretro-common/queues/fifo_queue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fifo_queue.c). diff --git a/libretro-common/queues/message_queue.c b/libretro-common/queues/message_queue.c index dda5cbf5a1..a8086c3b9f 100644 --- a/libretro-common/queues/message_queue.c +++ b/libretro-common/queues/message_queue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (message_queue.c). diff --git a/libretro-common/queues/task_queue.c b/libretro-common/queues/task_queue.c index 2d45f65ea0..2eb51dd9e7 100644 --- a/libretro-common/queues/task_queue.c +++ b/libretro-common/queues/task_queue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (task_queue.c). diff --git a/libretro-common/rthreads/ctr_pthread.h b/libretro-common/rthreads/ctr_pthread.h index 8c82e6e511..0a393ebb8f 100644 --- a/libretro-common/rthreads/ctr_pthread.h +++ b/libretro-common/rthreads/ctr_pthread.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (gx_pthread.h). diff --git a/libretro-common/rthreads/gx_pthread.h b/libretro-common/rthreads/gx_pthread.h index 8cb4616231..055c6afbde 100644 --- a/libretro-common/rthreads/gx_pthread.h +++ b/libretro-common/rthreads/gx_pthread.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (gx_pthread.h). diff --git a/libretro-common/rthreads/rthreads.c b/libretro-common/rthreads/rthreads.c index 9632c2a2d6..e155075555 100644 --- a/libretro-common/rthreads/rthreads.c +++ b/libretro-common/rthreads/rthreads.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rthreads.c). diff --git a/libretro-common/rthreads/xenon_sdl_threads.c b/libretro-common/rthreads/xenon_sdl_threads.c index 0097673528..ff1855c275 100644 --- a/libretro-common/rthreads/xenon_sdl_threads.c +++ b/libretro-common/rthreads/xenon_sdl_threads.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (xenon_sdl_threads.c). diff --git a/libretro-common/streams/chd_stream.c b/libretro-common/streams/chd_stream.c index ebd736f0ad..669bd43391 100644 --- a/libretro-common/streams/chd_stream.c +++ b/libretro-common/streams/chd_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (chd_stream.c). @@ -386,7 +386,7 @@ char *chdstream_gets(chdstream_t *stream, char *buffer, size_t len) return buffer; } -size_t chdstream_tell(chdstream_t *stream) +uint64_t chdstream_tell(chdstream_t *stream) { return stream->offset; } @@ -396,9 +396,9 @@ void chdstream_rewind(chdstream_t *stream) stream->offset = 0; } -int chdstream_seek(chdstream_t *stream, ssize_t offset, int whence) +int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence) { - ssize_t new_offset; + int64_t new_offset; switch (whence) { diff --git a/libretro-common/streams/file_stream.c b/libretro-common/streams/file_stream.c index 988ba73028..5ccdbcfacb 100644 --- a/libretro-common/streams/file_stream.c +++ b/libretro-common/streams/file_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream.c). @@ -111,9 +111,9 @@ bool filestream_exists(const char *path) return true; } -ssize_t filestream_get_size(RFILE *stream) +int64_t filestream_get_size(RFILE *stream) { - ssize_t output; + int64_t output; if (filestream_size_cb != NULL) output = filestream_size_cb(stream->hfile); @@ -191,7 +191,7 @@ int filestream_getc(RFILE *stream) return EOF; } -ssize_t filestream_seek(RFILE *stream, ssize_t offset, int seek_position) +int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position) { int64_t output; @@ -213,9 +213,9 @@ int filestream_eof(RFILE *stream) } -ssize_t filestream_tell(RFILE *stream) +int64_t filestream_tell(RFILE *stream) { - ssize_t output; + int64_t output; if (filestream_size_cb != NULL) output = filestream_tell_cb(stream->hfile); @@ -237,7 +237,7 @@ void filestream_rewind(RFILE *stream) stream->eof_flag = false; } -ssize_t filestream_read(RFILE *stream, void *s, int64_t len) +int64_t filestream_read(RFILE *stream, void *s, int64_t len) { int64_t output; @@ -294,7 +294,7 @@ const char *filestream_get_path(RFILE *stream) return retro_vfs_file_get_path_impl((libretro_vfs_implementation_file*)stream->hfile); } -ssize_t filestream_write(RFILE *stream, const void *s, int64_t len) +int64_t filestream_write(RFILE *stream, const void *s, int64_t len) { int64_t output; @@ -320,14 +320,14 @@ int filestream_putc(RFILE *stream, int c) int filestream_vprintf(RFILE *stream, const char* format, va_list args) { static char buffer[8 * 1024]; - int num_chars = vsprintf(buffer, format, args); + int64_t num_chars = vsprintf(buffer, format, args); if (num_chars < 0) return -1; else if (num_chars == 0) return 0; - return filestream_write(stream, buffer, num_chars); + return (int)filestream_write(stream, buffer, num_chars); } int filestream_printf(RFILE *stream, const char* format, ...) @@ -373,9 +373,9 @@ int filestream_close(RFILE *stream) * * Returns: number of items read, -1 on error. */ -int filestream_read_file(const char *path, void **buf, ssize_t *len) +int64_t filestream_read_file(const char *path, void **buf, int64_t *len) { - ssize_t ret = 0; + int64_t ret = 0; int64_t content_buf_size = 0; void *content_buf = NULL; RFILE *file = filestream_open(path, @@ -397,7 +397,7 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len) if (!content_buf) goto error; - if ((int64_t)(size_t)(content_buf_size + 1) != (content_buf_size + 1)) + if ((int64_t)(uint64_t)(content_buf_size + 1) != (content_buf_size + 1)) goto error; ret = filestream_read(file, content_buf, (int64_t)content_buf_size); @@ -441,9 +441,9 @@ error: * * Returns: true (1) on success, false (0) otherwise. */ -bool filestream_write_file(const char *path, const void *data, ssize_t size) +bool filestream_write_file(const char *path, const void *data, int64_t size) { - ssize_t ret = 0; + int64_t ret = 0; RFILE *file = filestream_open(path, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); diff --git a/libretro-common/streams/file_stream_transforms.c b/libretro-common/streams/file_stream_transforms.c index 8796073693..efeb7edd9c 100644 --- a/libretro-common/streams/file_stream_transforms.c +++ b/libretro-common/streams/file_stream_transforms.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream_transforms.c). @@ -72,12 +72,12 @@ int rfclose(RFILE* stream) return filestream_close(stream); } -long rftell(RFILE* stream) +int64_t rftell(RFILE* stream) { return filestream_tell(stream); } -int rfseek(RFILE* stream, long offset, int origin) +int64_t rfseek(RFILE* stream, int64_t offset, int origin) { int seek_position = -1; switch (origin) @@ -96,7 +96,7 @@ int rfseek(RFILE* stream, long offset, int origin) return filestream_seek(stream, offset, seek_position); } -size_t rfread(void* buffer, +int64_t rfread(void* buffer, size_t elem_size, size_t elem_count, RFILE* stream) { return filestream_read(stream, buffer, elem_size * elem_count); @@ -112,7 +112,7 @@ int rfgetc(RFILE* stream) return filestream_getc(stream); } -size_t rfwrite(void const* buffer, +int64_t rfwrite(void const* buffer, size_t elem_size, size_t elem_count, RFILE* stream) { return filestream_write(stream, buffer, elem_size * elem_count); diff --git a/libretro-common/streams/interface_stream.c b/libretro-common/streams/interface_stream.c index c61d12234b..0207823ce2 100644 --- a/libretro-common/streams/interface_stream.c +++ b/libretro-common/streams/interface_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (interface_stream.c). @@ -43,7 +43,7 @@ struct intfstream_internal struct { uint8_t *data; - unsigned size; + uint64_t size; } buf; memstream_t *fp; bool writable; @@ -57,7 +57,7 @@ struct intfstream_internal #endif }; -ssize_t intfstream_get_size(intfstream_internal_t *intf) +int64_t intfstream_get_size(intfstream_internal_t *intf) { if (!intf) return 0; @@ -219,7 +219,7 @@ error: return NULL; } -int intfstream_seek(intfstream_internal_t *intf, int offset, int whence) +int64_t intfstream_seek(intfstream_internal_t *intf, int64_t offset, int whence) { if (!intf) return -1; @@ -241,14 +241,14 @@ int intfstream_seek(intfstream_internal_t *intf, int offset, int whence) seek_position = RETRO_VFS_SEEK_POSITION_END; break; } - return (int)filestream_seek(intf->file.fp, (int)offset, + return (int64_t)filestream_seek(intf->file.fp, (int64_t)offset, seek_position); } case INTFSTREAM_MEMORY: - return (int)memstream_seek(intf->memory.fp, offset, whence); + return (int64_t)memstream_seek(intf->memory.fp, offset, whence); case INTFSTREAM_CHD: #ifdef HAVE_CHD - return (int)chdstream_seek(intf->chd.fp, offset, whence); + return (int64_t)chdstream_seek(intf->chd.fp, offset, whence); #else break; #endif @@ -257,7 +257,7 @@ int intfstream_seek(intfstream_internal_t *intf, int offset, int whence) return -1; } -ssize_t intfstream_read(intfstream_internal_t *intf, void *s, size_t len) +int64_t intfstream_read(intfstream_internal_t *intf, void *s, uint64_t len) { if (!intf) return 0; @@ -279,8 +279,8 @@ ssize_t intfstream_read(intfstream_internal_t *intf, void *s, size_t len) return -1; } -ssize_t intfstream_write(intfstream_internal_t *intf, - const void *s, size_t len) +int64_t intfstream_write(intfstream_internal_t *intf, + const void *s, uint64_t len) { if (!intf) return 0; @@ -299,7 +299,7 @@ ssize_t intfstream_write(intfstream_internal_t *intf, } char *intfstream_gets(intfstream_internal_t *intf, - char *buffer, size_t len) + char *buffer, uint64_t len) { if (!intf) return NULL; @@ -307,9 +307,11 @@ char *intfstream_gets(intfstream_internal_t *intf, switch (intf->type) { case INTFSTREAM_FILE: - return filestream_gets(intf->file.fp, buffer, len); + return filestream_gets(intf->file.fp, + buffer, (size_t)len); case INTFSTREAM_MEMORY: - return memstream_gets(intf->memory.fp, buffer, len); + return memstream_gets(intf->memory.fp, + buffer, (size_t)len); case INTFSTREAM_CHD: #ifdef HAVE_CHD return chdstream_gets(intf->chd.fp, buffer, len); @@ -343,7 +345,7 @@ int intfstream_getc(intfstream_internal_t *intf) return -1; } -int intfstream_tell(intfstream_internal_t *intf) +int64_t intfstream_tell(intfstream_internal_t *intf) { if (!intf) return -1; @@ -351,12 +353,12 @@ int intfstream_tell(intfstream_internal_t *intf) switch (intf->type) { case INTFSTREAM_FILE: - return (int)filestream_tell(intf->file.fp); + return (int64_t)filestream_tell(intf->file.fp); case INTFSTREAM_MEMORY: - return (int)memstream_pos(intf->memory.fp); + return (int64_t)memstream_pos(intf->memory.fp); case INTFSTREAM_CHD: #ifdef HAVE_CHD - return (int)chdstream_tell(intf->chd.fp); + return (int64_t)chdstream_tell(intf->chd.fp); #else break; #endif @@ -428,7 +430,7 @@ error: } intfstream_t *intfstream_open_memory(void *data, - unsigned mode, unsigned hints, size_t size) + unsigned mode, unsigned hints, uint64_t size) { intfstream_info_t info; intfstream_t *fd = NULL; diff --git a/libretro-common/streams/memory_stream.c b/libretro-common/streams/memory_stream.c index 014101227d..77a2c008d2 100644 --- a/libretro-common/streams/memory_stream.c +++ b/libretro-common/streams/memory_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.c). @@ -26,16 +26,16 @@ #include -static uint8_t* g_buffer = NULL; -static size_t g_size = 0; -static size_t last_file_size = 0; +static uint8_t* g_buffer = NULL; +static uint64_t g_size = 0; +static uint64_t last_file_size = 0; struct memstream { uint8_t *buf; - size_t size; - size_t ptr; - size_t max_ptr; + uint64_t size; + uint64_t ptr; + uint64_t max_ptr; unsigned writing; }; @@ -45,19 +45,19 @@ static void memstream_update_pos(memstream_t *stream) stream->max_ptr = stream->ptr; } -void memstream_set_buffer(uint8_t *buffer, size_t size) +void memstream_set_buffer(uint8_t *buffer, uint64_t size) { g_buffer = buffer; g_size = size; } -size_t memstream_get_last_size(void) +uint64_t memstream_get_last_size(void) { return last_file_size; } static void memstream_init(memstream_t *stream, - uint8_t *buffer, size_t max_size, unsigned writing) + uint8_t *buffer, uint64_t max_size, unsigned writing) { if (!stream) return; @@ -92,9 +92,9 @@ void memstream_close(memstream_t *stream) free(stream); } -size_t memstream_read(memstream_t *stream, void *data, size_t bytes) +uint64_t memstream_read(memstream_t *stream, void *data, uint64_t bytes) { - size_t avail = 0; + uint64_t avail = 0; if (!stream) return 0; @@ -103,15 +103,15 @@ size_t memstream_read(memstream_t *stream, void *data, size_t bytes) if (bytes > avail) bytes = avail; - memcpy(data, stream->buf + stream->ptr, bytes); + memcpy(data, stream->buf + stream->ptr, (size_t)bytes); stream->ptr += bytes; memstream_update_pos(stream); return bytes; } -size_t memstream_write(memstream_t *stream, const void *data, size_t bytes) +uint64_t memstream_write(memstream_t *stream, const void *data, uint64_t bytes) { - size_t avail = 0; + uint64_t avail = 0; if (!stream) return 0; @@ -120,15 +120,15 @@ size_t memstream_write(memstream_t *stream, const void *data, size_t bytes) if (bytes > avail) bytes = avail; - memcpy(stream->buf + stream->ptr, data, bytes); + memcpy(stream->buf + stream->ptr, data, (size_t)bytes); stream->ptr += bytes; memstream_update_pos(stream); return bytes; } -int memstream_seek(memstream_t *stream, int offset, int whence) +int64_t memstream_seek(memstream_t *stream, int64_t offset, int whence) { - size_t ptr; + uint64_t ptr; switch (whence) { @@ -159,7 +159,7 @@ void memstream_rewind(memstream_t *stream) memstream_seek(stream, 0L, SEEK_SET); } -size_t memstream_pos(memstream_t *stream) +uint64_t memstream_pos(memstream_t *stream) { return stream->ptr; } diff --git a/libretro-common/streams/stdin_stream.c b/libretro-common/streams/stdin_stream.c index c30c0f4575..6aedfae388 100644 --- a/libretro-common/streams/stdin_stream.c +++ b/libretro-common/streams/stdin_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (stdin_stream.c). diff --git a/libretro-common/streams/trans_stream.c b/libretro-common/streams/trans_stream.c index 10eea457a7..92f3207d64 100644 --- a/libretro-common/streams/trans_stream.c +++ b/libretro-common/streams/trans_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (trans_stream.c). diff --git a/libretro-common/streams/trans_stream_pipe.c b/libretro-common/streams/trans_stream_pipe.c index f30d5df390..5a2e076652 100644 --- a/libretro-common/streams/trans_stream_pipe.c +++ b/libretro-common/streams/trans_stream_pipe.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (trans_stream_pipe.c). diff --git a/libretro-common/streams/trans_stream_zlib.c b/libretro-common/streams/trans_stream_zlib.c index ec350119ca..7f797f12d6 100644 --- a/libretro-common/streams/trans_stream_zlib.c +++ b/libretro-common/streams/trans_stream_zlib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (trans_stream_zlib.c). diff --git a/libretro-common/string/stdstring.c b/libretro-common/string/stdstring.c index 02f8dad8ec..6e1555dbfe 100644 --- a/libretro-common/string/stdstring.c +++ b/libretro-common/string/stdstring.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (stdstring.c). @@ -169,7 +169,7 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode) } character = utf8skip(&string[i], 1); - char_len = character - &string[i]; + char_len = (unsigned)(character - &string[i]); if (!unicode) counter += char_len - 1; diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c index 95fbbf1d8d..ff8100f7f1 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vfs_implementation.c). @@ -264,7 +264,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) { - FILE *fp = fopen_utf8(path, mode_str); + FILE *fp = (FILE*)fopen_utf8(path, mode_str); if (!fp) goto error; diff --git a/libretro-db/.gitignore b/libretro-db/.gitignore new file mode 100644 index 0000000000..09ef21d176 --- /dev/null +++ b/libretro-db/.gitignore @@ -0,0 +1,4 @@ +# Ignore compiled binaries. +/c_converter +/libretrodb_tool +/rmsgpack_test diff --git a/libretro-db/c_converter.c b/libretro-db/c_converter.c index f08171ca17..3d2e2ac615 100644 --- a/libretro-db/c_converter.c +++ b/libretro-db/c_converter.c @@ -494,6 +494,7 @@ static dat_converter_list_t* dat_converter_parser( dat_converter_map_t map; dat_converter_list_item_t* current = lexer_list->values; bool skip = true; + bool warning_displayed = false; map.key = NULL; map.type = DAT_CONVERTER_LIST_MAP; @@ -531,13 +532,17 @@ static dat_converter_list_t* dat_converter_parser( // If the key is not found, report, and mark it to be skipped. if (!map.key) { - printf("Missing match key '"); - while (match_key->next) + if (warning_displayed == false) { - printf("%s.", match_key->value); - match_key = match_key->next; + printf(" - Missing match key '"); + while (match_key->next) + { + printf("%s.", match_key->value); + match_key = match_key->next; + } + printf("%s' on line %d\n", match_key->value, current->token.line_no); + warning_displayed = true; } - printf("%s' on line %d\n", match_key->value, current->token.line_no); skip = true; } } diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index 6d29ea73d7..c3bb2362c2 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -155,6 +155,7 @@ generic_deferred_push(deferred_push_directory_settings_list, DISPLAYLIST_ generic_deferred_push(deferred_push_privacy_settings_list, DISPLAYLIST_PRIVACY_SETTINGS_LIST) generic_deferred_push(deferred_push_audio_settings_list, DISPLAYLIST_AUDIO_SETTINGS_LIST) generic_deferred_push(deferred_push_input_settings_list, DISPLAYLIST_INPUT_SETTINGS_LIST) +generic_deferred_push(deferred_push_latency_settings_list, DISPLAYLIST_LATENCY_SETTINGS_LIST) generic_deferred_push(deferred_push_recording_settings_list, DISPLAYLIST_RECORDING_SETTINGS_LIST) generic_deferred_push(deferred_push_playlist_settings_list, DISPLAYLIST_PLAYLIST_SETTINGS_LIST) generic_deferred_push(deferred_push_input_hotkey_binds_list, DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST) @@ -202,12 +203,15 @@ static int deferred_push_cursor_manager_list_deferred( if (!string_is_empty(info->path_b)) free(info->path_b); + if (!string_is_empty(info->path_c)) free(info->path_c); + + info->path_b = strdup(info->path); + if (!string_is_empty(info->path)) free(info->path); - info->path_b = strdup(info->path); info->path_c = strdup(query); info->path = strdup(rdb_path); @@ -805,6 +809,11 @@ static int menu_cbs_init_bind_deferred_push_compare_label( { BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_audio_settings_list); } + else if (strstr(label, + msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST))) + { + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_latency_settings_list); + } else if (strstr(label, msg_hash_to_str(MENU_ENUM_LABEL_CORE_INFORMATION))) { @@ -1155,6 +1164,9 @@ static int menu_cbs_init_bind_deferred_push_compare_label( case MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_audio_settings_list); break; + case MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST: + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_latency_settings_list); + break; case MENU_ENUM_LABEL_DEFERRED_CORE_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_core_settings_list); break; diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c index ec8c1b4005..45827cc6da 100644 --- a/menu/cbs/menu_cbs_get_value.c +++ b/menu/cbs/menu_cbs_get_value.c @@ -54,7 +54,7 @@ cbs->action_get_value_ident = #name; #endif -extern struct key_desc key_descriptors[MENU_SETTINGS_INPUT_DESC_KBD_END]; +extern struct key_desc key_descriptors[RARCH_MAX_KEYS]; static void menu_action_setting_disp_set_label_cheat_num_passes( file_list_t* list, @@ -547,80 +547,50 @@ static void menu_action_setting_disp_set_label_input_desc( const char *path, char *s2, size_t len2) { - char descriptor[255]; - const struct retro_keybind *auto_bind = NULL; - const struct retro_keybind *keybind = NULL; + rarch_system_info_t *system = runloop_get_system_info(); settings_t *settings = config_get_ptr(); - unsigned inp_desc_index_offset = - type - MENU_SETTINGS_INPUT_DESC_BEGIN; - unsigned inp_desc_user = inp_desc_index_offset / - (RARCH_FIRST_CUSTOM_BIND + 4); - unsigned inp_desc_button_index_offset = inp_desc_index_offset - - (inp_desc_user * (RARCH_FIRST_CUSTOM_BIND + 4)); - unsigned remap_id = 0; + const char* descriptor = NULL; + char buf[256]; + + unsigned btn_idx, user_idx, remap_idx; if (!settings) return; - descriptor[0] = '\0'; + user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); + btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; - remap_id = settings->uints.input_remap_ids - [inp_desc_user][inp_desc_button_index_offset]; + remap_idx = + settings->uints.input_remap_ids[user_idx][btn_idx]; +/* + if (remap_idx == RARCH_UNMAPPED) + settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_UNMAPPED; +*/ + if (!system) + return; - keybind = &input_config_binds[inp_desc_user][remap_id]; - auto_bind = (const struct retro_keybind*) - input_config_get_bind_auto(inp_desc_user, remap_id); + descriptor = system->input_desc_btn[user_idx][remap_idx]; - input_config_get_bind_string(descriptor, - keybind, auto_bind, sizeof(descriptor)); - - if (inp_desc_button_index_offset < RARCH_FIRST_CUSTOM_BIND) + if (!string_is_empty(descriptor) && remap_idx < RARCH_FIRST_CUSTOM_BIND) + strlcpy(s, descriptor, len); + else if (!string_is_empty(descriptor) && remap_idx >= RARCH_FIRST_CUSTOM_BIND && remap_idx % 2 == 0) { - if(strstr(descriptor, "Auto") && !strstr(descriptor, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE))) - strlcpy(s, - descriptor, - len); - else - { - const struct retro_keybind *keyptr = &input_config_binds[inp_desc_user] - [remap_id]; - - strlcpy(s, msg_hash_to_str(keyptr->enum_idx), len); - } + snprintf(buf, sizeof(buf), "%s %c", descriptor, '+'); + strlcpy(s, buf, len); + } + else if (!string_is_empty(descriptor) && remap_idx >= RARCH_FIRST_CUSTOM_BIND && remap_idx % 2 != 0) + { + snprintf(buf, sizeof(buf), "%s %c", descriptor, '-'); + strlcpy(s, buf, len); } - - - else - { - const char *str = NULL; - switch (remap_id) - { - case 0: - str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X); - break; - case 1: - str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y); - break; - case 2: - str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X); - break; - case 3: - str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y); - break; - } + strlcpy(s, "---", len); - if (!string_is_empty(str)) - strlcpy(s, str, len); - } *w = 19; strlcpy(s2, path, len2); - } -#ifdef HAVE_KEYMAPPER static void menu_action_setting_disp_set_label_input_desc_kbd( file_list_t* list, unsigned *w, unsigned type, unsigned i, @@ -631,28 +601,40 @@ static void menu_action_setting_disp_set_label_input_desc_kbd( char *s2, size_t len2) { char desc[PATH_MAX_LENGTH]; - unsigned key_id; + unsigned key_id, id; unsigned remap_id; + unsigned offset = 0; + settings_t *settings = config_get_ptr(); if (!settings) return; - remap_id = - settings->uints.input_keymapper_ids[type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN]; + offset = type / ((MENU_SETTINGS_INPUT_DESC_KBD_END - + (MENU_SETTINGS_INPUT_DESC_KBD_END - + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN))) - 1; - for (key_id = 0; key_id < MENU_SETTINGS_INPUT_DESC_KBD_END - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; key_id++) + id = (type / (offset + 1)) - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; + remap_id = + settings->uints.input_keymapper_ids[offset][id]; + + for (key_id = 0; key_id < RARCH_MAX_KEYS - 1; key_id++) { if(remap_id == key_descriptors[key_id].key) break; } - snprintf(desc, sizeof(desc), "Keyboard %s", key_descriptors[key_id].desc); - strlcpy(s, desc, len); + + if (key_descriptors[key_id].key != RETROK_FIRST) + { + snprintf(desc, sizeof(desc), "Keyboard %s", key_descriptors[key_id].desc); + strlcpy(s, desc, len); + } + else + strlcpy(s, "---", len); *w = 19; strlcpy(s2, path, len2); } -#endif static void menu_action_setting_disp_set_label_cheat( file_list_t* list, @@ -940,6 +922,37 @@ static void menu_action_setting_disp_set_label_wifi_is_online( strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ONLINE), len); } +static void menu_action_setting_disp_set_label_xmb_layout( + file_list_t* list, + unsigned *w, unsigned type, unsigned i, + const char *label, + char *s, size_t len, + const char *entry_label, + const char *path, + char *s2, size_t len2) +{ + settings_t *settings = config_get_ptr(); + + strlcpy(s2, path, len2); + *w = 19; + + if (!settings) + return; + + switch (settings->uints.menu_xmb_layout) + { + case 0: + strlcpy(s, "Auto", len); + break; + case 1: + strlcpy(s, "Console", len); + break; + case 2: + strlcpy(s, "Handheld", len); + break; + } +} + static void menu_action_setting_disp_set_label_xmb_menu_color_theme( file_list_t* list, unsigned *w, unsigned type, unsigned i, @@ -1134,6 +1147,47 @@ static void menu_action_setting_disp_set_label_thumbnails( } } +static void menu_action_setting_disp_set_label_left_thumbnails( + file_list_t* list, + unsigned *w, unsigned type, unsigned i, + const char *label, + char *s, size_t len, + const char *entry_label, + const char *path, + char *s2, size_t len2) +{ + settings_t *settings = config_get_ptr(); + + if (!settings) + return; + + strlcpy(s2, path, len2); + *w = 19; + + switch (settings->uints.menu_left_thumbnails) + { + case 0: + strlcpy(s, msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_OFF), len); + break; + case 1: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_SCREENSHOTS), len); + break; + case 2: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_TITLE_SCREENS), len); + break; + case 3: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_BOXARTS), len); + break; + } +} + static void menu_action_setting_disp_set_label_menu_toggle_gamepad_combo( file_list_t* list, unsigned *w, unsigned type, unsigned i, @@ -1892,6 +1946,10 @@ static int menu_cbs_init_bind_get_string_representation_compare_label( BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_poll_type_behavior); break; + case MENU_ENUM_LABEL_XMB_LAYOUT: + BIND_ACTION_GET_VALUE(cbs, + menu_action_setting_disp_set_label_xmb_layout); + break; case MENU_ENUM_LABEL_XMB_THEME: BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_xmb_theme); @@ -1912,6 +1970,10 @@ static int menu_cbs_init_bind_get_string_representation_compare_label( BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_thumbnails); break; + case MENU_ENUM_LABEL_LEFT_THUMBNAILS: + BIND_ACTION_GET_VALUE(cbs, + menu_action_setting_disp_set_label_left_thumbnails); + break; case MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO: BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_menu_toggle_gamepad_combo); @@ -2056,14 +2118,12 @@ static int menu_cbs_init_bind_get_string_representation_compare_type( BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_libretro_perf_counters); } -#ifdef HAVE_KEYMAPPER else if (type >= MENU_SETTINGS_INPUT_DESC_KBD_BEGIN && type <= MENU_SETTINGS_INPUT_DESC_KBD_END) { BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_input_desc_kbd); } -#endif else { switch (type) diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index 230b6fea0d..c39289f671 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -35,6 +35,9 @@ #include "../../core_info.h" #include "../../managers/cheat_manager.h" #include "../../file_path_special.h" +#include "../../driver.h" +#include "../../audio/audio_driver.h" +#include "../../gfx/video_driver.h" #include "../../retroarch.h" #include "../../network/netplay/netplay.h" @@ -46,7 +49,255 @@ } while(0) #endif -extern struct key_desc key_descriptors[MENU_SETTINGS_INPUT_DESC_KBD_END]; +extern struct key_desc key_descriptors[RARCH_MAX_KEYS]; + +int setting_action_left_analog_dpad_mode(void *data, bool wraparound) +{ + unsigned port = 0; + rarch_setting_t *setting = (rarch_setting_t*)data; + settings_t *settings = config_get_ptr(); + + if (!setting) + return -1; + + port = setting->index_offset; + + configuration_set_uint(settings, settings->uints.input_analog_dpad_mode[port], + (settings->uints.input_analog_dpad_mode + [port] + ANALOG_DPAD_LAST - 1) % ANALOG_DPAD_LAST); + + return 0; +} + +int setting_action_left_libretro_device_type( + void *data, bool wraparound) +{ + retro_ctx_controller_info_t pad; + unsigned current_device, current_idx, i, devices[128], + types = 0, port = 0; + const struct retro_controller_info *desc = NULL; + rarch_setting_t *setting = (rarch_setting_t*)data; + rarch_system_info_t *system = NULL; + + if (!setting) + return -1; + + port = setting->index_offset; + + devices[types++] = RETRO_DEVICE_NONE; + devices[types++] = RETRO_DEVICE_JOYPAD; + + system = runloop_get_system_info(); + + if (system) + { + /* Only push RETRO_DEVICE_ANALOG as default if we use an + * older core which doesn't use SET_CONTROLLER_INFO. */ + if (!system->ports.size) + devices[types++] = RETRO_DEVICE_ANALOG; + + if (port < system->ports.size) + desc = &system->ports.data[port]; + } + + if (desc) + { + for (i = 0; i < desc->num_types; i++) + { + unsigned id = desc->types[i].id; + if (types < ARRAY_SIZE(devices) && + id != RETRO_DEVICE_NONE && + id != RETRO_DEVICE_JOYPAD) + devices[types++] = id; + } + } + + current_device = input_config_get_device(port); + current_idx = 0; + for (i = 0; i < types; i++) + { + if (current_device != devices[i]) + continue; + + current_idx = i; + break; + } + + current_device = devices + [(current_idx + types - 1) % types]; + + input_config_set_device(port, current_device); + + pad.port = port; + pad.device = current_device; + + core_set_controller_port_device(&pad); + + return 0; +} + +int setting_action_left_bind_device(void *data, bool wraparound) +{ + unsigned *p = NULL; + unsigned index_offset = 0; + unsigned max_devices = input_config_get_device_count(); + rarch_setting_t *setting = (rarch_setting_t*)data; + settings_t *settings = config_get_ptr(); + + if (!setting || max_devices == 0) + return -1; + + index_offset = setting->index_offset; + + p = &settings->uints.input_joypad_map[index_offset]; + + if ((*p) >= max_devices) + *p = max_devices - 1; + else if ((*p) > 0) + (*p)--; + + return 0; +} + +int setting_action_left_mouse_index(void *data, bool wraparound) +{ + rarch_setting_t *setting = (rarch_setting_t*)data; + settings_t *settings = config_get_ptr(); + + if (!setting) + return -1; + + if (settings->uints.input_mouse_index[setting->index_offset]) + { + --settings->uints.input_mouse_index[setting->index_offset]; + settings->modified = true; + } + + return 0; +} + +int setting_uint_action_left_custom_viewport_width( + void *data, bool wraparound) +{ + video_viewport_t vp; + struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); + video_viewport_t *custom = video_viewport_get_custom(); + settings_t *settings = config_get_ptr(); + struct retro_game_geometry *geom = (struct retro_game_geometry*) + &av_info->geometry; + + if (!settings || !av_info) + return -1; + + video_driver_get_viewport_info(&vp); + + if (custom->width <= 1) + custom->width = 1; + else if (settings->bools.video_scale_integer) + { + if (custom->width > geom->base_width) + custom->width -= geom->base_width; + } + else + custom->width -= 1; + + aspectratio_lut[ASPECT_RATIO_CUSTOM].value = + (float)custom->width / custom->height; + + return 0; +} + +int setting_uint_action_left_custom_viewport_height( + void *data, bool wraparound) +{ + video_viewport_t vp; + struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); + video_viewport_t *custom = video_viewport_get_custom(); + settings_t *settings = config_get_ptr(); + struct retro_game_geometry *geom = (struct retro_game_geometry*) + &av_info->geometry; + + if (!settings || !av_info) + return -1; + + video_driver_get_viewport_info(&vp); + + if (custom->height <= 1) + custom->height = 1; + else if (settings->bools.video_scale_integer) + { + if (custom->height > geom->base_height) + custom->height -= geom->base_height; + } + else + custom->height -= 1; + + aspectratio_lut[ASPECT_RATIO_CUSTOM].value = + (float)custom->width / custom->height; + + return 0; +} + +int setting_string_action_left_audio_device( + void *data, bool wraparound) +{ +#if !defined(RARCH_CONSOLE) + int audio_device_index; + struct string_list *ptr = NULL; + rarch_setting_t *setting = (rarch_setting_t*)data; + + if (!audio_driver_get_devices_list((void**)&ptr)) + return -1; + + if (!ptr) + return -1; + + /* Get index in the string list */ + audio_device_index = string_list_find_elem( + ptr, setting->value.target.string) - 1; + audio_device_index--; + + /* Reset index if needed */ + if (audio_device_index < 0) + audio_device_index = (int)(ptr->size - 1); + + strlcpy(setting->value.target.string, ptr->elems[audio_device_index].data, setting->size); +#endif + + return 0; +} + +int setting_string_action_left_driver(void *data, + bool wraparound) +{ + driver_ctx_info_t drv; + rarch_setting_t *setting = (rarch_setting_t*)data; + + if (!setting) + return -1; + + drv.label = setting->name; + drv.s = setting->value.target.string; + drv.len = setting->size; + + if (!driver_ctl(RARCH_DRIVER_CTL_FIND_PREV, &drv)) + { + settings_t *settings = config_get_ptr(); + + if (settings && settings->bools.menu_navigation_wraparound_enable) + { + drv.label = setting->name; + drv.s = setting->value.target.string; + drv.len = setting->size; + driver_ctl(RARCH_DRIVER_CTL_FIND_LAST, &drv); + } + } + + if (setting->change_handler) + setting->change_handler(setting); + + return 0; +} static int generic_shader_action_parameter_left( struct video_shader_parameter *param, @@ -91,38 +342,59 @@ static int action_left_cheat(unsigned type, const char *label, } static int action_left_input_desc(unsigned type, const char *label, - bool wraparound) + bool wraparound) { - unsigned inp_desc_index_offset = type - - MENU_SETTINGS_INPUT_DESC_BEGIN; - unsigned inp_desc_user = inp_desc_index_offset / - (RARCH_FIRST_CUSTOM_BIND + 4); - unsigned inp_desc_button_index_offset = inp_desc_index_offset - - (inp_desc_user * (RARCH_FIRST_CUSTOM_BIND + 4)); + rarch_system_info_t *system = runloop_get_system_info(); settings_t *settings = config_get_ptr(); + unsigned btn_idx, user_idx, remap_idx; - if (settings->uints.input_remap_ids[inp_desc_user][inp_desc_button_index_offset] > 0) - settings->uints.input_remap_ids[inp_desc_user][inp_desc_button_index_offset]--; + if (!settings || !system) + return 0; + + user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); + btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; + + if (settings->uints.input_remap_ids[user_idx][btn_idx] == RARCH_UNMAPPED) + settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_CUSTOM_BIND_LIST_END - 1; + + if (settings->uints.input_remap_ids[user_idx][btn_idx] > 0) + settings->uints.input_remap_ids[user_idx][btn_idx]--; + else if (settings->uints.input_remap_ids[user_idx][btn_idx] == 0) + settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_UNMAPPED; + else + settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_CUSTOM_BIND_LIST_END - 1; + + remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx]; + + /* skip the not used buttons (unless they are at the end by calling the right desc function recursively + also skip all the axes until analog remapping is implemented */ + if ((string_is_empty(system->input_desc_btn[user_idx][remap_idx]) && remap_idx < RARCH_CUSTOM_BIND_LIST_END) /*|| + (remap_idx >= RARCH_FIRST_CUSTOM_BIND && remap_idx < RARCH_CUSTOM_BIND_LIST_END)*/) + action_left_input_desc(type, label, wraparound); return 0; } -#ifdef HAVE_KEYMAPPER static int action_left_input_desc_kbd(unsigned type, const char *label, bool wraparound) { - char desc[PATH_MAX_LENGTH]; - unsigned key_id; unsigned remap_id; - unsigned offset = type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; + unsigned key_id, id, offset; settings_t *settings = config_get_ptr(); if (!settings) return 0; - remap_id = settings->uints.input_keymapper_ids[offset]; + offset = type / ((MENU_SETTINGS_INPUT_DESC_KBD_END - + (MENU_SETTINGS_INPUT_DESC_KBD_END - + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN))) - 1; - for (key_id = 0; key_id < MENU_SETTINGS_INPUT_DESC_KBD_END - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; key_id++) + id = (type / (offset + 1)) - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; + + remap_id = + settings->uints.input_keymapper_ids[offset][id]; + + for (key_id = 0; key_id < RARCH_MAX_KEYS - 1; key_id++) { if(remap_id == key_descriptors[key_id].key) break; @@ -131,13 +403,12 @@ static int action_left_input_desc_kbd(unsigned type, const char *label, if (key_id > 0) key_id--; else - key_id = MENU_SETTINGS_INPUT_DESC_KBD_END - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; + key_id = (RARCH_MAX_KEYS - 1) + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; - settings->uints.input_keymapper_ids[offset] = key_descriptors[key_id].key; + settings->uints.input_keymapper_ids[offset][id] = key_descriptors[key_id].key; return 0; } -#endif static int action_left_scroll(unsigned type, const char *label, bool wraparound) @@ -609,13 +880,11 @@ static int menu_cbs_init_bind_left_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_LEFT(cbs, action_left_input_desc); } -#ifdef HAVE_KEYMAPPER else if (type >= MENU_SETTINGS_INPUT_DESC_KBD_BEGIN && type <= MENU_SETTINGS_INPUT_DESC_KBD_END) { BIND_ACTION_LEFT(cbs, action_left_input_desc_kbd); } -#endif else if ((type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START)) { BIND_ACTION_LEFT(cbs, playlist_association_left); diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index da369491e7..ff85e2c327 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -26,13 +26,21 @@ #include "../../config.h" #endif +#include "../../config.def.h" +#include "../../config.def.keybinds.h" +#include "../../wifi/wifi_driver.h" +#include "../../driver.h" + #include "../menu_driver.h" #include "../menu_cbs.h" #include "../menu_setting.h" #include "../menu_shader.h" #include "../widgets/menu_dialog.h" +#include "../widgets/menu_entry.h" #include "../widgets/menu_filebrowser.h" #include "../widgets/menu_input_dialog.h" +#include "../widgets/menu_input_bind_dialog.h" +#include "../menu_input.h" #include "../menu_networking.h" #include "../menu_content.h" #include "../menu_shader.h" @@ -121,6 +129,120 @@ static char *lakka_get_project(void) info.enum_idx = a; \ dl_type = b; +int setting_action_ok_video_refresh_rate_auto(void *data, bool wraparound) +{ + double video_refresh_rate = 0.0; + double deviation = 0.0; + unsigned sample_points = 0; + rarch_setting_t *setting = (rarch_setting_t*)data; + + if (!setting) + return -1; + + if (video_monitor_fps_statistics(&video_refresh_rate, + &deviation, &sample_points)) + { + float video_refresh_rate_float = (float)video_refresh_rate; + driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &video_refresh_rate_float); + /* Incase refresh rate update forced non-block video. */ + command_event(CMD_EVENT_VIDEO_SET_BLOCKING_STATE, NULL); + } + + if (setting_generic_action_ok_default(setting, wraparound) != 0) + return -1; + + return 0; +} + +int setting_action_ok_video_refresh_rate_polled(void *data, bool wraparound) +{ + rarch_setting_t *setting = (rarch_setting_t*)data; + float refresh_rate = 0.0; + + if (!setting) + return -1; + + if ((refresh_rate = video_driver_get_refresh_rate()) == 0.0) + return -1; + + driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &refresh_rate); + /* Incase refresh rate update forced non-block video. */ + command_event(CMD_EVENT_VIDEO_SET_BLOCKING_STATE, NULL); + + if (setting_generic_action_ok_default(setting, wraparound) != 0) + return -1; + + return 0; +} + +int setting_action_ok_bind_all(void *data, bool wraparound) +{ + (void)wraparound; + if (!menu_input_key_bind_set_mode(MENU_INPUT_BINDS_CTL_BIND_ALL, data)) + return -1; + return 0; +} + +int setting_action_ok_bind_all_save_autoconfig(void *data, + bool wraparound) +{ + unsigned index_offset; + rarch_setting_t *setting = (rarch_setting_t*)data; + const char *name = NULL; + + (void)wraparound; + + if (!setting) + return -1; + + index_offset = setting->index_offset; + name = input_config_get_device_name(index_offset); + + if(!string_is_empty(name) && config_save_autoconf_profile(name, index_offset)) + runloop_msg_queue_push( + msg_hash_to_str(MSG_AUTOCONFIG_FILE_SAVED_SUCCESSFULLY), 1, 100, true); + else + runloop_msg_queue_push( + msg_hash_to_str(MSG_AUTOCONFIG_FILE_ERROR_SAVING), 1, 100, true); + + + return 0; +} + +int setting_action_ok_bind_defaults(void *data, bool wraparound) +{ + unsigned i; + menu_input_ctx_bind_limits_t lim; + struct retro_keybind *target = NULL; + const struct retro_keybind *def_binds = NULL; + rarch_setting_t *setting = (rarch_setting_t*)data; + + (void)wraparound; + + if (!setting) + return -1; + + target = &input_config_binds[setting->index_offset][0]; + def_binds = (setting->index_offset) ? + retro_keybinds_rest : retro_keybinds_1; + + lim.min = MENU_SETTINGS_BIND_BEGIN; + lim.max = MENU_SETTINGS_BIND_LAST; + + menu_input_key_bind_set_min_max(&lim); + + for (i = MENU_SETTINGS_BIND_BEGIN; + i <= MENU_SETTINGS_BIND_LAST; i++, target++) + { + target->key = def_binds[i - MENU_SETTINGS_BIND_BEGIN].key; + target->joykey = NO_BTN; + target->joyaxis = AXIS_NONE; + target->mbutton = NO_BTN; + } + + return 0; +} + static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl) { switch (lbl) @@ -129,6 +251,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl) return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_LIST; case ACTION_OK_DL_INPUT_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_INPUT_SETTINGS_LIST; + case ACTION_OK_DL_LATENCY_SETTINGS_LIST: + return MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST; case ACTION_OK_DL_DRIVER_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_DRIVER_SETTINGS_LIST; case ACTION_OK_DL_CORE_SETTINGS_LIST: @@ -676,6 +800,7 @@ int generic_action_ok_displaylist_push(const char *path, break; case ACTION_OK_DL_ACCOUNTS_LIST: case ACTION_OK_DL_INPUT_SETTINGS_LIST: + case ACTION_OK_DL_LATENCY_SETTINGS_LIST: case ACTION_OK_DL_DRIVER_SETTINGS_LIST: case ACTION_OK_DL_CORE_SETTINGS_LIST: case ACTION_OK_DL_VIDEO_SETTINGS_LIST: @@ -882,7 +1007,9 @@ static void content_add_to_playlist(const char *path) task_push_dbscan( settings->paths.directory_playlist, settings->paths.path_content_database, - path, false, handle_dbscan_finished); + path, false, + settings->bools.show_hidden_files, + handle_dbscan_finished); #endif } @@ -1388,9 +1515,8 @@ static int action_ok_playlist_entry_collection(const char *path, if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) return menu_cbs_exit(); - new_core_path[0] = '\0'; - - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &tmp_playlist); + new_core_path[0] = '\0'; + tmp_playlist = playlist_get_cached(); if (!tmp_playlist) { @@ -1437,17 +1563,18 @@ static int action_ok_playlist_entry_collection(const char *path, return ret; } - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &tmp_playlist); + tmp_playlist = playlist_get_cached(); - command_playlist_update_write( - tmp_playlist, - selection_ptr, - NULL, - NULL, - new_core_path, - core_info.inf->display_name, - NULL, - NULL); + if (tmp_playlist) + command_playlist_update_write( + tmp_playlist, + selection_ptr, + NULL, + NULL, + new_core_path, + core_info.inf->display_name, + NULL, + NULL); } else strlcpy(new_core_path, core_path, sizeof(new_core_path)); @@ -1457,6 +1584,8 @@ static int action_ok_playlist_entry_collection(const char *path, runloop_msg_queue_push( "File could not be loaded from playlist.\n", 1, 100, true); + if (playlist_initialized) + playlist_free(tmp_playlist); return menu_cbs_exit(); } @@ -1545,32 +1674,18 @@ static int action_ok_playlist_entry_start_content(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { size_t selection_ptr = 0; - bool playlist_initialized = false; - playlist_t *playlist = NULL; const char *entry_path = NULL; const char *entry_label = NULL; const char *core_path = NULL; const char *core_name = NULL; - playlist_t *tmp_playlist = NULL; menu_handle_t *menu = NULL; + playlist_t *playlist = playlist_get_cached(); - if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) + if ( !playlist || + !menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) return menu_cbs_exit(); - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &tmp_playlist); - - if (!tmp_playlist) - { - tmp_playlist = playlist_init( - menu->db_playlist_file, COLLECTION_SIZE); - - if (!tmp_playlist) - return menu_cbs_exit(); - playlist_initialized = true; - } - - playlist = tmp_playlist; - selection_ptr = menu->rdb_entry_start_game_selection_ptr; + selection_ptr = menu->rdb_entry_start_game_selection_ptr; playlist_get_index(playlist, selection_ptr, &entry_path, &entry_label, &core_path, &core_name, NULL, NULL); @@ -1597,21 +1712,16 @@ static int action_ok_playlist_entry_start_content(const char *path, if (!core_info_find(&core_info, new_core_path)) found_associated_core = false; + /* TODO: figure out if this should refer to + * the inner or outer entry_path. */ + /* TODO: make sure there's only one entry_path + * in this function. */ if (!found_associated_core) - { - /* TODO: figure out if this should refer to the inner or outer entry_path */ - /* TODO: make sure there's only one entry_path in this function */ - int ret = action_ok_file_load_with_detect_core(entry_path, + return action_ok_file_load_with_detect_core(entry_path, label, type, selection_ptr, entry_idx); - if (playlist_initialized) - playlist_free(tmp_playlist); - return ret; - } - - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &tmp_playlist); command_playlist_update_write( - tmp_playlist, + playlist, selection_ptr, NULL, NULL, @@ -1619,19 +1729,21 @@ static int action_ok_playlist_entry_start_content(const char *path, core_info.inf->display_name, NULL, NULL); - } - if (!playlist || !menu_content_playlist_load(playlist, selection_ptr)) + if (!menu_content_playlist_load(playlist, selection_ptr)) { runloop_msg_queue_push("File could not be loaded from playlist.\n", 1, 100, true); - return menu_cbs_exit(); + goto error; } playlist_get_index(playlist, selection_ptr, &path, NULL, NULL, NULL, NULL, NULL); return default_action_ok_load_content_from_playlist_from_menu(core_path, path, entry_label); + +error: + return menu_cbs_exit(); } static int action_ok_lookup_setting(const char *path, @@ -1644,8 +1756,7 @@ static int action_ok_audio_add_to_mixer(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { const char *entry_path = NULL; - playlist_t *tmp_playlist = NULL; - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &tmp_playlist); + playlist_t *tmp_playlist = playlist_get_cached(); if (!tmp_playlist) return -1; @@ -2158,17 +2269,28 @@ static int action_ok_path_scan_directory(const char *path, static int action_ok_core_deferred_set(const char *new_core_path, const char *content_label, unsigned type, size_t idx, size_t entry_idx) { + char ext_name[255]; char core_display_name[PATH_MAX_LENGTH]; + settings_t *settings = config_get_ptr(); menu_handle_t *menu = NULL; size_t selection = menu_navigation_get_selection(); + ext_name[0] = '\0'; + if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) return menu_cbs_exit(); + if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name))) + return menu_cbs_exit(); + core_display_name[0] = '\0'; core_info_get_name(new_core_path, - core_display_name, sizeof(core_display_name)); + core_display_name, sizeof(core_display_name), + settings->paths.path_libretro_info, + settings->paths.directory_libretro, + ext_name, + settings->bools.show_hidden_files); command_playlist_update_write( NULL, menu->rdb_entry_start_game_selection_ptr, @@ -2865,16 +2987,13 @@ static int action_ok_reset_core_association(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { const char *tmp_path = NULL; - playlist_t *tmp_playlist = NULL; menu_handle_t *menu = NULL; - - if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) - return menu_cbs_exit(); - - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &tmp_playlist); + playlist_t *tmp_playlist = playlist_get_cached(); if (!tmp_playlist) return 0; + if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) + return menu_cbs_exit(); playlist_get_index(tmp_playlist, menu->rpl_entry_selection_ptr, @@ -2899,16 +3018,13 @@ static int action_ok_add_to_favorites_playlist(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { const char *tmp_path = NULL; - playlist_t *tmp_playlist = NULL; menu_handle_t *menu = NULL; - - if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) - return menu_cbs_exit(); - - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &tmp_playlist); + playlist_t *tmp_playlist = playlist_get_cached(); if (!tmp_playlist) return 0; + if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) + return menu_cbs_exit(); playlist_get_index(tmp_playlist, menu->rpl_entry_selection_ptr, &tmp_path, @@ -2924,7 +3040,6 @@ static int action_ok_delete_entry(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { size_t new_selection_ptr; - playlist_t *playlist = NULL; char *conf_path = NULL; char *def_conf_path = NULL; char *def_conf_music_path = NULL; @@ -2935,12 +3050,11 @@ static int action_ok_delete_entry(const char *path, char *def_conf_img_path = NULL; #endif menu_handle_t *menu = NULL; + playlist_t *playlist = playlist_get_cached(); if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) return menu_cbs_exit(); - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &playlist); - conf_path = playlist_get_conf_path(playlist); def_conf_path = playlist_get_conf_path(g_defaults.content_history); def_conf_music_path = playlist_get_conf_path(g_defaults.music_history); @@ -3108,6 +3222,7 @@ default_action_ok_func(action_ok_push_configuration_settings_list, ACTION_OK_DL_ default_action_ok_func(action_ok_push_core_settings_list, ACTION_OK_DL_CORE_SETTINGS_LIST) default_action_ok_func(action_ok_push_audio_settings_list, ACTION_OK_DL_AUDIO_SETTINGS_LIST) default_action_ok_func(action_ok_push_input_settings_list, ACTION_OK_DL_INPUT_SETTINGS_LIST) +default_action_ok_func(action_ok_push_latency_settings_list, ACTION_OK_DL_LATENCY_SETTINGS_LIST) default_action_ok_func(action_ok_push_recording_settings_list, ACTION_OK_DL_RECORDING_SETTINGS_LIST) default_action_ok_func(action_ok_push_playlist_settings_list, ACTION_OK_DL_PLAYLIST_SETTINGS_LIST) default_action_ok_func(action_ok_push_input_hotkey_binds_list, ACTION_OK_DL_INPUT_HOTKEY_BINDS_LIST) @@ -4107,6 +4222,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_AUDIO_SETTINGS: BIND_ACTION_OK(cbs, action_ok_push_audio_settings_list); break; + case MENU_ENUM_LABEL_LATENCY_SETTINGS: + BIND_ACTION_OK(cbs, action_ok_push_latency_settings_list); + break; case MENU_ENUM_LABEL_CORE_SETTINGS: BIND_ACTION_OK(cbs, action_ok_push_core_settings_list); break; diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index 9469cbc98b..82b287240e 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -48,7 +48,7 @@ } while(0) #endif -extern struct key_desc key_descriptors[MENU_SETTINGS_INPUT_DESC_KBD_END]; +extern struct key_desc key_descriptors[RARCH_MAX_KEYS]; static int generic_shader_action_parameter_right(struct video_shader_parameter *param, unsigned type, const char *label, bool wraparound) @@ -101,58 +101,78 @@ int action_right_cheat(unsigned type, const char *label, wraparound); } -#ifdef HAVE_KEYMAPPER int action_right_input_desc_kbd(unsigned type, const char *label, bool wraparound) { - unsigned key_id; + unsigned key_id, id, offset; unsigned remap_id; - char desc[PATH_MAX_LENGTH]; - unsigned offset = type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; settings_t *settings = config_get_ptr(); if (!settings) return 0; - remap_id = settings->uints.input_keymapper_ids[offset]; + offset = type / ((MENU_SETTINGS_INPUT_DESC_KBD_END - + (MENU_SETTINGS_INPUT_DESC_KBD_END - + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN))) - 1; - for (key_id = 0; key_id < MENU_SETTINGS_INPUT_DESC_KBD_END - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; key_id++) + id = (type / (offset + 1)) - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN; + + remap_id = + settings->uints.input_keymapper_ids[offset][id]; + + for (key_id = 0; key_id < RARCH_MAX_KEYS - 1; key_id++) { if(remap_id == key_descriptors[key_id].key) break; } - if (key_id < MENU_SETTINGS_INPUT_DESC_KBD_END - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) + if (key_id < (RARCH_MAX_KEYS - 1) + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) key_id++; else key_id = 0; - settings->uints.input_keymapper_ids[offset] = key_descriptors[key_id].key; + settings->uints.input_keymapper_ids[offset][id] = key_descriptors[key_id].key; return 0; } -#endif +/* fix-me: incomplete, lacks error checking */ int action_right_input_desc(unsigned type, const char *label, bool wraparound) { -unsigned inp_desc_index_offset = type - MENU_SETTINGS_INPUT_DESC_BEGIN; -unsigned inp_desc_user = inp_desc_index_offset / (RARCH_FIRST_CUSTOM_BIND + 4); -unsigned inp_desc_button_index_offset = inp_desc_index_offset - (inp_desc_user * (RARCH_FIRST_CUSTOM_BIND + 4)); -settings_t *settings = config_get_ptr(); + rarch_system_info_t *system = runloop_get_system_info(); + settings_t *settings = config_get_ptr(); + unsigned btn_idx, user_idx, remap_idx; -if (inp_desc_button_index_offset < RARCH_FIRST_CUSTOM_BIND) -{ - if (settings->uints.input_remap_ids[inp_desc_user][inp_desc_button_index_offset] < RARCH_FIRST_CUSTOM_BIND - 1) - settings->uints.input_remap_ids[inp_desc_user][inp_desc_button_index_offset]++; -} -else -{ - if (settings->uints.input_remap_ids[inp_desc_user][inp_desc_button_index_offset] < 4 - 1) - settings->uints.input_remap_ids[inp_desc_user][inp_desc_button_index_offset]++; -} + if (!settings || !system) + return 0; -return 0; + user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); + btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; + + if (settings->uints.input_remap_ids[user_idx][btn_idx] < RARCH_CUSTOM_BIND_LIST_END - 1) + settings->uints.input_remap_ids[user_idx][btn_idx]++; + else if (settings->uints.input_remap_ids[user_idx][btn_idx] == RARCH_CUSTOM_BIND_LIST_END - 1) + settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_UNMAPPED; + else + settings->uints.input_remap_ids[user_idx][btn_idx] = 0; + + remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx]; + + /* skip the not used buttons (unless they are at the end by calling the right desc function recursively + also skip all the axes until analog remapping is implemented */ + if ((string_is_empty(system->input_desc_btn[user_idx][remap_idx]) && remap_idx < RARCH_CUSTOM_BIND_LIST_END) /*|| + (remap_idx >= RARCH_FIRST_CUSTOM_BIND && remap_idx < RARCH_CUSTOM_BIND_LIST_END)*/) + action_right_input_desc(type, label, wraparound); + +#if 0 + int i = 0; + //RARCH_LOG("[remap-debug] new descriptor for %d: %s\n", remap_idx, system->input_desc_btn[user_idx][remap_idx]); + for (i = 0; i < RARCH_ANALOG_BIND_LIST_END; i++) + RARCH_LOG("[remap-debug]: user %d button %d new id %d\n", user_idx, i, settings->uints.input_remap_ids[user_idx][i]); +#endif + + return 0; } static int action_right_scroll(unsigned type, const char *label, @@ -478,13 +498,11 @@ static int menu_cbs_init_bind_right_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_RIGHT(cbs, action_right_input_desc); } -#ifdef HAVE_KEYMAPPER else if (type >= MENU_SETTINGS_INPUT_DESC_KBD_BEGIN && type <= MENU_SETTINGS_INPUT_DESC_KBD_END) { BIND_ACTION_RIGHT(cbs, action_right_input_desc_kbd); } -#endif else if ((type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START)) { BIND_ACTION_RIGHT(cbs, playlist_association_right); diff --git a/menu/cbs/menu_cbs_scan.c b/menu/cbs/menu_cbs_scan.c index ed7fc081c1..150f226fa3 100644 --- a/menu/cbs/menu_cbs_scan.c +++ b/menu/cbs/menu_cbs_scan.c @@ -64,7 +64,9 @@ int action_scan_file(const char *path, task_push_dbscan( settings->paths.directory_playlist, settings->paths.path_content_database, - fullpath, false, handle_dbscan_finished); + fullpath, false, + settings->bools.show_hidden_files, + handle_dbscan_finished); return 0; } @@ -90,7 +92,9 @@ int action_scan_directory(const char *path, task_push_dbscan( settings->paths.directory_playlist, settings->paths.path_content_database, - fullpath, true, handle_dbscan_finished); + fullpath, true, + settings->bools.show_hidden_files, + handle_dbscan_finished); return 0; } @@ -104,14 +108,22 @@ int action_switch_thumbnail(const char *path, if (!settings) return -1; - settings->uints.menu_thumbnails++; - - if (settings->uints.menu_thumbnails > 3) - settings->uints.menu_thumbnails = 0; - - menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); - menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); - + if (settings->uints.menu_thumbnails == 0) + { + settings->uints.menu_left_thumbnails++; + if (settings->uints.menu_left_thumbnails > 3) + settings->uints.menu_left_thumbnails = 1; + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); + } + else + { + settings->uints.menu_thumbnails++; + if (settings->uints.menu_thumbnails > 3) + settings->uints.menu_thumbnails = 1; + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); + } return 0; } diff --git a/menu/cbs/menu_cbs_select.c b/menu/cbs/menu_cbs_select.c index 0246455d0d..7a6bc5e047 100644 --- a/menu/cbs/menu_cbs_select.c +++ b/menu/cbs/menu_cbs_select.c @@ -146,14 +146,12 @@ static int action_select_input_desc(const char *path, const char *label, unsigne return action_right_input_desc(type, label, true); } -#ifdef HAVE_KEYMAPPER static int action_select_input_desc_kbd(const char *path, const char *label, unsigned type, size_t idx) { return action_right_input_desc_kbd(type, label, true); } -#endif #ifdef HAVE_NETWORKING static int action_select_netplay_connect_room(const char *path, @@ -223,13 +221,11 @@ static int menu_cbs_init_bind_select_compare_type( { BIND_ACTION_SELECT(cbs, action_select_input_desc); } -#ifdef HAVE_KEYMAPPER else if (type >= MENU_SETTINGS_INPUT_DESC_KBD_BEGIN && type <= MENU_SETTINGS_INPUT_DESC_KBD_END) { BIND_ACTION_SELECT(cbs, action_select_input_desc_kbd); } -#endif else { diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 23d511aabd..7361b6f8a2 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -39,6 +39,7 @@ #include "../../retroarch.h" #include "../../content.h" +#include "../../configuration.h" #define default_sublabel_macro(func_name, lbl) \ static int (func_name)(file_list_t *list, unsigned type, unsigned i, const char *label, const char *path, char *s, size_t len) \ @@ -47,6 +48,8 @@ return 0; \ } +default_sublabel_macro(action_bind_sublabel_crt_switchres, MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION) +default_sublabel_macro(action_bind_sublabel_crt_switchres_super, MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER) default_sublabel_macro(action_bind_sublabel_automatically_add_content_to_playlist, MENU_ENUM_SUBLABEL_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST) default_sublabel_macro(action_bind_sublabel_driver_settings_list, MENU_ENUM_SUBLABEL_DRIVER_SETTINGS) default_sublabel_macro(action_bind_sublabel_retro_achievements_settings_list, MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS) @@ -78,6 +81,7 @@ default_sublabel_macro(action_bind_sublabel_suspend_screensaver_enable, MENU_ default_sublabel_macro(action_bind_sublabel_video_window_scale, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_SCALE) default_sublabel_macro(action_bind_sublabel_audio_settings_list, MENU_ENUM_SUBLABEL_AUDIO_SETTINGS) default_sublabel_macro(action_bind_sublabel_input_settings_list, MENU_ENUM_SUBLABEL_INPUT_SETTINGS) +default_sublabel_macro(action_bind_sublabel_latency_settings_list, MENU_ENUM_SUBLABEL_LATENCY_SETTINGS) default_sublabel_macro(action_bind_sublabel_wifi_settings_list, MENU_ENUM_SUBLABEL_WIFI_SETTINGS) default_sublabel_macro(action_bind_sublabel_netplay_lan_scan_settings_list,MENU_ENUM_SUBLABEL_NETPLAY_LAN_SCAN_SETTINGS) default_sublabel_macro(action_bind_sublabel_help_list, MENU_ENUM_SUBLABEL_HELP_LIST) @@ -131,6 +135,7 @@ default_sublabel_macro(action_bind_sublabel_core_allow_rotate, MENU_ default_sublabel_macro(action_bind_sublabel_dummy_on_core_shutdown, MENU_ENUM_SUBLABEL_DUMMY_ON_CORE_SHUTDOWN) default_sublabel_macro(action_bind_sublabel_dummy_check_missing_firmware, MENU_ENUM_SUBLABEL_CHECK_FOR_MISSING_FIRMWARE) default_sublabel_macro(action_bind_sublabel_video_refresh_rate, MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE) +default_sublabel_macro(action_bind_sublabel_video_refresh_rate_polled, MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_POLLED) default_sublabel_macro(action_bind_sublabel_audio_enable, MENU_ENUM_SUBLABEL_AUDIO_ENABLE) default_sublabel_macro(action_bind_sublabel_audio_max_timing_skew, MENU_ENUM_SUBLABEL_AUDIO_MAX_TIMING_SKEW) default_sublabel_macro(action_bind_sublabel_pause_nonactive, MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE) @@ -172,6 +177,9 @@ default_sublabel_macro(action_bind_sublabel_savestate_auto_index, MENU_ default_sublabel_macro(action_bind_sublabel_block_sram_overwrite, MENU_ENUM_SUBLABEL_BLOCK_SRAM_OVERWRITE) default_sublabel_macro(action_bind_sublabel_fastforward_ratio, MENU_ENUM_SUBLABEL_FASTFORWARD_RATIO) default_sublabel_macro(action_bind_sublabel_slowmotion_ratio, MENU_ENUM_SUBLABEL_SLOWMOTION_RATIO) +default_sublabel_macro(action_bind_sublabel_run_ahead_enabled, MENU_ENUM_SUBLABEL_RUN_AHEAD_ENABLED) +default_sublabel_macro(action_bind_sublabel_run_ahead_secondary_instance, MENU_ENUM_SUBLABEL_RUN_AHEAD_SECONDARY_INSTANCE) +default_sublabel_macro(action_bind_sublabel_run_ahead_frames, MENU_ENUM_SUBLABEL_RUN_AHEAD_FRAMES) default_sublabel_macro(action_bind_sublabel_rewind, MENU_ENUM_SUBLABEL_REWIND_ENABLE) default_sublabel_macro(action_bind_sublabel_rewind_granularity, MENU_ENUM_SUBLABEL_REWIND_GRANULARITY) default_sublabel_macro(action_bind_sublabel_libretro_log_level, MENU_ENUM_SUBLABEL_LIBRETRO_LOG_LEVEL) @@ -222,6 +230,7 @@ default_sublabel_macro(action_bind_sublabel_stdin_cmd_enable, MENU_ default_sublabel_macro(action_bind_sublabel_mouse_enable, MENU_ENUM_SUBLABEL_MOUSE_ENABLE) default_sublabel_macro(action_bind_sublabel_pointer_enable, MENU_ENUM_SUBLABEL_POINTER_ENABLE) default_sublabel_macro(action_bind_sublabel_thumbnails, MENU_ENUM_SUBLABEL_THUMBNAILS) +default_sublabel_macro(action_bind_sublabel_left_thumbnails, MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS) default_sublabel_macro(action_bind_sublabel_timedate_enable, MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE) default_sublabel_macro(action_bind_sublabel_battery_level_enable, MENU_ENUM_SUBLABEL_BATTERY_LEVEL_ENABLE) default_sublabel_macro(action_bind_sublabel_navigation_wraparound, MENU_ENUM_SUBLABEL_NAVIGATION_WRAPAROUND) @@ -291,8 +300,10 @@ default_sublabel_macro(action_bind_sublabel_disk_image_append, default_sublabel_macro(action_bind_sublabel_disk_index, MENU_ENUM_SUBLABEL_DISK_INDEX) default_sublabel_macro(action_bind_sublabel_disk_options, MENU_ENUM_SUBLABEL_DISK_OPTIONS) default_sublabel_macro(action_bind_sublabel_menu_throttle_framerate, MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE) +default_sublabel_macro(action_bind_sublabel_xmb_layout, MENU_ENUM_SUBLABEL_XMB_LAYOUT) default_sublabel_macro(action_bind_sublabel_xmb_icon_theme, MENU_ENUM_SUBLABEL_XMB_THEME) default_sublabel_macro(action_bind_sublabel_xmb_shadows_enable, MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE) +default_sublabel_macro(action_bind_sublabel_xmb_vertical_thumbnails, MENU_ENUM_SUBLABEL_XMB_VERTICAL_THUMBNAILS) default_sublabel_macro(action_bind_sublabel_menu_color_theme, MENU_ENUM_SUBLABEL_MATERIALUI_MENU_COLOR_THEME) default_sublabel_macro(action_bind_sublabel_menu_wallpaper_opacity, MENU_ENUM_SUBLABEL_MENU_WALLPAPER_OPACITY) default_sublabel_macro(action_bind_sublabel_menu_framebuffer_opacity, MENU_ENUM_SUBLABEL_MENU_FRAMEBUFFER_OPACITY) @@ -306,6 +317,9 @@ default_sublabel_macro(action_bind_sublabel_quick_menu_show_options, default_sublabel_macro(action_bind_sublabel_quick_menu_show_controls, MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CONTROLS) default_sublabel_macro(action_bind_sublabel_quick_menu_show_cheats, MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CHEATS) default_sublabel_macro(action_bind_sublabel_quick_menu_show_shaders, MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SHADERS) +default_sublabel_macro(action_bind_sublabel_content_show_overlays, MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS) +default_sublabel_macro(action_bind_sublabel_content_show_rewind, MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND) +default_sublabel_macro(action_bind_sublabel_content_show_latency, MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY) default_sublabel_macro(action_bind_sublabel_quick_menu_show_save_core_overrides, MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES) default_sublabel_macro(action_bind_sublabel_quick_menu_show_save_game_overrides, MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES) default_sublabel_macro(action_bind_sublabel_quick_menu_show_information, MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_INFORMATION) @@ -330,6 +344,7 @@ default_sublabel_macro(action_bind_sublabel_menu_settings_tab, default_sublabel_macro(action_bind_sublabel_menu_settings_tab_enable_password, MENU_ENUM_SUBLABEL_CONTENT_SHOW_SETTINGS_PASSWORD) default_sublabel_macro(action_bind_sublabel_menu_history_tab, MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY) default_sublabel_macro(action_bind_sublabel_menu_import_content_tab, MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD) +default_sublabel_macro(action_bind_sublabel_menu_playlist_tabs, MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS) default_sublabel_macro(action_bind_sublabel_main_menu_enable_settings, MENU_ENUM_SUBLABEL_XMB_MAIN_MENU_ENABLE_SETTINGS) default_sublabel_macro(action_bind_sublabel_rgui_show_start_screen, MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN) default_sublabel_macro(action_bind_sublabel_menu_header_opacity, MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY) @@ -407,20 +422,65 @@ static int action_bind_sublabel_subsystem_add( const char *label, const char *path, char *s, size_t len) { - rarch_system_info_t *system = runloop_get_system_info(); - const struct retro_subsystem_info* subsystem = NULL; - subsystem = system->subsystem.data + (type - MENU_SETTINGS_SUBSYSTEM_ADD); + rarch_system_info_t *system = runloop_get_system_info(); + const struct retro_subsystem_info *subsystem = system ? + system->subsystem.data + (type - MENU_SETTINGS_SUBSYSTEM_ADD) : NULL; if (subsystem && content_get_subsystem_rom_id() < subsystem->num_roms) snprintf(s, len, " Current Content: %s", - content_get_subsystem() == type - MENU_SETTINGS_SUBSYSTEM_ADD - ? subsystem->roms[content_get_subsystem_rom_id()].desc + content_get_subsystem() == type - MENU_SETTINGS_SUBSYSTEM_ADD + ? subsystem->roms[content_get_subsystem_rom_id()].desc : subsystem->roms[0].desc); return 0; } +static int action_bind_sublabel_remap_kbd_sublabel( + file_list_t *list, + unsigned type, unsigned i, + const char *label, const char *path, + char *s, size_t len) +{ + unsigned offset; + settings_t *settings = config_get_ptr(); + if (!settings) + return 0; + + offset = type / ((MENU_SETTINGS_INPUT_DESC_KBD_END - + (MENU_SETTINGS_INPUT_DESC_KBD_END - + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN))) - 1; + + snprintf(s, len, "User #%d: %s", offset + 1, + input_config_get_device_display_name(offset) ? + input_config_get_device_display_name(offset) : + (input_config_get_device_name(offset) ? + input_config_get_device_name(offset) : "N/A")); + return 0; +} + + +static int action_bind_sublabel_remap_sublabel( + file_list_t *list, + unsigned type, unsigned i, + const char *label, const char *path, + char *s, size_t len) +{ + unsigned offset; + settings_t *settings = config_get_ptr(); + + if (!settings) + return 0; + + offset = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); + + snprintf(s, len, "User #%d: %s", offset + 1, + input_config_get_device_display_name(offset) ? + input_config_get_device_display_name(offset) : + (input_config_get_device_name(offset) ? + input_config_get_device_name(offset) : "N/A")); + return 0; +} #ifdef HAVE_NETWORKING static int action_bind_sublabel_netplay_room( @@ -480,10 +540,28 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_generic); + if (type >= MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + && type <= MENU_SETTINGS_INPUT_DESC_KBD_END) + { + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_remap_kbd_sublabel); + } + + if (type >= MENU_SETTINGS_INPUT_DESC_BEGIN + && type <= MENU_SETTINGS_INPUT_DESC_END) + { + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_remap_sublabel); + } + if (cbs->enum_idx != MSG_UNKNOWN) { switch (cbs->enum_idx) { + case MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_crt_switchres); + break; + case MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION_SUPER: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_crt_switchres_super); + break; case MENU_ENUM_LABEL_AUDIO_RESAMPLER_QUALITY: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_audio_resampler_quality); break; @@ -634,6 +712,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_CONTENT_SHOW_ADD: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_import_content_tab); break; + case MENU_ENUM_LABEL_CONTENT_SHOW_PLAYLISTS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_playlist_tabs); + break; case MENU_ENUM_LABEL_XMB_MAIN_MENU_ENABLE_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_main_menu_enable_settings); break; @@ -679,6 +760,15 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_QUICK_MENU_SHOW_CHEATS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_quick_menu_show_cheats); break; + case MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_show_latency); + break; + case MENU_ENUM_LABEL_CONTENT_SHOW_REWIND: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_show_rewind); + break; + case MENU_ENUM_LABEL_CONTENT_SHOW_OVERLAYS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_show_overlays); + break; case MENU_ENUM_LABEL_QUICK_MENU_SHOW_SHADERS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_quick_menu_show_shaders); break; @@ -761,6 +851,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_XMB_SHADOWS_ENABLE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_xmb_shadows_enable); break; + case MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_xmb_vertical_thumbnails); + break; + case MENU_ENUM_LABEL_XMB_LAYOUT: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_xmb_layout); + break; case MENU_ENUM_LABEL_XMB_THEME: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_xmb_icon_theme); break; @@ -959,6 +1055,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_THUMBNAILS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_thumbnails); break; + case MENU_ENUM_LABEL_LEFT_THUMBNAILS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_left_thumbnails); + break; case MENU_ENUM_LABEL_MOUSE_ENABLE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_mouse_enable); break; @@ -1109,6 +1208,15 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_SLOWMOTION_RATIO: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_slowmotion_ratio); break; + case MENU_ENUM_LABEL_RUN_AHEAD_ENABLED: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_run_ahead_enabled); + break; + case MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_run_ahead_secondary_instance); + break; + case MENU_ENUM_LABEL_RUN_AHEAD_FRAMES: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_run_ahead_frames); + break; case MENU_ENUM_LABEL_FASTFORWARD_RATIO: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_fastforward_ratio); break; @@ -1341,6 +1449,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_AUTO: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_refresh_rate_auto); break; + case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_refresh_rate_polled); + break; case MENU_ENUM_LABEL_VIDEO_MONITOR_INDEX: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_monitor_index); break; @@ -1419,6 +1530,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_AUDIO_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_audio_settings_list); break; + case MENU_ENUM_LABEL_LATENCY_SETTINGS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_latency_settings_list); + break; case MENU_ENUM_LABEL_RECORDING_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_recording_settings_list); break; diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index c5f99e6dc6..0396b7826c 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -125,6 +125,7 @@ default_title_macro(action_get_privacy_settings_list, MENU_ENUM_LABEL_ default_title_macro(action_get_updater_settings_list, MENU_ENUM_LABEL_VALUE_UPDATER_SETTINGS) default_title_macro(action_get_audio_settings_list, MENU_ENUM_LABEL_VALUE_AUDIO_SETTINGS) default_title_macro(action_get_input_settings_list, MENU_ENUM_LABEL_VALUE_INPUT_SETTINGS) +default_title_macro(action_get_latency_settings_list, MENU_ENUM_LABEL_VALUE_LATENCY_SETTINGS) default_title_macro(action_get_core_cheat_options_list, MENU_ENUM_LABEL_VALUE_CORE_CHEAT_OPTIONS) default_title_macro(action_get_load_content_list, MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST) default_title_macro(action_get_load_content_special, MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_SPECIAL) @@ -475,6 +476,11 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, BIND_ACTION_GET_TITLE(cbs, action_get_audio_settings_list); return 0; } + else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST))) + { + BIND_ACTION_GET_TITLE(cbs, action_get_latency_settings_list); + return 0; + } else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SYSTEM_INFORMATION))) { BIND_ACTION_GET_TITLE(cbs, action_get_system_information_list); diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index c37f93ab55..dc18cff33b 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -407,100 +407,6 @@ static void materialui_draw_tab( &tab_color[0]); } -/* Draw the onscreen keyboard */ -static void materialui_render_keyboard(materialui_handle_t *mui, - video_frame_info_t *video_info, - const char *grid[], unsigned id) -{ - int ptr_width, ptr_height; - unsigned i; - unsigned width = video_info->width; - unsigned height = video_info->height; - float dark[16] = { - 0.00, 0.00, 0.00, 0.85, - 0.00, 0.00, 0.00, 0.85, - 0.00, 0.00, 0.00, 0.85, - 0.00, 0.00, 0.00, 0.85, - }; - - float white[16] = { - 1.00, 1.00, 1.00, 1.00, - 1.00, 1.00, 1.00, 1.00, - 1.00, 1.00, 1.00, 1.00, - 1.00, 1.00, 1.00, 1.00, - }; - - menu_display_draw_quad( - video_info, - 0, - height/2.0, width, height/2.0, - width, height, - &dark[0]); - - ptr_width = width / 11; - ptr_height = height / 10; - - if (ptr_width >= ptr_height) - ptr_width = ptr_height; - - for (i = 0; i < 44; i++) - { - int line_y = (i / 11)*height/10.0; - uintptr_t texture = mui->textures.list[MUI_TEXTURE_KEY]; - - if (i == id) - texture = mui->textures.list[MUI_TEXTURE_KEY_HOVER]; - - menu_display_blend_begin(video_info); - - menu_display_draw_texture( - video_info, - width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width, - height/2.0 + ptr_height*1.5 + line_y, - ptr_width, ptr_height, - width, height, - &white[0], - texture); - - menu_display_draw_text(mui->font, grid[i], - width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width + ptr_width/2.0, - height/2.0 + ptr_height + line_y + mui->font->size / 3, - width, height, 0xffffffff, TEXT_ALIGN_CENTER, 1.0f, - false, 0); - } -} - -/* Returns the OSK key at a given position */ -static int materialui_osk_ptr_at_pos(void *data, int x, int y, - unsigned width, unsigned height) -{ - unsigned i; - int ptr_width, ptr_height; - materialui_handle_t *mui = (materialui_handle_t*)data; - - if (!mui) - return -1; - - ptr_width = width / 11; - ptr_height = height / 10; - - if (ptr_width >= ptr_height) - ptr_width = ptr_height; - - for (i = 0; i < 44; i++) - { - int line_y = (i / 11)*height/10.0; - int ptr_x = width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width; - int ptr_y = height/2.0 + ptr_height*1.5 + line_y - ptr_height; - - if (x > ptr_x && x < ptr_x + ptr_width - && y > ptr_y && y < ptr_y + ptr_height) - return i; - } - - return -1; -} - /* Draw the tabs background */ static void materialui_draw_tab_begin( materialui_handle_t *mui, @@ -631,7 +537,7 @@ static void materialui_render_messagebox(materialui_handle_t *mui, { longest = len; longest_width = font_driver_get_message_width( - mui->font, msg, strlen(msg), 1); + mui->font, msg, (unsigned)strlen(msg), 1); } } @@ -661,7 +567,9 @@ static void materialui_render_messagebox(materialui_handle_t *mui, } if (menu_input_dialog_get_display_kb()) - materialui_render_keyboard(mui, + menu_display_draw_keyboard( + mui->textures.list[MUI_TEXTURE_KEY_HOVER], + mui->font, video_info, menu_event_get_osk_grid(), menu_event_get_osk_ptr()); @@ -697,7 +605,7 @@ static void materialui_compute_entries_box(materialui_handle_t* mui, int width) char *sublabel_str = NULL; unsigned lines = 0; materialui_node_t *node = (materialui_node_t*) - file_list_get_userdata_at_offset(list, i); + file_list_get_userdata_at_offset(list, i); menu_entry_init(&entry); menu_entry_get(&entry, 0, i, NULL, true); @@ -733,7 +641,7 @@ static void materialui_compute_entries_box(materialui_handle_t* mui, int width) } /* Called on each frame. We use this callback to implement the touch scroll -with acceleration */ + with acceleration */ static void materialui_render(void *data, bool is_idle) { menu_animation_ctx_delta_t delta; @@ -778,12 +686,12 @@ static void materialui_render(void *data, bool is_idle) for (ii = 0; ii < entries_end; ii++) { materialui_node_t *node = (materialui_node_t*) - file_list_get_userdata_at_offset(list, ii); + file_list_get_userdata_at_offset(list, ii); if (pointer_y > (-mui->scroll_y + header_height + node->y) - && pointer_y < (-mui->scroll_y + header_height + node->y + node->line_height) - ) - menu_input_ctl(MENU_INPUT_CTL_POINTER_PTR, &ii); + && pointer_y < (-mui->scroll_y + header_height + node->y + node->line_height) + ) + menu_input_ctl(MENU_INPUT_CTL_POINTER_PTR, &ii); } menu_input_ctl(MENU_INPUT_CTL_POINTER_ACCEL_READ, &old_accel_val); @@ -804,12 +712,12 @@ static void materialui_render(void *data, bool is_idle) for (ii = 0; ii < entries_end; ii++) { materialui_node_t *node = (materialui_node_t*) - file_list_get_userdata_at_offset(list, ii); + file_list_get_userdata_at_offset(list, ii); if (mouse_y > (-mui->scroll_y + header_height + node->y) - && mouse_y < (-mui->scroll_y + header_height + node->y + node->line_height) - ) - menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &ii); + && mouse_y < (-mui->scroll_y + header_height + node->y + node->line_height) + ) + menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &ii); } } @@ -891,7 +799,7 @@ static void materialui_render_label_value( do_draw_text = true; } else if (string_is_equal(value, msg_hash_to_str(MENU_ENUM_LABEL_ENABLED)) || - (string_is_equal(value, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)))) + (string_is_equal(value, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)))) { if (mui->textures.list[MUI_TEXTURE_SWITCH_ON]) { @@ -988,11 +896,11 @@ static void materialui_render_label_value( 0, 1, &label_color[0] - ); + ); if (texture_switch) { - /* This will be used instead of label_color if + /* This will be used instead of label_color if * texture_switch is 'off' icon */ float pure_white[16]= { 1.00, 1.00, 1.00, 1.00, @@ -1051,7 +959,7 @@ static void materialui_render_menu_list( char *rich_label = NULL; bool entry_selected = false; materialui_node_t *node = (materialui_node_t*) - file_list_get_userdata_at_offset(list, i); + file_list_get_userdata_at_offset(list, i); size_t selection = menu_navigation_get_selection(); int y = header_height - mui->scroll_y + sum; @@ -1074,21 +982,21 @@ static void materialui_render_menu_list( /* Render label, value, and associated icons */ materialui_render_label_value( - mui, - video_info, - node, - (int)i, - y, - width, - height, - frame_count / 20, - font_hover_color, - entry_selected, - rich_label, - entry_value, - menu_list_color, - sublabel_color - ); + mui, + video_info, + node, + (int)i, + y, + width, + height, + frame_count / 20, + font_hover_color, + entry_selected, + rich_label, + entry_value, + menu_list_color, + sublabel_color + ); menu_entry_free(&entry); free(rich_label); @@ -1167,7 +1075,7 @@ static void materialui_draw_bg(menu_display_ctx_draw_t *draw, } /* Main function of the menu driver. Takes care of drawing the header, the tabs, -and the menu list */ + and the menu list */ static void materialui_frame(void *data, video_frame_info_t *video_info) { /* This controls the main background color */ @@ -1328,7 +1236,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) clearcolor.a = 0.75f; break; case MATERIALUI_THEME_GREEN: - hex32_to_rgba_normalized(0x4CAF50, green_500, 1.00); + hex32_to_rgba_normalized(0x4CAF50, green_500, 1.00); hex32_to_rgba_normalized(0x4CAF50, header_bg_color_real, 1.00); hex32_to_rgba_normalized(0xC8E6C9, green_50, 0.90); hex32_to_rgba_normalized(0xFFFFFF, footer_bg_color_real, 1.00); @@ -1568,7 +1476,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) { materialui_draw_tab_begin(mui, video_info, - width, height, + width, height, footer_bg_color ? &footer_bg_color[0] : NULL, &grey_bg[0]); @@ -1630,7 +1538,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) ); } - ticker_limit = usable_width / mui->glyph_width; + ticker_limit = (unsigned)(usable_width / mui->glyph_width); ticker.s = title_buf; ticker.len = ticker_limit; @@ -1667,9 +1575,9 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) if (mui->font) menu_display_draw_text(mui->font, title_buf, - title_margin, - header_height / 2 + mui->font->size / 3, - width, height, font_header_color, TEXT_ALIGN_LEFT, 1.0f, false, 0); + title_margin, + header_height / 2 + mui->font->size / 3, + width, height, font_header_color, TEXT_ALIGN_LEFT, 1.0f, false, 0); materialui_draw_scrollbar(mui, video_info, width, height, &grey_bg[0]); @@ -1683,7 +1591,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) snprintf(msg, sizeof(msg), "%s\n%s", label, str); materialui_render_messagebox(mui, video_info, - msg, &body_bg_color[0], font_hover_color); + msg, &body_bg_color[0], font_hover_color); } if (!string_is_empty(mui->box_message)) @@ -1692,7 +1600,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) 0, 0, width, height, width, height, &black_bg[0]); materialui_render_messagebox(mui, video_info, - mui->box_message, &body_bg_color[0], font_hover_color); + mui->box_message, &body_bg_color[0], font_hover_color); free(mui->box_message); mui->box_message = NULL; @@ -1778,6 +1686,7 @@ static void materialui_layout(materialui_handle_t *mui, bool video_is_threaded) static void *materialui_init(void **userdata, bool video_is_threaded) { + float scale_factor = menu_display_get_dpi(); materialui_handle_t *mui = NULL; menu_handle_t *menu = (menu_handle_t*) calloc(1, sizeof(*menu)); @@ -1794,7 +1703,7 @@ static void *materialui_init(void **userdata, bool video_is_threaded) goto error; *userdata = mui; - mui->cursor_size = 64.0; + mui->cursor_size = scale_factor / 3; mui->need_compute = false; return menu; @@ -1860,6 +1769,7 @@ static bool materialui_load_image(void *userdata, void *data, enum menu_image_ty menu_display_allocate_white_texture(); break; case MENU_IMAGE_THUMBNAIL: + case MENU_IMAGE_LEFT_THUMBNAIL: case MENU_IMAGE_SAVESTATE_THUMBNAIL: break; } @@ -1885,10 +1795,10 @@ static float materialui_get_scroll(materialui_handle_t *mui) for (i = 0; i < selection; i++) { materialui_node_t *node = (materialui_node_t*) - file_list_get_userdata_at_offset(list, i); + file_list_get_userdata_at_offset(list, i); if (node) - sum += node->line_height; + sum += node->line_height; } if (sum < half) @@ -1898,7 +1808,7 @@ static float materialui_get_scroll(materialui_handle_t *mui) } /* The navigation pointer has been updated (for example by pressing up or down -on the keyboard). We use this function to animate the scroll. */ + on the keyboard). We use this function to animate the scroll. */ static void materialui_navigation_set(void *data, bool scroll) { menu_animation_ctx_entry_t entry; @@ -2043,7 +1953,7 @@ static void materialui_preswitch_tabs(materialui_handle_t *mui, unsigned action) } /* This callback is not caching anything. We use it to navigate the tabs -with the keyboard */ + with the keyboard */ static void materialui_list_cache(void *data, enum menu_list_type type, unsigned action) { @@ -2093,7 +2003,7 @@ static void materialui_list_cache(void *data, } /* A new list has been pushed. We use this callback to customize a few lists for -this menu driver */ + this menu driver */ static int materialui_list_push(void *data, void *userdata, menu_displaylist_info_t *info, unsigned type) { @@ -2266,7 +2176,7 @@ static size_t materialui_list_get_selection(void *data) } /* The pointer or the mouse is pressed down. We use this callback to -highlight the entry that has been pressed */ + highlight the entry that has been pressed */ static int materialui_pointer_down(void *userdata, unsigned x, unsigned y, unsigned ptr, menu_file_list_cbs_t *cbs, @@ -2299,11 +2209,11 @@ static int materialui_pointer_down(void *userdata, for (ii = 0; ii < entries_end; ii++) { materialui_node_t *node = (materialui_node_t*) - file_list_get_userdata_at_offset(list, ii); + file_list_get_userdata_at_offset(list, ii); if (y > (-mui->scroll_y + header_height + node->y) - && y < (-mui->scroll_y + header_height + node->y + node->line_height) - ) + && y < (-mui->scroll_y + header_height + node->y + node->line_height) + ) menu_navigation_set_selection(ii); } @@ -2314,9 +2224,9 @@ static int materialui_pointer_down(void *userdata, } /* The pointer or the left mouse button has been released. -If we clicked on the header, we perform a cancel action. -If we clicked on the tabs, we switch to a new list. -If we clicked on a menu entry, we call the entry action callback. */ + If we clicked on the header, we perform a cancel action. + If we clicked on the tabs, we switch to a new list. + If we clicked on a menu entry, we call the entry action callback. */ static int materialui_pointer_up(void *userdata, unsigned x, unsigned y, unsigned ptr, menu_file_list_cbs_t *cbs, @@ -2368,11 +2278,11 @@ static int materialui_pointer_up(void *userdata, for (ii = 0; ii < entries_end; ii++) { materialui_node_t *node = (materialui_node_t*) - file_list_get_userdata_at_offset(list, ii); + file_list_get_userdata_at_offset(list, ii); if (y > (-mui->scroll_y + header_height + node->y) - && y < (-mui->scroll_y + header_height + node->y + node->line_height) - ) + && y < (-mui->scroll_y + header_height + node->y + node->line_height) + ) { if (ptr == ii && cbs && cbs->action_select) return menu_entry_action(entry, (unsigned)ii, MENU_ACTION_SELECT); @@ -2572,13 +2482,15 @@ static void materialui_list_insert(void *userdata, else if ( string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_FAVORITES)) || + string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_GOTO_FAVORITES)) ) { node->texture_switch2_index = MUI_TEXTURE_ADD_TO_FAVORITES; node->texture_switch2_set = true; } - else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_RENAME_ENTRY))) + else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_RENAME_ENTRY)) || + string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_RESET_CORE_ASSOCIATION))) { node->texture_switch2_index = MUI_TEXTURE_RENAME; node->texture_switch2_set = true; @@ -2726,6 +2638,8 @@ static void materialui_list_insert(void *userdata, || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_INPUT_SETTINGS)) || + string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_LATENCY_SETTINGS)) + || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_INPUT_HOTKEY_BINDS)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CORE_SETTINGS)) @@ -2870,7 +2784,7 @@ menu_ctx_driver_t menu_ctx_mui = { NULL, NULL, NULL, - materialui_osk_ptr_at_pos, + menu_display_osk_ptr_at_pos, NULL, NULL, materialui_pointer_down, diff --git a/menu/drivers/menu_generic.c b/menu/drivers/menu_generic.c index 82ed2dc04e..3661d5d5e2 100644 --- a/menu/drivers/menu_generic.c +++ b/menu/drivers/menu_generic.c @@ -136,11 +136,9 @@ int generic_menu_iterate(void *data, void *userdata, enum menu_action action) file_list_get_actiondata_at_offset(selection_buf, selection) : NULL; - if (cbs->enum_idx != MSG_UNKNOWN) - { + if (cbs && cbs->enum_idx != MSG_UNKNOWN) ret = menu_hash_get_help_enum(cbs->enum_idx, menu->menu_state_msg, sizeof(menu->menu_state_msg)); - } else { unsigned type = 0; diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 16de9c2c43..4c7beca70b 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -55,11 +55,14 @@ typedef struct { + bool bg_modified; bool force_redraw; bool mouse_show; unsigned last_width; unsigned last_height; unsigned frame_count; + bool bg_thickness; + bool border_thickness; float scroll_y; char *msgbox; } rgui_t; @@ -86,10 +89,10 @@ static uint16_t argb32_to_rgba4444(uint32_t col) #endif -static uint16_t rgui_gray_filler(unsigned x, unsigned y) +static uint16_t rgui_gray_filler(rgui_t *rgui, unsigned x, unsigned y) { - unsigned col = (((x >> 1) + (y >> 1)) & 1) + 1; - + unsigned shft = (rgui->bg_thickness ? 1 : 0); + unsigned col = (((x >> shft) + (y >> shft)) & 1) + 1; #if defined(GEKKO) || defined(PSP) return (6 << 12) | (col << 8) | (col << 4) | (col << 0); #else @@ -97,9 +100,10 @@ static uint16_t rgui_gray_filler(unsigned x, unsigned y) #endif } -static uint16_t rgui_green_filler(unsigned x, unsigned y) +static uint16_t rgui_green_filler(rgui_t *rgui, unsigned x, unsigned y) { - unsigned col = (((x >> 1) + (y >> 1)) & 1) + 1; + unsigned shft = (rgui->border_thickness ? 1 : 0); + unsigned col = (((x >> shft) + (y >> shft)) & 1) + 1; #if defined(GEKKO) || defined(PSP) return (6 << 12) | (col << 8) | (col << 5) | (col << 0); #else @@ -108,17 +112,18 @@ static uint16_t rgui_green_filler(unsigned x, unsigned y) } static void rgui_fill_rect( + rgui_t *rgui, uint16_t *data, size_t pitch, unsigned x, unsigned y, unsigned width, unsigned height, - uint16_t (*col)(unsigned x, unsigned y)) + uint16_t (*col)(rgui_t *rgui, unsigned x, unsigned y)) { unsigned i, j; for (j = y; j < y + height; j++) for (i = x; i < x + width; i++) - data[j * (pitch >> 1) + i] = col(i, j); + data[j * (pitch >> 1) + i] = col(rgui, i, j); } static void rgui_color_rect( @@ -239,7 +244,7 @@ static bool rguidisp_init_font(menu_handle_t *menu) return true; } -static void rgui_render_background(void) +static void rgui_render_background(rgui_t *rgui) { size_t pitch_in_pixels, size; size_t fb_pitch; @@ -263,12 +268,17 @@ static void rgui_render_background(void) if (rgui_framebuf_data) { - rgui_fill_rect(rgui_framebuf_data, fb_pitch, 5, 5, fb_width - 10, 5, rgui_green_filler); - rgui_fill_rect(rgui_framebuf_data, fb_pitch, 5, fb_height - 10, fb_width - 10, 5, rgui_green_filler); + settings_t *settings = config_get_ptr(); - rgui_fill_rect(rgui_framebuf_data, fb_pitch, 5, 5, 5, fb_height - 10, rgui_green_filler); - rgui_fill_rect(rgui_framebuf_data, fb_pitch, fb_width - 10, 5, 5, fb_height - 10, - rgui_green_filler); + if (settings->bools.menu_rgui_border_filler_enable) + { + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, 5, fb_width - 10, 5, rgui_green_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, fb_height - 10, fb_width - 10, 5, rgui_green_filler); + + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 5, 5, 5, fb_height - 10, rgui_green_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, fb_width - 10, 5, 5, fb_height - 10, + rgui_green_filler); + } } } @@ -285,7 +295,7 @@ static void rgui_set_message(void *data, const char *message) rgui->force_redraw = true; } -static void rgui_render_messagebox(const char *message) +static void rgui_render_messagebox(rgui_t *rgui, const char *message) { int x, y; uint16_t color; @@ -338,20 +348,24 @@ static void rgui_render_messagebox(const char *message) if (rgui_framebuf_data) { - rgui_fill_rect(rgui_framebuf_data, + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, x + 5, y + 5, width - 10, height - 10, rgui_gray_filler); - rgui_fill_rect(rgui_framebuf_data, - fb_pitch, x, y, width - 5, 5, rgui_green_filler); - rgui_fill_rect(rgui_framebuf_data, - fb_pitch, x + width - 5, y, 5, - height - 5, rgui_green_filler); - rgui_fill_rect(rgui_framebuf_data, - fb_pitch, x + 5, y + height - 5, - width - 5, 5, rgui_green_filler); - rgui_fill_rect(rgui_framebuf_data, - fb_pitch, x, y + 5, 5, - height - 5, rgui_green_filler); + + if (settings->bools.menu_rgui_border_filler_enable) + { + rgui_fill_rect(rgui, rgui_framebuf_data, + fb_pitch, x, y, width - 5, 5, rgui_green_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, + fb_pitch, x + width - 5, y, 5, + height - 5, rgui_green_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, + fb_pitch, x + 5, y + height - 5, + width - 5, 5, rgui_green_filler); + rgui_fill_rect(rgui, rgui_framebuf_data, + fb_pitch, x, y + 5, 5, + height - 5, rgui_green_filler); + } } color = NORMAL_COLOR(settings); @@ -390,6 +404,15 @@ static void rgui_blit_cursor(void) static void rgui_frame(void *data, video_frame_info_t *video_info) { rgui_t *rgui = (rgui_t*)data; + settings_t *settings = config_get_ptr(); + + if ((settings->bools.menu_rgui_background_filler_thickness_enable != rgui->bg_thickness) || + (settings->bools.menu_rgui_border_filler_thickness_enable != rgui->border_thickness) + ) + rgui->bg_modified = true; + + rgui->bg_thickness = settings->bools.menu_rgui_background_filler_thickness_enable; + rgui->border_thickness = settings->bools.menu_rgui_border_filler_thickness_enable; rgui->frame_count++; } @@ -430,14 +453,17 @@ static void rgui_render(void *data, bool is_idle) &fb_pitch); /* if the framebuffer changed size, recache the background */ - if (rgui->last_width != fb_width || rgui->last_height != fb_height) + if (rgui->bg_modified || rgui->last_width != fb_width || rgui->last_height != fb_height) { if (rgui_framebuf_data) - rgui_fill_rect(rgui_framebuf_data, + rgui_fill_rect(rgui, rgui_framebuf_data, fb_pitch, 0, fb_height, fb_width, 4, rgui_gray_filler); rgui->last_width = fb_width; rgui->last_height = fb_height; } + + if (rgui->bg_modified) + rgui->bg_modified = false; menu_display_set_framebuffer_dirty_flag(); menu_animation_ctl(MENU_ANIMATION_CTL_CLEAR_ACTIVE, NULL); @@ -502,7 +528,7 @@ static void rgui_render(void *data, bool is_idle) end = ((old_start + RGUI_TERM_HEIGHT(fb_width, fb_height)) <= (entries_end)) ? old_start + RGUI_TERM_HEIGHT(fb_width, fb_height) : entries_end; - rgui_render_background(); + rgui_render_background(rgui); menu_entries_get_title(title, sizeof(title)); @@ -648,12 +674,12 @@ static void rgui_render(void *data, bool is_idle) const char *label = menu_input_dialog_get_label_buffer(); snprintf(msg, sizeof(msg), "%s\n%s", label, str); - rgui_render_messagebox(msg); + rgui_render_messagebox(rgui, msg); } if (!string_is_empty(rgui->msgbox)) { - rgui_render_messagebox(rgui->msgbox); + rgui_render_messagebox(rgui, rgui->msgbox); free(rgui->msgbox); rgui->msgbox = NULL; rgui->force_redraw = true; @@ -684,6 +710,7 @@ static void *rgui_init(void **userdata, bool video_is_threaded) unsigned fb_width, fb_height, new_font_height; rgui_t *rgui = NULL; bool ret = false; + settings_t *settings = config_get_ptr(); menu_handle_t *menu = (menu_handle_t*)calloc(1, sizeof(*menu)); if (!menu) @@ -694,7 +721,7 @@ static void *rgui_init(void **userdata, bool video_is_threaded) if (!rgui) goto error; - *userdata = rgui; + *userdata = rgui; /* 4 extra lines to cache the checked background */ rgui_framebuf_data = (uint16_t*) @@ -721,10 +748,9 @@ static void *rgui_init(void **userdata, bool video_is_threaded) if (!ret) goto error; - if (rgui_framebuf_data) - rgui_fill_rect(rgui_framebuf_data, - fb_pitch, 0, fb_height, - fb_width, 4, rgui_gray_filler); + rgui->bg_thickness = settings->bools.menu_rgui_background_filler_thickness_enable; + rgui->border_thickness = settings->bools.menu_rgui_border_filler_thickness_enable; + rgui->bg_modified = true; rgui->last_width = fb_width; rgui->last_height = fb_height; diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 532cfac8bf..57dffb84b5 100755 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -2,6 +2,7 @@ * Copyright (C) 2011-2017 - Daniel De Matteis * Copyright (C) 2014-2017 - Jean-André Santoni * Copyright (C) 2016-2017 - Brad Parker + * Copyright (C) 2018 - Alfredo Monclús * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -104,9 +105,11 @@ enum #ifdef HAVE_NETWORKING XMB_TEXTURE_NETPLAY, XMB_TEXTURE_ROOM, -/* stub these out until we have the icons +#if 0 + /* stub these out until we have the icons */ XMB_TEXTURE_ROOM_LAN, - XMB_TEXTURE_ROOM_MITM,*/ + XMB_TEXTURE_ROOM_MITM, +#endif #endif #ifdef HAVE_IMAGEVIEWER XMB_TEXTURE_IMAGES, @@ -180,6 +183,7 @@ enum typedef struct xmb_handle { bool mouse_show; + bool use_ps3_layout; uint8_t system_tab_end; uint8_t tabs[XMB_SYSTEM_TAB_MAX_LENGTH]; @@ -196,12 +200,15 @@ typedef struct xmb_handle unsigned categories_active_idx; unsigned categories_active_idx_old; uintptr_t thumbnail; + uintptr_t left_thumbnail; uintptr_t savestate_thumbnail; float x; float alpha; float thumbnail_width; float thumbnail_height; + float left_thumbnail_width; + float left_thumbnail_height; float savestate_thumbnail_width; float savestate_thumbnail_height; float above_subitem_offset; @@ -243,6 +250,7 @@ typedef struct xmb_handle char *thumbnail_content; char *savestate_thumbnail_file_path; char *thumbnail_file_path; + char *left_thumbnail_file_path; char *bg_file_path; file_list_t *selection_buf_old; @@ -274,27 +282,8 @@ typedef struct xmb_handle video_font_raster_block_t raster_block2; } xmb_handle_t; -/* scaling multiplier resulting from equations using values below */ -/* applied in xmb_init */ -/* values for xmb_scale 50 = {2.5, 2.5, 2, 1.7, 2.5, 4, 2.4, 2.5} */ -/* values for xmb_scale 75 = {2, 1.6, 1.6, 1.4, 1.5, 2.3, 1.9, 1.3} */ float scale_mod[8] = { - /* text length & word wrap (base 35 apply to file browser, 1st column) */ - 1, - /* playlist text length when thumbnail is ON (small, base 40) */ - 1, - /* playlist text length when thumbnail is OFF (large, base 70) */ - 1, - /* sub-label length & word wrap */ - 1, - /* thumbnail size & vertical margin from top */ - 1, - /* thumbnail horizontal left margin (horizontal positioning) */ - 1, - /* margin before 2nd column start (shaders parameters, cheats...) */ - 1, - /* text length & word wrap (base 35 apply to 2nd column in cheats, shaders...) */ - 1 + 1, 1, 1, 1, 1, 1, 1, 1 }; static float coord_shadow[] = { @@ -331,9 +320,9 @@ static float item_color[] = { float gradient_dark_purple[16] = { - 20/255.0, 13/255.0, 20/255.0, 1.0, - 20/255.0, 13/255.0, 20/255.0, 1.0, - 92/255.0, 44/255.0, 92/255.0, 1.0, + 20/255.0, 13/255.0, 20/255.0, 1.0, + 20/255.0, 13/255.0, 20/255.0, 1.0, + 92/255.0, 44/255.0, 92/255.0, 1.0, 148/255.0, 90/255.0, 148/255.0, 1.0, }; @@ -359,24 +348,24 @@ float gradient_legacy_red[16] = { }; float gradient_electric_blue[16] = { - 1/255.0, 2/255.0, 67/255.0, 1.0, - 1/255.0, 73/255.0, 183/255.0, 1.0, - 1/255.0, 93/255.0, 194/255.0, 1.0, - 3/255.0, 162/255.0, 254/255.0, 1.0, + 1/255.0, 2/255.0, 67/255.0, 1.0, + 1/255.0, 73/255.0, 183/255.0, 1.0, + 1/255.0, 93/255.0, 194/255.0, 1.0, + 3/255.0, 162/255.0, 254/255.0, 1.0, }; float gradient_apple_green[16] = { 102/255.0, 134/255.0, 58/255.0, 1.0, 122/255.0, 131/255.0, 52/255.0, 1.0, - 82/255.0, 101/255.0, 35/255.0, 1.0, - 63/255.0, 95/255.0, 30/255.0, 1.0, + 82/255.0, 101/255.0, 35/255.0, 1.0, + 63/255.0, 95/255.0, 30/255.0, 1.0, }; float gradient_undersea[16] = { - 23/255.0, 18/255.0, 41/255.0, 1.0, - 30/255.0, 72/255.0, 114/255.0, 1.0, - 52/255.0, 88/255.0, 110/255.0, 1.0, - 69/255.0, 125/255.0, 140/255.0, 1.0, + 23/255.0, 18/255.0, 41/255.0, 1.0, + 30/255.0, 72/255.0, 114/255.0, 1.0, + 52/255.0, 88/255.0, 110/255.0, 1.0, + 69/255.0, 125/255.0, 140/255.0, 1.0, }; @@ -459,15 +448,15 @@ static xmb_node_t *xmb_alloc_node(void) static void xmb_free_node(xmb_node_t *node) { - if (!node) - return; + if (!node) + return; - if (node->fullpath) - free(node->fullpath); + if (node->fullpath) + free(node->fullpath); - node->fullpath = NULL; + node->fullpath = NULL; - free(node); + free(node); } /** @@ -482,7 +471,7 @@ static void xmb_free_node(xmb_node_t *node) */ static void xmb_free_list_nodes(file_list_t *list, bool actiondata) { - unsigned i, size = file_list_get_size(list); + unsigned i, size = (unsigned)file_list_get_size(list); for (i = 0; i < size; ++i) { @@ -506,11 +495,17 @@ static xmb_node_t *xmb_copy_node(const xmb_node_t *old_node) return new_node; } -static const char *xmb_thumbnails_ident(void) +static const char *xmb_thumbnails_ident(char pos) { + char folder = 0; settings_t *settings = config_get_ptr(); - switch (settings->uints.menu_thumbnails) + if (pos == 'R') + folder = settings->uints.menu_thumbnails; + if (pos == 'L') + folder = settings->uints.menu_left_thumbnails; + + switch (folder) { case 1: return "Named_Snaps"; @@ -587,7 +582,8 @@ static size_t xmb_list_get_size(void *data, enum menu_list_type type) return 0; } -static void *xmb_list_get_entry(void *data, enum menu_list_type type, unsigned i) +static void *xmb_list_get_entry(void *data, + enum menu_list_type type, unsigned i) { size_t list_size = 0; xmb_handle_t *xmb = (xmb_handle_t*)data; @@ -736,8 +732,8 @@ static void xmb_draw_thumbnail( coords.tex_coord = NULL; coords.lut_tex_coord = NULL; - draw.width = w * scale_mod[4]; - draw.height = h * scale_mod[4]; + draw.width = w; + draw.height = h; draw.coords = &coords; draw.matrix_data = &mymat; draw.texture = texture; @@ -807,100 +803,6 @@ static void xmb_messagebox(void *data, const char *message) xmb->box_message = strdup(message); } -static void xmb_render_keyboard(xmb_handle_t *xmb, - video_frame_info_t *video_info, - const char *grid[], unsigned id) -{ - unsigned i; - int ptr_width, ptr_height; - unsigned width = video_info->width; - unsigned height = video_info->height; - float dark[16] = { - 0.00, 0.00, 0.00, 0.85, - 0.00, 0.00, 0.00, 0.85, - 0.00, 0.00, 0.00, 0.85, - 0.00, 0.00, 0.00, 0.85, - }; - - float white[16]= { - 1.00, 1.00, 1.00, 1.00, - 1.00, 1.00, 1.00, 1.00, - 1.00, 1.00, 1.00, 1.00, - 1.00, 1.00, 1.00, 1.00, - }; - - menu_display_draw_quad( - video_info, - 0, height/2.0, width, height/2.0, - width, height, - &dark[0]); - - ptr_width = width / 11; - ptr_height = height / 10; - - if (ptr_width >= ptr_height) - ptr_width = ptr_height; - - for (i = 0; i < 44; i++) - { - int line_y = (i / 11) * height / 10.0; - - if (i == id) - { - uintptr_t texture = xmb->textures.list[XMB_TEXTURE_KEY_HOVER]; - - menu_display_blend_begin(video_info); - - menu_display_draw_texture( - video_info, - width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width, - height/2.0 + ptr_height*1.5 + line_y, - ptr_width, ptr_height, - width, height, - &white[0], - texture); - - menu_display_blend_end(video_info); - } - - menu_display_draw_text(xmb->font, grid[i], - width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width + ptr_width/2.0, - height/2.0 + ptr_height + line_y + xmb->font->size / 3, - width, height, 0xffffffff, TEXT_ALIGN_CENTER, 1.0f, - false, 0); - } -} - -/* Returns the OSK key at a given position */ -static int xmb_osk_ptr_at_pos(void *data, int x, int y, unsigned width, unsigned height) -{ - unsigned i; - int ptr_width, ptr_height; - xmb_handle_t *xmb = (xmb_handle_t*)data; - - if (!xmb) - return -1; - - ptr_width = width / 11; - ptr_height = height / 10; - - if (ptr_width >= ptr_height) - ptr_width = ptr_height; - - for (i = 0; i < 44; i++) - { - int line_y = (i / 11)*height/10.0; - int ptr_x = width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width; - int ptr_y = height/2.0 + ptr_height*1.5 + line_y - ptr_height; - - if (x > ptr_x && x < ptr_x + ptr_width - && y > ptr_y && y < ptr_y + ptr_height) - return i; - } - - return -1; -} - static void xmb_render_messagebox_internal( video_frame_info_t *video_info, xmb_handle_t *xmb, const char *message, float* coord_white) @@ -942,7 +844,7 @@ static void xmb_render_messagebox_internal( { longest = len; longest_width = font_driver_get_message_width( - xmb->font, msg, strlen(msg), 1); + xmb->font, msg, (unsigned)strlen(msg), 1); } } @@ -972,7 +874,9 @@ static void xmb_render_messagebox_internal( } if (menu_input_dialog_get_display_kb()) - xmb_render_keyboard(xmb, + menu_display_draw_keyboard( + xmb->textures.list[XMB_TEXTURE_KEY_HOVER], + xmb->font, video_info, menu_event_get_osk_grid(), menu_event_get_osk_ptr()); @@ -981,7 +885,7 @@ end: string_list_free(list); } -static void xmb_update_thumbnail_path(void *data, unsigned i) +static void xmb_update_thumbnail_path(void *data, unsigned i, char pos) { menu_entry_t entry; unsigned entry_type = 0; @@ -1006,7 +910,9 @@ static void xmb_update_thumbnail_path(void *data, unsigned i) xmb_node_t *node = (xmb_node_t*) file_list_get_userdata_at_offset(selection_buf, i); - if (!string_is_empty(node->fullpath)) + if (!string_is_empty(node->fullpath) && + (pos == 'R' || (pos == 'L' && string_is_equal(xmb_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))))) { if (!string_is_empty(entry.path)) fill_pathname_join( @@ -1024,7 +930,7 @@ static void xmb_update_thumbnail_path(void *data, unsigned i) goto end; } - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &playlist); + playlist = playlist_get_cached(); if (playlist) { @@ -1034,9 +940,21 @@ static void xmb_update_thumbnail_path(void *data, unsigned i) if (string_is_equal(core_name, "imageviewer")) { - if (!string_is_empty(entry.label)) - strlcpy(new_path, entry.label, - sizeof(new_path)); + if ( + (pos == 'R') || + ( + pos == 'L' && + string_is_equal(xmb_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) + ) + ) + { + if (!string_is_empty(entry.label)) + strlcpy(new_path, entry.label, + sizeof(new_path)); + } + else + xmb->left_thumbnail = 0; goto end; } } @@ -1056,9 +974,13 @@ static void xmb_update_thumbnail_path(void *data, unsigned i) tmp_new2[0] = '\0'; - /* Append Named_Snaps/Named_Boxart/Named_Titles */ - fill_pathname_join(tmp_new2, new_path, - xmb_thumbnails_ident(), PATH_MAX_LENGTH * sizeof(char)); + /* Append Named_Snaps/Named_Boxarts/Named_Titles */ + if (pos == 'R') + fill_pathname_join(tmp_new2, new_path, + xmb_thumbnails_ident('R'), PATH_MAX_LENGTH * sizeof(char)); + if (pos == 'L') + fill_pathname_join(tmp_new2, new_path, + xmb_thumbnails_ident('L'), PATH_MAX_LENGTH * sizeof(char)); strlcpy(new_path, tmp_new2, PATH_MAX_LENGTH * sizeof(char)); @@ -1104,7 +1026,13 @@ static void xmb_update_thumbnail_path(void *data, unsigned i) end: if (xmb && !string_is_empty(new_path)) - xmb->thumbnail_file_path = strdup(new_path); + { + if (pos == 'R') + xmb->thumbnail_file_path = strdup(new_path); + if (pos == 'L') + xmb->left_thumbnail_file_path = strdup(new_path); + } + menu_entry_free(&entry); } @@ -1170,17 +1098,32 @@ static void xmb_update_savestate_thumbnail_path(void *data, unsigned i) static void xmb_update_thumbnail_image(void *data) { xmb_handle_t *xmb = (xmb_handle_t*)data; - if (!xmb || string_is_empty(xmb->thumbnail_file_path)) + if (!xmb) return; - if (filestream_exists(xmb->thumbnail_file_path)) - task_push_image_load(xmb->thumbnail_file_path, - menu_display_handle_thumbnail_upload, NULL); - else - xmb->thumbnail = 0; + if (!(string_is_empty(xmb->thumbnail_file_path))) + { + if (filestream_exists(xmb->thumbnail_file_path)) + task_push_image_load(xmb->thumbnail_file_path, + menu_display_handle_thumbnail_upload, NULL); + else + xmb->thumbnail = 0; - free(xmb->thumbnail_file_path); - xmb->thumbnail_file_path = NULL; + free(xmb->thumbnail_file_path); + xmb->thumbnail_file_path = NULL; + } + + if (!(string_is_empty(xmb->left_thumbnail_file_path))) + { + if (filestream_exists(xmb->left_thumbnail_file_path)) + task_push_image_load(xmb->left_thumbnail_file_path, + menu_display_handle_left_thumbnail_upload, NULL); + else + xmb->left_thumbnail = 0; + + free(xmb->left_thumbnail_file_path); + xmb->left_thumbnail_file_path = NULL; + } } static void xmb_set_thumbnail_system(void *data, char*s, size_t len) @@ -1248,7 +1191,8 @@ static void xmb_selection_pointer_changed( menu_list_t *menu_list = NULL; file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); size_t selection = menu_navigation_get_selection(); - const char *thumb_ident = xmb_thumbnails_ident(); + const char *thumb_ident = xmb_thumbnails_ident('R'); + const char *lft_thumb_ident= xmb_thumbnails_ident('L'); menu_entries_ctl(MENU_ENTRIES_CTL_LIST_GET, &menu_list); menu_entry_init(&entry); @@ -1290,32 +1234,62 @@ static void xmb_selection_pointer_changed( ia = xmb->items_active_alpha; iz = xmb->items_active_zoom; - if (!string_is_equal(thumb_ident, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) || !string_is_equal(lft_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) { if ((xmb_system_tab > XMB_SYSTEM_TAB_SETTINGS && depth == 1) || - (xmb_system_tab < XMB_SYSTEM_TAB_SETTINGS && depth == 4)) + (xmb_system_tab < XMB_SYSTEM_TAB_SETTINGS && depth == 4)) { if (!string_is_empty(entry.path)) xmb_set_thumbnail_content(xmb, entry.path, 0 /* will be ignored */); - xmb_update_thumbnail_path(xmb, i); - xmb_update_thumbnail_image(xmb); + if (!string_is_equal(thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + xmb_update_thumbnail_path(xmb, i, 'R'); + xmb_update_thumbnail_image(xmb); + } + if (!string_is_equal(lft_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + xmb_update_thumbnail_path(xmb, i, 'L'); + xmb_update_thumbnail_image(xmb); + } } else if (((entry_type == FILE_TYPE_IMAGE || entry_type == FILE_TYPE_IMAGEVIEWER || entry_type == FILE_TYPE_RDB || entry_type == FILE_TYPE_RDB_ENTRY) - && xmb_system_tab <= XMB_SYSTEM_TAB_SETTINGS)) + && xmb_system_tab <= XMB_SYSTEM_TAB_SETTINGS)) { if (!string_is_empty(entry.path)) xmb_set_thumbnail_content(xmb, entry.path, 0 /* will be ignored */); - xmb_update_thumbnail_path(xmb, i); - xmb_update_thumbnail_image(xmb); + if (!string_is_equal(thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + xmb_update_thumbnail_path(xmb, i, 'R'); + xmb_update_thumbnail_image(xmb); + } + else if (!string_is_equal(lft_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + xmb_update_thumbnail_path(xmb, i, 'L'); + xmb_update_thumbnail_image(xmb); + } } else if (filebrowser_get_type() != FILEBROWSER_NONE) { xmb_reset_thumbnail_content(xmb); - xmb_update_thumbnail_path(xmb, i); - xmb_update_thumbnail_image(xmb); + if (!string_is_equal(thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + xmb_update_thumbnail_path(xmb, i, 'R'); + xmb_update_thumbnail_image(xmb); + } + else if (!string_is_equal(lft_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + xmb_update_thumbnail_path(xmb, i, 'L'); + xmb_update_thumbnail_image(xmb); + } } } xmb_update_savestate_thumbnail_path(xmb, i); @@ -1324,7 +1298,7 @@ static void xmb_selection_pointer_changed( if ( (!allow_animations) || (real_iy < -threshold - || real_iy > height+threshold)) + || real_iy > height+threshold)) { node->alpha = node->label_alpha = ia; node->y = iy; @@ -1495,21 +1469,25 @@ static void xmb_list_open_new(xmb_handle_t *xmb, xmb->old_depth = xmb->depth; menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &skip); - xmb_system_tab = xmb_get_system_tab(xmb, (unsigned)xmb->categories_selection_ptr); + xmb_system_tab = xmb_get_system_tab(xmb, + (unsigned)xmb->categories_selection_ptr); if (xmb_system_tab <= XMB_SYSTEM_TAB_SETTINGS) { if (xmb->depth < 4) xmb_reset_thumbnail_content(xmb); - xmb_update_thumbnail_path(xmb, 0); + xmb_update_thumbnail_path(xmb, 0, 'R'); + xmb_update_thumbnail_image(xmb); + xmb_update_thumbnail_path(xmb, 0, 'L'); xmb_update_thumbnail_image(xmb); } } -static xmb_node_t *xmb_node_allocate_userdata(xmb_handle_t *xmb, unsigned i) +static xmb_node_t *xmb_node_allocate_userdata( + xmb_handle_t *xmb, unsigned i) { + xmb_node_t *tmp = NULL; xmb_node_t *node = xmb_alloc_node(); - xmb_node_t *tmp; if (!node) { @@ -1526,7 +1504,8 @@ static xmb_node_t *xmb_node_allocate_userdata(xmb_handle_t *xmb, unsigned i) node->zoom = xmb->categories_active_zoom; } - tmp = (xmb_node_t*)file_list_get_userdata_at_offset(xmb->horizontal_list, i); + tmp = (xmb_node_t*)file_list_get_userdata_at_offset( + xmb->horizontal_list, i); xmb_free_node(tmp); file_list_set_userdata(xmb->horizontal_list, i, node); @@ -1541,7 +1520,8 @@ static xmb_node_t* xmb_get_userdata_from_horizontal_list( file_list_get_userdata_at_offset(xmb->horizontal_list, i); } -static void xmb_push_animations(xmb_node_t *node, uintptr_t tag, float ia, float ix) +static void xmb_push_animations(xmb_node_t *node, + uintptr_t tag, float ia, float ix) { menu_animation_ctx_entry_t anim_entry; @@ -1567,16 +1547,16 @@ static void xmb_push_animations(xmb_node_t *node, uintptr_t tag, float ia, float static void xmb_list_switch_old(xmb_handle_t *xmb, file_list_t *list, int dir, size_t current) { - unsigned i, first, last, height; - size_t end = file_list_get_size(list); - float ix = -xmb->icon_spacing_horizontal * dir; - float ia = 0; - - first = 0; - last = end > 0 ? end - 1 : 0; + unsigned i, height; + size_t end = file_list_get_size(list); + float ix = -xmb->icon_spacing_horizontal * dir; + float ia = 0; + unsigned first = 0; + unsigned last = (unsigned)(end > 0 ? end - 1 : 0); video_driver_get_size(NULL, &height); - xmb_calculate_visible_range(xmb, height, end, current, &first, &last); + xmb_calculate_visible_range(xmb, height, end, + (unsigned)current, &first, &last); for (i = 0; i < end; i++) { @@ -1629,28 +1609,28 @@ static void xmb_list_switch_new(xmb_handle_t *xmb, fill_pathname_application_special(path, path_size, APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_BG); - if(!string_is_equal(path, xmb->bg_file_path)) - { - if(filestream_exists(path)) - { - task_push_image_load(path, + if(!string_is_equal(path, xmb->bg_file_path)) + { + if(filestream_exists(path)) + { + task_push_image_load(path, menu_display_handle_wallpaper_upload, NULL); - if (!string_is_empty(xmb->bg_file_path)) - free(xmb->bg_file_path); - xmb->bg_file_path = strdup(path); - } - } + if (!string_is_empty(xmb->bg_file_path)) + free(xmb->bg_file_path); + xmb->bg_file_path = strdup(path); + } + } - free(path); + free(path); } end = file_list_get_size(list); first = 0; - last = end > 0 ? end - 1 : 0; + last = (unsigned)(end > 0 ? end - 1 : 0); video_driver_get_size(NULL, &height); - xmb_calculate_visible_range(xmb, height, end, current, &first, &last); + xmb_calculate_visible_range(xmb, height, end, (unsigned)current, &first, &last); for (i = 0; i < end; i++) { @@ -1695,7 +1675,8 @@ static void xmb_set_title(xmb_handle_t *xmb) if (!path) return; - fill_pathname_base_noext(xmb->title_name, path, sizeof(xmb->title_name)); + fill_pathname_base_noext( + xmb->title_name, path, sizeof(xmb->title_name)); } } @@ -1789,7 +1770,8 @@ static void xmb_list_switch(xmb_handle_t *xmb) xmb_list_switch_horizontal_list(xmb); anim_entry.duration = XMB_DELAY; - anim_entry.target_value = xmb->icon_spacing_horizontal * -(float)xmb->categories_selection_ptr; + anim_entry.target_value = xmb->icon_spacing_horizontal + * -(float)xmb->categories_selection_ptr; anim_entry.subject = &xmb->categories_x_pos; anim_entry.easing_enum = EASING_OUT_QUAD; /* TODO/FIXME - integer conversion resulted in change of sign */ @@ -1811,7 +1793,7 @@ static void xmb_list_switch(xmb_handle_t *xmb) xmb_list_switch_new(xmb, selection_buf, dir, selection); xmb->categories_active_idx_old = (unsigned)xmb->categories_selection_ptr; - if (!string_is_equal(xmb_thumbnails_ident(), + if (!string_is_equal(xmb_thumbnails_ident('R'), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) { menu_entry_t entry; @@ -1824,7 +1806,23 @@ static void xmb_list_switch(xmb_handle_t *xmb) menu_entry_free(&entry); - xmb_update_thumbnail_path(xmb, 0); + xmb_update_thumbnail_path(xmb, 0, 'R'); + xmb_update_thumbnail_image(xmb); + } + if (!string_is_equal(xmb_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + menu_entry_t entry; + + menu_entry_init(&entry); + menu_entry_get(&entry, 0, selection, NULL, true); + + if (!string_is_empty(entry.path)) + xmb_set_thumbnail_content(xmb, entry.path, 0 /* will be ignored */); + + menu_entry_free(&entry); + + xmb_update_thumbnail_path(xmb, 0, 'L'); xmb_update_thumbnail_image(xmb); } } @@ -1903,7 +1901,7 @@ static void xmb_init_horizontal_list(xmb_handle_t *xmb) info.type_default = FILE_TYPE_PLAIN; info.enum_idx = MENU_ENUM_LABEL_CONTENT_COLLECTION_LIST; - if (!string_is_empty(info.path)) + if (settings->bools.menu_content_show_playlists && !string_is_empty(info.path)) { if (menu_displaylist_ctl(DISPLAYLIST_DATABASE_PLAYLISTS_HORIZONTAL, &info)) { @@ -1951,11 +1949,12 @@ static void xmb_context_reset_horizontal_list( size_t list_size = xmb_list_get_size(xmb, MENU_LIST_HORIZONTAL); - xmb->categories_x_pos = xmb->icon_spacing_horizontal * + xmb->categories_x_pos = + xmb->icon_spacing_horizontal * -(float)xmb->categories_selection_ptr; - depth = (xmb->depth > 1) ? 2 : 1; - xmb->x = xmb->icon_size * -(depth*2-2); + depth = (xmb->depth > 1) ? 2 : 1; + xmb->x = xmb->icon_size * -(depth*2-2); for (i = 0; i < list_size; i++) { @@ -1983,12 +1982,15 @@ static void xmb_context_reset_horizontal_list( { struct texture_image ti; char sysname[256]; - char *iconpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); - char *texturepath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); - char *content_texturepath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + char *iconpath = (char*) + malloc(PATH_MAX_LENGTH * sizeof(char)); + char *texturepath = (char*) + malloc(PATH_MAX_LENGTH * sizeof(char)); + char *content_texturepath = (char*) + malloc(PATH_MAX_LENGTH * sizeof(char)); iconpath[0] = sysname[0] = - texturepath[0] = content_texturepath[0] = '\0'; + texturepath[0] = content_texturepath[0] = '\0'; fill_pathname_base_noext(sysname, path, sizeof(sysname)); @@ -2055,7 +2057,8 @@ static void xmb_refresh_horizontal_list(xmb_handle_t *xmb) menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL); - xmb->horizontal_list = (file_list_t*)calloc(1, sizeof(file_list_t)); + xmb->horizontal_list = (file_list_t*) + calloc(1, sizeof(file_list_t)); if (xmb->horizontal_list) xmb_init_horizontal_list(xmb); @@ -2159,10 +2162,13 @@ static void xmb_populate_entries(void *data, { xmb_selection_pointer_changed(xmb, false); menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL); - if (!string_is_equal(xmb_thumbnails_ident(), + if (!string_is_equal(xmb_thumbnails_ident('R'), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) xmb_update_thumbnail_image(xmb); xmb_update_savestate_thumbnail_image(xmb); + if (!string_is_equal(xmb_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + xmb_update_thumbnail_image(xmb); return; } @@ -2241,7 +2247,8 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, if (core_node) return core_node->content_icon; - switch (xmb_get_system_tab(xmb, (unsigned)xmb->categories_selection_ptr)) + switch (xmb_get_system_tab(xmb, + (unsigned)xmb->categories_selection_ptr)) { case XMB_SYSTEM_TAB_FAVORITES: return xmb->textures.list[XMB_TEXTURE_FAVORITE]; @@ -2259,6 +2266,9 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, break; } return xmb->textures.list[XMB_TEXTURE_FILE]; + case FILE_TYPE_SHADER: + case FILE_TYPE_SHADER_PRESET: + return xmb->textures.list[XMB_TEXTURE_SHADER_OPTIONS]; case FILE_TYPE_CARCHIVE: return xmb->textures.list[XMB_TEXTURE_ZIP]; case FILE_TYPE_MUSIC: @@ -2316,11 +2326,13 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, #ifdef HAVE_NETWORKING case MENU_ROOM: return xmb->textures.list[XMB_TEXTURE_ROOM]; - /* stub these out until we have the icons +#if 0 + /* stub these out until we have the icons */ case MENU_ROOM_LAN: return xmb->textures.list[XMB_TEXTURE_ROOM_LAN]; case MENU_ROOM_MITM: - return xmb->textures.list[XMB_TEXTURE_ROOM_MITM]; */ + return xmb->textures.list[XMB_TEXTURE_ROOM_MITM]; +#endif #endif } @@ -2349,13 +2361,14 @@ static void xmb_calculate_visible_range(const xmb_handle_t *xmb, float base_y = xmb->margins_screen_top; *first = 0; - *last = list_size ? list_size - 1 : 0; + *last = (unsigned)(list_size ? list_size - 1 : 0); if (current) { for (j = current; j-- > 0; ) { - float bottom = xmb_item_y(xmb, j, current) + base_y + xmb->icon_size; + float bottom = xmb_item_y(xmb, j, current) + + base_y + xmb->icon_size; if (bottom < 0) break; @@ -2384,6 +2397,7 @@ static int xmb_draw_item( file_list_t *list, float *color, const char *thumb_ident, + const char *left_thumb_ident, uint64_t frame_count, size_t i, size_t current, @@ -2402,6 +2416,7 @@ static int xmb_draw_item( unsigned ticker_limit = 35 * scale_mod[0]; xmb_node_t * node = (xmb_node_t*) file_list_get_userdata_at_offset(list, i); + settings_t *settings = config_get_ptr(); if (!node) goto iterate; @@ -2440,16 +2455,20 @@ static int xmb_draw_item( } } - if (string_is_equal(entry->value, msg_hash_to_str(MENU_ENUM_LABEL_DISABLED)) || - (string_is_equal(entry->value, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))) + if (string_is_equal(entry->value, + msg_hash_to_str(MENU_ENUM_LABEL_DISABLED)) || + (string_is_equal(entry->value, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))) { if (xmb->textures.list[XMB_TEXTURE_SWITCH_OFF]) texture_switch = xmb->textures.list[XMB_TEXTURE_SWITCH_OFF]; else do_draw_text = true; } - else if (string_is_equal(entry->value, msg_hash_to_str(MENU_ENUM_LABEL_ENABLED)) || - (string_is_equal(entry->value, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)))) + else if (string_is_equal(entry->value, + msg_hash_to_str(MENU_ENUM_LABEL_ENABLED)) || + (string_is_equal(entry->value, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)))) { if (xmb->textures.list[XMB_TEXTURE_SWITCH_ON]) texture_switch = xmb->textures.list[XMB_TEXTURE_SWITCH_ON]; @@ -2462,6 +2481,8 @@ static int xmb_draw_item( { if ( string_is_equal(entry->value, "...") || + string_is_equal(entry->value, "(PRESET)") || + string_is_equal(entry->value, "(SHADER)") || string_is_equal(entry->value, "(COMP)") || string_is_equal(entry->value, "(CORE)") || string_is_equal(entry->value, "(MOVIE)") || @@ -2476,7 +2497,7 @@ static int xmb_draw_item( { } else - do_draw_text = true; + do_draw_text = true; } else do_draw_text = true; @@ -2486,10 +2507,16 @@ static int xmb_draw_item( if (string_is_empty(entry->value)) { if (xmb->savestate_thumbnail || + !xmb->use_ps3_layout || (!string_is_equal (thumb_ident, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) - && xmb->thumbnail) + && xmb->thumbnail) || + (!string_is_equal + (left_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) + && xmb->left_thumbnail + && settings->bools.menu_xmb_vertical_thumbnails) ) ticker_limit = 40 * scale_mod[1]; else @@ -2640,7 +2667,8 @@ static void xmb_draw_items( xmb_node_t *core_node = NULL; size_t end = 0; uint64_t frame_count = xmb ? xmb->frame_count : 0; - const char *thumb_ident = xmb_thumbnails_ident(); + const char *thumb_ident = xmb_thumbnails_ident('R'); + const char *left_thumb_ident= xmb_thumbnails_ident('L'); if (!list || !list->size || !xmb) return; @@ -2665,7 +2693,7 @@ static void xmb_draw_items( if (list == xmb->selection_buf_old) { xmb_node_t *node = (xmb_node_t*) - file_list_get_userdata_at_offset(list, current); + file_list_get_userdata_at_offset(list, current); if (node && (uint8_t)(255 * node->alpha) == 0) return; @@ -2673,10 +2701,10 @@ static void xmb_draw_items( i = 0; } - first = i; - last = end - 1; + first = (unsigned)i; + last = (unsigned)(end - 1); - xmb_calculate_visible_range(xmb, height, end, current, &first, &last); + xmb_calculate_visible_range(xmb, height, end, (unsigned)current, &first, &last); menu_display_blend_begin(video_info); @@ -2690,7 +2718,7 @@ static void xmb_draw_items( &entry, &mymat, xmb, core_node, - list, color, thumb_ident, + list, color, thumb_ident, left_thumb_ident, frame_count, i, current, width, height); @@ -2725,17 +2753,18 @@ static void xmb_render(void *data, bool is_idle) if (pointer_enable || mouse_enable) { + unsigned height; size_t selection = menu_navigation_get_selection(); int16_t pointer_y = menu_input_pointer_state(MENU_POINTER_Y_AXIS); int16_t mouse_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS) + (xmb->cursor_size/2); unsigned first = 0, last = end; - unsigned height; video_driver_get_size(NULL, &height); if (height) - xmb_calculate_visible_range(xmb, height, end, selection, &first, &last); + xmb_calculate_visible_range(xmb, height, + end, (unsigned)selection, &first, &last); for (i = first; i <= last; i++) { @@ -2923,39 +2952,45 @@ static void xmb_draw_dark_layer( static void xmb_frame(void *data, video_frame_info_t *video_info) { - size_t selection; - size_t percent_width = 0; math_matrix_4x4 mymat; unsigned i; - float thumb_width, thumb_height; menu_display_ctx_rotate_draw_t rotate_draw; char msg[1024]; char title_msg[255]; char title_truncated[255]; - settings_t *settings = config_get_ptr(); - unsigned width = video_info->width; - unsigned height = video_info->height; + size_t selection = 0; + size_t percent_width = 0; + const int min_thumb_size = 50; bool render_background = false; file_list_t *selection_buf = NULL; + unsigned width = video_info->width; + unsigned height = video_info->height; + const float under_thumb_margin = 0.96; + float scale_factor = 0.0f; + float pseudo_font_length = 0.0f; xmb_handle_t *xmb = (xmb_handle_t*)data; + settings_t *settings = config_get_ptr(); if (!xmb) return; + scale_factor = (settings->uints.menu_xmb_scale_factor * (float)width) / (1920.0 * 100); + pseudo_font_length = xmb->icon_spacing_horizontal * 4 - xmb->icon_size / 4; + xmb->frame_count++; msg[0] = '\0'; title_msg[0] = '\0'; title_truncated[0] = '\0'; - font_driver_bind_block(xmb->font, &xmb->raster_block); + font_driver_bind_block(xmb->font, &xmb->raster_block); font_driver_bind_block(xmb->font2, &xmb->raster_block2); - xmb->raster_block.carr.coords.vertices = 0; + xmb->raster_block.carr.coords.vertices = 0; xmb->raster_block2.carr.coords.vertices = 0; menu_display_set_alpha(coord_black, MIN( - (float)video_info->xmb_alpha_factor/100, xmb->alpha)); + (float)video_info->xmb_alpha_factor/100, xmb->alpha)); menu_display_set_alpha(coord_white, xmb->alpha); xmb_draw_bg( @@ -2970,11 +3005,13 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) selection = menu_navigation_get_selection(); - strlcpy(title_truncated, xmb->title_name, sizeof(title_truncated)); + strlcpy(title_truncated, + xmb->title_name, sizeof(title_truncated)); + if (selection > 1) { /* skip 25 utf8 multi-byte chars */ - char* end = title_truncated; + char *end = title_truncated; for(i = 0; i < 25 && *end; i++) { @@ -3009,48 +3046,288 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) menu_display_rotate_z(&rotate_draw, video_info); menu_display_blend_begin(video_info); + /* Save State thumbnail, right side */ if (xmb->savestate_thumbnail) + { xmb_draw_thumbnail(video_info, xmb, &coord_white[0], width, height, - xmb->margins_screen_left * scale_mod[5] - + xmb->icon_spacing_horizontal + - xmb->icon_spacing_horizontal * 4 - xmb->icon_size / 4, - xmb->margins_screen_top + xmb->icon_size + xmb->savestate_thumbnail_height * scale_mod[4], - xmb->savestate_thumbnail_width, xmb->savestate_thumbnail_height, + xmb->margins_screen_left * scale_mod[5] + + xmb->icon_spacing_horizontal + pseudo_font_length, + xmb->margins_screen_top + xmb->icon_size + + xmb->savestate_thumbnail_height * scale_mod[4], + xmb->savestate_thumbnail_width * scale_mod[4], + xmb->savestate_thumbnail_height * scale_mod[4], xmb->savestate_thumbnail); - else if (xmb->thumbnail - && !string_is_equal(xmb_thumbnails_ident(), - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + } + + /* Right thumbnail big size */ + if (xmb->use_ps3_layout && + (!settings->bools.menu_xmb_vertical_thumbnails || + (settings->bools.menu_xmb_vertical_thumbnails && !xmb->left_thumbnail))) { + /* Do not draw the right thumbnail if there is no space available */ + + if (((xmb->margins_screen_top + + xmb->icon_size + min_thumb_size) <= height) && + ((xmb->margins_screen_left * scale_mod[5] + + xmb->icon_spacing_horizontal + + pseudo_font_length + min_thumb_size) <= width)) + { + if (xmb->thumbnail + && !string_is_equal(xmb_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + /* Limit thumbnail width */ + + float thumb_width = 0.0f; + float thumb_height = 0.0f; + float thumb_max_width = (float)width - (xmb->icon_size / 6) + - (xmb->margins_screen_left * scale_mod[5]) - + xmb->icon_spacing_horizontal - pseudo_font_length; + #ifdef XMB_DEBUG - RARCH_LOG("[XMB thumbnail] width: %.2f, height: %.2f\n", xmb->thumbnail_width, xmb->thumbnail_height); - RARCH_LOG("[XMB thumbnail] w: %.2f, h: %.2f\n", width, height); + RARCH_LOG("[XMB thumbnail] width: %.2f, height: %.2f\n", + xmb->thumbnail_width, xmb->thumbnail_height); + RARCH_LOG("[XMB thumbnail] w: %.2f, h: %.2f\n", width, height); #endif - /* Limit thumbnail height to screen height + margin. */ - if( xmb->margins_screen_top + xmb->icon_size + xmb->thumbnail_height * scale_mod[4] >= - (float)(height * 0.96) ) - { - thumb_width = xmb->thumbnail_width * - (((float)(height * 0.96) - xmb->margins_screen_top - xmb->icon_size) / - (xmb->thumbnail_height * scale_mod[4])); - thumb_height = xmb->thumbnail_height * - (((float)(height * 0.96) - xmb->margins_screen_top - xmb->icon_size) / - (xmb->thumbnail_height * scale_mod[4])); - } - else - { - thumb_width = xmb->thumbnail_width; - thumb_height = xmb->thumbnail_height; - } + if (xmb->thumbnail_width * scale_mod[4] > thumb_max_width) + { + thumb_width = (xmb->thumbnail_width * scale_mod[4]) * + (thumb_max_width / (xmb->thumbnail_width * scale_mod[4])); + thumb_height = (xmb->thumbnail_height * scale_mod[4]) * + (thumb_max_width / (xmb->thumbnail_width * scale_mod[4])); + } + else + { + thumb_width = xmb->thumbnail_width * scale_mod[4]; + thumb_height = xmb->thumbnail_height * scale_mod[4]; + } - xmb_draw_thumbnail(video_info, - xmb, &coord_white[0], width, height, - xmb->margins_screen_left * scale_mod[5] + xmb->icon_spacing_horizontal + - xmb->icon_spacing_horizontal*4 - xmb->icon_size / 4, - xmb->margins_screen_top + xmb->icon_size + thumb_height * scale_mod[4], - thumb_width, thumb_height, - xmb->thumbnail); + /* Limit thumbnail height to screen height + margin. */ + + if (xmb->margins_screen_top + xmb->icon_size + thumb_height >= + ((float)height * under_thumb_margin)) + { + thumb_width = thumb_width * + ((((float)height * under_thumb_margin) - + xmb->margins_screen_top - xmb->icon_size) / + thumb_height); + thumb_height = thumb_height * + ((((float)height * under_thumb_margin) - + xmb->margins_screen_top - xmb->icon_size) / + thumb_height); + } + + xmb_draw_thumbnail(video_info, + xmb, &coord_white[0], width, height, + (float)width - (xmb->icon_size / 6) - thumb_max_width + + ((thumb_max_width - thumb_width) / 2), + xmb->margins_screen_top + xmb->icon_size + thumb_height, + thumb_width, thumb_height, + xmb->thumbnail); + } + } + } + + /* Left thumbnail in the left margin */ + /* Do not draw the left thumbnail if there is no space available */ + if (xmb->use_ps3_layout && + !settings->bools.menu_xmb_vertical_thumbnails && + (xmb->margins_screen_top + xmb->icon_size * + (!(xmb->depth == 1)? 2.1 : 1) + min_thumb_size) + <= (float)height) + { + /* Left Thumbnail in the left margin */ + + if (xmb->left_thumbnail + && !string_is_equal(xmb_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + /* Limit left thumbnail width */ + + float left_thumb_width = 0.0f; + float left_thumb_height = 0.0f; + float thumb_max_width = xmb->icon_size * 3.4; + +#ifdef XMB_DEBUG + RARCH_LOG("[XMB left thumbnail] width: %.2f, height: %.2f\n", + xmb->left_thumbnail_width, xmb->left_thumbnail_height); + RARCH_LOG("[XMB left thumbnail] w: %.2f, h: %.2f\n", width, height); +#endif + + if (xmb->left_thumbnail_width * scale_mod[4] > thumb_max_width) + { + left_thumb_width = (xmb->left_thumbnail_width * scale_mod[4]) * + (thumb_max_width / (xmb->left_thumbnail_width * scale_mod[4])); + left_thumb_height = (xmb->left_thumbnail_height * scale_mod[4]) * + (thumb_max_width / (xmb->left_thumbnail_width * scale_mod[4])); + } + else + { + left_thumb_width = xmb->left_thumbnail_width * scale_mod[4]; + left_thumb_height = xmb->left_thumbnail_height * scale_mod[4]; + } + + /* Limit left thumbnail height to screen height + margin. */ + if (xmb->margins_screen_top + xmb->icon_size * + (!(xmb->depth == 1)? 2.1 : 1) + + left_thumb_height >= + ((float)height - (96.0 * scale_factor))) + { + left_thumb_width = left_thumb_width * + ((((float)height - (96.0 * scale_factor)) + - xmb->margins_screen_top - + (xmb->icon_size * (!(xmb->depth == 1)? 2.1 : 1))) / + left_thumb_height); + + left_thumb_height = left_thumb_height * + ((((float)height - (96.0 * scale_factor)) + - xmb->margins_screen_top - + (xmb->icon_size * (!(xmb->depth == 1)? 2.1 : 1))) / + left_thumb_height); + } + + xmb_draw_thumbnail(video_info, + xmb, &coord_white[0], width, height, + (xmb->icon_size / 6) + + ((thumb_max_width - left_thumb_width) / 2), + xmb->margins_screen_top + xmb->icon_size * + (!(xmb->depth == 1)? 2.1 : 1) + left_thumb_height, + left_thumb_width, left_thumb_height, + xmb->left_thumbnail); + } + } + + /* No Right Thumbnail, draw only the left one big size */ + if (xmb->use_ps3_layout && + settings->bools.menu_xmb_vertical_thumbnails && !xmb->thumbnail) + { + /* Do not draw the left thumbnail if there is no space available */ + + if (((xmb->margins_screen_top + + xmb->icon_size + min_thumb_size) <= height) && + ((xmb->margins_screen_left * scale_mod[5] + + xmb->icon_spacing_horizontal + + pseudo_font_length + min_thumb_size) <= width)) + { + if (xmb->left_thumbnail + && !string_is_equal(xmb_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + /* Limit left thumbnail width */ + + float left_thumb_width = 0.0f; + float left_thumb_height = 0.0f; + float thumb_max_width = (float)width - (xmb->icon_size / 6) + - (xmb->margins_screen_left * scale_mod[5]) - + xmb->icon_spacing_horizontal - pseudo_font_length; + +#ifdef XMB_DEBUG + RARCH_LOG("[XMB thumbnail] width: %.2f, height: %.2f\n", + xmb->thumbnail_width, xmb->thumbnail_height); + RARCH_LOG("[XMB thumbnail] w: %.2f, h: %.2f\n", width, height); +#endif + + if (xmb->left_thumbnail_width * scale_mod[4] > thumb_max_width) + { + left_thumb_width = (xmb->left_thumbnail_width * scale_mod[4]) * + (thumb_max_width / (xmb->left_thumbnail_width * scale_mod[4])); + left_thumb_height = (xmb->left_thumbnail_height * scale_mod[4]) * + (thumb_max_width / (xmb->left_thumbnail_width * scale_mod[4])); + } + else + { + left_thumb_width = xmb->left_thumbnail_width * scale_mod[4]; + left_thumb_height = xmb->left_thumbnail_height * scale_mod[4]; + } + + /* Limit left thumbnail height to screen height + margin. */ + + if (xmb->margins_screen_top + xmb->icon_size + left_thumb_height >= + ((float)height * under_thumb_margin)) + { + left_thumb_width = left_thumb_width * + ((((float)height * under_thumb_margin) - + xmb->margins_screen_top - xmb->icon_size) / + left_thumb_height); + left_thumb_height = left_thumb_height * + ((((float)height * under_thumb_margin) - + xmb->margins_screen_top - xmb->icon_size) / + left_thumb_height); + } + + xmb_draw_thumbnail(video_info, + xmb, &coord_white[0], width, height, + (float)width - (xmb->icon_size / 6) - thumb_max_width + + ((thumb_max_width - left_thumb_width) / 2), + xmb->margins_screen_top + xmb->icon_size + left_thumb_height, + left_thumb_width, left_thumb_height, + xmb->left_thumbnail); + } + } + } + + /* PSP Layout Only - Left thumbnail in the left margin */ + /* Do not draw the left thumbnail if there is no space available */ + if (!xmb->use_ps3_layout && + (xmb->margins_screen_top + xmb->icon_size * 1.5) + <= (float)height) + { + /* Left Thumbnail in the left margin */ + + if (xmb->left_thumbnail + && !string_is_equal(xmb_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + /* Limit left thumbnail width */ + + float left_thumb_width = 0.0f; + float left_thumb_height = 0.0f; + float thumb_max_width = xmb->icon_size * 2.4; + +#ifdef XMB_DEBUG + RARCH_LOG("[XMB left thumbnail] width: %.2f, height: %.2f\n", + xmb->left_thumbnail_width, xmb->left_thumbnail_height); + RARCH_LOG("[XMB left thumbnail] w: %.2f, h: %.2f\n", width, height); +#endif + + if (xmb->left_thumbnail_width > thumb_max_width) + { + left_thumb_width = xmb->left_thumbnail_width * + (thumb_max_width / xmb->left_thumbnail_width); + left_thumb_height = xmb->left_thumbnail_height * + (thumb_max_width / xmb->left_thumbnail_width); + } + else + { + left_thumb_width = xmb->left_thumbnail_width; + left_thumb_height = xmb->left_thumbnail_height; + } + + /* Limit left thumbnail height to screen height + margin. */ + if (xmb->margins_screen_top + xmb->icon_size + + left_thumb_height >= ((float)height - (xmb->icon_size * 0.5))) + { + left_thumb_width = left_thumb_width * + (((float)height - (xmb->icon_size * 0.5) - + xmb->margins_screen_top - xmb->icon_size) / + left_thumb_height); + + left_thumb_height = left_thumb_height * + (((float)height - (xmb->icon_size * 0.5) - + xmb->margins_screen_top - xmb->icon_size) / + left_thumb_height); + } + + xmb_draw_thumbnail(video_info, + xmb, &coord_white[0], width, height, + ((thumb_max_width - left_thumb_width) / 2), + xmb->margins_screen_top + (xmb->icon_size * (!(xmb->depth == 1)? 2.2 : 0.75)) + + left_thumb_height, + left_thumb_width, left_thumb_height, + xmb->left_thumbnail); + } } /* Clock image */ @@ -3099,7 +3376,9 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) snprintf(msg, sizeof(msg), "%d%%", percent); - percent_width = (unsigned)font_driver_get_message_width(xmb->font, msg, (unsigned)strlen(msg), 1); + percent_width = (unsigned) + font_driver_get_message_width( + xmb->font, msg, (unsigned)strlen(msg), 1); xmb_draw_text(video_info, xmb, msg, width - xmb->margins_title_left - x_pos, @@ -3154,7 +3433,8 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) } /* Arrow image */ - menu_display_set_alpha(coord_white, MIN(xmb->textures_arrow_alpha, xmb->alpha)); + menu_display_set_alpha(coord_white, + MIN(xmb->textures_arrow_alpha, xmb->alpha)); if (coord_white[3] != 0) xmb_draw_icon(video_info, @@ -3162,7 +3442,8 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) &mymat, xmb->textures.list[XMB_TEXTURE_ARROW], xmb->x + xmb->margins_screen_left + - xmb->icon_spacing_horizontal - xmb->icon_size / 2.0 + xmb->icon_size, + xmb->icon_spacing_horizontal - + xmb->icon_size / 2.0 + xmb->icon_size, xmb->margins_screen_top + xmb->icon_size / 2.0 + xmb->icon_spacing_vertical * xmb->active_item_factor, @@ -3178,7 +3459,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) /* Horizontal tab icons */ for (i = 0; i <= xmb_list_get_size(xmb, MENU_LIST_HORIZONTAL) - + xmb->system_tab_end; i++) + + xmb->system_tab_end; i++) { xmb_node_t *node = xmb_get_node(xmb, i); @@ -3193,9 +3474,11 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) math_matrix_4x4 mymat; uintptr_t texture = node->icon; float x = xmb->x + xmb->categories_x_pos + - xmb->margins_screen_left + - xmb->icon_spacing_horizontal * (i + 1) - xmb->icon_size / 2.0; - float y = xmb->margins_screen_top + xmb->icon_size / 2.0; + xmb->margins_screen_left + + xmb->icon_spacing_horizontal + * (i + 1) - xmb->icon_size / 2.0; + float y = xmb->margins_screen_top + + xmb->icon_size / 2.0; float rotation = 0; float scale_factor = node->zoom; @@ -3224,6 +3507,141 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) } } + /* Right side 2 thumbnails on top of each other */ + /* here to be displayed above the horizontal icons */ + if (xmb->use_ps3_layout && + xmb->left_thumbnail && xmb->thumbnail && + settings->bools.menu_xmb_vertical_thumbnails) + { + /* Do not draw the right thumbnail if there is no space available */ + if (((xmb->margins_screen_top + + xmb->icon_size + min_thumb_size) <= height) && + ((xmb->margins_screen_left * scale_mod[5] + + xmb->icon_spacing_horizontal + + pseudo_font_length + min_thumb_size) <= width)) + { + if (xmb->thumbnail && + !string_is_equal(xmb_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + /* Limit right thumbnail width */ + + float thumb_width = 0.0f; + float thumb_height = 0.0f; + float thumb_max_width = (float)width - (xmb->icon_size / 6) - + (xmb->margins_screen_left * scale_mod[5]) - + xmb->icon_spacing_horizontal - pseudo_font_length; + +#ifdef XMB_DEBUG + RARCH_LOG("[XMB thumbnail] width: %.2f, height: %.2f\n", + xmb->thumbnail_width, xmb->thumbnail_height); + RARCH_LOG("[XMB thumbnail] w: %.2f, h: %.2f\n", width, height); +#endif + + if (xmb->thumbnail_width * scale_mod[4] > thumb_max_width) + { + thumb_width = (xmb->thumbnail_width * scale_mod[4]) * + (thumb_max_width / (xmb->thumbnail_width * scale_mod[4])); + thumb_height = (xmb->thumbnail_height * scale_mod[4]) * + (thumb_max_width / (xmb->thumbnail_width * scale_mod[4])); + } + else + { + thumb_width = xmb->thumbnail_width * scale_mod[4]; + thumb_height = xmb->thumbnail_height * scale_mod[4]; + } + + /* Limit right thumbnail height to usable area. */ + + if (thumb_height >= + ((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) + { + thumb_width = thumb_width * + ((((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) / + thumb_height); + thumb_height = thumb_height * + ((((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) / + thumb_height); + } + + xmb_draw_thumbnail(video_info, + xmb, &coord_white[0], width, height, + (float)width - (xmb->icon_size / 6) - thumb_max_width + + ((thumb_max_width - thumb_width) / 2), + xmb->icon_size + ((((float)height / 2 - + (xmb->icon_size + (xmb->icon_size/12))) - thumb_height) / 2) + + thumb_height, + thumb_width, thumb_height, + xmb->thumbnail); + } + } + + /* Do not draw the left thumbnail if there is no space available */ + + if (((xmb->margins_screen_top + + xmb->icon_size + min_thumb_size) <= height) && + ((xmb->margins_screen_left * scale_mod[5] + + xmb->icon_spacing_horizontal + + pseudo_font_length + min_thumb_size) <= width)) + { + if (xmb->left_thumbnail && + !string_is_equal(xmb_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + /* Limit left thumbnail width */ + + float left_thumb_width = 0.0f; + float left_thumb_height = 0.0f; + float thumb_max_width = (float)width - (xmb->icon_size / 6) - + (xmb->margins_screen_left * scale_mod[5]) - + xmb->icon_spacing_horizontal - pseudo_font_length; + +#ifdef XMB_DEBUG + RARCH_LOG("[XMB left thumbnail] width: %.2f, height: %.2f\n", + xmb->left_thumbnail_width, xmb->left_thumbnail_height); + RARCH_LOG("[XMB left thumbnail] w: %.2f, h: %.2f\n", width, height); +#endif + + if (xmb->left_thumbnail_width * scale_mod[4] > thumb_max_width) + { + left_thumb_width = (xmb->left_thumbnail_width * scale_mod[4]) * + (thumb_max_width / (xmb->left_thumbnail_width * scale_mod[4])); + left_thumb_height = (xmb->left_thumbnail_height * scale_mod[4]) * + (thumb_max_width / (xmb->left_thumbnail_width * scale_mod[4])); + } + else + { + left_thumb_width = xmb->left_thumbnail_width * scale_mod[4]; + left_thumb_height = xmb->left_thumbnail_height * scale_mod[4]; + } + + /* Limit left thumbnail height to usable area. */ + + if (left_thumb_height >= + ((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) + { + left_thumb_width = left_thumb_width * + ((((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) / + left_thumb_height); + left_thumb_height = left_thumb_height * + ((((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) / + left_thumb_height); + } + + xmb_draw_thumbnail(video_info, + xmb, &coord_white[0], width, height, + (float)width - (xmb->icon_size / 6) - thumb_max_width + + ((thumb_max_width - left_thumb_width) / 2), + xmb->icon_size + + (((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) + + (((((float)height - ((xmb->icon_size / 6) * 2) - xmb->icon_size) / 2) - + left_thumb_height) / 2) + left_thumb_height, + left_thumb_width, left_thumb_height, + xmb->left_thumbnail); + } + } + } + menu_display_blend_end(video_info); /* Vertical icons */ @@ -3234,7 +3652,8 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) xmb->selection_buf_old, xmb->selection_ptr_old, (xmb_list_get_size(xmb, MENU_LIST_PLAIN) > 1) - ? xmb->categories_selection_ptr : xmb->categories_selection_ptr_old, + ? xmb->categories_selection_ptr : + xmb->categories_selection_ptr_old, &item_color[0], width, height); @@ -3333,7 +3752,8 @@ static void xmb_layout_ps3(xmb_handle_t *xmb, int width) new_header_height = 128.0 * scale_factor; - xmb->thumbnail_width = 460.0 * scale_factor; + xmb->thumbnail_width = 1024.0 * scale_factor; + xmb->left_thumbnail_width = 1024.0 * scale_factor; xmb->savestate_thumbnail_width= 460.0 * scale_factor; xmb->cursor_size = 64.0 * scale_factor; @@ -3358,20 +3778,6 @@ static void xmb_layout_ps3(xmb_handle_t *xmb, int width) xmb->icon_size = 128.0 * scale_factor; xmb->font_size = new_font_size; -#ifdef XMB_DEBUG - RARCH_LOG("[XMB] margin screen left: %.2f\n", xmb->margins_screen_left); - RARCH_LOG("[XMB] margin screen top: %.2f\n", xmb->margins_screen_top); - RARCH_LOG("[XMB] margin title left: %.2f\n", xmb->margins_title_left); - RARCH_LOG("[XMB] margin title top: %.2f\n", xmb->margins_title_top); - RARCH_LOG("[XMB] margin title bott: %.2f\n", xmb->margins_title_bottom); - RARCH_LOG("[XMB] margin label left: %.2f\n", xmb->margins_label_left); - RARCH_LOG("[XMB] margin label top: %.2f\n", xmb->margins_label_top); - RARCH_LOG("[XMB] margin sett left: %.2f\n", xmb->margins_setting_left); - RARCH_LOG("[XMB] icon spacing hor: %.2f\n", xmb->icon_spacing_horizontal); - RARCH_LOG("[XMB] icon spacing ver: %.2f\n", xmb->icon_spacing_vertical); - RARCH_LOG("[XMB] icon size: %.2f\n", xmb->icon_size); -#endif - menu_display_set_header_height(new_header_height); } @@ -3381,9 +3787,9 @@ static void xmb_layout_psp(xmb_handle_t *xmb, int width) settings_t *settings = config_get_ptr(); float scale_factor = ((settings->uints.menu_xmb_scale_factor * width) / (1920.0 * 100)) * 1.5; - #ifdef _3DS - scale_factor = settings->uints.menu_xmb_scale_factor / 400.0; + scale_factor = + settings->uints.menu_xmb_scale_factor / 400.0; #endif xmb->above_subitem_offset = 1.5; @@ -3409,6 +3815,7 @@ static void xmb_layout_psp(xmb_handle_t *xmb, int width) xmb->margins_screen_top = (256+32) * scale_factor; xmb->thumbnail_width = 460.0 * scale_factor; + xmb->left_thumbnail_width = 400.0 * scale_factor; xmb->savestate_thumbnail_width= 460.0 * scale_factor; xmb->cursor_size = 64.0; @@ -3427,6 +3834,49 @@ static void xmb_layout_psp(xmb_handle_t *xmb, int width) xmb->icon_size = 128.0 * scale_factor; xmb->font_size = new_font_size; + menu_display_set_header_height(new_header_height); +} + +static void xmb_layout(xmb_handle_t *xmb) +{ + unsigned width, height, i, current, end; + settings_t *settings = config_get_ptr(); + file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); + size_t selection = menu_navigation_get_selection(); + + video_driver_get_size(&width, &height); + + switch (settings->uints.menu_xmb_layout) + { + /* Automatic */ + case 0: + { + xmb->use_ps3_layout = false; + xmb->use_ps3_layout = width > 320 && height > 240; + + /* Mimic the layout of the PSP instead of the PS3 on tiny screens */ + if (xmb->use_ps3_layout) + xmb_layout_ps3(xmb, width); + else + xmb_layout_psp(xmb, width); + } + break; + /* PS3 */ + case 1: + { + xmb->use_ps3_layout = true; + xmb_layout_ps3(xmb, width); + } + break; + /* PSP */ + case 2: + { + xmb->use_ps3_layout = false; + xmb_layout_psp(xmb, width); + } + break; + } + #ifdef XMB_DEBUG RARCH_LOG("[XMB] margin screen left: %.2f\n", xmb->margins_screen_left); RARCH_LOG("[XMB] margin screen top: %.2f\n", xmb->margins_screen_top); @@ -3441,30 +3891,13 @@ static void xmb_layout_psp(xmb_handle_t *xmb, int width) RARCH_LOG("[XMB] icon size: %.2f\n", xmb->icon_size); #endif - menu_display_set_header_height(new_header_height); -} - -static void xmb_layout(xmb_handle_t *xmb) -{ - unsigned width, height, i, current, end; - file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); - size_t selection = menu_navigation_get_selection(); - - video_driver_get_size(&width, &height); - - /* Mimic the layout of the PSP instead of the PS3 on tiny screens */ - if (width > 320 && height > 240) - xmb_layout_ps3(xmb, width); - else - xmb_layout_psp(xmb, width); - current = (unsigned)selection; end = (unsigned)menu_entries_get_size(); for (i = 0; i < end; i++) { - float ia = xmb->items_passive_alpha; - float iz = xmb->items_passive_zoom; + float ia = xmb->items_passive_alpha; + float iz = xmb->items_passive_zoom; xmb_node_t *node = (xmb_node_t*)file_list_get_userdata_at_offset( selection_buf, i); @@ -3565,16 +3998,28 @@ static void *xmb_init(void **userdata, bool video_is_threaded) menu_handle_t *menu = (menu_handle_t*)calloc(1, sizeof(*menu)); float scale_value = settings->uints.menu_xmb_scale_factor; + /* scaling multiplier formulas made from these values: */ + /* xmb_scale 50 = {2.5, 2.5, 2, 1.7, 2.5, 4, 2.4, 2.5} */ + /* xmb_scale 75 = { 2, 1.6, 1.6, 1.4, 1.5, 2.3, 1.9, 1.3} */ + if (scale_value < 100) { - scale_mod[0] = -0.03 * scale_value + 4.083333; + /* text length & word wrap (base 35 apply to file browser, 1st column) */ + scale_mod[0] = -0.03 * scale_value + 4.083; + /* playlist text length when thumbnail is ON (small, base 40) */ scale_mod[1] = -0.03 * scale_value + 3.95; - scale_mod[2] = -0.02 * scale_value + 3.033333; - scale_mod[3] = -0.014 * scale_value + 2.416667; - scale_mod[4] = -0.03 * scale_value + 3.916667; - scale_mod[5] = -0.06 * scale_value + 6.933333; - scale_mod[6] = -0.028 * scale_value + 3.866667; - scale_mod[7] = 134.179 * pow(scale_value, -1.077852); + /* playlist text length when thumbnail is OFF (large, base 70) */ + scale_mod[2] = -0.02 * scale_value + 3.033; + /* sub-label length & word wrap */ + scale_mod[3] = -0.014 * scale_value + 2.416; + /* thumbnail size & vertical margin from top */ + scale_mod[4] = -0.03 * scale_value + 3.916; + /* thumbnail horizontal left margin (horizontal positioning) */ + scale_mod[5] = -0.06 * scale_value + 6.933; + /* margin before 2nd column start (shaders parameters, cheats...) */ + scale_mod[6] = -0.028 * scale_value + 3.866; + /* text length & word wrap (base 35 apply to 2nd column in cheats, shaders, etc) */ + scale_mod[7] = 134.179 * pow(scale_value, -1.0778); for (i = 0; i < 8; i++) if (scale_mod[i] < 1) @@ -3601,7 +4046,7 @@ static void *xmb_init(void **userdata, bool video_is_threaded) if (!xmb->selection_buf_old) goto error; - xmb->categories_active_idx = 0; + xmb->categories_active_idx = 0; xmb->categories_active_idx_old = 0; xmb->x = 0; xmb->categories_x_pos = 0; @@ -3710,6 +4155,8 @@ static void xmb_free(void *data) free(xmb->savestate_thumbnail_file_path); if (!string_is_empty(xmb->thumbnail_file_path)) free(xmb->thumbnail_file_path); + if (!string_is_empty(xmb->left_thumbnail_file_path)) + free(xmb->left_thumbnail_file_path); if (!string_is_empty(xmb->bg_file_path)) free(xmb->bg_file_path); } @@ -3754,6 +4201,16 @@ static bool xmb_load_image(void *userdata, void *data, enum menu_image_type type TEXTURE_FILTER_MIPMAP_LINEAR, &xmb->thumbnail); } break; + case MENU_IMAGE_LEFT_THUMBNAIL: + { + struct texture_image *img = (struct texture_image*)data; + xmb->left_thumbnail_height = xmb->left_thumbnail_width + * (float)img->height / (float)img->width; + video_driver_texture_unload(&xmb->left_thumbnail); + video_driver_texture_load(data, + TEXTURE_FILTER_MIPMAP_LINEAR, &xmb->left_thumbnail); + } + break; case MENU_IMAGE_SAVESTATE_THUMBNAIL: { struct texture_image *img = (struct texture_image*)data; @@ -3876,12 +4333,13 @@ static const char *xmb_texture_path(unsigned id) return "netplay.png"; case XMB_TEXTURE_ROOM: return "room.png"; - /* stub these out until we have the icons +#if 0 + /* stub these out until we have the icons */ case XMB_TEXTURE_ROOM_LAN: return "room_lan.png"; case XMB_TEXTURE_ROOM_MITM: return "room_mitm.png"; - */ +#endif #endif case XMB_TEXTURE_KEY: return "key.png"; @@ -4008,7 +4466,10 @@ static void xmb_context_reset(void *data, bool is_threaded) xmb_context_reset_background(iconpath); xmb_context_reset_horizontal_list(xmb); - if (!string_is_equal(xmb_thumbnails_ident(), + if (!string_is_equal(xmb_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + xmb_update_thumbnail_image(xmb); + if (!string_is_equal(xmb_thumbnails_ident('R'), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) xmb_update_thumbnail_image(xmb); xmb_update_savestate_thumbnail_image(xmb); @@ -4179,7 +4640,7 @@ static void xmb_list_cache(void *data, enum menu_list_type type, unsigned action xmb->selection_ptr_old = selection; xmb_calculate_visible_range(xmb, height, selection_buf->size, - xmb->selection_ptr_old, &first, &last); + (unsigned)xmb->selection_ptr_old, &first, &last); xmb_list_deep_copy(selection_buf, xmb->selection_buf_old, first, last); @@ -4316,6 +4777,7 @@ static void xmb_context_destroy(void *data) video_driver_texture_unload(&xmb->textures.list[i]); video_driver_texture_unload(&xmb->thumbnail); + video_driver_texture_unload(&xmb->left_thumbnail); video_driver_texture_unload(&xmb->savestate_thumbnail); xmb_context_destroy_horizontal_list(xmb); @@ -4368,7 +4830,7 @@ static void xmb_toggle(void *userdata, bool menu_on) static int deferred_push_content_actions(menu_displaylist_info_t *info) { if (!menu_displaylist_ctl( - DISPLAYLIST_HORIZONTAL_CONTENT_ACTIONS, info)) + DISPLAYLIST_HORIZONTAL_CONTENT_ACTIONS, info)) return -1; menu_displaylist_process(info); menu_displaylist_info_free(info); @@ -4406,7 +4868,7 @@ static int xmb_list_push(void *data, void *userdata, { menu_displaylist_ctx_parse_entry_t entry; int ret = -1; - int i = 0; + unsigned i = 0; core_info_list_t *list = NULL; menu_handle_t *menu = (menu_handle_t*)data; @@ -4509,7 +4971,7 @@ static int xmb_list_push(void *data, void *userdata, if (subsystem) { - for (i = 0; i < system->subsystem.size; i++, subsystem++) + for (i = 0; i < (unsigned)system->subsystem.size; i++, subsystem++) { char s[PATH_MAX_LENGTH]; if (content_get_subsystem() == i) @@ -4732,7 +5194,7 @@ menu_ctx_driver_t menu_ctx_xmb = { xmb_update_thumbnail_image, xmb_set_thumbnail_system, xmb_set_thumbnail_content, - xmb_osk_ptr_at_pos, + menu_display_osk_ptr_at_pos, xmb_update_savestate_thumbnail_path, xmb_update_savestate_thumbnail_image }; diff --git a/menu/drivers/xui.cpp b/menu/drivers/xui.cpp index 0d4c8767d0..837a4cb023 100644 --- a/menu/drivers/xui.cpp +++ b/menu/drivers/xui.cpp @@ -15,6 +15,8 @@ * If not, see . */ +#define CINTERFACE + #include #include #include @@ -47,6 +49,7 @@ #include "../../gfx/drivers/d3d.h" #include "../../gfx/common/d3d_common.h" +#include "../../gfx/common/d3d9_common.h" #define XUI_CONTROL_NAVIGATE_OK (XUI_CONTROL_NAVIGATE_RIGHT + 1) @@ -236,7 +239,7 @@ HRESULT XuiTextureLoader(IXuiDevice *pDevice, LPCWSTR szFileName, D3DX_DEFAULT_NONPOW2, 1, D3DUSAGE_CPU_CACHED_MEMORY, - (D3DFORMAT)d3d_get_argb8888_format(), + (D3DFORMAT)d3d9_get_argb8888_format(), D3DPOOL_DEFAULT, D3DX_FILTER_NONE, D3DX_FILTER_NONE, diff --git a/menu/drivers/zarch.c b/menu/drivers/zarch.c index 609341055f..495f1eab7d 100644 --- a/menu/drivers/zarch.c +++ b/menu/drivers/zarch.c @@ -1084,7 +1084,7 @@ static bool zarch_load_image(void *userdata, &zui->textures.bg); break; case MENU_IMAGE_THUMBNAIL: - break; + case MENU_IMAGE_LEFT_THUMBNAIL: case MENU_IMAGE_SAVESTATE_THUMBNAIL: /* TODO/FIXME -implement */ break; diff --git a/menu/drivers_display/menu_display_d3d10.c b/menu/drivers_display/menu_display_d3d10.c new file mode 100644 index 0000000000..7579fc8791 --- /dev/null +++ b/menu/drivers_display/menu_display_d3d10.c @@ -0,0 +1,289 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2018 - Daniel De Matteis + * Copyright (C) 2014-2018 - Ali Bouhlel + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#define CINTERFACE + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../menu_driver.h" + +#include "../../retroarch.h" +#include "../../gfx/font_driver.h" +#include "../../gfx/video_driver.h" +#include "../../gfx/common/d3d10_common.h" + +static const float* menu_display_d3d10_get_default_vertices(void) +{ + return NULL; +} + +static const float* menu_display_d3d10_get_default_tex_coords(void) +{ + return NULL; +} + +static void* menu_display_d3d10_get_default_mvp(video_frame_info_t *video_info) +{ + return NULL; +} + +static void menu_display_d3d10_blend_begin(video_frame_info_t *video_info) +{ + d3d10_video_t* d3d10 = video_info ? (d3d10_video_t*)video_info->userdata : NULL; + D3D10SetBlendState(d3d10->device, + d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); +} + +static void menu_display_d3d10_blend_end(video_frame_info_t *video_info) +{ + d3d10_video_t* d3d10 = video_info ? (d3d10_video_t*)video_info->userdata : NULL; + D3D10SetBlendState(d3d10->device, + d3d10->blend_disable, NULL, D3D10_DEFAULT_SAMPLE_MASK); +} + +static void menu_display_d3d10_viewport(void* data, video_frame_info_t *video_info) +{ +} + +static void menu_display_d3d10_draw(void* data, video_frame_info_t *video_info) +{ + int vertex_count; + d3d10_video_t* d3d10 = video_info ? (d3d10_video_t*)video_info->userdata : NULL; + menu_display_ctx_draw_t* draw = (menu_display_ctx_draw_t*)data; + + if (!d3d10 || !draw || !draw->texture) + return; + + switch (draw->pipeline.id) + { + case VIDEO_SHADER_MENU: + case VIDEO_SHADER_MENU_2: + case VIDEO_SHADER_MENU_3: + case VIDEO_SHADER_MENU_4: + case VIDEO_SHADER_MENU_5: + case VIDEO_SHADER_MENU_6: + d3d10_set_shader(d3d10->device, &d3d10->shaders[draw->pipeline.id]); + D3D10Draw(d3d10->device, draw->coords->vertices, 0); + + D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); + d3d10_set_shader(d3d10->device, &d3d10->sprites.shader); + D3D10SetVertexBuffer(d3d10->device, 0, d3d10->sprites.vbo, sizeof(d3d10_sprite_t), 0); + D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_POINTLIST); + return; + } + + if (draw->coords->vertex && draw->coords->tex_coord && draw->coords->color) + vertex_count = draw->coords->vertices; + else + vertex_count = 1; + + if (!d3d10->sprites.enabled || vertex_count > d3d10->sprites.capacity) + return; + + if (d3d10->sprites.offset + vertex_count > d3d10->sprites.capacity) + d3d10->sprites.offset = 0; + + { + void* mapped_vbo; + d3d10_sprite_t* sprite = NULL; + + D3D10MapBuffer(d3d10->sprites.vbo, D3D10_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo); + + sprite = (d3d10_sprite_t*)mapped_vbo + d3d10->sprites.offset; + + if (vertex_count == 1) + { + sprite->pos.x = draw->x / (float)d3d10->viewport.Width; + sprite->pos.y = + (d3d10->viewport.Height - draw->y - draw->height) / (float)d3d10->viewport.Height; + sprite->pos.w = draw->width / (float)d3d10->viewport.Width; + sprite->pos.h = draw->height / (float)d3d10->viewport.Height; + + sprite->coords.u = 0.0f; + sprite->coords.v = 0.0f; + sprite->coords.w = 1.0f; + sprite->coords.h = 1.0f; + + if (draw->scale_factor) + sprite->params.scaling = draw->scale_factor; + else + sprite->params.scaling = 1.0f; + + sprite->params.rotation = draw->rotation; + + sprite->colors[3] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[0], 0xFF * draw->coords->color[1], + 0xFF * draw->coords->color[2], 0xFF * draw->coords->color[3]); + sprite->colors[2] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[4], 0xFF * draw->coords->color[5], + 0xFF * draw->coords->color[6], 0xFF * draw->coords->color[7]); + sprite->colors[1] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[8], 0xFF * draw->coords->color[9], + 0xFF * draw->coords->color[10], 0xFF * draw->coords->color[11]); + sprite->colors[0] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[12], 0xFF * draw->coords->color[13], + 0xFF * draw->coords->color[14], 0xFF * draw->coords->color[15]); + } + else + { + int i; + const float* vertex = draw->coords->vertex; + const float* tex_coord = draw->coords->tex_coord; + const float* color = draw->coords->color; + + for (i = 0; i < vertex_count; i++) + { + d3d10_vertex_t* v = (d3d10_vertex_t*)sprite; + v->position[0] = *vertex++; + v->position[1] = *vertex++; + v->texcoord[0] = *tex_coord++; + v->texcoord[1] = *tex_coord++; + v->color[0] = *color++; + v->color[1] = *color++; + v->color[2] = *color++; + v->color[3] = *color++; + + sprite++; + } + + d3d10_set_shader(d3d10->device, &d3d10->shaders[VIDEO_SHADER_STOCK_BLEND]); + D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + } + + D3D10UnmapBuffer(d3d10->sprites.vbo); + } + + d3d10_set_texture_and_sampler(d3d10->device, 0, (d3d10_texture_t*)draw->texture); + D3D10Draw(d3d10->device, vertex_count, d3d10->sprites.offset); + d3d10->sprites.offset += vertex_count; + + if (vertex_count > 1) + { + d3d10_set_shader(d3d10->device, &d3d10->sprites.shader); + D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_POINTLIST); + } + + return; +} + +static void menu_display_d3d10_draw_pipeline(void* data, + video_frame_info_t *video_info) +{ + menu_display_ctx_draw_t* draw = (menu_display_ctx_draw_t*)data; + d3d10_video_t* d3d10 = video_info ? (d3d10_video_t*)video_info->userdata : NULL; + + if (!d3d10 || !draw) + return; + + switch (draw->pipeline.id) + { + case VIDEO_SHADER_MENU: + case VIDEO_SHADER_MENU_2: + { + video_coord_array_t* ca = menu_display_get_coords_array(); + + if (!d3d10->menu_pipeline_vbo) + { + D3D10_BUFFER_DESC desc = { 0 }; + desc.Usage = D3D10_USAGE_IMMUTABLE; + desc.ByteWidth = ca->coords.vertices * 2 * sizeof(float); + desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; + + D3D10_SUBRESOURCE_DATA vertexData = { ca->coords.vertex }; + D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->menu_pipeline_vbo); + } + D3D10SetVertexBuffer(d3d10->device, 0, d3d10->menu_pipeline_vbo, 2 * sizeof(float), 0); + draw->coords->vertices = ca->coords.vertices; + D3D10SetBlendState(d3d10->device, d3d10->blend_pipeline, NULL, D3D10_DEFAULT_SAMPLE_MASK); + break; + } + + case VIDEO_SHADER_MENU_3: + case VIDEO_SHADER_MENU_4: + case VIDEO_SHADER_MENU_5: + case VIDEO_SHADER_MENU_6: + D3D10SetVertexBuffer(d3d10->device, 0, d3d10->frame.vbo, sizeof(d3d10_vertex_t), 0); + draw->coords->vertices = 4; + break; + default: + return; + } + + D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + d3d10->ubo_values.time += 0.01f; + + { + void* mapped_ubo; + D3D10MapBuffer(d3d10->ubo, D3D10_MAP_WRITE_DISCARD, 0, (void**)&mapped_ubo); + *(d3d10_uniform_t*)mapped_ubo = d3d10->ubo_values; + D3D10UnmapBuffer(d3d10->ubo); + } +} + +static void menu_display_d3d10_restore_clear_color(void) {} + +static void menu_display_d3d10_clear_color( + menu_display_ctx_clearcolor_t* clearcolor, + video_frame_info_t *video_info) +{ + d3d10_video_t *d3d10 = video_info ? + (d3d10_video_t*)video_info->userdata : NULL; + + if (!d3d10 || !clearcolor) + return; + + D3D10ClearRenderTargetView(d3d10->device, + d3d10->renderTargetView, (float*)clearcolor); +} + +static bool menu_display_d3d10_font_init_first( + void** font_handle, + void* video_data, + const char* font_path, + float font_size, + bool is_threaded) +{ + font_data_t** handle = (font_data_t**)font_handle; + font_data_t* new_handle = font_driver_init_first( + video_data, font_path, font_size, true, + is_threaded, FONT_DRIVER_RENDER_D3D10_API); + if (!new_handle) + return false; + *handle = new_handle; + return true; +} + +menu_display_ctx_driver_t menu_display_ctx_d3d10 = { + menu_display_d3d10_draw, + menu_display_d3d10_draw_pipeline, + menu_display_d3d10_viewport, + menu_display_d3d10_blend_begin, + menu_display_d3d10_blend_end, + menu_display_d3d10_restore_clear_color, + menu_display_d3d10_clear_color, + menu_display_d3d10_get_default_mvp, + menu_display_d3d10_get_default_vertices, + menu_display_d3d10_get_default_tex_coords, + menu_display_d3d10_font_init_first, + MENU_VIDEO_DRIVER_DIRECT3D10, + "menu_display_d3d10", + true +}; diff --git a/menu/drivers_display/menu_display_d3d8.c b/menu/drivers_display/menu_display_d3d8.c index 208f6b566d..c71270d004 100644 --- a/menu/drivers_display/menu_display_d3d8.c +++ b/menu/drivers_display/menu_display_d3d8.c @@ -13,6 +13,8 @@ * If not, see . */ +#define CINTERFACE + #include #include diff --git a/menu/drivers_display/menu_display_d3d9.c b/menu/drivers_display/menu_display_d3d9.c index cb62c95972..cd83a8bce6 100644 --- a/menu/drivers_display/menu_display_d3d9.c +++ b/menu/drivers_display/menu_display_d3d9.c @@ -13,6 +13,8 @@ * If not, see . */ +#define CINTERFACE + #include #include diff --git a/menu/menu_cbs.c b/menu/menu_cbs.c index 28dd055114..33d4b5a01e 100644 --- a/menu/menu_cbs.c +++ b/menu/menu_cbs.c @@ -32,7 +32,7 @@ static void menu_cbs_init_log(const char *entry_label, const char *bind_label, c #endif } -struct key_desc key_descriptors[MENU_SETTINGS_INPUT_DESC_KBD_END] = +struct key_desc key_descriptors[RARCH_MAX_KEYS] = { {RETROK_FIRST, "Unmapped"}, {RETROK_BACKSPACE, "Backspace"}, diff --git a/menu/menu_cbs.h b/menu/menu_cbs.h index a6e629394e..b0fff984c9 100644 --- a/menu/menu_cbs.h +++ b/menu/menu_cbs.h @@ -68,6 +68,7 @@ enum ACTION_OK_DL_DRIVER_SETTINGS_LIST, ACTION_OK_DL_VIDEO_SETTINGS_LIST, ACTION_OK_DL_AUDIO_SETTINGS_LIST, + ACTION_OK_DL_LATENCY_SETTINGS_LIST, ACTION_OK_DL_CONFIGURATION_SETTINGS_LIST, ACTION_OK_DL_SAVING_SETTINGS_LIST, ACTION_OK_DL_LOGGING_SETTINGS_LIST, @@ -161,6 +162,38 @@ int action_right_input_desc_kbd(unsigned type, const char *label, int action_right_cheat(unsigned type, const char *label, bool wraparound); +int setting_action_ok_video_refresh_rate_auto(void *data, bool wraparound); + +int setting_action_ok_video_refresh_rate_polled(void *data, bool wraparound); + +int setting_action_ok_bind_all(void *data, bool wraparound); + +int setting_action_ok_bind_all_save_autoconfig(void *data, + bool wraparound); + +int setting_action_ok_bind_defaults(void *data, bool wraparound); + +int setting_action_left_analog_dpad_mode(void *data, bool wraparound); + +int setting_action_left_libretro_device_type( + void *data, bool wraparound); + +int setting_action_left_bind_device(void *data, bool wraparound); + +int setting_action_left_mouse_index(void *data, bool wraparound); + +int setting_uint_action_left_custom_viewport_width( + void *data, bool wraparound); + +int setting_uint_action_left_custom_viewport_height( + void *data, bool wraparound); + +int setting_string_action_left_driver(void *data, + bool wraparound); + +int setting_string_action_left_audio_device( + void *data, bool wraparound); + /* End of function callbacks */ int menu_cbs_init_bind_left(menu_file_list_cbs_t *cbs, diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 27547051dc..7553f8082d 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -153,6 +153,7 @@ static int menu_displaylist_parse_core_info(menu_displaylist_info_t *info) unsigned i; char tmp[PATH_MAX_LENGTH]; core_info_t *core_info = NULL; + settings_t *settings = config_get_ptr(); tmp[0] = '\0'; @@ -284,12 +285,21 @@ static int menu_displaylist_parse_core_info(menu_displaylist_info_t *info) if (core_info->firmware_count > 0) { core_info_ctx_firmware_t firmware_info; + bool update_missing_firmware = false; + bool set_missing_firmware = false; settings_t *settings = config_get_ptr(); firmware_info.path = core_info->path; firmware_info.directory.system = settings->paths.directory_system; - if (core_info_list_update_missing_firmware(&firmware_info)) + rarch_ctl(RARCH_CTL_UNSET_MISSING_BIOS, NULL); + + update_missing_firmware = core_info_list_update_missing_firmware(&firmware_info, &set_missing_firmware); + + if (set_missing_firmware) + rarch_ctl(RARCH_CTL_SET_MISSING_BIOS, NULL); + + if (update_missing_firmware) { fill_pathname_noext(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE), @@ -336,11 +346,12 @@ static int menu_displaylist_parse_core_info(menu_displaylist_info_t *info) } } - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_DELETE), - msg_hash_to_str(MENU_ENUM_LABEL_CORE_DELETE), - MENU_ENUM_LABEL_CORE_DELETE, - MENU_SETTING_ACTION_CORE_DELETE, 0, 0); + if (settings->bools.menu_show_core_updater) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_DELETE), + msg_hash_to_str(MENU_ENUM_LABEL_CORE_DELETE), + MENU_ENUM_LABEL_CORE_DELETE, + MENU_SETTING_ACTION_CORE_DELETE, 0, 0); return 0; } @@ -505,14 +516,14 @@ static int menu_displaylist_parse_system_info(menu_displaylist_info_t *info) MENU_SETTINGS_CORE_INFO_NONE, 0, 0); snprintf(tmp, sizeof(tmp), "Port #%d device display name: %s", controller, - input_config_get_device_display_name(controller) ? + input_config_get_device_display_name(controller) ? input_config_get_device_display_name(controller) : "N/A"); menu_entries_append_enum(info->list, tmp, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0); snprintf(tmp, sizeof(tmp), "Port #%d device config name: %s", controller, - input_config_get_device_display_name(controller) ? + input_config_get_device_display_name(controller) ? input_config_get_device_config_name(controller) : "N/A"); menu_entries_append_enum(info->list, tmp, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, @@ -1563,6 +1574,17 @@ error: return -1; } +static enum msg_file_type extension_to_file_hash_type(const char *ext) +{ + if (string_is_equal(ext, "sha1")) + return FILE_TYPE_SHA1; + else if (string_is_equal(ext, "crc")) + return FILE_TYPE_CRC; + else if (string_is_equal(ext, "md5")) + return FILE_TYPE_MD5; + return FILE_TYPE_NONE; +} + static int menu_displaylist_parse_database_entry(menu_displaylist_info_t *info) { unsigned i, j, k; @@ -1651,7 +1673,7 @@ static int menu_displaylist_parse_database_entry(menu_displaylist_info_t *info) const char *elem0 = tmp_str_list->elems[0].data; const char *elem1 = tmp_str_list->elems[1].data; - switch (msg_hash_to_file_type(msg_hash_calculate(elem1))) + switch (extension_to_file_hash_type(elem1)) { case FILE_TYPE_CRC: if (string_is_equal(crc_str, elem0)) @@ -2464,13 +2486,16 @@ static int menu_displaylist_parse_settings_enum(void *data, static void menu_displaylist_set_new_playlist( menu_handle_t *menu, const char *path) { - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_FREE, NULL); - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_INIT, - (void*)path); - strlcpy( - menu->db_playlist_file, - path, - sizeof(menu->db_playlist_file)); + menu->db_playlist_file[0] = '\0'; + + if (playlist_get_cached()) + playlist_free_cached(); + + if (playlist_init_cached(path, COLLECTION_SIZE)) + strlcpy( + menu->db_playlist_file, + path, + sizeof(menu->db_playlist_file)); } @@ -2523,12 +2548,15 @@ static int menu_displaylist_parse_horizontal_list( menu_displaylist_set_new_playlist(menu, path_playlist); } - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &playlist); + playlist = playlist_get_cached(); - playlist_qsort(playlist); - - menu_displaylist_parse_playlist(info, - playlist, msg_hash_to_str(MENU_ENUM_LABEL_COLLECTION), is_historylist); + if (playlist) + { + playlist_qsort(playlist); + menu_displaylist_parse_playlist(info, + playlist, + msg_hash_to_str(MENU_ENUM_LABEL_COLLECTION), is_historylist); + } return 0; } @@ -2596,7 +2624,7 @@ static int menu_displaylist_parse_load_content_settings( } - if (settings->bools.quick_menu_show_save_load_state + if (settings->bools.quick_menu_show_save_load_state #ifdef HAVE_CHEEVOS && !(settings->bools.cheevos_hardcore_mode_enable && cheevos_loaded) #endif @@ -2656,6 +2684,33 @@ static int menu_displaylist_parse_load_content_settings( MENU_SETTING_ACTION, 0, 0); } + if (settings->bools.menu_show_overlays) + { + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ONSCREEN_OVERLAY_SETTINGS), + msg_hash_to_str(MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS), + MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS, + MENU_SETTING_ACTION, 0, 0); + } + + if (settings->bools.menu_show_rewind) + { + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REWIND_SETTINGS), + msg_hash_to_str(MENU_ENUM_LABEL_REWIND_SETTINGS), + MENU_ENUM_LABEL_REWIND_SETTINGS, + MENU_SETTING_ACTION, 0, 0); + } + + if (settings->bools.menu_show_latency) + { + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LATENCY_SETTINGS), + msg_hash_to_str(MENU_ENUM_LABEL_LATENCY_SETTINGS), + MENU_ENUM_LABEL_LATENCY_SETTINGS, + MENU_SETTING_ACTION, 0, 0); + } + #if 0 menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SETTINGS), @@ -2752,7 +2807,7 @@ static int menu_displaylist_parse_horizontal_content_actions( const char *core_path = NULL; const char *core_name = NULL; const char *db_name = NULL; - playlist_t *playlist = NULL; + playlist_t *playlist = playlist_get_cached(); settings_t *settings = config_get_ptr(); const char *fullpath = path_get(RARCH_PATH_CONTENT); @@ -2761,10 +2816,9 @@ static int menu_displaylist_parse_horizontal_content_actions( idx = menu->rpl_entry_selection_ptr; - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &playlist); - - playlist_get_index(playlist, idx, - &entry_path, &label, &core_path, &core_name, NULL, &db_name); + if (playlist) + playlist_get_index(playlist, idx, + &entry_path, &label, &core_path, &core_name, NULL, &db_name); content_loaded = !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL) && string_is_equal(menu->deferred_path, fullpath); @@ -2793,14 +2847,16 @@ static int menu_displaylist_parse_horizontal_content_actions( msg_hash_to_str(MENU_ENUM_LABEL_RUN), MENU_ENUM_LABEL_RUN, FILE_TYPE_PLAYLIST_ENTRY, 0, idx); - if (settings->bools.playlist_entry_rename && !settings->bools.kiosk_mode_enable) + if (settings->bools.playlist_entry_rename && + !settings->bools.kiosk_mode_enable) menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY), msg_hash_to_str(MENU_ENUM_LABEL_RENAME_ENTRY), MENU_ENUM_LABEL_RENAME_ENTRY, FILE_TYPE_PLAYLIST_ENTRY, 0, idx); - if (settings->bools.playlist_entry_remove && !settings->bools.kiosk_mode_enable) + if (settings->bools.playlist_entry_remove && + !settings->bools.kiosk_mode_enable) menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DELETE_ENTRY), msg_hash_to_str(MENU_ENUM_LABEL_DELETE_ENTRY), @@ -3240,76 +3296,74 @@ static int menu_displaylist_parse_options_remappings( if (system) { + settings_t *settings = config_get_ptr(); + unsigned device; for (p = 0; p < max_users; p++) { - for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND + 4; retro_id++) + device = settings->uints.input_libretro_device[p]; + device &= RETRO_DEVICE_MASK; + + if (device == RETRO_DEVICE_JOYPAD || device == RETRO_DEVICE_ANALOG) { - char desc_label[64]; - unsigned user = p + 1; - unsigned desc_offset = retro_id; - const char *description = NULL; - - desc_label[0] = '\0'; - - if (desc_offset >= RARCH_FIRST_CUSTOM_BIND) - desc_offset = RARCH_FIRST_CUSTOM_BIND - + (desc_offset - RARCH_FIRST_CUSTOM_BIND) * 2; - - description = system->input_desc_btn[p][desc_offset]; - - if (!description) - continue; - - snprintf(desc_label, sizeof(desc_label), - "%s %u %s : ", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_USER), - user, description); - menu_entries_append_enum(info->list, desc_label, "", - MSG_UNKNOWN, - MENU_SETTINGS_INPUT_DESC_BEGIN + - (p * (RARCH_FIRST_CUSTOM_BIND + 4)) + retro_id, 0, 0); - } - } - } - #ifdef HAVE_KEYMAPPER - if (system) - { - settings_t *settings = config_get_ptr(); - - unsigned device = settings->uints.input_libretro_device[settings->uints.keymapper_port]; - device &= RETRO_DEVICE_MASK; - - if (device == RETRO_DEVICE_KEYBOARD) - { - for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++) - { - unsigned user = settings->uints.keymapper_port + 1; - unsigned desc_offset = retro_id; - char descriptor[255]; - const struct retro_keybind *auto_bind = NULL; - const struct retro_keybind *keybind = NULL; - - keybind = &input_config_binds[settings->uints.keymapper_port][retro_id]; - auto_bind = (const struct retro_keybind*) - input_config_get_bind_auto(settings->uints.keymapper_port, retro_id); - - input_config_get_bind_string(descriptor, - keybind, auto_bind, sizeof(descriptor)); - - if(!strstr(descriptor, "Auto")) + for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND + 8; retro_id++) { - const struct retro_keybind *keyptr = - &input_config_binds[settings->uints.keymapper_port][retro_id]; + char desc_label[64]; + char descriptor[255]; + const struct retro_keybind *auto_bind = NULL; + const struct retro_keybind *keybind = NULL; - strlcpy(descriptor, msg_hash_to_str(keyptr->enum_idx), sizeof(descriptor)); + keybind = &input_config_binds[p][retro_id]; + auto_bind = (const struct retro_keybind*) + input_config_get_bind_auto(p, retro_id); + + input_config_get_bind_string(descriptor, + keybind, auto_bind, sizeof(descriptor)); + + if(!strstr(descriptor, "Auto")) + { + const struct retro_keybind *keyptr = + &input_config_binds[p][retro_id]; + + snprintf(desc_label, sizeof(desc_label), "%s %s", msg_hash_to_str(keyptr->enum_idx), descriptor); + strlcpy(descriptor, desc_label, sizeof(descriptor)); + } + + menu_entries_append_enum(info->list, descriptor, "", + MSG_UNKNOWN, + MENU_SETTINGS_INPUT_DESC_BEGIN + + (p * (RARCH_FIRST_CUSTOM_BIND + 8)) + retro_id, 0, 0); } + } + else if (device == RETRO_DEVICE_KEYBOARD) + { + for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++) + { + char descriptor[255]; + const struct retro_keybind *auto_bind = NULL; + const struct retro_keybind *keybind = NULL; - menu_entries_append_enum(info->list, descriptor, "", - MSG_UNKNOWN, - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + retro_id, 0, 0); + keybind = &input_config_binds[p][retro_id]; + auto_bind = (const struct retro_keybind*) + input_config_get_bind_auto(p, retro_id); + + input_config_get_bind_string(descriptor, + keybind, auto_bind, sizeof(descriptor)); + + if(!strstr(descriptor, "Auto")) + { + const struct retro_keybind *keyptr = + &input_config_binds[p][retro_id]; + + strlcpy(descriptor, msg_hash_to_str(keyptr->enum_idx), sizeof(descriptor)); + } + + menu_entries_append_enum(info->list, descriptor, "", + MSG_UNKNOWN, + (MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + retro_id) * (p + 1), 0, 0); + } } } } - #endif return 0; } @@ -3950,9 +4004,8 @@ static void menu_displaylist_parse_playlist_generic( menu_displaylist_set_new_playlist(menu, playlist_path); - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &playlist); - - path_playlist = strdup(playlist_name); + playlist = playlist_get_cached(); + path_playlist = strdup(playlist_name); *ret = menu_displaylist_parse_playlist(info, playlist, path_playlist, true); @@ -4147,6 +4200,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) { size_t i; menu_ctx_displaylist_t disp_list; + unsigned count = 0; int ret = 0; core_info_list_t *list = NULL; menu_handle_t *menu = NULL; @@ -4381,12 +4435,15 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) msg_hash_to_str(MENU_ENUM_LABEL_COLLECTION), sizeof(path_playlist)); - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_GET, &playlist); + playlist = playlist_get_cached(); - playlist_qsort(playlist); + if (playlist) + { + playlist_qsort(playlist); - ret = menu_displaylist_parse_playlist(info, - playlist, path_playlist, false); + ret = menu_displaylist_parse_playlist(info, + playlist, path_playlist, false); + } if (ret == 0) { @@ -4596,7 +4653,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) const char *core_name = cores_names->elems[i].data; if ( !path_is_empty(RARCH_PATH_CORE) && - string_is_equal(core_path, path_get(RARCH_PATH_CORE))) + string_is_equal(core_path, path_get(RARCH_PATH_CORE))) { strlcpy(new_path_entry, core_path, sizeof(new_path_entry)); snprintf(new_entry, sizeof(new_entry), "Current core (%s)", core_name); @@ -4689,7 +4746,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) const char *core_name = cores_names->elems[i].data; if ( !path_is_empty(RARCH_PATH_CORE) && - string_is_equal(core_path, path_get(RARCH_PATH_CORE))) + string_is_equal(core_path, path_get(RARCH_PATH_CORE))) { strlcpy(new_path_entry, core_path, sizeof(new_path_entry)); snprintf(new_entry, sizeof(new_entry), "Current core (%s)", core_name); @@ -4832,8 +4889,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) for (i = 0; i < RARCH_BIND_LIST_END; i++) { ret = menu_displaylist_parse_settings_enum(menu, info, - (enum msg_hash_enums)(MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN + i), - PARSE_ONLY_BIND, false); + (enum msg_hash_enums)(MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN + i), + PARSE_ONLY_BIND, false); (void)ret; } } @@ -4985,10 +5042,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) break; case DISPLAYLIST_ONSCREEN_DISPLAY_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); -#ifdef HAVE_OVERLAY menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS, PARSE_ACTION, false); -#endif menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_SETTINGS, PARSE_ACTION, false); @@ -5116,16 +5171,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT, PARSE_ONLY_BOOL, false); -#if defined(HAVE_NETWORKING) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_MENU_SHOW_ONLINE_UPDATER, PARSE_ONLY_BOOL, false); -#if !defined(HAVE_LAKKA) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_MENU_SHOW_CORE_UPDATER, PARSE_ONLY_BOOL, false); -#endif -#endif menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_MENU_SHOW_INFORMATION, @@ -5139,7 +5190,6 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) MENU_ENUM_LABEL_MENU_SHOW_HELP, PARSE_ONLY_BOOL, false); -#if defined(HAVE_LAKKA) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_MENU_SHOW_QUIT_RETROARCH, PARSE_ONLY_BOOL, false); @@ -5147,7 +5197,6 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_MENU_SHOW_REBOOT, PARSE_ONLY_BOOL, false); -#endif menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONTENT_SHOW_SETTINGS, @@ -5158,35 +5207,30 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) PARSE_ONLY_STRING, false); menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CONTENT_SHOW_FAVORITES, - PARSE_ONLY_BOOL, false); + MENU_ENUM_LABEL_CONTENT_SHOW_FAVORITES, + PARSE_ONLY_BOOL, false); -#ifdef HAVE_IMAGEVIEWER menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONTENT_SHOW_IMAGES, PARSE_ONLY_BOOL, false); -#endif menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONTENT_SHOW_MUSIC, PARSE_ONLY_BOOL, false); -#ifdef HAVE_FFMPEG menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONTENT_SHOW_VIDEO, PARSE_ONLY_BOOL, false); -#endif -#ifdef HAVE_NETWORKING menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONTENT_SHOW_NETPLAY, PARSE_ONLY_BOOL, false); -#endif menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONTENT_SHOW_HISTORY, PARSE_ONLY_BOOL, false); -#ifdef HAVE_LIBRETRODB menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONTENT_SHOW_ADD, PARSE_ONLY_BOOL, false); -#endif + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CONTENT_SHOW_PLAYLISTS, + PARSE_ONLY_BOOL, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_TIMEDATE_ENABLE, PARSE_ONLY_BOOL, false); @@ -5237,6 +5281,15 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_QUICK_MENU_SHOW_SHADERS, PARSE_ONLY_BOOL, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CONTENT_SHOW_REWIND, + PARSE_ONLY_BOOL, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY, + PARSE_ONLY_BOOL, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CONTENT_SHOW_OVERLAYS, + PARSE_ONLY_BOOL, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, PARSE_ONLY_BOOL, false); @@ -5255,84 +5308,141 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) case DISPLAYLIST_MENU_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_WALLPAPER, - PARSE_ONLY_PATH, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_DYNAMIC_WALLPAPER, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_WALLPAPER_OPACITY, - PARSE_ONLY_FLOAT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_FRAMEBUFFER_OPACITY, - PARSE_ONLY_FLOAT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_LINEAR_FILTER, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_HORIZONTAL_ANIMATION, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_ENTRY_NORMAL_COLOR, - PARSE_ONLY_HEX, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_ENTRY_HOVER_COLOR, - PARSE_ONLY_HEX, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_TITLE_COLOR, - PARSE_ONLY_HEX, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_DPI_OVERRIDE_ENABLE, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_DPI_OVERRIDE_VALUE, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_XMB_ALPHA_FACTOR, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_XMB_SCALE_FACTOR, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_XMB_FONT, - PARSE_ONLY_PATH, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_FONT_COLOR_RED, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_FONT_COLOR_GREEN, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MENU_FONT_COLOR_BLUE, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_XMB_THEME, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_XMB_SHADOWS_ENABLE, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_XMB_RIBBON_ENABLE, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_XMB_MENU_COLOR_THEME, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MATERIALUI_ICONS_ENABLE, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MATERIALUI_MENU_COLOR_THEME, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MATERIALUI_MENU_HEADER_OPACITY, - PARSE_ONLY_FLOAT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_MATERIALUI_MENU_FOOTER_OPACITY, - PARSE_ONLY_FLOAT, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_THUMBNAILS, - PARSE_ONLY_UINT, false); + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_WALLPAPER, + PARSE_ONLY_PATH, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_DYNAMIC_WALLPAPER, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_WALLPAPER_OPACITY, + PARSE_ONLY_FLOAT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_FRAMEBUFFER_OPACITY, + PARSE_ONLY_FLOAT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_ENABLE, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_LINEAR_FILTER, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_HORIZONTAL_ANIMATION, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_ENTRY_NORMAL_COLOR, + PARSE_ONLY_HEX, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_ENTRY_HOVER_COLOR, + PARSE_ONLY_HEX, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_TITLE_COLOR, + PARSE_ONLY_HEX, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_DPI_OVERRIDE_ENABLE, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_DPI_OVERRIDE_VALUE, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_ALPHA_FACTOR, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_SCALE_FACTOR, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_FONT, + PARSE_ONLY_PATH, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_FONT_COLOR_RED, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_FONT_COLOR_GREEN, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_FONT_COLOR_BLUE, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_LAYOUT, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_THEME, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_SHADOWS_ENABLE, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_RIBBON_ENABLE, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_MENU_COLOR_THEME, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MATERIALUI_ICONS_ENABLE, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MATERIALUI_MENU_COLOR_THEME, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MATERIALUI_MENU_HEADER_OPACITY, + PARSE_ONLY_FLOAT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MATERIALUI_MENU_FOOTER_OPACITY, + PARSE_ONLY_FLOAT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_THUMBNAILS, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_LEFT_THUMBNAILS, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, + PARSE_ONLY_BOOL, false) == 0) + count++; + + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), + msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), + MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, + FILE_TYPE_NONE, 0, 0); info->need_refresh = true; info->need_push = true; @@ -5407,8 +5517,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) if (string_is_equal(settings->arrays.menu_driver, "xmb")) { menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CHEEVOS_BADGES_ENABLE, - PARSE_ONLY_BOOL, false); + MENU_ENUM_LABEL_CHEEVOS_BADGES_ENABLE, + PARSE_ONLY_BOOL, false); } menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CHEEVOS_TEST_UNOFFICIAL, @@ -5425,28 +5535,25 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) break; case DISPLAYLIST_UPDATER_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - { - unsigned count = 0; - if (menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL, - PARSE_ONLY_STRING, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL, + PARSE_ONLY_STRING, false) != -1) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_BUILDBOT_ASSETS_URL, PARSE_ONLY_STRING, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE, PARSE_ONLY_BOOL, false) != -1) - count++; + count++; - if (count == 0) - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), - msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), - MENU_ENUM_LABEL_NO_SETTINGS_FOUND, - 0, 0, 0); - } + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), + MENU_ENUM_LABEL_NO_SETTINGS_FOUND, + 0, 0, 0); info->need_refresh = true; info->need_push = true; @@ -5502,161 +5609,184 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) break; case DISPLAYLIST_NETWORK_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - { - unsigned user; - unsigned count = 0; - if (menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_PUBLIC_ANNOUNCE, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_USE_MITM_SERVER, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_MITM_SERVER, PARSE_ONLY_STRING, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_IP_ADDRESS, PARSE_ONLY_STRING, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT, PARSE_ONLY_UINT, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_PASSWORD, PARSE_ONLY_STRING, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_SPECTATE_PASSWORD, PARSE_ONLY_STRING, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_START_AS_SPECTATOR, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_ALLOW_SLAVES, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_REQUIRE_SLAVES, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_STATELESS_MODE, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_CHECK_FRAMES, PARSE_ONLY_INT, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_INPUT_LATENCY_FRAMES_MIN, PARSE_ONLY_INT, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_INPUT_LATENCY_FRAMES_RANGE, PARSE_ONLY_INT, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_NAT_TRAVERSAL, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_SHARE_DIGITAL, PARSE_ONLY_UINT, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_SHARE_ANALOG, PARSE_ONLY_UINT, false) != -1) - count++; + count++; + + { + unsigned user; for (user = 0; user < MAX_USERS; user++) { if (menu_displaylist_parse_settings_enum(menu, info, - (enum msg_hash_enums)(MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1 + user), - PARSE_ONLY_BOOL, false) != -1) + (enum msg_hash_enums)(MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1 + user), + PARSE_ONLY_BOOL, false) != -1) count++; } - if (menu_displaylist_parse_settings_enum(menu, info, + } + + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETWORK_CMD_ENABLE, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETWORK_CMD_PORT, PARSE_ONLY_UINT, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETWORK_REMOTE_ENABLE, PARSE_ONLY_BOOL, false) != -1) - count++; - if (menu_displaylist_parse_settings_enum(menu, info, + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETWORK_REMOTE_PORT, PARSE_ONLY_UINT, false) != -1) - count++; + count++; + { + unsigned user; + unsigned max_users = *(input_driver_get_uint(INPUT_ACTION_MAX_USERS)); + for(user = 0; user < max_users; user++) { - unsigned max_users = *(input_driver_get_uint(INPUT_ACTION_MAX_USERS)); - for(user = 0; user < max_users; user++) - { - if (menu_displaylist_parse_settings_enum(menu, info, - (enum msg_hash_enums)(MENU_ENUM_LABEL_NETWORK_REMOTE_USER_1_ENABLE + user), - PARSE_ONLY_BOOL, false) != -1) - count++; - } + if (menu_displaylist_parse_settings_enum(menu, info, + (enum msg_hash_enums)(MENU_ENUM_LABEL_NETWORK_REMOTE_USER_1_ENABLE + user), + PARSE_ONLY_BOOL, false) != -1) + count++; } + } - if (menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_STDIN_CMD_ENABLE, PARSE_ONLY_BOOL, false) != -1) - count++; + count++; - if (menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_UPDATER_SETTINGS, PARSE_ACTION, false) != -1) - count++; + count++; - if (count == 0) - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), - msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), - MENU_ENUM_LABEL_NO_SETTINGS_FOUND, - 0, 0, 0); - } + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), + MENU_ENUM_LABEL_NO_SETTINGS_FOUND, + 0, 0, 0); info->need_refresh = true; info->need_push = true; break; case DISPLAYLIST_LAKKA_SERVICES_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_SSH_ENABLE, - PARSE_ONLY_BOOL, false); + PARSE_ONLY_BOOL, false) == 0) + count++; - menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_SAMBA_ENABLE, - PARSE_ONLY_BOOL, false); + PARSE_ONLY_BOOL, false) == 0) + count++; - menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_BLUETOOTH_ENABLE, - PARSE_ONLY_BOOL, false); + PARSE_ONLY_BOOL, false) == 0) + count++; + + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), + MENU_ENUM_LABEL_NO_SETTINGS_FOUND, + 0, 0, 0); info->need_refresh = true; info->need_push = true; break; case DISPLAYLIST_USER_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - menu_displaylist_parse_settings_enum(menu, info, + + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_ACCOUNTS_LIST, - PARSE_ACTION, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ACTION, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETPLAY_NICKNAME, - PARSE_ONLY_STRING, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_STRING, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_USER_LANGUAGE, - PARSE_ONLY_UINT, false); + PARSE_ONLY_UINT, false) == 0) + count++; + + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), + MENU_ENUM_LABEL_NO_SETTINGS_FOUND, + 0, 0, 0); info->need_refresh = true; info->need_push = true; @@ -5744,27 +5874,25 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) break; case DISPLAYLIST_PRIVACY_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - { - bool available = false; - if (menu_displaylist_parse_settings_enum(menu, info, + + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CAMERA_ALLOW, PARSE_ONLY_BOOL, false) == 0) - available = true; - if (menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_LOCATION_ALLOW, - PARSE_ONLY_BOOL, true) == 0) - available = true; + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_LOCATION_ALLOW, + PARSE_ONLY_BOOL, true) == 0) + count++; - if (!available) - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), - msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), - MENU_ENUM_LABEL_NO_SETTINGS_FOUND, - 0, 0, 0); + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), + MENU_ENUM_LABEL_NO_SETTINGS_FOUND, + 0, 0, 0); - info->need_refresh = true; - info->need_push = true; - } + info->need_refresh = true; + info->need_push = true; break; case DISPLAYLIST_VIDEO_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -5774,12 +5902,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_SCREEN_RESOLUTION, PARSE_ACTION, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION_SUPER, - PARSE_ONLY_UINT, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION, + PARSE_ONLY_BOOL, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION_SUPER, + PARSE_ONLY_UINT, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_PAL60_ENABLE, PARSE_ONLY_BOOL, false); @@ -5813,6 +5941,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_AUTO, PARSE_ONLY_FLOAT, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED, + PARSE_ONLY_FLOAT, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_FORCE_SRGB_DISABLE, PARSE_ONLY_BOOL, false); @@ -5870,18 +6001,22 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_SWAP_INTERVAL, PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_HARD_SYNC, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_HARD_SYNC_FRAMES, - PARSE_ONLY_UINT, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_FRAME_DELAY, - PARSE_ONLY_UINT, false); + PARSE_ONLY_UINT, false) == 0) + count++; menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION, PARSE_ONLY_BOOL, false); @@ -5942,9 +6077,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_AUDIO_SYNC, PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_AUDIO_LATENCY, - PARSE_ONLY_UINT, false); + PARSE_ONLY_UINT, false) == 0) + count++; menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_AUDIO_RESAMPLER_QUALITY, PARSE_ONLY_UINT, false); @@ -5966,7 +6102,6 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN, PARSE_ONLY_PATH, false); -#ifdef HAVE_WASAPI menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_AUDIO_WASAPI_EXCLUSIVE_MODE, PARSE_ONLY_BOOL, false); @@ -5976,7 +6111,6 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_AUDIO_WASAPI_SH_BUFFER_LENGTH, PARSE_ONLY_INT, false); -#endif info->need_refresh = true; info->need_push = true; @@ -5986,31 +6120,28 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_MAX_USERS, PARSE_ONLY_UINT, false); -#if TARGET_OS_IPHONE ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_SMALL_KEYBOARD_ENABLE, PARSE_ONLY_BOOL, false); -#endif ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_UNIFIED_MENU_CONTROLS, PARSE_ONLY_BOOL, false); - ret = menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR, - PARSE_ONLY_UINT, false); + PARSE_ONLY_UINT, false) == 0) + count++; ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_ICADE_ENABLE, PARSE_ONLY_BOOL, false); ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_KEYBOARD_GAMEPAD_MAPPING_TYPE, PARSE_ONLY_UINT, false); -#ifdef VITA ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_TOUCH_ENABLE, PARSE_ONLY_BOOL, false); ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_PREFER_FRONT_TOUCH, PARSE_ONLY_BOOL, false); -#endif ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, PARSE_ONLY_UINT, false); ret = menu_displaylist_parse_settings_enum(menu, info, @@ -6049,6 +6180,56 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) } } + info->need_refresh = true; + info->need_push = true; + break; + case DISPLAYLIST_LATENCY_SETTINGS_LIST: + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); + + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_VIDEO_HARD_SYNC, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_VIDEO_HARD_SYNC_FRAMES, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_VIDEO_FRAME_DELAY, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_AUDIO_LATENCY, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_RUN_AHEAD_ENABLED, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_RUN_AHEAD_FRAMES, + PARSE_ONLY_UINT, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE, + PARSE_ONLY_BOOL, false) == 0) + count++; + + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), + MENU_ENUM_LABEL_NO_SETTINGS_FOUND, + 0, 0, 0); + info->need_refresh = true; info->need_push = true; break; @@ -6062,6 +6243,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) MENU_ENUM_LABEL_AUDIO_SETTINGS, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_INPUT_SETTINGS, PARSE_ACTION, false); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_LATENCY_SETTINGS, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CORE_SETTINGS, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, @@ -6079,14 +6262,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) MENU_ENUM_LABEL_ONSCREEN_DISPLAY_SETTINGS, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_USER_INTERFACE_SETTINGS, PARSE_ACTION, false); -#ifdef HAVE_CHEEVOS ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS, PARSE_ACTION, false); -#endif -#ifdef HAVE_LAKKA ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_WIFI_SETTINGS, PARSE_ACTION, false); -#endif ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETWORK_SETTINGS, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, @@ -6162,7 +6341,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) case DISPLAYLIST_LOAD_CONTENT_LIST: case DISPLAYLIST_LOAD_CONTENT_SPECIAL: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - + if (!string_is_empty(settings->paths.directory_menu_content)) menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FAVORITES), @@ -6170,33 +6349,34 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) MENU_ENUM_LABEL_FAVORITES, MENU_SETTING_ACTION, 0, 0); - if (settings->bools.menu_content_show_favorites) - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES), - msg_hash_to_str(MENU_ENUM_LABEL_GOTO_FAVORITES), - MENU_ENUM_LABEL_GOTO_FAVORITES, - MENU_SETTING_ACTION, 0, 0); + if (settings->bools.menu_content_show_favorites) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES), + msg_hash_to_str(MENU_ENUM_LABEL_GOTO_FAVORITES), + MENU_ENUM_LABEL_GOTO_FAVORITES, + MENU_SETTING_ACTION, 0, 0); - if (settings->bools.menu_content_show_images) - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_IMAGES), - msg_hash_to_str(MENU_ENUM_LABEL_GOTO_IMAGES), - MENU_ENUM_LABEL_GOTO_IMAGES, - MENU_SETTING_ACTION, 0, 0); - if (settings->bools.menu_content_show_music) - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_MUSIC), - msg_hash_to_str(MENU_ENUM_LABEL_GOTO_MUSIC), - MENU_ENUM_LABEL_GOTO_MUSIC, - MENU_SETTING_ACTION, 0, 0); + if (settings->bools.menu_content_show_images) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_IMAGES), + msg_hash_to_str(MENU_ENUM_LABEL_GOTO_IMAGES), + MENU_ENUM_LABEL_GOTO_IMAGES, + MENU_SETTING_ACTION, 0, 0); + + if (settings->bools.menu_content_show_music) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_MUSIC), + msg_hash_to_str(MENU_ENUM_LABEL_GOTO_MUSIC), + MENU_ENUM_LABEL_GOTO_MUSIC, + MENU_SETTING_ACTION, 0, 0); #ifdef HAVE_FFMPEG - if (settings->bools.menu_content_show_video) - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_VIDEO), - msg_hash_to_str(MENU_ENUM_LABEL_GOTO_VIDEO), - MENU_ENUM_LABEL_GOTO_VIDEO, - MENU_SETTING_ACTION, 0, 0); + if (settings->bools.menu_content_show_video) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_VIDEO), + msg_hash_to_str(MENU_ENUM_LABEL_GOTO_VIDEO), + MENU_ENUM_LABEL_GOTO_VIDEO, + MENU_SETTING_ACTION, 0, 0); #endif if (core_info_list_num_info_files(list)) @@ -6305,24 +6485,37 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) break; case DISPLAYLIST_RECORDING_SETTINGS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - menu_displaylist_parse_settings_enum(menu, info, + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_RECORD_ENABLE, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_RECORD_CONFIG, - PARSE_ONLY_PATH, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_PATH, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_RECORD_PATH, - PARSE_ONLY_STRING, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_STRING, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_RECORD_USE_OUTPUT_DIRECTORY, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_GPU_RECORD, - PARSE_ONLY_BOOL, false); - menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_POST_FILTER_RECORD, - PARSE_ONLY_BOOL, false); + PARSE_ONLY_BOOL, false) == 0) + count++; + + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), + MENU_ENUM_LABEL_NO_SETTINGS_FOUND, + 0, 0, 0); info->need_push = true; break; @@ -6349,65 +6542,59 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) if (frontend_driver_has_fork()) #endif { - if (settings->bools.menu_show_load_core) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CORE_LIST, PARSE_ACTION, false); + if (settings->bools.menu_show_load_core) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CORE_LIST, PARSE_ACTION, false); } - if (settings->bools.menu_show_load_content) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_LOAD_CONTENT_LIST, - PARSE_ACTION, false); - if (settings->bools.menu_content_show_history) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY, - PARSE_ACTION, false); - if (settings->bools.menu_content_show_add) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_ADD_CONTENT_LIST, - PARSE_ACTION, false); -#ifdef HAVE_NETWORKING - if (settings->bools.menu_content_show_netplay) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_NETPLAY, - PARSE_ACTION, false); - if (settings->bools.menu_show_online_updater) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_ONLINE_UPDATER, - PARSE_ACTION, false); -#endif + if (settings->bools.menu_show_load_content) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_LOAD_CONTENT_LIST, + PARSE_ACTION, false); + if (settings->bools.menu_content_show_history) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY, + PARSE_ACTION, false); + if (settings->bools.menu_content_show_add) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_ADD_CONTENT_LIST, + PARSE_ACTION, false); + if (settings->bools.menu_content_show_netplay) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_NETPLAY, + PARSE_ACTION, false); + if (settings->bools.menu_show_online_updater) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_ONLINE_UPDATER, + PARSE_ACTION, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_SETTINGS, PARSE_ACTION, false); - if (settings->bools.menu_show_information) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_INFORMATION_LIST, - PARSE_ACTION, false); -#ifndef HAVE_DYNAMIC + if (settings->bools.menu_show_information) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_INFORMATION_LIST, + PARSE_ACTION, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_RESTART_RETROARCH, PARSE_ACTION, false); -#endif - if (settings->bools.menu_show_configurations) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CONFIGURATIONS_LIST, - PARSE_ACTION, false); - if (settings->bools.menu_show_help) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_HELP_LIST, - PARSE_ACTION, false); - if (settings->bools.menu_show_quit_retroarch) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_QUIT_RETROARCH, - PARSE_ACTION, false); -#if defined(HAVE_LAKKA) - if (settings->bools.menu_show_reboot) - menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_REBOOT, - PARSE_ACTION, false); + if (settings->bools.menu_show_configurations) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CONFIGURATIONS_LIST, + PARSE_ACTION, false); + if (settings->bools.menu_show_help) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_HELP_LIST, + PARSE_ACTION, false); + if (settings->bools.menu_show_quit_retroarch) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_QUIT_RETROARCH, + PARSE_ACTION, false); + if (settings->bools.menu_show_reboot) + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_REBOOT, + PARSE_ACTION, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_SHUTDOWN, PARSE_ACTION, false); -#endif info->need_push = true; } break; @@ -6509,39 +6696,43 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) break; case DISPLAYLIST_ACCOUNTS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); -#ifdef HAVE_CHEEVOS - ret = menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_ACCOUNTS_RETRO_ACHIEVEMENTS, - PARSE_ACTION, false); -#else - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), - msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), - MENU_ENUM_LABEL_NO_ITEMS, - MENU_SETTING_NO_ITEM, 0, 0); - ret = 0; -#endif + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_ACCOUNTS_RETRO_ACHIEVEMENTS, + PARSE_ACTION, false) == 0) + count++; + + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), + msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), + MENU_ENUM_LABEL_NO_ITEMS, + MENU_SETTING_NO_ITEM, 0, 0); + + ret = 0; info->need_refresh = true; info->need_push = true; break; case DISPLAYLIST_ACCOUNTS_CHEEVOS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); -#ifdef HAVE_CHEEVOS - ret = menu_displaylist_parse_settings_enum(menu, info, + + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CHEEVOS_USERNAME, - PARSE_ONLY_STRING, false); - ret = menu_displaylist_parse_settings_enum(menu, info, + PARSE_ONLY_STRING, false) == 0) + count++; + if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CHEEVOS_PASSWORD, - PARSE_ONLY_STRING, false); -#else - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), - msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), - MENU_ENUM_LABEL_NO_ITEMS, - MENU_SETTING_NO_ITEM, 0, 0); - ret = 0; -#endif + PARSE_ONLY_STRING, false) == 0) + count++; + + if (count == 0) + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), + msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), + MENU_ENUM_LABEL_NO_ITEMS, + MENU_SETTING_NO_ITEM, 0, 0); + + ret = 0; info->need_refresh = true; info->need_push = true; break; @@ -6626,16 +6817,19 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) free(info->exts); if (info->path) free(info->path); - info->exts = strdup("dbc"); - info->path = strdup(settings->paths.directory_cursor); + info->exts = strdup("dbc"); + info->path = strdup(settings->paths.directory_cursor); break; case DISPLAYLIST_CONFIG_FILES: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); filebrowser_clear_type(); + info->type_default = FILE_TYPE_CONFIG; + if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("cfg"); + + info->exts = strdup("cfg"); load_content = false; use_filebrowser = true; break; @@ -6655,17 +6849,17 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) info->type_default = FILE_TYPE_SHADER_PRESET; if (video_shader_is_supported(RARCH_SHADER_CG) && - video_shader_get_type_from_ext("cgp", &is_preset) + video_shader_get_type_from_ext("cgp", &is_preset) != RARCH_SHADER_NONE) string_list_append(str_list, "cgp", attr); if (video_shader_is_supported(RARCH_SHADER_GLSL) && - video_shader_get_type_from_ext("glslp", &is_preset) + video_shader_get_type_from_ext("glslp", &is_preset) != RARCH_SHADER_NONE) string_list_append(str_list, "glslp", attr); if (video_shader_is_supported(RARCH_SHADER_SLANG) && - video_shader_get_type_from_ext("slangp", &is_preset) + video_shader_get_type_from_ext("slangp", &is_preset) != RARCH_SHADER_NONE) string_list_append(str_list, "slangp", attr); string_list_join_concat(new_exts, sizeof(new_exts), str_list, "|"); @@ -6694,17 +6888,17 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) if (video_shader_is_supported(RARCH_SHADER_CG) && - video_shader_get_type_from_ext("cg", &is_preset) + video_shader_get_type_from_ext("cg", &is_preset) != RARCH_SHADER_NONE) string_list_append(str_list, "cg", attr); if (video_shader_is_supported(RARCH_SHADER_GLSL) && - video_shader_get_type_from_ext("glsl", &is_preset) + video_shader_get_type_from_ext("glsl", &is_preset) != RARCH_SHADER_NONE) string_list_append(str_list, "glsl", attr); if (video_shader_is_supported(RARCH_SHADER_SLANG) && - video_shader_get_type_from_ext("slang", &is_preset) + video_shader_get_type_from_ext("slang", &is_preset) != RARCH_SHADER_NONE) string_list_append(str_list, "slang", attr); @@ -6724,7 +6918,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("filt"); + info->exts = strdup("filt"); break; case DISPLAYLIST_IMAGES: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -6806,7 +7000,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("dsp"); + info->exts = strdup("dsp"); break; case DISPLAYLIST_CHEAT_FILES: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -6816,7 +7010,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("cht"); + info->exts = strdup("cht"); break; case DISPLAYLIST_CONTENT_HISTORY: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -6825,7 +7019,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("lpl"); + info->exts = strdup("lpl"); break; case DISPLAYLIST_FONTS: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -6835,7 +7029,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("ttf"); + info->exts = strdup("ttf"); break; case DISPLAYLIST_OVERLAYS: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -6845,7 +7039,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("cfg"); + info->exts = strdup("cfg"); break; case DISPLAYLIST_RECORD_CONFIG_FILES: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -6855,17 +7049,17 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("cfg"); + info->exts = strdup("cfg"); break; case DISPLAYLIST_REMAP_FILES: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); filebrowser_clear_type(); - info->type_default = FILE_TYPE_REMAP; - load_content = false; - use_filebrowser = true; + info->type_default = FILE_TYPE_REMAP; + load_content = false; + use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); - info->exts = strdup("rmp"); + info->exts = strdup("rmp"); break; case DISPLAYLIST_DATABASE_PLAYLISTS_HORIZONTAL: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); diff --git a/menu/menu_displaylist.h b/menu/menu_displaylist.h index 7bcd105959..3147c9f62a 100644 --- a/menu/menu_displaylist.h +++ b/menu/menu_displaylist.h @@ -120,6 +120,7 @@ enum menu_displaylist_ctl_state DISPLAYLIST_AUDIO_SETTINGS_LIST, DISPLAYLIST_CORE_SETTINGS_LIST, DISPLAYLIST_INPUT_SETTINGS_LIST, + DISPLAYLIST_LATENCY_SETTINGS_LIST, DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST, DISPLAYLIST_ONSCREEN_OVERLAY_SETTINGS_LIST, DISPLAYLIST_ONSCREEN_DISPLAY_SETTINGS_LIST, diff --git a/menu/menu_driver.c b/menu/menu_driver.c index afe4010343..45580c12f5 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -61,6 +61,12 @@ #define PARTICLES_COUNT 100 +typedef struct menu_ctx_load_image +{ + void *data; + enum menu_image_type type; +} menu_ctx_load_image_t; + /* Menu drivers */ static const menu_ctx_driver_t *menu_ctx_drivers[] = { #if defined(HAVE_XUI) @@ -93,6 +99,9 @@ static menu_display_ctx_driver_t *menu_display_ctx_drivers[] = { #ifdef HAVE_D3D9 &menu_display_ctx_d3d9, #endif +#ifdef HAVE_D3D10 + &menu_display_ctx_d3d10, +#endif #ifdef HAVE_D3D11 &menu_display_ctx_d3d11, #endif @@ -176,9 +185,6 @@ static bool menu_driver_pending_shutdown = false; /* Are we binding a button inside the menu? */ static bool menu_driver_is_binding = false; -/* The currently active playlist that we are using inside the menu */ -static playlist_t *menu_driver_playlist = NULL; - static menu_handle_t *menu_driver_data = NULL; static const menu_ctx_driver_t *menu_driver_ctx = NULL; static void *menu_userdata = NULL; @@ -190,6 +196,31 @@ static unsigned scroll_index_size = 0; static unsigned scroll_acceleration = 0; static size_t menu_driver_selection_ptr = 0; +/* Returns the OSK key at a given position */ +int menu_display_osk_ptr_at_pos(void *data, int x, int y, + unsigned width, unsigned height) +{ + unsigned i; + int ptr_width = width / 11; + int ptr_height = height / 10; + + if (ptr_width >= ptr_height) + ptr_width = ptr_height; + + for (i = 0; i < 44; i++) + { + int line_y = (i / 11)*height/10.0; + int ptr_x = width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width; + int ptr_y = height/2.0 + ptr_height*1.5 + line_y - ptr_height; + + if (x > ptr_x && x < ptr_x + ptr_width + && y > ptr_y && y < ptr_y + ptr_height) + return i; + } + + return -1; +} + enum menu_toggle_reason menu_display_toggle_get_reason(void) { return menu_display_toggle_reason; @@ -233,6 +264,10 @@ static bool menu_display_check_compatibility( if (string_is_equal(video_driver, "d3d9")) return true; break; + case MENU_VIDEO_DRIVER_DIRECT3D10: + if (string_is_equal(video_driver, "d3d10")) + return true; + break; case MENU_VIDEO_DRIVER_DIRECT3D11: if (string_is_equal(video_driver, "d3d11")) return true; @@ -536,20 +571,26 @@ void menu_display_unset_framebuffer_dirty_flag(void) * RGUI or XMB use this. */ float menu_display_get_dpi(void) { - gfx_ctx_metrics_t metrics; + unsigned width, height; settings_t *settings = config_get_ptr(); - float dpi = menu_dpi_override_value; + float dpi = 0.0f; + float diagonal = 6.5f; + + video_driver_get_size(&width, &height); if (!settings) return true; - metrics.type = DISPLAY_METRIC_DPI; - metrics.value = &dpi; +#ifdef RARCH_MOBILE + diagonal = 5.0f; +#endif + + /* Generic dpi calculation formula, + * the divider is the screen diagonal in inches */ + dpi = sqrt((width * width) + (height * height)) / diagonal; if (settings->bools.menu_dpi_override_enable) return settings->uints.menu_dpi_override_value; - else if (!video_context_driver_get_metrics(&metrics) || !dpi) - return menu_dpi_override_value; return dpi; } @@ -630,7 +671,7 @@ void menu_display_draw_bg(menu_display_ctx_draw_t *draw, coords.vertex = new_vertex; coords.tex_coord = new_tex_coord; coords.lut_tex_coord = new_tex_coord; - coords.color = (const float*)draw->color; + coords.color = (const float*)draw->color; draw->coords = &coords; draw->scale_factor = 1.0f; @@ -1024,9 +1065,9 @@ void menu_display_rotate_z(menu_display_ctx_rotate_draw_t *draw, math_matrix_4x4 *b = NULL; if ( - !draw || - !menu_disp || - !menu_disp->get_default_mvp || + !draw || + !menu_disp || + !menu_disp->get_default_mvp || menu_disp->handles_transform ) return; @@ -1059,6 +1100,14 @@ bool menu_display_get_tex_coords(menu_display_ctx_coord_draw_t *draw) return true; } +static bool menu_driver_load_image(menu_ctx_load_image_t *load_image_info) +{ + if (menu_driver_ctx && menu_driver_ctx->load_image) + return menu_driver_ctx->load_image(menu_userdata, + load_image_info->data, load_image_info->type); + return false; +} + void menu_display_handle_thumbnail_upload(void *task_data, void *user_data, const char *err) { @@ -1075,6 +1124,22 @@ void menu_display_handle_thumbnail_upload(void *task_data, free(user_data); } +void menu_display_handle_left_thumbnail_upload(void *task_data, + void *user_data, const char *err) +{ + menu_ctx_load_image_t load_image_info; + struct texture_image *img = (struct texture_image*)task_data; + + load_image_info.data = img; + load_image_info.type = MENU_IMAGE_LEFT_THUMBNAIL; + + menu_driver_load_image(&load_image_info); + + image_texture_free(img); + free(img); + free(user_data); +} + void menu_display_handle_savestate_thumbnail_upload(void *task_data, void *user_data, const char *err) { @@ -1291,6 +1356,71 @@ void menu_display_snow(int width, int height) } } +void menu_display_draw_keyboard( + uintptr_t hover_texture, + const font_data_t *font, + video_frame_info_t *video_info, + char *grid[], unsigned id) +{ + unsigned i; + int ptr_width, ptr_height; + unsigned width = video_info->width; + unsigned height = video_info->height; + float dark[16] = { + 0.00, 0.00, 0.00, 0.85, + 0.00, 0.00, 0.00, 0.85, + 0.00, 0.00, 0.00, 0.85, + 0.00, 0.00, 0.00, 0.85, + }; + + float white[16]= { + 1.00, 1.00, 1.00, 1.00, + 1.00, 1.00, 1.00, 1.00, + 1.00, 1.00, 1.00, 1.00, + 1.00, 1.00, 1.00, 1.00, + }; + + menu_display_draw_quad( + video_info, + 0, height/2.0, width, height/2.0, + width, height, + &dark[0]); + + ptr_width = width / 11; + ptr_height = height / 10; + + if (ptr_width >= ptr_height) + ptr_width = ptr_height; + + for (i = 0; i < 44; i++) + { + int line_y = (i / 11) * height / 10.0; + + if (i == id) + { + menu_display_blend_begin(video_info); + + menu_display_draw_texture( + video_info, + width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width, + height/2.0 + ptr_height*1.5 + line_y, + ptr_width, ptr_height, + width, height, + &white[0], + hover_texture); + + menu_display_blend_end(video_info); + } + + menu_display_draw_text(font, grid[i], + width/2.0 - (11*ptr_width)/2.0 + (i % 11) + * ptr_width + ptr_width/2.0, + height/2.0 + ptr_height + line_y + font->size / 3, + width, height, 0xffffffff, TEXT_ALIGN_CENTER, 1.0f, + false, 0); + } +} + /* Draw text on top of the screen. */ void menu_display_draw_text( @@ -1789,14 +1919,6 @@ void menu_driver_populate_entries(menu_displaylist_info_t *info) info->label, info->type); } -bool menu_driver_load_image(menu_ctx_load_image_t *load_image_info) -{ - if (menu_driver_ctx && menu_driver_ctx->load_image) - return menu_driver_ctx->load_image(menu_userdata, - load_image_info->data, load_image_info->type); - return false; -} - bool menu_driver_push_list(menu_ctx_displaylist_t *disp_list) { if (menu_driver_ctx->list_push) @@ -1852,11 +1974,6 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) case RARCH_MENU_CTL_SET_PENDING_SHUTDOWN: menu_driver_pending_shutdown = true; break; - case RARCH_MENU_CTL_PLAYLIST_FREE: - if (menu_driver_playlist) - playlist_free(menu_driver_playlist); - menu_driver_playlist = NULL; - break; case RARCH_MENU_CTL_FIND_DRIVER: { int i; @@ -1897,23 +2014,6 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) } } break; - case RARCH_MENU_CTL_PLAYLIST_INIT: - { - const char *path = (const char*)data; - if (string_is_empty(path)) - return false; - menu_driver_playlist = playlist_init(path, - COLLECTION_SIZE); - } - break; - case RARCH_MENU_CTL_PLAYLIST_GET: - { - playlist_t **playlist = (playlist_t**)data; - if (!playlist) - return false; - *playlist = menu_driver_playlist; - } - break; case RARCH_MENU_CTL_SET_PREVENT_POPULATE: menu_driver_prevent_populate = true; break; @@ -1945,7 +2045,7 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) if (menu_driver_data_own) return true; - menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_FREE, NULL); + playlist_free_cached(); menu_shader_manager_free(); if (menu_driver_data) @@ -2184,7 +2284,8 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) if (!menu_driver_ctx || !menu_driver_ctx->update_thumbnail_path) return false; - menu_driver_ctx->update_thumbnail_path(menu_userdata, (unsigned)selection); + menu_driver_ctx->update_thumbnail_path(menu_userdata, (unsigned)selection, 'L'); + menu_driver_ctx->update_thumbnail_path(menu_userdata, (unsigned)selection, 'R'); } break; case RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE: diff --git a/menu/menu_driver.h b/menu/menu_driver.h index ed2489c0b1..e27825514b 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -61,6 +61,7 @@ enum menu_image_type MENU_IMAGE_NONE = 0, MENU_IMAGE_WALLPAPER, MENU_IMAGE_THUMBNAIL, + MENU_IMAGE_LEFT_THUMBNAIL, MENU_IMAGE_SAVESTATE_THUMBNAIL }; @@ -99,9 +100,6 @@ enum rarch_menu_ctl_state RARCH_MENU_CTL_SET_OWN_DRIVER, RARCH_MENU_CTL_UNSET_OWN_DRIVER, RARCH_MENU_CTL_OWNS_DRIVER, - RARCH_MENU_CTL_PLAYLIST_FREE, - RARCH_MENU_CTL_PLAYLIST_INIT, - RARCH_MENU_CTL_PLAYLIST_GET, RARCH_MENU_CTL_FIND_DRIVER, RARCH_MENU_CTL_LIST_FREE, RARCH_MENU_CTL_LIST_SET_SELECTION, @@ -205,9 +203,9 @@ enum menu_settings_type MENU_SETTINGS_CHEAT_BEGIN, MENU_SETTINGS_CHEAT_END = MENU_SETTINGS_CHEAT_BEGIN + (MAX_CHEAT_COUNTERS - 1), MENU_SETTINGS_INPUT_DESC_BEGIN, - MENU_SETTINGS_INPUT_DESC_END = MENU_SETTINGS_INPUT_DESC_BEGIN + (MAX_USERS * (RARCH_FIRST_CUSTOM_BIND + 4)), + MENU_SETTINGS_INPUT_DESC_END = MENU_SETTINGS_INPUT_DESC_BEGIN + ((RARCH_FIRST_CUSTOM_BIND + 8) * MAX_USERS), MENU_SETTINGS_INPUT_DESC_KBD_BEGIN, - MENU_SETTINGS_INPUT_DESC_KBD_END = MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + 135, + MENU_SETTINGS_INPUT_DESC_KBD_END = MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + (RARCH_MAX_KEYS * MAX_USERS), MENU_SETTINGS_SUBSYSTEM_LOAD, @@ -287,6 +285,7 @@ enum menu_display_driver_type MENU_VIDEO_DRIVER_VULKAN, MENU_VIDEO_DRIVER_DIRECT3D8, MENU_VIDEO_DRIVER_DIRECT3D9, + MENU_VIDEO_DRIVER_DIRECT3D10, MENU_VIDEO_DRIVER_DIRECT3D11, MENU_VIDEO_DRIVER_DIRECT3D12, MENU_VIDEO_DRIVER_VITA2D, @@ -491,7 +490,7 @@ typedef struct menu_ctx_driver int (*pointer_tap)(void *data, unsigned x, unsigned y, unsigned ptr, menu_file_list_cbs_t *cbs, menu_entry_t *entry, unsigned action); - void (*update_thumbnail_path)(void *data, unsigned i); + void (*update_thumbnail_path)(void *data, unsigned i, char pos); void (*update_thumbnail_image)(void *data); void (*set_thumbnail_system)(void *data, char* s, size_t len); void (*set_thumbnail_content)(void *data, char* s, size_t len); @@ -506,12 +505,6 @@ typedef struct menu_ctx_driver menu_entry_t *entry, unsigned action); } menu_ctx_driver_t; -typedef struct menu_ctx_load_image -{ - void *data; - enum menu_image_type type; -} menu_ctx_load_image_t; - typedef struct menu_ctx_displaylist { menu_displaylist_info_t *info; @@ -629,8 +622,6 @@ void menu_driver_navigation_set(bool scroll); void menu_driver_populate_entries(menu_displaylist_info_t *info); -bool menu_driver_load_image(menu_ctx_load_image_t *load_image_info); - bool menu_driver_push_list(menu_ctx_displaylist_t *disp_list); bool menu_driver_init(bool video_is_threaded); @@ -684,6 +675,11 @@ void menu_display_clear_color(menu_display_ctx_clearcolor_t *color, video_frame_info_t *video_info); void menu_display_draw(menu_display_ctx_draw_t *draw, video_frame_info_t *video_info); +void menu_display_draw_keyboard( + uintptr_t hover_texture, + const font_data_t *font, + video_frame_info_t *video_info, + char *grid[], unsigned id); void menu_display_draw_pipeline(menu_display_ctx_draw_t *draw, video_frame_info_t *video_info); @@ -721,6 +717,9 @@ void menu_display_handle_wallpaper_upload(void *task_data, void menu_display_handle_thumbnail_upload(void *task_data, void *user_data, const char *err); +void menu_display_handle_left_thumbnail_upload(void *task_data, + void *user_data, const char *err); + void menu_display_handle_savestate_thumbnail_upload(void *task_data, void *user_data, const char *err); @@ -746,11 +745,20 @@ void menu_display_draw_text( #define menu_display_set_alpha(color, alpha_value) (color[3] = color[7] = color[11] = color[15] = (alpha_value)) -font_data_t *menu_display_font(enum application_special_type type, float font_size, +font_data_t *menu_display_font( + enum application_special_type type, + float font_size, bool video_is_threaded); -void menu_display_reset_textures_list(const char *texture_path, const char *iconpath, - uintptr_t *item, enum texture_filter_type filter_type); +void menu_display_reset_textures_list( + const char *texture_path, + const char *iconpath, + uintptr_t *item, + enum texture_filter_type filter_type); + +/* Returns the OSK key at a given position */ +int menu_display_osk_ptr_at_pos(void *data, int x, int y, + unsigned width, unsigned height); void menu_driver_destroy(void); @@ -760,6 +768,7 @@ extern menu_display_ctx_driver_t menu_display_ctx_gl; extern menu_display_ctx_driver_t menu_display_ctx_vulkan; extern menu_display_ctx_driver_t menu_display_ctx_d3d8; extern menu_display_ctx_driver_t menu_display_ctx_d3d9; +extern menu_display_ctx_driver_t menu_display_ctx_d3d10; extern menu_display_ctx_driver_t menu_display_ctx_d3d11; extern menu_display_ctx_driver_t menu_display_ctx_d3d12; extern menu_display_ctx_driver_t menu_display_ctx_vita2d; diff --git a/menu/menu_entries.c b/menu/menu_entries.c index ff893aad4d..05d4b69707 100644 --- a/menu/menu_entries.c +++ b/menu/menu_entries.c @@ -62,29 +62,40 @@ static void menu_list_free_list(file_list_t *list) static void menu_list_free(menu_list_t *menu_list) { - unsigned i; if (!menu_list) return; - for (i = 0; i < menu_list->menu_stack_size; i++) + if (menu_list->menu_stack) { - if (!menu_list->menu_stack[i]) - continue; + unsigned i; - menu_list_free_list(menu_list->menu_stack[i]); - menu_list->menu_stack[i] = NULL; - } - for (i = 0; i < menu_list->selection_buf_size; i++) - { - if (!menu_list->selection_buf[i]) - continue; + for (i = 0; i < menu_list->menu_stack_size; i++) + { + if (!menu_list->menu_stack[i]) + continue; - menu_list_free_list(menu_list->selection_buf[i]); - menu_list->selection_buf[i] = NULL; + menu_list_free_list(menu_list->menu_stack[i]); + menu_list->menu_stack[i] = NULL; + } + + free(menu_list->menu_stack); } - free(menu_list->menu_stack); - free(menu_list->selection_buf); + if (menu_list->selection_buf) + { + unsigned i; + + for (i = 0; i < menu_list->selection_buf_size; i++) + { + if (!menu_list->selection_buf[i]) + continue; + + menu_list_free_list(menu_list->selection_buf[i]); + menu_list->selection_buf[i] = NULL; + } + + free(menu_list->selection_buf); + } free(menu_list); } diff --git a/menu/menu_event.c b/menu/menu_event.c index 01eb555188..f08fa404e1 100644 --- a/menu/menu_event.c +++ b/menu/menu_event.c @@ -139,7 +139,7 @@ void menu_event_kb_set(bool down, enum retro_key key) * entire button state either but do a separate event per button * state. */ -unsigned menu_event(retro_bits_t* p_input, retro_bits_t* p_trigger_input) +unsigned menu_event(input_bits_t *p_input, input_bits_t *p_trigger_input) { menu_animation_ctx_delta_t delta; float delta_time; diff --git a/menu/menu_event.h b/menu/menu_event.h index ce00c5e5dd..cae9ec381b 100644 --- a/menu/menu_event.h +++ b/menu/menu_event.h @@ -44,7 +44,7 @@ RETRO_BEGIN_DECLS * entire button state either but do a separate event per button * state. */ -unsigned menu_event(retro_bits_t* p_input, retro_bits_t* p_trigger_state); +unsigned menu_event(input_bits_t *p_input, input_bits_t *p_trigger_state); /* Set a specific keyboard key. * diff --git a/menu/menu_setting.c b/menu/menu_setting.c index ee0a20a8df..5717d2f7d1 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -55,6 +55,7 @@ #include "widgets/menu_input_bind_dialog.h" #include "menu_setting.h" +#include "menu_cbs.h" #include "menu_driver.h" #include "menu_animation.h" #include "menu_input.h" @@ -234,37 +235,8 @@ static void setting_get_string_representation_int_audio_wasapi_sh_buffer_length( } #endif -static int setting_uint_action_left_custom_viewport_width(void *data, bool wraparound) -{ - video_viewport_t vp; - struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); - video_viewport_t *custom = video_viewport_get_custom(); - settings_t *settings = config_get_ptr(); - struct retro_game_geometry *geom = (struct retro_game_geometry*) - &av_info->geometry; - - if (!settings || !av_info) - return -1; - - video_driver_get_viewport_info(&vp); - - if (custom->width <= 1) - custom->width = 1; - else if (settings->bools.video_scale_integer) - { - if (custom->width > geom->base_width) - custom->width -= geom->base_width; - } - else - custom->width -= 1; - - aspectratio_lut[ASPECT_RATIO_CUSTOM].value = - (float)custom->width / custom->height; - - return 0; -} - -static int setting_uint_action_right_custom_viewport_width(void *data, bool wraparound) +static int setting_uint_action_right_custom_viewport_width( + void *data, bool wraparound) { video_viewport_t vp; struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); @@ -289,37 +261,8 @@ static int setting_uint_action_right_custom_viewport_width(void *data, bool wrap return 0; } -static int setting_uint_action_left_custom_viewport_height(void *data, bool wraparound) -{ - video_viewport_t vp; - struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); - video_viewport_t *custom = video_viewport_get_custom(); - settings_t *settings = config_get_ptr(); - struct retro_game_geometry *geom = (struct retro_game_geometry*) - &av_info->geometry; - - if (!settings || !av_info) - return -1; - - video_driver_get_viewport_info(&vp); - - if (custom->height <= 1) - custom->height = 1; - else if (settings->bools.video_scale_integer) - { - if (custom->height > geom->base_height) - custom->height -= geom->base_height; - } - else - custom->height -= 1; - - aspectratio_lut[ASPECT_RATIO_CUSTOM].value = - (float)custom->width / custom->height; - - return 0; -} - -static int setting_uint_action_right_custom_viewport_height(void *data, bool wraparound) +static int setting_uint_action_right_custom_viewport_height( + void *data, bool wraparound) { video_viewport_t vp; struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); @@ -345,32 +288,8 @@ static int setting_uint_action_right_custom_viewport_height(void *data, bool wra } #if !defined(RARCH_CONSOLE) -static int setting_string_action_left_audio_device(void *data, bool wraparound) -{ - int audio_device_index; - struct string_list *ptr = NULL; - rarch_setting_t *setting = (rarch_setting_t*)data; - - if (!audio_driver_get_devices_list((void**)&ptr)) - return -1; - - if (!ptr) - return -1; - - /* Get index in the string list */ - audio_device_index = string_list_find_elem(ptr,setting->value.target.string) - 1; - audio_device_index--; - - /* Reset index if needed */ - if (audio_device_index < 0) - audio_device_index = (int)(ptr->size - 1); - - strlcpy(setting->value.target.string, ptr->elems[audio_device_index].data, setting->size); - - return 0; -} - -static int setting_string_action_right_audio_device(void *data, bool wraparound) +static int setting_string_action_right_audio_device( + void *data, bool wraparound) { int audio_device_index; struct string_list *ptr = NULL; @@ -396,38 +315,6 @@ static int setting_string_action_right_audio_device(void *data, bool wraparound) } #endif -static int setting_string_action_left_driver(void *data, - bool wraparound) -{ - driver_ctx_info_t drv; - rarch_setting_t *setting = (rarch_setting_t*)data; - - if (!setting) - return -1; - - drv.label = setting->name; - drv.s = setting->value.target.string; - drv.len = setting->size; - - if (!driver_ctl(RARCH_DRIVER_CTL_FIND_PREV, &drv)) - { - settings_t *settings = config_get_ptr(); - - if (settings && settings->bools.menu_navigation_wraparound_enable) - { - drv.label = setting->name; - drv.s = setting->value.target.string; - drv.len = setting->size; - driver_ctl(RARCH_DRIVER_CTL_FIND_LAST, &drv); - } - } - - if (setting->change_handler) - setting->change_handler(setting); - - return 0; -} - static int setting_string_action_right_driver(void *data, bool wraparound) { @@ -1145,24 +1032,6 @@ static int setting_action_start_video_refresh_rate_auto( ******* ACTION TOGGLE CALLBACK FUNCTIONS ******* **/ -static int setting_action_left_analog_dpad_mode(void *data, bool wraparound) -{ - unsigned port = 0; - rarch_setting_t *setting = (rarch_setting_t*)data; - settings_t *settings = config_get_ptr(); - - if (!setting) - return -1; - - port = setting->index_offset; - - configuration_set_uint(settings, settings->uints.input_analog_dpad_mode[port], - (settings->uints.input_analog_dpad_mode - [port] + ANALOG_DPAD_LAST - 1) % ANALOG_DPAD_LAST); - - return 0; -} - static int setting_action_right_analog_dpad_mode(void *data, bool wraparound) { unsigned port = 0; @@ -1182,73 +1051,6 @@ static int setting_action_right_analog_dpad_mode(void *data, bool wraparound) return 0; } -static int setting_action_left_libretro_device_type( - void *data, bool wraparound) -{ - retro_ctx_controller_info_t pad; - unsigned current_device, current_idx, i, devices[128], - types = 0, port = 0; - const struct retro_controller_info *desc = NULL; - rarch_setting_t *setting = (rarch_setting_t*)data; - rarch_system_info_t *system = NULL; - - if (!setting) - return -1; - - port = setting->index_offset; - - devices[types++] = RETRO_DEVICE_NONE; - devices[types++] = RETRO_DEVICE_JOYPAD; - - system = runloop_get_system_info(); - - if (system) - { - /* Only push RETRO_DEVICE_ANALOG as default if we use an - * older core which doesn't use SET_CONTROLLER_INFO. */ - if (!system->ports.size) - devices[types++] = RETRO_DEVICE_ANALOG; - - if (port < system->ports.size) - desc = &system->ports.data[port]; - } - - if (desc) - { - for (i = 0; i < desc->num_types; i++) - { - unsigned id = desc->types[i].id; - if (types < ARRAY_SIZE(devices) && - id != RETRO_DEVICE_NONE && - id != RETRO_DEVICE_JOYPAD) - devices[types++] = id; - } - } - - current_device = input_config_get_device(port); - current_idx = 0; - for (i = 0; i < types; i++) - { - if (current_device != devices[i]) - continue; - - current_idx = i; - break; - } - - current_device = devices - [(current_idx + types - 1) % types]; - - input_config_set_device(port, current_device); - - pad.port = port; - pad.device = current_device; - - core_set_controller_port_device(&pad); - - return 0; -} - static int setting_action_right_libretro_device_type( void *data, bool wraparound) { @@ -1314,29 +1116,6 @@ static int setting_action_right_libretro_device_type( return 0; } -static int setting_action_left_bind_device(void *data, bool wraparound) -{ - unsigned *p = NULL; - unsigned index_offset = 0; - unsigned max_devices = input_config_get_device_count(); - rarch_setting_t *setting = (rarch_setting_t*)data; - settings_t *settings = config_get_ptr(); - - if (!setting || max_devices == 0) - return -1; - - index_offset = setting->index_offset; - - p = &settings->uints.input_joypad_map[index_offset]; - - if ((*p) >= max_devices) - *p = max_devices - 1; - else if ((*p) > 0) - (*p)--; - - return 0; -} - static int setting_action_right_bind_device(void *data, bool wraparound) { unsigned index_offset; @@ -1358,23 +1137,6 @@ static int setting_action_right_bind_device(void *data, bool wraparound) return 0; } -static int setting_action_left_mouse_index(void *data, bool wraparound) -{ - rarch_setting_t *setting = (rarch_setting_t*)data; - settings_t *settings = config_get_ptr(); - - if (!setting) - return -1; - - if (settings->uints.input_mouse_index[setting->index_offset]) - { - --settings->uints.input_mouse_index[setting->index_offset]; - settings->modified = true; - } - - return 0; -} - static int setting_action_right_mouse_index(void *data, bool wraparound) { rarch_setting_t *setting = (rarch_setting_t*)data; @@ -1393,71 +1155,11 @@ static int setting_action_right_mouse_index(void *data, bool wraparound) ******* ACTION OK CALLBACK FUNCTIONS ******* **/ -static int setting_action_ok_bind_all(void *data, bool wraparound) +static void +setting_get_string_representation_st_float_video_refresh_rate_polled( + void *data, char *s, size_t len) { - (void)wraparound; - if (!menu_input_key_bind_set_mode(MENU_INPUT_BINDS_CTL_BIND_ALL, data)) - return -1; - return 0; -} - -static int setting_action_ok_bind_all_save_autoconfig(void *data, bool wraparound) -{ - unsigned index_offset; - rarch_setting_t *setting = (rarch_setting_t*)data; - const char *name = NULL; - - (void)wraparound; - - if (!setting) - return -1; - - index_offset = setting->index_offset; - name = input_config_get_device_name(index_offset); - - if(!string_is_empty(name) && config_save_autoconf_profile(name, index_offset)) - runloop_msg_queue_push( - msg_hash_to_str(MSG_AUTOCONFIG_FILE_SAVED_SUCCESSFULLY), 1, 100, true); - else - runloop_msg_queue_push( - msg_hash_to_str(MSG_AUTOCONFIG_FILE_ERROR_SAVING), 1, 100, true); - - - return 0; -} - -static int setting_action_ok_bind_defaults(void *data, bool wraparound) -{ - unsigned i; - menu_input_ctx_bind_limits_t lim; - struct retro_keybind *target = NULL; - const struct retro_keybind *def_binds = NULL; - rarch_setting_t *setting = (rarch_setting_t*)data; - - (void)wraparound; - - if (!setting) - return -1; - - target = &input_config_binds[setting->index_offset][0]; - def_binds = (setting->index_offset) ? - retro_keybinds_rest : retro_keybinds_1; - - lim.min = MENU_SETTINGS_BIND_BEGIN; - lim.max = MENU_SETTINGS_BIND_LAST; - - menu_input_key_bind_set_min_max(&lim); - - for (i = MENU_SETTINGS_BIND_BEGIN; - i <= MENU_SETTINGS_BIND_LAST; i++, target++) - { - target->key = def_binds[i - MENU_SETTINGS_BIND_BEGIN].key; - target->joykey = NO_BTN; - target->joyaxis = AXIS_NONE; - target->mbutton = NO_BTN; - } - - return 0; + snprintf(s, len, "%.3f Hz", video_driver_get_refresh_rate()); } static void @@ -1482,31 +1184,6 @@ setting_get_string_representation_st_float_video_refresh_rate_auto( strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), len); } -static int setting_action_ok_video_refresh_rate_auto(void *data, bool wraparound) -{ - double video_refresh_rate = 0.0; - double deviation = 0.0; - unsigned sample_points = 0; - rarch_setting_t *setting = (rarch_setting_t*)data; - - if (!setting) - return -1; - - if (video_monitor_fps_statistics(&video_refresh_rate, - &deviation, &sample_points)) - { - float video_refresh_rate_float = (float)video_refresh_rate; - driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &video_refresh_rate_float); - /* Incase refresh rate update forced non-block video. */ - command_event(CMD_EVENT_VIDEO_SET_BLOCKING_STATE, NULL); - } - - if (setting_generic_action_ok_default(setting, wraparound) != 0) - return -1; - - return 0; -} - static void get_string_representation_bind_device(void * data, char *s, size_t len) { @@ -1523,7 +1200,7 @@ static void get_string_representation_bind_device(void * data, char *s, if (map < max_devices) { - const char *device_name = input_config_get_device_display_name(map) ? + const char *device_name = input_config_get_device_display_name(map) ? input_config_get_device_display_name(map) : input_config_get_device_name(map); if (!string_is_empty(device_name)) @@ -1736,6 +1413,12 @@ void general_write_handler(void *data) case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_AUTO: driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, setting->value.target.fraction); + /* In case refresh rate update forced non-block video. */ + rarch_cmd = CMD_EVENT_VIDEO_SET_BLOCKING_STATE; + break; + case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED: + driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, setting->value.target.fraction); + /* In case refresh rate update forced non-block video. */ rarch_cmd = CMD_EVENT_VIDEO_SET_BLOCKING_STATE; break; @@ -2425,7 +2108,7 @@ static bool setting_append_list( &subgroup_info, parent_group); -#ifndef __CELLOS_LV2__ +#if !defined(__CELLOS_LV2__) && !defined(HAVE_DYNAMIC) CONFIG_ACTION( list, list_info, MENU_ENUM_LABEL_RESTART_RETROARCH, @@ -2568,6 +2251,14 @@ static bool setting_append_list( &subgroup_info, parent_group); + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_LATENCY_SETTINGS, + MENU_ENUM_LABEL_VALUE_LATENCY_SETTINGS, + &group_info, + &subgroup_info, + parent_group); + CONFIG_ACTION( list, list_info, MENU_ENUM_LABEL_CORE_SETTINGS, @@ -2640,6 +2331,7 @@ static bool setting_append_list( parent_group); settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); +#ifdef HAVE_OVERLAY CONFIG_ACTION( list, list_info, MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS, @@ -2648,6 +2340,7 @@ static bool setting_append_list( &subgroup_info, parent_group); settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); +#endif CONFIG_ACTION( list, list_info, @@ -2699,6 +2392,7 @@ static bool setting_append_list( parent_group); settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); +#ifdef HAVE_CHEEVOS CONFIG_ACTION( list, list_info, MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS, @@ -2706,6 +2400,7 @@ static bool setting_append_list( &group_info, &subgroup_info, parent_group); +#endif CONFIG_ACTION( list, list_info, @@ -2716,6 +2411,7 @@ static bool setting_append_list( parent_group); settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED); +#ifdef HAVE_LAKKA if (string_is_not_equal(settings->arrays.wifi_driver, "null")) { CONFIG_ACTION( @@ -2726,6 +2422,7 @@ static bool setting_append_list( &subgroup_info, parent_group); } +#endif CONFIG_ACTION( list, list_info, @@ -3342,7 +3039,8 @@ static bool setting_append_list( parent_group, general_write_handler, general_read_handler, - SD_FLAG_NONE); + SD_FLAG_ADVANCED + ); CONFIG_UINT( list, list_info, @@ -3355,21 +3053,22 @@ static bool setting_append_list( parent_group, general_write_handler, general_read_handler); + settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED); - CONFIG_BOOL( - list, list_info, - &settings->bools.video_framecount_show, - MENU_ENUM_LABEL_FRAMECOUNT_SHOW, - MENU_ENUM_LABEL_VALUE_FRAMECOUNT_SHOW, - fps_show, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler, - SD_FLAG_NONE); + CONFIG_BOOL( + list, list_info, + &settings->bools.video_framecount_show, + MENU_ENUM_LABEL_FRAMECOUNT_SHOW, + MENU_ENUM_LABEL_VALUE_FRAMECOUNT_SHOW, + fps_show, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); END_SUB_GROUP(list, list_info, parent_group); START_SUB_GROUP(list, list_info, "Platform-specific", &group_info, &subgroup_info, parent_group); @@ -3496,6 +3195,30 @@ static bool setting_append_list( &setting_get_string_representation_st_float_video_refresh_rate_auto; settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); + { + float actual_refresh_rate = video_driver_get_refresh_rate(); + if (actual_refresh_rate > 0.0) + { + CONFIG_FLOAT( + list, list_info, + &settings->floats.video_refresh_rate, + MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED, + MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_POLLED, + actual_refresh_rate, + "%.3f Hz", + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].action_ok = &setting_action_ok_video_refresh_rate_polled; + (*list)[list_info->index - 1].action_select = &setting_action_ok_video_refresh_rate_polled; + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_st_float_video_refresh_rate_polled; + settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); + } + } + if (string_is_equal(settings->arrays.video_driver, "gl")) { CONFIG_BOOL( @@ -3864,53 +3587,83 @@ static bool setting_append_list( settings_data_list_current_add_flags(list, list_info, SD_FLAG_CMD_APPLY_AUTO); settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); - CONFIG_UINT( - list, list_info, - &settings->uints.video_max_swapchain_images, - MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, - MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES, - max_swapchain_images, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler); - menu_settings_list_current_add_range(list, list_info, 1, 4, 1, true, true); - settings_data_list_current_add_flags(list, list_info, SD_FLAG_CMD_APPLY_AUTO); - settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); - - if (string_is_equal(settings->arrays.video_driver, "gl")) { - CONFIG_BOOL( - list, list_info, - &settings->bools.video_hard_sync, - MENU_ENUM_LABEL_VIDEO_HARD_SYNC, - MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC, - hard_sync, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler, - SD_FLAG_NONE - ); - settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); + gfx_ctx_flags_t flags; + bool customizable_swapchain_set = false; - CONFIG_UINT( - list, list_info, - &settings->uints.video_hard_sync_frames, - MENU_ENUM_LABEL_VIDEO_HARD_SYNC_FRAMES, - MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC_FRAMES, - hard_sync_frames, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler); - menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); - settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); + if (video_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES)) + customizable_swapchain_set = true; + + flags.flags = 0; + + if (video_context_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES)) + customizable_swapchain_set = true; + + if (customizable_swapchain_set) + { + CONFIG_UINT( + list, list_info, + &settings->uints.video_max_swapchain_images, + MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, + MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES, + max_swapchain_images, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 1, 4, 1, true, true); + settings_data_list_current_add_flags(list, list_info, SD_FLAG_CMD_APPLY_AUTO); + } + } + + { + gfx_ctx_flags_t flags; + bool hard_sync_supported = false; + + if (video_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_HARD_SYNC)) + hard_sync_supported = true; + + flags.flags = 0; + + if (video_context_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_HARD_SYNC)) + hard_sync_supported = true; + + if (hard_sync_supported) + { + CONFIG_BOOL( + list, list_info, + &settings->bools.video_hard_sync, + MENU_ENUM_LABEL_VIDEO_HARD_SYNC, + MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC, + hard_sync, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + + CONFIG_UINT( + list, list_info, + &settings->uints.video_hard_sync_frames, + MENU_ENUM_LABEL_VIDEO_HARD_SYNC_FRAMES, + MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC_FRAMES, + hard_sync_frames, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); + } } CONFIG_UINT( @@ -3928,22 +3681,40 @@ static bool setting_append_list( settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); #if !defined(RARCH_MOBILE) - CONFIG_BOOL( - list, list_info, - &settings->bools.video_black_frame_insertion, - MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION, - MENU_ENUM_LABEL_VALUE_VIDEO_BLACK_FRAME_INSERTION, - black_frame_insertion, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler, - SD_FLAG_NONE - ); - settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); + { + gfx_ctx_flags_t flags; + bool black_frame_insertion_supported = false; + + if (video_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION)) + black_frame_insertion_supported = true; + + flags.flags = 0; + + if (video_context_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION)) + black_frame_insertion_supported = true; + + if (black_frame_insertion_supported) + { + CONFIG_BOOL( + list, list_info, + &settings->bools.video_black_frame_insertion, + MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION, + MENU_ENUM_LABEL_VALUE_VIDEO_BLACK_FRAME_INSERTION, + black_frame_insertion, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); + } + } #endif END_SUB_GROUP(list, list_info, parent_group); START_SUB_GROUP( @@ -4862,6 +4633,53 @@ static bool setting_append_list( general_read_handler); menu_settings_list_current_add_range(list, list_info, 1, 10, 0.1, true, true); + CONFIG_BOOL( + list, list_info, + &settings->bools.run_ahead_enabled, + MENU_ENUM_LABEL_RUN_AHEAD_ENABLED, + MENU_ENUM_LABEL_VALUE_RUN_AHEAD_ENABLED, + false, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + + CONFIG_UINT( + list, list_info, + &settings->uints.run_ahead_frames, + MENU_ENUM_LABEL_RUN_AHEAD_FRAMES, + MENU_ENUM_LABEL_VALUE_RUN_AHEAD_FRAMES, + 1, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 1, 6, 1, true, true); + +#ifdef HAVE_DYNAMIC + CONFIG_BOOL( + list, list_info, + &settings->bools.run_ahead_secondary_instance, + MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE, + MENU_ENUM_LABEL_VALUE_RUN_AHEAD_SECONDARY_INSTANCE, + false, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); +#endif + CONFIG_BOOL( list, list_info, &settings->bools.menu_throttle_framerate, @@ -5350,44 +5168,112 @@ static bool setting_append_list( SD_FLAG_ADVANCED ); - CONFIG_BOOL( - list, list_info, - &settings->bools.menu_linear_filter, - MENU_ENUM_LABEL_MENU_LINEAR_FILTER, - MENU_ENUM_LABEL_VALUE_MENU_LINEAR_FILTER, - true, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler, - SD_FLAG_ADVANCED - ); + if (string_is_equal(settings->arrays.menu_driver, "rgui")) + { + gfx_ctx_flags_t flags; + bool setting_set = false; - CONFIG_BOOL( - list, list_info, - &settings->bools.menu_horizontal_animation, - MENU_ENUM_LABEL_MENU_HORIZONTAL_ANIMATION, - MENU_ENUM_LABEL_VALUE_MENU_HORIZONTAL_ANIMATION, - true, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler, - SD_FLAG_ADVANCED - ); + if (video_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING)) + setting_set = true; + flags.flags = 0; + + if (video_context_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING)) + setting_set = true; + + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_rgui_border_filler_enable, + MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_ENABLE, + MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_rgui_background_filler_thickness_enable, + MENU_ENUM_LABEL_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_rgui_border_filler_thickness_enable, + MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + + if (setting_set) + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_linear_filter, + MENU_ENUM_LABEL_MENU_LINEAR_FILTER, + MENU_ENUM_LABEL_VALUE_MENU_LINEAR_FILTER, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + } + + if (string_is_equal(settings->arrays.menu_driver, "xmb")) + { + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_horizontal_animation, + MENU_ENUM_LABEL_MENU_HORIZONTAL_ANIMATION, + MENU_ENUM_LABEL_VALUE_MENU_HORIZONTAL_ANIMATION, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_ADVANCED + ); #ifdef RARCH_MOBILE - /* We don't want mobile users being able to switch this off. */ - (*list)[list_info->index - 1].action_left = NULL; - (*list)[list_info->index - 1].action_right = NULL; - (*list)[list_info->index - 1].action_start = NULL; + /* We don't want mobile users being able to switch this off. */ + (*list)[list_info->index - 1].action_left = NULL; + (*list)[list_info->index - 1].action_right = NULL; + (*list)[list_info->index - 1].action_start = NULL; #endif + } + END_SUB_GROUP(list, list_info, parent_group); @@ -5528,7 +5414,7 @@ static bool setting_append_list( if (string_is_equal(settings->arrays.menu_driver, "glui")) { - /* only GLUI uses these values, don't show + /* only GLUI uses these values, don't show * them on other drivers */ CONFIG_BOOL( list, list_info, @@ -5562,7 +5448,7 @@ static bool setting_append_list( #ifdef HAVE_XMB if (string_is_equal(settings->arrays.menu_driver, "xmb")) { - /* only XMB uses these values, don't show + /* only XMB uses these values, don't show * them on other drivers. */ CONFIG_UINT( list, list_info, @@ -5649,6 +5535,20 @@ static bool setting_append_list( menu_settings_list_current_add_range(list, list_info, 0, 255, 1, true, true); settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED); + CONFIG_UINT( + list, list_info, + &settings->uints.menu_xmb_layout, + MENU_ENUM_LABEL_XMB_LAYOUT, + MENU_ENUM_LABEL_VALUE_XMB_LAYOUT, + xmb_menu_layout, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 0, 2, 1, true, true); + menu_settings_list_current_add_cmd(list, list_info, CMD_EVENT_REINIT); + CONFIG_UINT( list, list_info, &settings->uints.menu_xmb_theme, @@ -5768,6 +5668,51 @@ static bool setting_append_list( general_read_handler, SD_FLAG_LAKKA_ADVANCED); + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_show_overlays, + MENU_ENUM_LABEL_CONTENT_SHOW_OVERLAYS, + MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_LAKKA_ADVANCED); + + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_show_latency, + MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY, + MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_LAKKA_ADVANCED); + + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_show_rewind, + MENU_ENUM_LABEL_CONTENT_SHOW_REWIND, + MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_LAKKA_ADVANCED); + CONFIG_BOOL( list, list_info, &settings->bools.menu_show_help, @@ -5783,6 +5728,8 @@ static bool setting_append_list( general_read_handler, SD_FLAG_LAKKA_ADVANCED); + +#ifdef HAVE_LAKKA CONFIG_BOOL( list, list_info, &settings->bools.menu_show_quit_retroarch, @@ -5797,8 +5744,7 @@ static bool setting_append_list( general_write_handler, general_read_handler, SD_FLAG_NONE); - -#ifdef HAVE_LAKKA + CONFIG_BOOL( list, list_info, &settings->bools.menu_show_reboot, @@ -5814,7 +5760,7 @@ static bool setting_append_list( general_read_handler, SD_FLAG_NONE); #endif - + #ifdef HAVE_XMB if (string_is_equal(settings->arrays.menu_driver, "xmb")) { @@ -5833,7 +5779,7 @@ static bool setting_append_list( general_read_handler, SD_FLAG_NONE); settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); - + CONFIG_STRING( list, list_info, settings->paths.menu_content_show_settings_password, @@ -5849,7 +5795,7 @@ static bool setting_append_list( settings_data_list_current_add_flags(list, list_info, SD_FLAG_ALLOW_INPUT | SD_FLAG_LAKKA_ADVANCED); } #endif - + CONFIG_BOOL( list, list_info, &settings->bools.menu_content_show_favorites, @@ -5964,10 +5910,25 @@ static bool setting_append_list( settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); #endif + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_content_show_playlists, + MENU_ENUM_LABEL_CONTENT_SHOW_PLAYLISTS, + MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_PLAYLISTS, + content_show_playlists, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + #ifdef HAVE_MATERIALUI if (string_is_equal(settings->arrays.menu_driver, "glui")) { - /* only MaterialUI uses these values, don't show + /* only MaterialUI uses these values, don't show * them on other drivers. */ CONFIG_BOOL( list, list_info, @@ -6056,6 +6017,34 @@ static bool setting_append_list( general_write_handler, general_read_handler); menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); + + CONFIG_UINT( + list, list_info, + &settings->uints.menu_left_thumbnails, + MENU_ENUM_LABEL_LEFT_THUMBNAILS, + MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS, + menu_left_thumbnails_default, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); + + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_xmb_vertical_thumbnails, + MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, + MENU_ENUM_LABEL_VALUE_XMB_VERTICAL_THUMBNAILS, + xmb_vertical_thumbnails, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); } CONFIG_BOOL( @@ -6254,6 +6243,7 @@ static bool setting_append_list( settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); #endif +#ifdef HAVE_NETWORKING CONFIG_BOOL( list, list_info, &settings->bools.menu_show_online_updater, @@ -6269,6 +6259,7 @@ static bool setting_append_list( general_read_handler, SD_FLAG_NONE); +#if !defined(HAVE_LAKKA) CONFIG_BOOL( list, list_info, &settings->bools.menu_show_core_updater, @@ -6283,6 +6274,8 @@ static bool setting_append_list( general_write_handler, general_read_handler, SD_FLAG_NONE); +#endif +#endif CONFIG_BOOL( list, list_info, diff --git a/menu/widgets/menu_filebrowser.c b/menu/widgets/menu_filebrowser.c index ac1edb47f2..86c943adcb 100644 --- a/menu/widgets/menu_filebrowser.c +++ b/menu/widgets/menu_filebrowser.c @@ -66,7 +66,6 @@ void filebrowser_parse(void *data, unsigned type_data) unsigned dirs_count = 0; settings_t *settings = config_get_ptr(); rarch_system_info_t *system = runloop_get_system_info(); - const struct retro_subsystem_info* subsystem = NULL; menu_displaylist_info_t *info = (menu_displaylist_info_t*)data; enum menu_displaylist_ctl_state type = (enum menu_displaylist_ctl_state) type_data; @@ -86,29 +85,31 @@ void filebrowser_parse(void *data, unsigned type_data) str_list = file_archive_get_file_list(path, info->exts); else { - subsystem = system->subsystem.data + content_get_subsystem(); - str_list = file_archive_get_file_list(path, subsystem->roms[content_get_subsystem_rom_id()].valid_extensions); + const struct retro_subsystem_info *subsystem = system->subsystem.data + content_get_subsystem(); + + if (subsystem) + str_list = file_archive_get_file_list(path, subsystem->roms[content_get_subsystem_rom_id()].valid_extensions); } } - else if (!string_is_empty(path) && filebrowser_types != FILEBROWSER_SELECT_FILE_SUBSYSTEM) + else if (!string_is_empty(path)) { - str_list = dir_list_new(path, - (filter_ext && info) ? info->exts : NULL, - true, settings->bools.show_hidden_files, true, false); - } - else if (!string_is_empty(path) && filebrowser_types == FILEBROWSER_SELECT_FILE_SUBSYSTEM) - { - subsystem = system->subsystem.data + content_get_subsystem(); - - if (subsystem && content_get_subsystem_rom_id() < subsystem->num_roms) + if (filebrowser_types == FILEBROWSER_SELECT_FILE_SUBSYSTEM) { - str_list = dir_list_new(path, - (filter_ext && info) ? subsystem->roms[content_get_subsystem_rom_id()].valid_extensions : NULL, - true, settings->bools.show_hidden_files, true, false); - } + const struct retro_subsystem_info *subsystem = + system->subsystem.data + content_get_subsystem(); + if (subsystem && content_get_subsystem_rom_id() < subsystem->num_roms) + str_list = dir_list_new(path, + (filter_ext && info) ? subsystem->roms[content_get_subsystem_rom_id()].valid_extensions : NULL, + true, settings->bools.show_hidden_files, true, false); + } + else + str_list = dir_list_new(path, + (filter_ext && info) ? info->exts : NULL, + true, settings->bools.show_hidden_files, true, false); } + switch (filebrowser_types) { case FILEBROWSER_SCAN_DIR: diff --git a/menu/widgets/menu_osk.c b/menu/widgets/menu_osk.c index 1e2342bb6f..65e17b04cc 100644 --- a/menu/widgets/menu_osk.c +++ b/menu/widgets/menu_osk.c @@ -32,7 +32,7 @@ #include "../../input/input_driver.h" -static const char *osk_grid[45] = {NULL}; +static char *osk_grid[45] = {NULL}; static int osk_ptr = 0; static enum osk_type osk_idx = OSK_LOWERCASE_LATIN; @@ -148,7 +148,7 @@ void menu_event_osk_iterate(void) } } -const char** menu_event_get_osk_grid(void) +char** menu_event_get_osk_grid(void) { return osk_grid; } diff --git a/menu/widgets/menu_osk.h b/menu/widgets/menu_osk.h index be11d86e7f..2c460a7efb 100644 --- a/menu/widgets/menu_osk.h +++ b/menu/widgets/menu_osk.h @@ -59,7 +59,7 @@ void menu_event_osk_append(int a); void menu_event_osk_iterate(void); -const char** menu_event_get_osk_grid(void); +char** menu_event_get_osk_grid(void); RETRO_END_DECLS diff --git a/movie.c b/movie.c index f84635d176..0dc0da9860 100644 --- a/movie.c +++ b/movie.c @@ -290,7 +290,7 @@ static void bsv_movie_frame_rewind(bsv_movie_t *handle) { /* If we're at the beginning... */ handle->frame_ptr = 0; - intfstream_seek(handle->file, handle->min_file_pos, SEEK_SET); + intfstream_seek(handle->file, (int)handle->min_file_pos, SEEK_SET); } else { @@ -303,7 +303,7 @@ static void bsv_movie_frame_rewind(bsv_movie_t *handle) handle->frame_ptr = (handle->frame_ptr - (handle->first_rewind ? 1 : 2)) & handle->frame_mask; intfstream_seek(handle->file, - handle->frame_pos[handle->frame_ptr], SEEK_SET); + (int)handle->frame_pos[handle->frame_ptr], SEEK_SET); } if (intfstream_tell(handle->file) <= (long)handle->min_file_pos) @@ -327,7 +327,7 @@ static void bsv_movie_frame_rewind(bsv_movie_t *handle) intfstream_write(handle->file, handle->state, handle->state_size); } else - intfstream_seek(handle->file, handle->min_file_pos, SEEK_SET); + intfstream_seek(handle->file, (int)handle->min_file_pos, SEEK_SET); } } diff --git a/msg_hash.c b/msg_hash.c index 37a871b222..afdc0c4d0f 100644 --- a/msg_hash.c +++ b/msg_hash.c @@ -31,6 +31,7 @@ static unsigned uint_user_language; int menu_hash_get_help_enum(enum msg_hash_enums msg, char *s, size_t len) { +#ifdef HAVE_MENU int ret = -1; #ifdef HAVE_LANGEXTRA @@ -90,6 +91,9 @@ int menu_hash_get_help_enum(enum msg_hash_enums msg, char *s, size_t len) return ret; return menu_hash_get_help_us_enum(msg, s, len); +#else + return 0; +#endif } const char *msg_hash_to_str(enum msg_hash_enums msg) diff --git a/msg_hash.h b/msg_hash.h index 1a1c5e07df..3b3f9842d5 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -184,7 +184,7 @@ enum msg_hash_enums MSG_NETPLAY_CHANGED_NICK, MSG_ADDED_TO_FAVORITES, MSG_RESET_CORE_ASSOCIATION, - MSG_CORE_ASSOCIATION_RESET, + MSG_CORE_ASSOCIATION_RESET, MSG_AUTODETECT, MSG_AUDIO_VOLUME, MSG_AUDIO_MIXER_VOLUME, @@ -719,6 +719,7 @@ enum msg_hash_enums MENU_LABEL(VIDEO_WINDOW_SCALE), MENU_LABEL(VIDEO_REFRESH_RATE), MENU_LABEL(VIDEO_REFRESH_RATE_AUTO), + MENU_LABEL(VIDEO_REFRESH_RATE_POLLED), MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE, @@ -747,6 +748,9 @@ enum msg_hash_enums MENU_LABEL(PAUSE_NONACTIVE), MENU_LABEL(MOUSE_ENABLE), MENU_LABEL(POINTER_ENABLE), + MENU_LABEL(MENU_RGUI_BORDER_FILLER_ENABLE), + MENU_LABEL(MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE), + MENU_LABEL(MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE), MENU_LABEL(MENU_LINEAR_FILTER), MENU_LABEL(MENU_HORIZONTAL_ANIMATION), MENU_LABEL(NAVIGATION_WRAPAROUND), @@ -760,10 +764,14 @@ enum msg_hash_enums MENU_LABEL(MENU_FONT_COLOR_GREEN), MENU_LABEL(MENU_FONT_COLOR_BLUE), MENU_LABEL(XMB_FONT), + MENU_LABEL(XMB_LAYOUT), MENU_LABEL(XMB_THEME), MENU_LABEL(XMB_MAIN_MENU_ENABLE_SETTINGS), MENU_LABEL(XMB_MENU_COLOR_THEME), MENU_LABEL(XMB_SHADOWS_ENABLE), + MENU_LABEL(CONTENT_SHOW_REWIND), + MENU_LABEL(CONTENT_SHOW_LATENCY), + MENU_LABEL(CONTENT_SHOW_OVERLAYS), MENU_LABEL(CONTENT_SHOW_SETTINGS), MENU_LABEL(CONTENT_SHOW_SETTINGS_PASSWORD), MENU_LABEL(CONTENT_SHOW_FAVORITES), @@ -773,8 +781,11 @@ enum msg_hash_enums MENU_LABEL(CONTENT_SHOW_NETPLAY), MENU_LABEL(CONTENT_SHOW_HISTORY), MENU_LABEL(CONTENT_SHOW_ADD), + MENU_LABEL(CONTENT_SHOW_PLAYLISTS), MENU_LABEL(XMB_RIBBON_ENABLE), MENU_LABEL(THUMBNAILS), + MENU_LABEL(LEFT_THUMBNAILS), + MENU_LABEL(XMB_VERTICAL_THUMBNAILS), MENU_LABEL(TIMEDATE_ENABLE), MENU_LABEL(BATTERY_LEVEL_ENABLE), MENU_LABEL(MATERIALUI_MENU_COLOR_THEME), @@ -973,6 +984,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_DEFERRED_RECORDING_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_INPUT_SETTINGS_LIST, + MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_DRIVER_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_VIDEO_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST, @@ -1264,6 +1276,9 @@ enum msg_hash_enums MENU_LABEL(THUMBNAILS_DIRECTORY), MENU_LABEL(SLOWMOTION_RATIO), + MENU_LABEL(RUN_AHEAD_ENABLED), + MENU_LABEL(RUN_AHEAD_SECONDARY_INSTANCE), + MENU_LABEL(RUN_AHEAD_FRAMES), MENU_LABEL(TURBO), /* Privacy settings */ @@ -1471,6 +1486,7 @@ enum msg_hash_enums MENU_LABEL(DRIVER_SETTINGS), MENU_LABEL(VIDEO_SETTINGS), MENU_LABEL(AUDIO_SETTINGS), + MENU_LABEL(LATENCY_SETTINGS), MENU_LABEL(CORE_SETTINGS), MENU_LABEL(CONFIGURATION_SETTINGS), MENU_LABEL(LOGGING_SETTINGS), @@ -1717,6 +1733,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_CB_LAKKA_DOWNLOAD, MENU_ENUM_LABEL_CB_LAKKA_LIST, MENU_ENUM_LABEL_CB_MENU_THUMBNAIL, + MENU_ENUM_LABEL_CB_MENU_LEFT_THUMBNAIL, MENU_ENUM_LABEL_CB_MENU_SAVESTATE_THUMBNAIL, MENU_ENUM_LABEL_CB_MENU_WALLPAPER, MENU_ENUM_LABEL_CB_THUMBNAILS_UPDATER_DOWNLOAD, diff --git a/network/netplay/netplay_delta.c b/network/netplay/netplay_delta.c index d6b7efe58b..2b770075ee 100644 --- a/network/netplay/netplay_delta.c +++ b/network/netplay/netplay_delta.c @@ -155,10 +155,10 @@ netplay_input_state_t netplay_input_state_for(netplay_input_state_t *list, ret = (netplay_input_state_t)calloc(1, sizeof(struct netplay_input_state) + (size-1) * sizeof(uint32_t)); if (!ret) return NULL; - *list = ret; + *list = ret; ret->client_num = client_num; - ret->used = true; - ret->size = size; + ret->used = true; + ret->size = (uint32_t)size; return ret; } diff --git a/network/netplay/netplay_discovery.c b/network/netplay/netplay_discovery.c index 33118802b1..372a818b3d 100644 --- a/network/netplay/netplay_discovery.c +++ b/network/netplay/netplay_discovery.c @@ -168,7 +168,7 @@ bool netplay_discovery_driver_ctl(enum rarch_netplay_discovery_ctl_state state, NETPLAY_HOST_STR_LEN); /* And send it off */ - ret = sendto(lan_ad_client_fd, (const char *) &ad_packet_buffer, + ret = (int)sendto(lan_ad_client_fd, (const char *) &ad_packet_buffer, sizeof(struct ad_packet), 0, addr->ai_addr, addr->ai_addrlen); if (ret < (ssize_t) (2*sizeof(uint32_t))) RARCH_WARN("[discovery] Failed to send netplay discovery query (error: %d)\n", errno); @@ -262,8 +262,7 @@ bool netplay_lan_ad_server(netplay_t *netplay) /* Somebody queried, so check that it's valid */ addr_size = sizeof(their_addr); - - ret = recvfrom(lan_ad_server_fd, (char*)&ad_packet_buffer, + ret = (int)recvfrom(lan_ad_server_fd, (char*)&ad_packet_buffer, sizeof(struct ad_packet), 0, &their_addr, &addr_size); if (ret >= (ssize_t) (2 * sizeof(uint32_t))) { diff --git a/network/netplay/netplay_handshake.c b/network/netplay/netplay_handshake.c index a005a963fc..021b51d35c 100644 --- a/network/netplay/netplay_handshake.c +++ b/network/netplay/netplay_handshake.c @@ -564,8 +564,8 @@ bool netplay_handshake_sync(netplay_t *netplay, autosave_unlock(); /* Send basic sync info */ - cmd[0] = htonl(NETPLAY_CMD_SYNC); - cmd[1] = htonl(2*sizeof(uint32_t) + cmd[0] = htonl(NETPLAY_CMD_SYNC); + cmd[1] = htonl(2*sizeof(uint32_t) /* Controller devices */ + MAX_INPUT_DEVICES*sizeof(uint32_t) @@ -580,11 +580,13 @@ bool netplay_handshake_sync(netplay_t *netplay, /* And finally, sram */ + mem_info.size); - cmd[2] = htonl(netplay->self_frame_count); - client_num = connection - netplay->connections + 1; + cmd[2] = htonl(netplay->self_frame_count); + client_num = (uint32_t)(connection - netplay->connections + 1); + if (netplay->local_paused || netplay->remote_paused) client_num |= NETPLAY_CMD_SYNC_BIT_PAUSED; - cmd[3] = htonl(client_num); + + cmd[3] = htonl(client_num); if (!netplay_send(&connection->send_packet_buffer, connection->fd, cmd, sizeof(cmd))) diff --git a/network/netplay/netplay_io.c b/network/netplay/netplay_io.c index d87cc1459a..4028515719 100644 --- a/network/netplay/netplay_io.c +++ b/network/netplay/netplay_io.c @@ -142,7 +142,7 @@ void netplay_hangup(netplay_t *netplay, struct netplay_connection *connection) } else { - uint32_t client_num = connection - netplay->connections + 1; + uint32_t client_num = (uint32_t)(connection - netplay->connections + 1); /* Mark the player for removal */ if (connection->mode == NETPLAY_CONNECTION_PLAYING || @@ -177,22 +177,23 @@ void netplay_hangup(netplay_t *netplay, struct netplay_connection *connection) */ void netplay_delayed_state_change(netplay_t *netplay) { - struct netplay_connection *connection; - size_t i; + unsigned i; for (i = 0; i < netplay->connections_size; i++) { - uint32_t client_num = i+1; - connection = &netplay->connections[i]; + uint32_t client_num = (uint32_t)(i + 1); + struct netplay_connection *connection = &netplay->connections[i]; + if ((connection->active || connection->mode == NETPLAY_CONNECTION_DELAYED_DISCONNECT) && connection->delay_frame && connection->delay_frame <= netplay->self_frame_count) { /* Something was delayed! Prepare the MODE command */ uint32_t payload[15] = {0}; - payload[0] = htonl(connection->delay_frame); - payload[1] = htonl(client_num); - payload[2] = htonl(0); + payload[0] = htonl(connection->delay_frame); + payload[1] = htonl(client_num); + payload[2] = htonl(0); + memcpy(payload + 3, netplay->device_share_modes, sizeof(netplay->device_share_modes)); strncpy((char *) (payload + 7), connection->nick, NETPLAY_NICK_LEN); @@ -294,7 +295,7 @@ bool netplay_send_cur_input(netplay_t *netplay, if (netplay->is_server) { - to_client = connection - netplay->connections + 1; + to_client = (uint32_t)(connection - netplay->connections + 1); /* Send the other players' input data (FIXME: This involves an * unacceptable amount of recalculating) */ @@ -302,6 +303,7 @@ bool netplay_send_cur_input(netplay_t *netplay, { if (from_client == to_client) continue; + if ((netplay->connected_players & (1<have_real[from_client]) @@ -957,7 +959,7 @@ static bool netplay_get_cmd(netplay_t *netplay, RARCH_ERR("Netplay input from non-participating player.\n"); return netplay_cmd_nak(netplay, connection); } - client_num = connection - netplay->connections + 1; + client_num = (uint32_t)(connection - netplay->connections + 1); } if (client_num > MAX_CLIENTS) @@ -1129,7 +1131,7 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); } - client_num = connection - netplay->connections + 1; + client_num = (uint32_t)(connection - netplay->connections + 1); handle_play_spectate(netplay, client_num, connection, cmd, 0, NULL); break; @@ -1180,7 +1182,7 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); } - client_num = connection - netplay->connections + 1; + client_num = (unsigned)(connection - netplay->connections + 1); handle_play_spectate(netplay, client_num, connection, cmd, cmd_size, payload); break; @@ -1552,12 +1554,12 @@ static bool netplay_get_cmd(netplay_t *netplay, uint32_t frame; uint32_t isize; uint32_t rd, wn; - uint32_t client, client_num; + uint32_t client; uint32_t load_frame_count; size_t load_ptr; - struct compression_transcoder *ctrans; - - client_num = connection - netplay->connections + 1; + struct compression_transcoder *ctrans = NULL; + uint32_t client_num = (uint32_t) + (connection - netplay->connections + 1); /* Make sure we're ready for it */ if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION) @@ -1926,8 +1928,8 @@ void netplay_handle_slaves(netplay_t *netplay) if (connection->active && connection->mode == NETPLAY_CONNECTION_SLAVE) { - uint32_t client_num = i + 1; uint32_t devices, device; + uint32_t client_num = (uint32_t)(i + 1); /* This is a slave connection. First, should we do anything at all? If * we've already "read" this data, then we can just ignore it */ diff --git a/network/netplay/netplay_sync.c b/network/netplay/netplay_sync.c index 69386916c5..0035ac7baf 100644 --- a/network/netplay/netplay_sync.c +++ b/network/netplay/netplay_sync.c @@ -126,35 +126,51 @@ static void netplay_merge_digital(netplay_t *netplay, { netplay_input_state_t simstate; uint32_t word, bit, client; - uint8_t share_mode = netplay->device_share_modes[device] & NETPLAY_SHARE_DIGITAL_BITS; + uint8_t share_mode = netplay->device_share_modes[device] + & NETPLAY_SHARE_DIGITAL_BITS; /* Make sure all real clients are accounted for */ - for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) + for (simstate = simframe->real_input[device]; + simstate; simstate = simstate->next) { - if (!simstate->used || simstate->size != resstate->size) continue; + if (!simstate->used || simstate->size != resstate->size) + continue; clients |= 1<client_num; } if (share_mode == NETPLAY_SHARE_DIGITAL_VOTE) { + unsigned i, j; + /* This just assumes we have no more than + * three words, will need to be adjusted for new devices */ + struct vote_count votes[3]; /* Vote mode requires counting all the bits */ - uint32_t client_count = 0; + uint32_t client_count = 0; + + for (i = 0; i < 3; i++) + for (j = 0; j < 32; j++) + votes[i].votes[j] = 0; - /* This just assumes we have no more than three words, will need to be adjusted for new devices */ - struct vote_count votes[3] = {0}; for (client = 0; client < MAX_CLIENTS; client++) { - if (!(clients & (1<size; word++) { - if (!digital[word]) continue; + if (!digital[word]) + continue; for (bit = 0; bit < 32; bit++) { - if (!(digital[word] & (1<data[word] & (1<data[word] |= (1<size; word++) { uint32_t part; - if (!digital[word]) continue; + if (!digital[word]) + continue; part = simstate->data[word]; + if (digital[word] == (uint32_t) -1) { /* Combine the whole word */ switch (share_mode) { - case NETPLAY_SHARE_DIGITAL_XOR: resstate->data[word] ^= part; break; - default: resstate->data[word] |= part; + case NETPLAY_SHARE_DIGITAL_XOR: + resstate->data[word] ^= part; + break; + default: + resstate->data[word] |= part; } } @@ -199,11 +223,15 @@ static void netplay_merge_digital(netplay_t *netplay, { for (bit = 0; bit < 32; bit++) { - if (!(digital[word] & (1<data[word] ^= part & (1<data[word] |= part & (1<data[word] ^= part & (1<data[word] |= part & (1<device_share_modes[device] & NETPLAY_SHARE_ANALOG_BITS; + uint8_t share_mode = netplay->device_share_modes[device] + & NETPLAY_SHARE_ANALOG_BITS; int32_t value = 0, new_value; /* Make sure all real clients are accounted for */ for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) { - if (!simstate->used || simstate->size != resstate->size) continue; + if (!simstate->used || simstate->size != resstate->size) + continue; clients |= 1<client_num; } for (client = 0; client < MAX_CLIENTS; client++) { - if (!(clients & (1<data[word]>>bit) & 0xFFFF); switch (share_mode) @@ -259,7 +292,8 @@ static void merge_analog_part(netplay_t *netplay, } if (share_mode == NETPLAY_SHARE_ANALOG_AVERAGE) - value /= client_count; + if (client_count > 0) /* Prevent potential divide by zero */ + value /= client_count; resstate->data[word] |= ((uint32_t) (uint16_t) value) << bit; } @@ -307,37 +341,41 @@ static void netplay_merge_analog(netplay_t *netplay, bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) { size_t prev; - struct delta_frame *simframe, *pframe; - netplay_input_state_t simstate, client_state = NULL, resstate, oldresstate, pstate; - uint32_t clients, client, client_count; uint32_t device; - bool ret = false; - - simframe = &netplay->buffer[sim_ptr]; + uint32_t clients, client, client_count; + netplay_input_state_t simstate, client_state = NULL, + resstate, oldresstate, pstate; + bool ret = false; + struct delta_frame *pframe = NULL; + struct delta_frame *simframe = &netplay->buffer[sim_ptr]; for (device = 0; device < MAX_INPUT_DEVICES; device++) { unsigned dtype = netplay->config_devices[device]&RETRO_DEVICE_MASK; uint32_t dsize = netplay_expected_input_size(netplay, 1 << device); - clients = netplay->device_clients[device]; - client_count = 0; + clients = netplay->device_clients[device]; + client_count = 0; /* Make sure all real clients are accounted for */ for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) { - if (!simstate->used || simstate->size != dsize) continue; + if (!simstate->used || simstate->size != dsize) + continue; clients |= 1<client_num; } for (client = 0; client < MAX_CLIENTS; client++) { - if (!(clients & (1<real_input[device], client, dsize, false, true); + simstate = netplay_input_state_for( + &simframe->real_input[device], client, dsize, false, true); if (!simstate) { - /* Don't already have this input, so must simulate if we're supposed to have it at all */ + /* Don't already have this input, so must + * simulate if we're supposed to have it at all */ if (netplay->read_frame_count[client] > simframe->frame) continue; simstate = netplay_input_state_for(&simframe->simlated_input[device], client, dsize, false, false); @@ -368,37 +406,39 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) * wavefronts. */ const uint32_t keep = - (1U<data[0] &= keep; simstate->data[0] |= pstate->data[0] & ~keep; } else - { memcpy(simstate->data, pstate->data, dsize * sizeof(uint32_t)); - } } client_state = simstate; client_count++; } - /* The frontend always uses the first resolved input, so make sure it's right */ + /* The frontend always uses the first resolved input, + * so make sure it's right */ while (simframe->resolved_input[device] && (simframe->resolved_input[device]->size != dsize || simframe->resolved_input[device]->client_num != 0)) { /* The default resolved input is of the wrong size! */ - netplay_input_state_t nextistate = simframe->resolved_input[device]->next; + netplay_input_state_t nextistate = + simframe->resolved_input[device]->next; free(simframe->resolved_input[device]); simframe->resolved_input[device] = nextistate; } - /* Now we copy the state, whether real or simulated, out into the resolved state */ - resstate = netplay_input_state_for(&simframe->resolved_input[device], 0, + /* Now we copy the state, whether real or simulated, + * out into the resolved state */ + resstate = netplay_input_state_for( + &simframe->resolved_input[device], 0, dsize, false, false); if (!resstate) continue; @@ -406,9 +446,11 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) if (client_count == 1) { /* Trivial in the common 1-client case */ - if (memcmp(resstate->data, client_state->data, dsize * sizeof(uint32_t))) + if (memcmp(resstate->data, client_state->data, + dsize * sizeof(uint32_t))) ret = true; - memcpy(resstate->data, client_state->data, dsize * sizeof(uint32_t)); + memcpy(resstate->data, client_state->data, + dsize * sizeof(uint32_t)); } else if (client_count == 0) @@ -426,23 +468,27 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) { /* Merge them */ /* Most devices have all the digital parts in the first word. */ - static const uint32_t digital_common[3] = {~0u, 0u, 0u}; + static const uint32_t digital_common[3] = {~0u, 0u, 0u}; static const uint32_t digital_keyboard[5] = {~0u, ~0u, ~0u, ~0u, ~0u}; const uint32_t *digital; if (dtype == RETRO_DEVICE_KEYBOARD) digital = digital_keyboard; else digital = digital_common; - oldresstate = netplay_input_state_for(&simframe->resolved_input[device], 1, dsize, false, false); + oldresstate = netplay_input_state_for( + &simframe->resolved_input[device], 1, dsize, false, false); if (!oldresstate) continue; memcpy(oldresstate->data, resstate->data, dsize * sizeof(uint32_t)); memset(resstate->data, 0, dsize * sizeof(uint32_t)); - netplay_merge_digital(netplay, resstate, simframe, device, clients, digital); - netplay_merge_analog(netplay, resstate, simframe, device, clients, dtype); + netplay_merge_digital(netplay, resstate, simframe, + device, clients, digital); + netplay_merge_analog(netplay, resstate, simframe, + device, clients, dtype); - if (memcmp(resstate->data, oldresstate->data, dsize * sizeof(uint32_t))) + if (memcmp(resstate->data, oldresstate->data, + dsize * sizeof(uint32_t))) ret = true; } @@ -451,7 +497,8 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) return ret; } -static void netplay_handle_frame_hash(netplay_t *netplay, struct delta_frame *delta) +static void netplay_handle_frame_hash(netplay_t *netplay, + struct delta_frame *delta) { if (netplay->is_server) { @@ -468,12 +515,10 @@ static void netplay_handle_frame_hash(netplay_t *netplay, struct delta_frame *de uint32_t local_crc = netplay_delta_frame_crc(netplay, delta); if (local_crc != delta->crc) { + /* If the very first check frame is wrong, + * they probably just don't work */ if (!netplay->crc_validity_checked) - { - /* If the very first check frame is wrong, they probably just don't - * work */ netplay->crcs_valid = false; - } else if (netplay->crcs_valid) { /* Fix this! */ @@ -483,15 +528,11 @@ static void netplay_handle_frame_hash(netplay_t *netplay, struct delta_frame *de RARCH_ERR("Netplay CRCs mismatch!\n"); } else - { netplay_cmd_request_savestate(netplay); - } } } else if (!netplay->crc_validity_checked) - { netplay->crc_validity_checked = true; - } } } @@ -505,29 +546,33 @@ bool netplay_sync_pre_frame(netplay_t *netplay) { retro_ctx_serialize_info_t serial_info; - if (netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->run_ptr], netplay->run_frame_count)) + if (netplay_delta_frame_ready(netplay, + &netplay->buffer[netplay->run_ptr], netplay->run_frame_count)) { serial_info.data_const = NULL; - serial_info.data = netplay->buffer[netplay->run_ptr].state; - serial_info.size = netplay->state_size; + serial_info.data = netplay->buffer[netplay->run_ptr].state; + serial_info.size = netplay->state_size; memset(serial_info.data, 0, serial_info.size); - if ((netplay->quirks & NETPLAY_QUIRK_INITIALIZATION) || netplay->run_frame_count == 0) + if ((netplay->quirks & NETPLAY_QUIRK_INITIALIZATION) + || netplay->run_frame_count == 0) { /* Don't serialize until it's safe */ } - else if (!(netplay->quirks & NETPLAY_QUIRK_NO_SAVESTATES) && core_serialize(&serial_info)) + else if (!(netplay->quirks & NETPLAY_QUIRK_NO_SAVESTATES) + && core_serialize(&serial_info)) { - if (netplay->force_send_savestate && !netplay->stall && !netplay->remote_paused) + if (netplay->force_send_savestate && !netplay->stall + && !netplay->remote_paused) { - /* Bring our running frame and input frames into parity so we don't - * send old info */ + /* Bring our running frame and input frames into + * parity so we don't send old info. */ if (netplay->run_ptr != netplay->self_ptr) { memcpy(netplay->buffer[netplay->self_ptr].state, netplay->buffer[netplay->run_ptr].state, netplay->state_size); - netplay->run_ptr = netplay->self_ptr; + netplay->run_ptr = netplay->self_ptr; netplay->run_frame_count = netplay->self_frame_count; } @@ -545,7 +590,8 @@ bool netplay_sync_pre_frame(netplay_t *netplay) netplay->stateless_mode = true; } - /* If we can't transmit savestates, we must stall until the client is ready */ + /* If we can't transmit savestates, we must stall + * until the client is ready. */ if (netplay->run_frame_count > 0 && (netplay->quirks & (NETPLAY_QUIRK_NO_SAVESTATES|NETPLAY_QUIRK_NO_TRANSMISSION)) && (netplay->connections_size == 0 || !netplay->connections[0].active || @@ -566,11 +612,14 @@ bool netplay_sync_pre_frame(netplay_t *netplay) /* Check for a connection */ FD_ZERO(&fds); FD_SET(netplay->listen_fd, &fds); - if (socket_select(netplay->listen_fd + 1, &fds, NULL, NULL, &tmp_tv) > 0 && + if (socket_select(netplay->listen_fd + 1, + &fds, NULL, NULL, &tmp_tv) > 0 && FD_ISSET(netplay->listen_fd, &fds)) { addr_size = sizeof(their_addr); - new_fd = accept(netplay->listen_fd, (struct sockaddr*)&their_addr, &addr_size); + new_fd = accept(netplay->listen_fd, + (struct sockaddr*)&their_addr, &addr_size); + if (new_fd < 0) { RARCH_ERR("%s\n", msg_hash_to_str(MSG_NETPLAY_FAILED)); @@ -614,8 +663,10 @@ bool netplay_sync_pre_frame(netplay_t *netplay) { if (connection_num == 0) { - netplay->connections = (struct netplay_connection*)malloc(sizeof(struct netplay_connection)); - if (netplay->connections == NULL) + netplay->connections = (struct netplay_connection*) + malloc(sizeof(struct netplay_connection)); + + if (!netplay->connections) { socket_close(new_fd); goto process; @@ -626,10 +677,13 @@ bool netplay_sync_pre_frame(netplay_t *netplay) else { size_t new_connections_size = netplay->connections_size * 2; - struct netplay_connection *new_connections = (struct netplay_connection*) + struct netplay_connection + *new_connections = (struct netplay_connection*) + realloc(netplay->connections, new_connections_size*sizeof(struct netplay_connection)); - if (new_connections == NULL) + + if (!new_connections) { socket_close(new_fd); goto process; @@ -694,7 +748,8 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled) /* We've finished an input frame even if we're stalling */ if ((!stalled || netplay->stall == NETPLAY_STALL_INPUT_LATENCY) && - netplay->self_frame_count < netplay->run_frame_count + netplay->input_latency_frames) + netplay->self_frame_count < + netplay->run_frame_count + netplay->input_latency_frames) { netplay->self_ptr = NEXT_PTR(netplay->self_ptr); netplay->self_frame_count++; @@ -947,12 +1002,14 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled) * clients ahead of us stall */ for (i = 0; i < netplay->connections_size; i++) { - struct netplay_connection *connection = &netplay->connections[i]; uint32_t client_num; + struct netplay_connection *connection = &netplay->connections[i]; + if (!connection->active || connection->mode != NETPLAY_CONNECTION_PLAYING) continue; - client_num = i + 1; + + client_num = (uint32_t)(i + 1); /* Are they ahead? */ if (netplay->self_frame_count + 3 < netplay->read_frame_count[client_num]) diff --git a/pkg/android/phoenix/AndroidManifest.xml b/pkg/android/phoenix/AndroidManifest.xml index 64fb606419..9671cc6bbf 100644 --- a/pkg/android/phoenix/AndroidManifest.xml +++ b/pkg/android/phoenix/AndroidManifest.xml @@ -1,7 +1,7 @@ diff --git a/pkg/android/phoenix/jni/Android.mk b/pkg/android/phoenix/jni/Android.mk index 20cb44d57a..c5a6291e07 100644 --- a/pkg/android/phoenix/jni/Android.mk +++ b/pkg/android/phoenix/jni/Android.mk @@ -67,7 +67,7 @@ else DEFINES += -DHAVE_OPENGLES2 endif -DEFINES += -DRARCH_MOBILE -DHAVE_GRIFFIN -DHAVE_STB_VORBIS -DHAVE_LANGEXTRA -DANDROID -DHAVE_DYNAMIC -DHAVE_OPENGL -DHAVE_OVERLAY -DHAVE_OPENGLES -DGLSL_DEBUG -DHAVE_DYLIB -DHAVE_EGL -DHAVE_GLSL -DHAVE_MENU -DHAVE_RGUI -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DINLINE=inline -DHAVE_THREADS -D__LIBRETRO__ -DHAVE_RSOUND -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DRARCH_INTERNAL -DHAVE_FILTERS_BUILTIN -DHAVE_MATERIALUI -DHAVE_XMB -DHAVE_SHADERPIPELINE -DHAVE_LIBRETRODB -DHAVE_STB_FONT -DHAVE_IMAGEVIEWER -DHAVE_UPDATE_ASSETS -DHAVE_CC_RESAMPLER -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -DHAVE_KEYMAPPER -DHAVE_NETWORKGAMEPAD -DHAVE_FLAC -DHAVE_CHD +DEFINES += -DRARCH_MOBILE -DHAVE_GRIFFIN -DHAVE_STB_VORBIS -DHAVE_LANGEXTRA -DANDROID -DHAVE_DYNAMIC -DHAVE_OPENGL -DHAVE_OVERLAY -DHAVE_OPENGLES -DGLSL_DEBUG -DHAVE_DYLIB -DHAVE_EGL -DHAVE_GLSL -DHAVE_MENU -DHAVE_RGUI -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DINLINE=inline -DHAVE_THREADS -D__LIBRETRO__ -DHAVE_RSOUND -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DRARCH_INTERNAL -DHAVE_FILTERS_BUILTIN -DHAVE_MATERIALUI -DHAVE_XMB -DHAVE_SHADERPIPELINE -DHAVE_LIBRETRODB -DHAVE_STB_FONT -DHAVE_IMAGEVIEWER -DHAVE_UPDATE_ASSETS -DHAVE_CC_RESAMPLER -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -DHAVE_KEYMAPPER -DHAVE_NETWORKGAMEPAD -DHAVE_FLAC -DHAVE_DR_FLAC -DHAVE_DR_MP3 -DHAVE_CHD -DHAVE_RUNAHEAD DEFINES += -DWANT_IFADDRS ifeq ($(HAVE_VULKAN),1) diff --git a/pkg/apple/RetroArch.xcodeproj/project.pbxproj b/pkg/apple/RetroArch.xcodeproj/project.pbxproj index d3f84fbbc0..73e4e0c3bf 100644 --- a/pkg/apple/RetroArch.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch.xcodeproj/project.pbxproj @@ -497,8 +497,11 @@ MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_FLAC", + "-DHAVE_DR_FLAC", + "-DHAVE_DR_MP3", "-DHAVE_LROUND", "-DFLAC__HAS_OGG=0", "-DHAVE_CHD", @@ -557,8 +560,11 @@ GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.5; OTHER_CFLAGS = ( + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_FLAC", + "-DHAVE_DR_FLAC", + "-DHAVE_DR_MP3", "-DHAVE_LROUND", "-DFLAC__HAS_OGG=0", "-DHAVE_CHD", diff --git a/pkg/apple/RetroArch_PPC.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_PPC.xcodeproj/project.pbxproj index 88d2fe4f7b..af4c288810 100644 --- a/pkg/apple/RetroArch_PPC.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_PPC.xcodeproj/project.pbxproj @@ -288,6 +288,7 @@ ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-DMSB_FIRST", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_MINIUPNPC", "-DHAVE_BUILTINMINIUPNPC", @@ -362,6 +363,7 @@ "-DNS_BLOCK_ASSERTIONS=1", "-DNDEBUG", "-DMSB_FIRST", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_MINIUPNPC", "-DHAVE_BUILTINMINIUPNPC", diff --git a/pkg/apple/RetroArch_iOS10.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_iOS10.xcodeproj/project.pbxproj index 5a76d298f8..b7d7273f6a 100644 --- a/pkg/apple/RetroArch_iOS10.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_iOS10.xcodeproj/project.pbxproj @@ -332,6 +332,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -417,6 +418,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -469,6 +471,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -555,6 +558,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -625,6 +629,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", diff --git a/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj index 5c0b588200..b1a0bbe5f7 100644 --- a/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj @@ -332,6 +332,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -418,6 +419,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -471,6 +473,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -558,6 +561,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -628,6 +632,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", diff --git a/pkg/apple/RetroArch_iOS6.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_iOS6.xcodeproj/project.pbxproj index ce77a3519e..0e8c0d9496 100644 --- a/pkg/apple/RetroArch_iOS6.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_iOS6.xcodeproj/project.pbxproj @@ -344,6 +344,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -425,6 +426,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -473,6 +475,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -554,6 +557,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -623,6 +627,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", diff --git a/pkg/apple/RetroArch_iOS8.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_iOS8.xcodeproj/project.pbxproj index 713811bdd1..bf4b24262e 100644 --- a/pkg/apple/RetroArch_iOS8.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_iOS8.xcodeproj/project.pbxproj @@ -347,6 +347,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -416,6 +417,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -490,6 +492,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -574,6 +577,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -625,6 +629,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", diff --git a/pkg/apple/RetroArch_iOS9.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_iOS9.xcodeproj/project.pbxproj index 30534c7f2e..6def3a6b4d 100644 --- a/pkg/apple/RetroArch_iOS9.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_iOS9.xcodeproj/project.pbxproj @@ -362,6 +362,7 @@ "-DHAVE_CORETEXT", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -445,6 +446,7 @@ "-DHAVE_CORETEXT", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -495,6 +497,7 @@ "-DHAVE_CORETEXT", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -580,6 +583,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", @@ -649,6 +653,7 @@ "-DHAVE_HID", "-DHAVE_NETWORKING", "-DHAVE_AVFOUNDATION", + "-DHAVE_RUNAHEAD", "-DHAVE_GRIFFIN", "-DHAVE_STB_VORBIS", "-DHAVE_MINIUPNPC", diff --git a/pkg/ctr/Makefile.cores b/pkg/ctr/Makefile.cores index ec73cf9b5d..8fabdb8bd7 100644 --- a/pkg/ctr/Makefile.cores +++ b/pkg/ctr/Makefile.cores @@ -75,9 +75,9 @@ else ifeq ($(LIBRETRO), freeintv) APP_TITLE = FreeIntv APP_AUTHOR = various APP_PRODUCT_CODE = RARCH-FREEINTV - APP_UNIQUE_ID = 0xBAC1G - APP_ICON = pkg/ctr/assets/default.png - APP_BANNER = pkg/ctr/assets/libretro_banner.png + APP_UNIQUE_ID = 0xBAC21 + APP_ICON = pkg/ctr/assets/freeintv.png + APP_BANNER = pkg/ctr/assets/freeintv_banner.png else ifeq ($(LIBRETRO), fuse) APP_TITLE = Fuse @@ -273,7 +273,7 @@ else ifeq ($(LIBRETRO), stella) APP_UNIQUE_ID = 0xBAC2C APP_ICON = pkg/ctr/assets/stella.png APP_BANNER = pkg/ctr/assets/stella_banner.png - + else ifeq ($(LIBRETRO), pokemini) APP_TITLE = PokeMini APP_AUTHOR = justburn @@ -282,4 +282,4 @@ else ifeq ($(LIBRETRO), pokemini) APP_ICON = pkg/ctr/assets/default.png APP_BANNER = pkg/ctr/assets/libretro_banner.png -endif \ No newline at end of file +endif diff --git a/pkg/ctr/assets/2048.png b/pkg/ctr/assets/2048.png index 04b79d3d21..06e4cc3da7 100644 Binary files a/pkg/ctr/assets/2048.png and b/pkg/ctr/assets/2048.png differ diff --git a/pkg/ctr/assets/2048_banner.png b/pkg/ctr/assets/2048_banner.png index 461bdb396d..c110b894e6 100644 Binary files a/pkg/ctr/assets/2048_banner.png and b/pkg/ctr/assets/2048_banner.png differ diff --git a/pkg/ctr/assets/4do.png b/pkg/ctr/assets/4do.png index 296f31bc51..7eab685bfb 100644 Binary files a/pkg/ctr/assets/4do.png and b/pkg/ctr/assets/4do.png differ diff --git a/pkg/ctr/assets/4do_banner.png b/pkg/ctr/assets/4do_banner.png index 1f3057dd16..c0fcbae420 100644 Binary files a/pkg/ctr/assets/4do_banner.png and b/pkg/ctr/assets/4do_banner.png differ diff --git a/pkg/ctr/assets/81.png b/pkg/ctr/assets/81.png index b0404d6731..691add6e27 100644 Binary files a/pkg/ctr/assets/81.png and b/pkg/ctr/assets/81.png differ diff --git a/pkg/ctr/assets/81_banner.png b/pkg/ctr/assets/81_banner.png index 76697a38e1..8896cc5973 100644 Binary files a/pkg/ctr/assets/81_banner.png and b/pkg/ctr/assets/81_banner.png differ diff --git a/pkg/ctr/assets/assets.7z b/pkg/ctr/assets/assets.7z index de2e1c4acf..b627acef6c 100644 Binary files a/pkg/ctr/assets/assets.7z and b/pkg/ctr/assets/assets.7z differ diff --git a/pkg/ctr/assets/atari800.png b/pkg/ctr/assets/atari800.png index 05796ded0d..501edde06b 100644 Binary files a/pkg/ctr/assets/atari800.png and b/pkg/ctr/assets/atari800.png differ diff --git a/pkg/ctr/assets/atari800_banner.png b/pkg/ctr/assets/atari800_banner.png index 0b731557de..4f93af10e3 100644 Binary files a/pkg/ctr/assets/atari800_banner.png and b/pkg/ctr/assets/atari800_banner.png differ diff --git a/pkg/ctr/assets/default.png b/pkg/ctr/assets/default.png index b6c6d67f6c..54f3fb4c28 100644 Binary files a/pkg/ctr/assets/default.png and b/pkg/ctr/assets/default.png differ diff --git a/pkg/ctr/assets/dosbox.png b/pkg/ctr/assets/dosbox.png index e6700a5d68..44446baa4e 100644 Binary files a/pkg/ctr/assets/dosbox.png and b/pkg/ctr/assets/dosbox.png differ diff --git a/pkg/ctr/assets/dosbox_banner.png b/pkg/ctr/assets/dosbox_banner.png index 30b41d5480..905f917d56 100644 Binary files a/pkg/ctr/assets/dosbox_banner.png and b/pkg/ctr/assets/dosbox_banner.png differ diff --git a/pkg/ctr/assets/fbalpha2012.png b/pkg/ctr/assets/fbalpha2012.png index c0cf19e75d..307f97b345 100644 Binary files a/pkg/ctr/assets/fbalpha2012.png and b/pkg/ctr/assets/fbalpha2012.png differ diff --git a/pkg/ctr/assets/fbalpha2012_banner.png b/pkg/ctr/assets/fbalpha2012_banner.png index 82f6bced5a..4090e9a5d7 100644 Binary files a/pkg/ctr/assets/fbalpha2012_banner.png and b/pkg/ctr/assets/fbalpha2012_banner.png differ diff --git a/pkg/ctr/assets/fbalpha2012_cps1.png b/pkg/ctr/assets/fbalpha2012_cps1.png index 29b32d7855..4ad709cd8b 100644 Binary files a/pkg/ctr/assets/fbalpha2012_cps1.png and b/pkg/ctr/assets/fbalpha2012_cps1.png differ diff --git a/pkg/ctr/assets/fbalpha2012_cps1_banner.png b/pkg/ctr/assets/fbalpha2012_cps1_banner.png index 57ab42ae40..3d2fe99a22 100644 Binary files a/pkg/ctr/assets/fbalpha2012_cps1_banner.png and b/pkg/ctr/assets/fbalpha2012_cps1_banner.png differ diff --git a/pkg/ctr/assets/fbalpha2012_cps2.png b/pkg/ctr/assets/fbalpha2012_cps2.png index e1addcc885..22a3280c19 100644 Binary files a/pkg/ctr/assets/fbalpha2012_cps2.png and b/pkg/ctr/assets/fbalpha2012_cps2.png differ diff --git a/pkg/ctr/assets/fbalpha2012_cps2_banner.png b/pkg/ctr/assets/fbalpha2012_cps2_banner.png index 0c8fde0440..2fc3073b74 100644 Binary files a/pkg/ctr/assets/fbalpha2012_cps2_banner.png and b/pkg/ctr/assets/fbalpha2012_cps2_banner.png differ diff --git a/pkg/ctr/assets/fbalpha2012_cps3.png b/pkg/ctr/assets/fbalpha2012_cps3.png index f153dc1ebf..03f3f01689 100644 Binary files a/pkg/ctr/assets/fbalpha2012_cps3.png and b/pkg/ctr/assets/fbalpha2012_cps3.png differ diff --git a/pkg/ctr/assets/fbalpha2012_cps3_banner.png b/pkg/ctr/assets/fbalpha2012_cps3_banner.png index fab265981a..50bd926bf8 100644 Binary files a/pkg/ctr/assets/fbalpha2012_cps3_banner.png and b/pkg/ctr/assets/fbalpha2012_cps3_banner.png differ diff --git a/pkg/ctr/assets/fbalpha2012_neogeo.png b/pkg/ctr/assets/fbalpha2012_neogeo.png index 444890bdcc..f1b12857d4 100644 Binary files a/pkg/ctr/assets/fbalpha2012_neogeo.png and b/pkg/ctr/assets/fbalpha2012_neogeo.png differ diff --git a/pkg/ctr/assets/fbalpha2012_neogeo_banner.png b/pkg/ctr/assets/fbalpha2012_neogeo_banner.png index 769101af1b..c1cf8f79a5 100644 Binary files a/pkg/ctr/assets/fbalpha2012_neogeo_banner.png and b/pkg/ctr/assets/fbalpha2012_neogeo_banner.png differ diff --git a/pkg/ctr/assets/fceumm.png b/pkg/ctr/assets/fceumm.png index c3b106f7fc..4af02ff4ac 100644 Binary files a/pkg/ctr/assets/fceumm.png and b/pkg/ctr/assets/fceumm.png differ diff --git a/pkg/ctr/assets/fceumm_banner.png b/pkg/ctr/assets/fceumm_banner.png index 7a94dcedf8..fbf12f2523 100644 Binary files a/pkg/ctr/assets/fceumm_banner.png and b/pkg/ctr/assets/fceumm_banner.png differ diff --git a/pkg/ctr/assets/fmsx.png b/pkg/ctr/assets/fmsx.png index 4163e28480..6b62bc3285 100644 Binary files a/pkg/ctr/assets/fmsx.png and b/pkg/ctr/assets/fmsx.png differ diff --git a/pkg/ctr/assets/fmsx_banner.png b/pkg/ctr/assets/fmsx_banner.png index 6a175d2307..0463689a6a 100644 Binary files a/pkg/ctr/assets/fmsx_banner.png and b/pkg/ctr/assets/fmsx_banner.png differ diff --git a/pkg/ctr/assets/freeintv.png b/pkg/ctr/assets/freeintv.png new file mode 100644 index 0000000000..3df7222f04 Binary files /dev/null and b/pkg/ctr/assets/freeintv.png differ diff --git a/pkg/ctr/assets/freeintv_banner.png b/pkg/ctr/assets/freeintv_banner.png new file mode 100644 index 0000000000..a3e13504c4 Binary files /dev/null and b/pkg/ctr/assets/freeintv_banner.png differ diff --git a/pkg/ctr/assets/fuse.png b/pkg/ctr/assets/fuse.png index 4d94048205..93ddeebbd8 100644 Binary files a/pkg/ctr/assets/fuse.png and b/pkg/ctr/assets/fuse.png differ diff --git a/pkg/ctr/assets/fuse_banner.png b/pkg/ctr/assets/fuse_banner.png index eec7ab0ac4..66f402b8f1 100644 Binary files a/pkg/ctr/assets/fuse_banner.png and b/pkg/ctr/assets/fuse_banner.png differ diff --git a/pkg/ctr/assets/gambatte.png b/pkg/ctr/assets/gambatte.png index 8b9226a588..ff939c8356 100644 Binary files a/pkg/ctr/assets/gambatte.png and b/pkg/ctr/assets/gambatte.png differ diff --git a/pkg/ctr/assets/gambatte_banner.png b/pkg/ctr/assets/gambatte_banner.png index 855510b492..4da4319f08 100644 Binary files a/pkg/ctr/assets/gambatte_banner.png and b/pkg/ctr/assets/gambatte_banner.png differ diff --git a/pkg/ctr/assets/genesis_plus_gx.png b/pkg/ctr/assets/genesis_plus_gx.png index 1efb88e4fc..b051576a0d 100644 Binary files a/pkg/ctr/assets/genesis_plus_gx.png and b/pkg/ctr/assets/genesis_plus_gx.png differ diff --git a/pkg/ctr/assets/genesis_plus_gx_banner.png b/pkg/ctr/assets/genesis_plus_gx_banner.png index cb9c2bd297..4c9531b7e7 100644 Binary files a/pkg/ctr/assets/genesis_plus_gx_banner.png and b/pkg/ctr/assets/genesis_plus_gx_banner.png differ diff --git a/pkg/ctr/assets/gpsp.png b/pkg/ctr/assets/gpsp.png index 9373f51939..e237c09b7b 100644 Binary files a/pkg/ctr/assets/gpsp.png and b/pkg/ctr/assets/gpsp.png differ diff --git a/pkg/ctr/assets/gpsp_banner.png b/pkg/ctr/assets/gpsp_banner.png index e5a8777a23..74b0728236 100644 Binary files a/pkg/ctr/assets/gpsp_banner.png and b/pkg/ctr/assets/gpsp_banner.png differ diff --git a/pkg/ctr/assets/gw.png b/pkg/ctr/assets/gw.png index 2ed4457d87..94036488c2 100644 Binary files a/pkg/ctr/assets/gw.png and b/pkg/ctr/assets/gw.png differ diff --git a/pkg/ctr/assets/gw_banner.png b/pkg/ctr/assets/gw_banner.png index a08b68936b..c13466cf54 100644 Binary files a/pkg/ctr/assets/gw_banner.png and b/pkg/ctr/assets/gw_banner.png differ diff --git a/pkg/ctr/assets/handy.png b/pkg/ctr/assets/handy.png index 4681ac4b1d..fe1f44e42b 100644 Binary files a/pkg/ctr/assets/handy.png and b/pkg/ctr/assets/handy.png differ diff --git a/pkg/ctr/assets/handy_banner.png b/pkg/ctr/assets/handy_banner.png index 22be94e292..d8576a5cd3 100644 Binary files a/pkg/ctr/assets/handy_banner.png and b/pkg/ctr/assets/handy_banner.png differ diff --git a/pkg/ctr/assets/libretro_banner.png b/pkg/ctr/assets/libretro_banner.png index 284b6f91e3..6e06290421 100644 Binary files a/pkg/ctr/assets/libretro_banner.png and b/pkg/ctr/assets/libretro_banner.png differ diff --git a/pkg/ctr/assets/libretro_neutral_shaded_banner.png b/pkg/ctr/assets/libretro_neutral_shaded_banner.png index dbfa96dd4a..83254d29af 100644 Binary files a/pkg/ctr/assets/libretro_neutral_shaded_banner.png and b/pkg/ctr/assets/libretro_neutral_shaded_banner.png differ diff --git a/pkg/ctr/assets/mame2000.png b/pkg/ctr/assets/mame2000.png index ad439a5254..d3f6d0b3d5 100644 Binary files a/pkg/ctr/assets/mame2000.png and b/pkg/ctr/assets/mame2000.png differ diff --git a/pkg/ctr/assets/mame2000_banner.png b/pkg/ctr/assets/mame2000_banner.png index 86f5e192d0..a44c77e104 100644 Binary files a/pkg/ctr/assets/mame2000_banner.png and b/pkg/ctr/assets/mame2000_banner.png differ diff --git a/pkg/ctr/assets/mame2003.png b/pkg/ctr/assets/mame2003.png index c6985d7798..edd1cd2ea4 100644 Binary files a/pkg/ctr/assets/mame2003.png and b/pkg/ctr/assets/mame2003.png differ diff --git a/pkg/ctr/assets/mame2003_banner.png b/pkg/ctr/assets/mame2003_banner.png index c44892b266..c1eb1586e0 100644 Binary files a/pkg/ctr/assets/mame2003_banner.png and b/pkg/ctr/assets/mame2003_banner.png differ diff --git a/pkg/ctr/assets/mednafen_ngp.png b/pkg/ctr/assets/mednafen_ngp.png index f8e4987b12..70cdd30f09 100644 Binary files a/pkg/ctr/assets/mednafen_ngp.png and b/pkg/ctr/assets/mednafen_ngp.png differ diff --git a/pkg/ctr/assets/mednafen_ngp_banner.png b/pkg/ctr/assets/mednafen_ngp_banner.png index 22d3061056..ce15124f2e 100644 Binary files a/pkg/ctr/assets/mednafen_ngp_banner.png and b/pkg/ctr/assets/mednafen_ngp_banner.png differ diff --git a/pkg/ctr/assets/mednafen_pce_fast.png b/pkg/ctr/assets/mednafen_pce_fast.png index ed9c7a0434..5e280792be 100644 Binary files a/pkg/ctr/assets/mednafen_pce_fast.png and b/pkg/ctr/assets/mednafen_pce_fast.png differ diff --git a/pkg/ctr/assets/mednafen_pce_fast_banner.png b/pkg/ctr/assets/mednafen_pce_fast_banner.png index ad32f9b9b4..e86d4b38b0 100644 Binary files a/pkg/ctr/assets/mednafen_pce_fast_banner.png and b/pkg/ctr/assets/mednafen_pce_fast_banner.png differ diff --git a/pkg/ctr/assets/mednafen_vb.png b/pkg/ctr/assets/mednafen_vb.png index dae4ed473f..ada5e8b68a 100644 Binary files a/pkg/ctr/assets/mednafen_vb.png and b/pkg/ctr/assets/mednafen_vb.png differ diff --git a/pkg/ctr/assets/mednafen_vb_banner.png b/pkg/ctr/assets/mednafen_vb_banner.png index b48b742841..7349c53e38 100644 Binary files a/pkg/ctr/assets/mednafen_vb_banner.png and b/pkg/ctr/assets/mednafen_vb_banner.png differ diff --git a/pkg/ctr/assets/mednafen_wswan.png b/pkg/ctr/assets/mednafen_wswan.png index e62a1958ce..2e14411161 100644 Binary files a/pkg/ctr/assets/mednafen_wswan.png and b/pkg/ctr/assets/mednafen_wswan.png differ diff --git a/pkg/ctr/assets/mednafen_wswan_banner.png b/pkg/ctr/assets/mednafen_wswan_banner.png index 9d3c1646f1..028a4ed1ad 100644 Binary files a/pkg/ctr/assets/mednafen_wswan_banner.png and b/pkg/ctr/assets/mednafen_wswan_banner.png differ diff --git a/pkg/ctr/assets/mgba_banner.png b/pkg/ctr/assets/mgba_banner.png index fbaef75750..46be827979 100644 Binary files a/pkg/ctr/assets/mgba_banner.png and b/pkg/ctr/assets/mgba_banner.png differ diff --git a/pkg/ctr/assets/nekop2.png b/pkg/ctr/assets/nekop2.png index d7695ba10e..3114361c91 100644 Binary files a/pkg/ctr/assets/nekop2.png and b/pkg/ctr/assets/nekop2.png differ diff --git a/pkg/ctr/assets/nekop2_banner.png b/pkg/ctr/assets/nekop2_banner.png index c97662eb6e..13be556cf4 100644 Binary files a/pkg/ctr/assets/nekop2_banner.png and b/pkg/ctr/assets/nekop2_banner.png differ diff --git a/pkg/ctr/assets/nestopia.png b/pkg/ctr/assets/nestopia.png index b27ec6a51c..bc1793a05f 100644 Binary files a/pkg/ctr/assets/nestopia.png and b/pkg/ctr/assets/nestopia.png differ diff --git a/pkg/ctr/assets/nestopia_banner.png b/pkg/ctr/assets/nestopia_banner.png index 3676f2298e..559d9bf0af 100644 Binary files a/pkg/ctr/assets/nestopia_banner.png and b/pkg/ctr/assets/nestopia_banner.png differ diff --git a/pkg/ctr/assets/np2kai.png b/pkg/ctr/assets/np2kai.png index d7695ba10e..3114361c91 100644 Binary files a/pkg/ctr/assets/np2kai.png and b/pkg/ctr/assets/np2kai.png differ diff --git a/pkg/ctr/assets/np2kai_banner.png b/pkg/ctr/assets/np2kai_banner.png index 83a82db0f6..1321318099 100644 Binary files a/pkg/ctr/assets/np2kai_banner.png and b/pkg/ctr/assets/np2kai_banner.png differ diff --git a/pkg/ctr/assets/nxengine.png b/pkg/ctr/assets/nxengine.png index d6c788a779..f5077b0aba 100644 Binary files a/pkg/ctr/assets/nxengine.png and b/pkg/ctr/assets/nxengine.png differ diff --git a/pkg/ctr/assets/nxengine_banner.png b/pkg/ctr/assets/nxengine_banner.png index fe40fd4541..ab7c613e7f 100644 Binary files a/pkg/ctr/assets/nxengine_banner.png and b/pkg/ctr/assets/nxengine_banner.png differ diff --git a/pkg/ctr/assets/o2em.png b/pkg/ctr/assets/o2em.png index 5be6e266b4..db0595c3d3 100644 Binary files a/pkg/ctr/assets/o2em.png and b/pkg/ctr/assets/o2em.png differ diff --git a/pkg/ctr/assets/o2em_banner.png b/pkg/ctr/assets/o2em_banner.png index 76f4d0647f..86123b74c5 100644 Binary files a/pkg/ctr/assets/o2em_banner.png and b/pkg/ctr/assets/o2em_banner.png differ diff --git a/pkg/ctr/assets/pcsx_rearmed.png b/pkg/ctr/assets/pcsx_rearmed.png index a7a57d55a5..d06c555ea5 100644 Binary files a/pkg/ctr/assets/pcsx_rearmed.png and b/pkg/ctr/assets/pcsx_rearmed.png differ diff --git a/pkg/ctr/assets/pcsx_rearmed_banner.png b/pkg/ctr/assets/pcsx_rearmed_banner.png index 0615758791..be38d0c041 100644 Binary files a/pkg/ctr/assets/pcsx_rearmed_banner.png and b/pkg/ctr/assets/pcsx_rearmed_banner.png differ diff --git a/pkg/ctr/assets/picodrive.png b/pkg/ctr/assets/picodrive.png index 181d1ac951..6f36612ea7 100644 Binary files a/pkg/ctr/assets/picodrive.png and b/pkg/ctr/assets/picodrive.png differ diff --git a/pkg/ctr/assets/picodrive_banner.png b/pkg/ctr/assets/picodrive_banner.png index 5401611057..770107e624 100644 Binary files a/pkg/ctr/assets/picodrive_banner.png and b/pkg/ctr/assets/picodrive_banner.png differ diff --git a/pkg/ctr/assets/prosystem.png b/pkg/ctr/assets/prosystem.png index a9a8c35009..018dc17e70 100644 Binary files a/pkg/ctr/assets/prosystem.png and b/pkg/ctr/assets/prosystem.png differ diff --git a/pkg/ctr/assets/prosystem_banner.png b/pkg/ctr/assets/prosystem_banner.png index a3c616585d..87308ad553 100644 Binary files a/pkg/ctr/assets/prosystem_banner.png and b/pkg/ctr/assets/prosystem_banner.png differ diff --git a/pkg/ctr/assets/quicknes.png b/pkg/ctr/assets/quicknes.png index 151a8a8ec6..b17568a94e 100644 Binary files a/pkg/ctr/assets/quicknes.png and b/pkg/ctr/assets/quicknes.png differ diff --git a/pkg/ctr/assets/quicknes_banner.png b/pkg/ctr/assets/quicknes_banner.png index a8f86f2f75..c6e871a5e8 100644 Binary files a/pkg/ctr/assets/quicknes_banner.png and b/pkg/ctr/assets/quicknes_banner.png differ diff --git a/pkg/ctr/assets/snes9x2002.png b/pkg/ctr/assets/snes9x2002.png index 34ce4dc24a..6c0ae34f6b 100644 Binary files a/pkg/ctr/assets/snes9x2002.png and b/pkg/ctr/assets/snes9x2002.png differ diff --git a/pkg/ctr/assets/snes9x2002_banner.png b/pkg/ctr/assets/snes9x2002_banner.png index ddab3b446a..98b42d2175 100644 Binary files a/pkg/ctr/assets/snes9x2002_banner.png and b/pkg/ctr/assets/snes9x2002_banner.png differ diff --git a/pkg/ctr/assets/snes9x2005.png b/pkg/ctr/assets/snes9x2005.png index a13439df65..e8efbc121b 100644 Binary files a/pkg/ctr/assets/snes9x2005.png and b/pkg/ctr/assets/snes9x2005.png differ diff --git a/pkg/ctr/assets/snes9x2005_banner.png b/pkg/ctr/assets/snes9x2005_banner.png index 1167f68256..79dfbcc6cb 100644 Binary files a/pkg/ctr/assets/snes9x2005_banner.png and b/pkg/ctr/assets/snes9x2005_banner.png differ diff --git a/pkg/ctr/assets/snes9x2005_plus.png b/pkg/ctr/assets/snes9x2005_plus.png index 6d5584c9f8..b415a6644e 100644 Binary files a/pkg/ctr/assets/snes9x2005_plus.png and b/pkg/ctr/assets/snes9x2005_plus.png differ diff --git a/pkg/ctr/assets/snes9x2005_plus_banner.png b/pkg/ctr/assets/snes9x2005_plus_banner.png index 1fb9707b84..41c98ddb78 100644 Binary files a/pkg/ctr/assets/snes9x2005_plus_banner.png and b/pkg/ctr/assets/snes9x2005_plus_banner.png differ diff --git a/pkg/ctr/assets/snes9x2010.png b/pkg/ctr/assets/snes9x2010.png index e4bc6eec8e..428d5add75 100644 Binary files a/pkg/ctr/assets/snes9x2010.png and b/pkg/ctr/assets/snes9x2010.png differ diff --git a/pkg/ctr/assets/snes9x2010_banner.png b/pkg/ctr/assets/snes9x2010_banner.png index 848afe1908..cc5c6df41c 100644 Binary files a/pkg/ctr/assets/snes9x2010_banner.png and b/pkg/ctr/assets/snes9x2010_banner.png differ diff --git a/pkg/ctr/assets/stella.png b/pkg/ctr/assets/stella.png index bc09eaa269..c4a2c1e291 100644 Binary files a/pkg/ctr/assets/stella.png and b/pkg/ctr/assets/stella.png differ diff --git a/pkg/ctr/assets/stella_banner.png b/pkg/ctr/assets/stella_banner.png index 99eba8899b..e9cc2e51a4 100644 Binary files a/pkg/ctr/assets/stella_banner.png and b/pkg/ctr/assets/stella_banner.png differ diff --git a/pkg/ctr/assets/vecx.png b/pkg/ctr/assets/vecx.png index bc2cab2b21..65d0e8fb4b 100644 Binary files a/pkg/ctr/assets/vecx.png and b/pkg/ctr/assets/vecx.png differ diff --git a/pkg/ctr/assets/vecx_banner.png b/pkg/ctr/assets/vecx_banner.png index 9064197771..ad120c78eb 100644 Binary files a/pkg/ctr/assets/vecx_banner.png and b/pkg/ctr/assets/vecx_banner.png differ diff --git a/pkg/ctr/assets/virtualjaguar.png b/pkg/ctr/assets/virtualjaguar.png index 2f998c8895..87856c2670 100644 Binary files a/pkg/ctr/assets/virtualjaguar.png and b/pkg/ctr/assets/virtualjaguar.png differ diff --git a/pkg/ctr/assets/virtualjaguar_banner.png b/pkg/ctr/assets/virtualjaguar_banner.png index b50aee5757..1c8fab5cb0 100644 Binary files a/pkg/ctr/assets/virtualjaguar_banner.png and b/pkg/ctr/assets/virtualjaguar_banner.png differ diff --git a/pkg/ctr/assets/yabause.png b/pkg/ctr/assets/yabause.png index c94d855455..a363fd4ef2 100644 Binary files a/pkg/ctr/assets/yabause.png and b/pkg/ctr/assets/yabause.png differ diff --git a/pkg/ctr/assets/yabause_banner.png b/pkg/ctr/assets/yabause_banner.png index 0dfc9675a4..ed72ed8cd6 100644 Binary files a/pkg/ctr/assets/yabause_banner.png and b/pkg/ctr/assets/yabause_banner.png differ diff --git a/pkg/msvc/RetroArch-360/RetroArch-360.vcxproj b/pkg/msvc/RetroArch-360/RetroArch-360.vcxproj index d297901003..85bd70e68c 100644 --- a/pkg/msvc/RetroArch-360/RetroArch-360.vcxproj +++ b/pkg/msvc/RetroArch-360/RetroArch-360.vcxproj @@ -113,7 +113,7 @@ true false MultiThreadedDebug - _DEBUG;_XBOX;HAVE_XINPUT2;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_XUI;HAVE_MENU;HAVE_NETWORKING;HAVE_NETWORKING;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN + _DEBUG;_XBOX;HAVE_XINPUT2;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_MENU;HAVE_NETWORKING;HAVE_NETWORKING;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN Callcap $(SolutionDir)\..\..\deps\zlib;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\stb;$(SolutionDir)\..\..\;%(AdditionalIncludeDirectories) @@ -152,7 +152,7 @@ AnalyzeOnly false MultiThreadedDebug - _DEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_XUI;HAVE_MENU;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN + _DEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_MENU;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN Callcap $(SolutionDir)\..\..\deps\zlib;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\stb;$(SolutionDir)\..\..\;%(AdditionalIncludeDirectories) @@ -192,7 +192,7 @@ Size false MultiThreaded - NDEBUG;_XBOX;PROFILE;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_XUI;HAVE_MENU;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN + NDEBUG;_XBOX;PROFILE;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_MENU;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN Callcap $(SolutionDir)\..\..\deps\zlib;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\stb;$(SolutionDir)\..\..\;%(AdditionalIncludeDirectories) @@ -237,7 +237,7 @@ Size false MultiThreaded - NDEBUG;_XBOX;PROFILE;FASTCAP;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XUI;HAVE_MENU;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN + NDEBUG;_XBOX;PROFILE;FASTCAP;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_MENU;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN $(SolutionDir)\..\..\deps\zlib;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\stb;$(SolutionDir)\..\..\;%(AdditionalIncludeDirectories) @@ -279,7 +279,7 @@ false false MultiThreaded - NDEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE=1;HAVE_NETWORKING;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XUI;HAVE_MENU;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN + NDEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE=1;HAVE_NETWORKING;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_MENU;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN $(SolutionDir)\..\..\deps\zlib;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\stb;$(SolutionDir)\..\..\;%(AdditionalIncludeDirectories) @@ -321,7 +321,7 @@ false false MultiThreaded - NDEBUG;_XBOX;LTCG;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_XUI;HAVE_MENU;HAVE_NETWORKING;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN + NDEBUG;_XBOX;LTCG;%(PreprocessorDefinitions);HAVE_XINPUT2;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_MENU;HAVE_NETWORKING;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_EXEC;D3DCOMPILE_USEVOIDS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_HLSL;HAVE_CC_RESAMPLER;HAVE_D3D9;HAVE_D3D;RARCH_INTERNAL;MSB_FIRST;_XBOX360;WANT_ZLIB;HAVE_XAUDIO;HAVE_RPNG;HAVE_RJPEG;HAVE_THREADS;HAVE_FILTERS_BUILTIN $(SolutionDir)\..\..\deps\zlib;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\stb;$(SolutionDir)\..\..\;%(AdditionalIncludeDirectories) diff --git a/pkg/msvc/RetroArch-Xbox1/RetroArch-Xbox1.vcproj b/pkg/msvc/RetroArch-Xbox1/RetroArch-Xbox1.vcproj index 120cbb84aa..0da7a53238 100644 --- a/pkg/msvc/RetroArch-Xbox1/RetroArch-Xbox1.vcproj +++ b/pkg/msvc/RetroArch-Xbox1/RetroArch-Xbox1.vcproj @@ -22,7 +22,7 @@ Optimization="3" OptimizeForProcessor="2" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\msvc-71";"$(SolutionDir)\..\..\deps\zlib"" - PreprocessorDefinitions="_DEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_GRIFFIN;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" + PreprocessorDefinitions="_DEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" MinimalRebuild="TRUE" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -72,7 +72,7 @@ OmitFramePointers="TRUE" OptimizeForProcessor="2" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\msvc-71";"$(SolutionDir)\..\..\deps\zlib"" - PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" + PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" StringPooling="TRUE" RuntimeLibrary="0" BufferSecurityCheck="TRUE" @@ -127,7 +127,7 @@ OmitFramePointers="TRUE" OptimizeForProcessor="2" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\msvc-71";"$(SolutionDir)\..\..\deps\zlib"" - PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;FASTCAP;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" + PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;FASTCAP;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" StringPooling="TRUE" RuntimeLibrary="0" BufferSecurityCheck="TRUE" @@ -188,7 +188,7 @@ EnableFiberSafeOptimizations="TRUE" OptimizeForProcessor="2" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\msvc-71";"$(SolutionDir)\..\..\deps\zlib"" - PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_GRIFFIN;HAVE_LANGEXTRA;inline=_inline;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" + PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;inline=_inline;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" StringPooling="TRUE" RuntimeLibrary="0" BufferSecurityCheck="TRUE" @@ -241,7 +241,7 @@ OmitFramePointers="TRUE" OptimizeForProcessor="2" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\msvc-71";"$(SolutionDir)\..\..\deps\zlib"" - PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;LTCG;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" + PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;LTCG;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" StringPooling="TRUE" RuntimeLibrary="0" BufferSecurityCheck="TRUE" @@ -300,7 +300,7 @@ EnableFiberSafeOptimizations="TRUE" OptimizeForProcessor="2" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\msvc-71";"$(SolutionDir)\..\..\deps\zlib"" - PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_GRIFFIN;HAVE_LANGEXTRA;inline=_inline;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" + PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;inline=_inline;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" StringPooling="TRUE" RuntimeLibrary="0" BufferSecurityCheck="TRUE" @@ -353,7 +353,7 @@ OmitFramePointers="TRUE" OptimizeForProcessor="2" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\msvc-71";"$(SolutionDir)\..\..\deps\zlib"" - PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;LTCG;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" + PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RGUI;HAVE_MENU;HAVE_OVERLAY;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;__STDC_CONSTANT_MACROS;HAVE_ZLIB;LTCG;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_RARCH_EXEC;HAVE_DSOUND;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D8;RARCH_INTERNAL;WANT_ZLIB;HAVE_THREADS;HAVE_RPNG;HAVE_FILTERS_BUILTIN" StringPooling="TRUE" RuntimeLibrary="0" BufferSecurityCheck="TRUE" diff --git a/pkg/msvc/RetroArch-msvc2015.sln b/pkg/msvc/RetroArch-msvc2015.sln index 2ee30da985..a20ab722df 100644 --- a/pkg/msvc/RetroArch-msvc2015.sln +++ b/pkg/msvc/RetroArch-msvc2015.sln @@ -1,6 +1,8 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2015 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RetroArch-msvc2015", "msvc-2015\RetroArch-msvc2015.vcxproj", "{27FF7CE1-4059-4AA1-8062-FD529560FA54}" EndProject Global @@ -17,16 +19,20 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|Win32.ActiveCfg = Debug Cg|Win32 {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|Win32.Build.0 = Debug Cg|Win32 - {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|x64.ActiveCfg = Debug Cg|Win32 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|x64.ActiveCfg = Debug Cg|x64 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|x64.Build.0 = Debug Cg|x64 {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|Win32.ActiveCfg = Debug|Win32 {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|Win32.Build.0 = Debug|Win32 - {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|x64.ActiveCfg = Debug|Win32 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|x64.ActiveCfg = Debug|x64 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|x64.Build.0 = Debug|x64 {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|Win32.ActiveCfg = Release Cg|Win32 {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|Win32.Build.0 = Release Cg|Win32 - {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|x64.ActiveCfg = Release Cg|Win32 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|x64.ActiveCfg = Release Cg|x64 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|x64.Build.0 = Release Cg|x64 {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|Win32.ActiveCfg = Release|Win32 {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|Win32.Build.0 = Release|Win32 - {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|x64.ActiveCfg = Release|Win32 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|x64.ActiveCfg = Release|x64 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/pkg/msvc/msvc-2003/RetroArch-msvc2003.vcproj b/pkg/msvc/msvc-2003/RetroArch-msvc2003.vcproj index c09ab98844..3bcfe59ddf 100644 --- a/pkg/msvc/msvc-2003/RetroArch-msvc2003.vcproj +++ b/pkg/msvc/msvc-2003/RetroArch-msvc2003.vcproj @@ -21,14 +21,14 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""$(SolutionDir)\..\..\libretro-common\include";"$(SolutionDir)\..\..\libretro-common\include\compat\msvc";"$(SolutionDir)\..\..\deps";"$(SolutionDir)\..\..\deps\stb";"$(SolutionDir)\..\..\gfx\include"" - PreprocessorDefinitions="_WIN32;WINVER=0x0400;_WIN32_WINNT=0x0400;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_GRIFFIN;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;WANT_ZLIB;HAVE_DINPUT;HAVE_DSOUND;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_OVERLAY;HAVE_RGUI;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT;HAVE_D3D;HAVE_D3D8;DEBUG;_DEBUG;__STDC_CONSTANT_MACROS" + PreprocessorDefinitions="_WIN32;WINVER=0x0400;_WIN32_WINNT=0x0400;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;WANT_ZLIB;HAVE_DINPUT;HAVE_DSOUND;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_OVERLAY;HAVE_RGUI;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT;HAVE_D3D;HAVE_D3D8;DEBUG;_DEBUG;__STDC_CONSTANT_MACROS" MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" UsePrecompiledHeader="0" WarningLevel="3" Detect64BitPortabilityProblems="TRUE" - DebugInformationFormat="4"/> + DebugInformationFormat="1"/> + DebugInformationFormat="1"/> + DebugInformationFormat="1"/> + DebugInformationFormat="1"/> - true + false $(DXSDK_DIR)Include;$(IncludePath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) AllRules.ruleset @@ -121,7 +121,7 @@ - true + false $(DXSDK_DIR)Include;$(CG_INC_PATH);$(IncludePath) $(DXSDK_DIR)Lib\x86;$(CG_LIB_PATH);$(LibraryPath) AllRules.ruleset @@ -129,7 +129,7 @@ - true + false $(DXSDK_DIR)Include;$(IncludePath) $(DXSDK_DIR)Lib\x64;$(LibraryPath) AllRules.ruleset @@ -137,7 +137,7 @@ - true + false $(DXSDK_DIR)Include;$(CG_INC_PATH);$(IncludePath) $(DXSDK_DIR)Lib\x64;$(CG_LIB64_PATH);$(LibraryPath) AllRules.ruleset @@ -182,12 +182,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions + OldStyle CONSOLE @@ -201,12 +202,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_CG;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions + OldStyle CONSOLE @@ -221,12 +223,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions2 + OldStyle CONSOLE @@ -240,12 +243,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_CG;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions2 + OldStyle CONSOLE @@ -262,13 +266,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions true + OldStyle WINDOWS @@ -287,13 +292,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3DX;HAVE_CG;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions true + OldStyle WINDOWS @@ -313,13 +319,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions2 true + OldStyle WINDOWS @@ -338,13 +345,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_CHEEVOS;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_CG;HAVE_GLSL;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_CHEEVOS;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions2 true + OldStyle WINDOWS @@ -375,4 +383,4 @@ - + \ No newline at end of file diff --git a/pkg/msvc/msvc-2013/RetroArch-msvc2013.vcxproj b/pkg/msvc/msvc-2013/RetroArch-msvc2013.vcxproj index 7e3efe3a57..7eda564904 100644 --- a/pkg/msvc/msvc-2013/RetroArch-msvc2013.vcxproj +++ b/pkg/msvc/msvc-2013/RetroArch-msvc2013.vcxproj @@ -84,8 +84,9 @@ Level3 Disabled - WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_MENU;HAVE_SLANG;HAVE_GLSLANG;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;_DEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) + WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_MENU;HAVE_SLANG;HAVE_GLSLANG;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;_DEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) $(SolutionDir)\..\..\gfx\include\dxsdk;$(SolutionDir)\..\..\gfx\include;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\glslang;$(SolutionDir)\..\..\deps\SPIRV-Cross;%(AdditionalIncludeDirectories) + OldStyle Console @@ -99,8 +100,9 @@ Level3 Disabled - WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_MENU;HAVE_SLANG;HAVE_GLSLANG;HAVE_UPDATE_ASSETS;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;_DEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) + WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_MENU;HAVE_SLANG;HAVE_GLSLANG;HAVE_UPDATE_ASSETS;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;_DEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) $(SolutionDir)\..\..\gfx\include\dxsdk;$(SolutionDir)\..\..\gfx\include;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\glslang;$(SolutionDir)\..\..\deps\SPIRV-Cross;%(AdditionalIncludeDirectories) + OldStyle Console @@ -116,8 +118,9 @@ MaxSpeed true true - WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;HAVE_MENU;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;NDEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_COMMAND;HAVE_NETWORK_CMD;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) + WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;HAVE_MENU;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;NDEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_COMMAND;HAVE_NETWORK_CMD;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) $(SolutionDir)\..\..\gfx\include\dxsdk;$(SolutionDir)\..\..\gfx\include;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\glslang;$(SolutionDir)\..\..\deps\SPIRV-Cross;%(AdditionalIncludeDirectories) + OldStyle Console @@ -135,8 +138,9 @@ MaxSpeed true true - WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_MENU;HAVE_SLANG;HAVE_GLSLANG;HAVE_UPDATE_ASSETS;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;NDEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) + WIN32;WANT_GLSLANG;HAVE_DYNAMIC;HAVE_DYLIB;HAVE_SPIRV_CROSS;HAVE_MENU;HAVE_SLANG;HAVE_GLSLANG;HAVE_UPDATE_ASSETS;HAVE_XMB;HAVE_SHADERPIPELINE;HAVE_RGUI;HAVE_MATERIALUI;NDEBUG;_WINDOWS;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DINPUT;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_OPENGL;HAVE_VULKAN;HAVE_GLSL;HAVE_THREADS;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_RJPEG;HAVE_RPNG;HAVE_ZLIB;WANT_ZLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_OVERLAY;HAVE_7ZIP;HAVE_LIBRETRODB;HAVE_STB_FONT;%(PreprocessorDefinitions) $(SolutionDir)\..\..\gfx\include\dxsdk;$(SolutionDir)\..\..\gfx\include;$(SolutionDir)\..\..\libretro-common\include;$(SolutionDir)\..\..\deps;$(SolutionDir)\..\..\deps\glslang;$(SolutionDir)\..\..\deps\SPIRV-Cross;%(AdditionalIncludeDirectories) + OldStyle Console diff --git a/pkg/msvc/msvc-2015/RetroArch-msvc2015.vcxproj b/pkg/msvc/msvc-2015/RetroArch-msvc2015.vcxproj index eb0955f903..f58275b30d 100644 --- a/pkg/msvc/msvc-2015/RetroArch-msvc2015.vcxproj +++ b/pkg/msvc/msvc-2015/RetroArch-msvc2015.vcxproj @@ -190,12 +190,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions + OldStyle Console @@ -209,12 +210,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions + OldStyle Console @@ -229,13 +231,14 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp /bigobj Fast StreamingSIMDExtensions2 + OldStyle Console @@ -249,12 +252,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions2 + OldStyle Console @@ -271,13 +275,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions true + OldStyle Console @@ -295,13 +300,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions true + OldStyle Console @@ -320,13 +326,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions2 true + OldStyle Console @@ -344,13 +351,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;HAVE_UPDATE_ASSETS;HAVE_SLANG;HAVE_GLSLANG;WANT_GLSLANG;HAVE_VULKAN;HAVE_SPIRV_CROSS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\gfx\include\dxsdk;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions2 true + OldStyle Console diff --git a/pkg/msvc/msvc-2017/RetroArch-msvc2017.vcxproj b/pkg/msvc/msvc-2017/RetroArch-msvc2017.vcxproj index 14aee7a1c8..a4cf7d356e 100644 --- a/pkg/msvc/msvc-2017/RetroArch-msvc2017.vcxproj +++ b/pkg/msvc/msvc-2017/RetroArch-msvc2017.vcxproj @@ -191,12 +191,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions + OldStyle Console @@ -210,12 +211,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_FBO;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_FBO;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions + OldStyle Console @@ -230,12 +232,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions2 + OldStyle Console @@ -249,12 +252,13 @@ Level3 Disabled - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_FBO;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_FBO;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp Fast StreamingSIMDExtensions2 + OldStyle Console @@ -271,13 +275,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions true + OldStyle Console @@ -295,13 +300,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_MENU;HAVE_RGUI;HAVE_GL_SYNC;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions true + OldStyle Console @@ -320,13 +326,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions2 true + OldStyle Console @@ -344,13 +351,14 @@ MaxSpeed true true - WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT + WIN32;RARCH_INTERNAL;HAVE_CC_RESAMPLER;WANT_GLSLANG;HAVE_SLANG;HAVE_GLSLANG;HAVE_SPIRV_CROSS;HAVE_UPDATE_ASSETS;HAVE_D3D;HAVE_D3D9;HAVE_D3D10;HAVE_D3D11;HAVE_D3D12;HAVE_VULKAN;HAVE_CG;HAVE_GLSL;HAVE_CHEEVOS;HAVE_RUNAHEAD;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_DINPUT;HAVE_XINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;WANT_ZLIB;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\..\;$(CG_INC_PATH);$(MSBuildProjectDirectory)\..\..\..\deps\zlib;$(MSBuildProjectDirectory)\..\..\..\libretro-common\include;$(MSBuildProjectDirectory)\..\..\..\deps;$(MSBuildProjectDirectory)\..\..\..\deps\glslang;$(MSBuildProjectDirectory)\..\..\..\deps\SPIRV-Cross;$(MSBuildProjectDirectory)\..\..\..\deps\stb;$(MSBuildProjectDirectory)\..\..\..\gfx\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp Fast StreamingSIMDExtensions2 true + OldStyle Console @@ -376,9 +384,12 @@ CompileAsC - + + /bigobj %(AdditionalOptions) + /bigobj %(AdditionalOptions) + - + \ No newline at end of file diff --git a/playlist.c b/playlist.c index 91d8ed032b..fba39fee5f 100644 --- a/playlist.c +++ b/playlist.c @@ -52,6 +52,7 @@ struct content_playlist char *conf_path; struct playlist_entry *entries; }; +static playlist_t *playlist_cached = NULL; typedef int (playlist_sort_fun_t)( const struct playlist_entry *a, @@ -554,6 +555,29 @@ end: return true; } +void playlist_free_cached(void) +{ + playlist_free(playlist_cached); + playlist_cached = NULL; +} + +playlist_t *playlist_get_cached(void) +{ + if (playlist_cached) + return playlist_cached; + return NULL; +} + +bool playlist_init_cached(const char *path, size_t size) +{ + playlist_t *playlist = playlist_init(path, size); + if (!playlist) + return false; + + playlist_cached = playlist; + return true; +} + /** * playlist_init: * @path : Path to playlist contents file. diff --git a/playlist.h b/playlist.h index a130df23c8..d3e8ef1176 100644 --- a/playlist.h +++ b/playlist.h @@ -129,6 +129,12 @@ void playlist_write_file(playlist_t *playlist); void playlist_qsort(playlist_t *playlist); +void playlist_free_cached(void); + +playlist_t *playlist_get_cached(void); + +bool playlist_init_cached(const char *path, size_t size); + RETRO_END_DECLS #endif diff --git a/qb/config.libs.sh b/qb/config.libs.sh index e0c3382d5b..701d8c162d 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -210,7 +210,6 @@ if [ "$HAVE_NETWORKING" = 'yes' ]; then check_lib '' MINIUPNPC '-lminiupnpc' else die : 'Warning: All networking features have been disabled.' - HAVE_KEYMAPPER='no' HAVE_NETWORK_CMD='no' HAVE_NETWORKGAMEPAD='no' HAVE_CHEEVOS='no' diff --git a/qb/config.params.sh b/qb/config.params.sh index a1be97d869..126744aabe 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -11,6 +11,7 @@ HAVE_MATERIALUI=auto # MaterialUI menu HAVE_XMB=auto # XMB menu HAVE_ZARCH=no # Zarch menu HAVE_NUKLEAR=no # Nuklear menu +HAVE_RUNAHEAD=yes # Runahead support HAVE_OVERLAY=yes # Overlay support HAVE_DYNAMIC=yes # Dynamic loading of libretro library HAVE_SDL=auto # SDL support @@ -30,7 +31,6 @@ HAVE_SSA=auto # SSA/ASS for FFmpeg subtitle support HAVE_DYLIB=auto # Dynamic loading support HAVE_NETWORKING=auto # Networking features (recommended) HAVE_NETWORKGAMEPAD=auto # Networked game pad (plus baked-in core) -HAVE_KEYMAPPER=yes # Networked game pad (plus baked-in core) C89_NETWORKGAMEPAD=no HAVE_MINIUPNPC=auto # Mini UPnP client library (for NAT traversal) HAVE_BUILTINMINIUPNPC=yes # Bake in Mini UPnP client library (for NAT traversal) @@ -38,7 +38,7 @@ C89_BUILTINMINIUPNPC=no HAVE_D3D8=no # Direct3D 8 support HAVE_D3D9=yes # Direct3D 9 support C89_D3D9=no -HAVE_D3D10=no # Direct3D 10 support +HAVE_D3D10=yes # Direct3D 10 support C89_D3D10=no HAVE_D3D11=yes # Direct3D 11 support C89_D3D11=no @@ -92,10 +92,10 @@ HAVE_NEON=no # ARM NEON optimizations HAVE_SSE=no # x86 SSE optimizations (SSE, SSE2) HAVE_FLOATHARD=no # Force hard float ABI (for ARM) HAVE_FLOATSOFTFP=no # Force soft float ABI (for ARM) +HAVE_CHD=yes # Compile in chd support HAVE_7ZIP=yes # Compile in 7z support HAVE_FLAC=auto # Compile in flac support HAVE_BUILTINFLAC=yes # Bake in flac support -C89_BUILTINFLAC=no HAVE_UPDATE_ASSETS=yes # Disable downloading assets with online updater HAVE_PRESERVE_DYLIB=no # Enable dlclose() for Valgrind support HAVE_PARPORT=auto # Parallel port joypad support diff --git a/qb/qb.params.sh b/qb/qb.params.sh index 8163c3c5c9..2a68f0605e 100644 --- a/qb/qb.params.sh +++ b/qb/qb.params.sh @@ -33,11 +33,12 @@ General environment variables: General options: EOF print_help_option "--prefix=PATH" "Install path prefix" - print_help_option "--global-config-dir=PATH" "System wide config file prefix" + print_help_option "--sysconfdir=PATH" "System wide config file prefix" print_help_option "--bindir=PATH" "Binary install directory" print_help_option "--datarootdir=PATH" "Read-only data install directory" print_help_option "--docdir=PATH" "Documentation install directory" print_help_option "--mandir=PATH" "Manpage install directory" + print_help_option "--global-config-dir=PATH" "System wide config file prefix (Deprecated)" print_help_option "--build=BUILD" "The build system (no-op)" print_help_option "--host=HOST" "Cross-compile with HOST-gcc instead of gcc" print_help_option "--help" "Show this help" @@ -87,7 +88,7 @@ parse_input() # Parse stuff :V while [ "$1" ]; do case "$1" in --prefix=*) PREFIX=${1##--prefix=};; - --global-config-dir=*) GLOBAL_CONFIG_DIR=${1##--global-config-dir=};; + --global-config-dir=*|--sysconfdir=*) GLOBAL_CONFIG_DIR="${1#*=}";; --bindir=*) BIN_DIR="${1#*=}";; --build=*) BUILD="${1#*=}";; --datarootdir=*) SHARE_DIR="${1#*=}";; diff --git a/retroarch.c b/retroarch.c index 3148d556bf..537ed82f37 100644 --- a/retroarch.c +++ b/retroarch.c @@ -118,6 +118,10 @@ #include "command.h" +#ifdef HAVE_RUNAHEAD +#include "runahead/run_ahead.h" +#endif + #define _PSUPP(var, name, desc) printf(" %s:\n\t\t%s: %s\n", name, desc, _##var##_supp ? "yes" : "no") #define FAIL_CPU(simd_type) do { \ @@ -743,6 +747,11 @@ static void retroarch_parse_input_and_config(int argc, char *argv[]) RARCH_OVERRIDE_SETTING_STATE_PATH, NULL); break; + /* Must handle '?' otherwise you get an infinite loop */ + case '?': + retroarch_print_help(argv[0]); + retroarch_fail(1, "retroarch_parse_input()"); + break; /* All other arguments are handled in the second pass */ } } @@ -2372,7 +2381,7 @@ bool runloop_msg_queue_pull(const char **ret) #ifdef HAVE_MENU static bool input_driver_toggle_button_combo( - unsigned mode, retro_bits_t* p_input) + unsigned mode, input_bits_t* p_input) { switch (mode) { @@ -2422,9 +2431,9 @@ static enum runloop_state runloop_check_state( bool input_nonblock_state, unsigned *sleep_ms) { - retro_bits_t current_input; + input_bits_t current_input; #ifdef HAVE_MENU - static retro_bits_t last_input = {{0}}; + static input_bits_t last_input = {{0}}; #endif static bool old_fs_toggle_pressed= false; static bool old_focus = true; @@ -2437,7 +2446,11 @@ static enum runloop_state runloop_check_state( #ifdef HAVE_MENU bool menu_driver_binding_state = menu_driver_is_binding_state(); bool menu_is_alive = menu_driver_is_alive(); +#endif + BIT256_CLEAR_ALL_PTR(¤t_input); + +#ifdef HAVE_MENU if (menu_is_alive && !(settings->bools.menu_unified_controls && !menu_input_dialog_get_display_kb())) input_menu_keys_pressed(settings, ¤t_input); else @@ -2590,7 +2603,7 @@ static enum runloop_state runloop_check_state( #ifdef HAVE_MENU if (menu_is_alive) { - static retro_bits_t old_input = {{0}}; + static input_bits_t old_input = {{0}}; menu_ctx_iterate_t iter; retro_ctx.poll_cb(); @@ -2598,7 +2611,7 @@ static enum runloop_state runloop_check_state( { enum menu_action action; bool focused = false; - retro_bits_t trigger_input = current_input; + input_bits_t trigger_input = current_input; bits_clear_bits(trigger_input.data, old_input.data, ARRAY_SIZE(trigger_input.data)); @@ -2825,11 +2838,13 @@ static enum runloop_state runloop_check_state( if (new_button_state && !old_button_state) { - if (input_nonblock_state) { + if (input_nonblock_state) + { input_driver_unset_nonblock_state(); runloop_fastmotion = false; } - else { + else + { input_driver_set_nonblock_state(); runloop_fastmotion = true; } @@ -2837,11 +2852,13 @@ static enum runloop_state runloop_check_state( } else if (old_hold_button_state != new_hold_button_state) { - if (new_hold_button_state) { + if (new_hold_button_state) + { input_driver_set_nonblock_state(); runloop_fastmotion = true; } - else { + else + { input_driver_unset_nonblock_state(); runloop_fastmotion = false; } @@ -2954,21 +2971,17 @@ static enum runloop_state runloop_check_state( if (new_slowmotion_button_state && !old_slowmotion_button_state) { - if (runloop_slowmotion) { + if (runloop_slowmotion) runloop_slowmotion = false; - } - else { + else runloop_slowmotion = true; - } } else if (old_slowmotion_hold_button_state != new_slowmotion_hold_button_state) { - if (new_slowmotion_hold_button_state) { + if (new_slowmotion_hold_button_state) runloop_slowmotion = true; - } - else { + else runloop_slowmotion = false; - } } if (runloop_slowmotion) @@ -3243,7 +3256,13 @@ int runloop_iterate(unsigned *sleep_ms) if ((settings->uints.video_frame_delay > 0) && !input_nonblock_state) retro_sleep(settings->uints.video_frame_delay); - core_run(); +#ifdef HAVE_RUNAHEAD + /* Run Ahead Feature replaces the call to core_run in this loop */ + if (settings->bools.run_ahead_enabled && settings->uints.run_ahead_frames > 0) + run_ahead(settings->uints.run_ahead_frames, settings->bools.run_ahead_secondary_instance); + else +#endif + core_run(); #ifdef HAVE_CHEEVOS if (runloop_check_cheevos()) diff --git a/retroarch.cfg b/retroarch.cfg index f4639e8031..019c14c326 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -700,6 +700,7 @@ video_message_bgcolor_opacity = 1.0 # Type of thumbnail to display. 0 = none, 1 = snaps, 2 = titles, 3 = boxarts # menu_thumbnails = 0 +# menu_left_thumbnails = 0 # Wrap-around to beginning and/or end if boundary of list is reached horizontally or vertically. # menu_navigation_wraparound_enable = false @@ -719,7 +720,7 @@ video_message_bgcolor_opacity = 1.0 # Check for firmware requirement(s) before loading a content. # check_firmware_before_loading = "false" -#### UI +#### User Interface # Suspends the screensaver if set to true. Is a hint that does not necessarily have to be honored # by video driver. diff --git a/runahead/copy_load_info.c b/runahead/copy_load_info.c new file mode 100644 index 0000000000..de9f736b39 --- /dev/null +++ b/runahead/copy_load_info.c @@ -0,0 +1,263 @@ +#include +#include + +#include +#include + +#include "../core.h" +#include "mem_util.h" +#include "copy_load_info.h" + +retro_ctx_load_content_info_t *load_content_info; +enum rarch_core_type last_core_type; + +static void free_retro_game_info(struct retro_game_info *dest) +{ + if (!dest) + return; + FREE(dest->path); + FREE(dest->data); + FREE(dest->meta); +} + +static struct retro_game_info* clone_retro_game_info(const + struct retro_game_info *src) +{ + void *data = NULL; + struct retro_game_info *dest = NULL; + + if (!src) + return NULL; + + dest = (struct retro_game_info*)calloc(1, + sizeof(struct retro_game_info)); + if (!dest) + return NULL; + + dest->data = NULL; + dest->path = strcpy_alloc(src->path); + + if (src->size && src->data) + { + data = malloc(src->size); + + if (data) + { + memcpy(data, src->data, src->size); + dest->data = data; + } + } + + dest->size = src->size; + dest->meta = strcpy_alloc(src->meta); + + return dest; +} + +static void free_string_list(struct string_list *dest) +{ + unsigned i; + if (!dest) + return; + for (i = 0; i < dest->size; i++) + { + FREE(dest->elems[i].data); + } + + FREE(dest->elems); +} + +static struct string_list *string_list_clone( + const struct string_list *src) +{ + unsigned i; + struct string_list_elem *elems = NULL; + struct string_list *dest = (struct string_list*) + calloc(1, sizeof(struct string_list)); + + if (!dest) + return NULL; + + dest->size = src->size; + dest->cap = src->cap; + if (dest->cap < dest->size) + { + dest->cap = dest->size; + } + + elems = (struct string_list_elem*) + calloc(dest->cap, sizeof(struct string_list_elem)); + + if (!elems) + { + free(dest); + return NULL; + } + + dest->elems = elems; + + for (i = 0; i < src->size; i++) + { + dest->elems[i].data = strcpy_alloc(src->elems[i].data); + dest->elems[i].attr = src->elems[i].attr; + } + + return dest; +} + +#if 0 +/* for cloning the Special field, however, attempting + * to use this feature crashes retroarch */ +static void free_retro_subsystem_memory_info(struct + retro_subsystem_memory_info *dest) +{ + if (!dest) + return; + FREE(dest->extension); +} + +static void clone_retro_subsystem_memory_info(struct + retro_subsystem_memory_info* dest, + const struct retro_subsystem_memory_info *src) +{ + dest->extension = strcpy_alloc(src->extension); + dest->type = src->type; +} + +static void free_retro_subsystem_rom_info(struct + retro_subsystem_rom_info *dest) +{ + int i; + if (!dest) + return; + + FREE(dest->desc); + FREE(dest->valid_extensions); + + for (i = 0; i < dest->num_memory; i++) + free_retro_subsystem_memory_info((struct + retro_subsystem_memory_info*)&dest->memory[i]); + + FREE(dest->memory); +} + +static void clone_retro_subsystem_rom_info(struct + retro_subsystem_rom_info *dest, + const struct retro_subsystem_rom_info *src) +{ + int i; + retro_subsystem_memory_info *memory = NULL; + + dest->need_fullpath = src->need_fullpath; + dest->block_extract = src->block_extract; + dest->required = src->required; + dest->num_memory = src->num_memory; + dest->desc = strcpy_alloc(src->desc); + dest->valid_extensions = strcpy_alloc(src->valid_extensions); + + memory = (struct retro_subsystem_memory_info*)calloc(1, + dest->num_memory * sizeof(struct retro_subsystem_memory_info)); + + dest->memory = memory; + + for (i = 0; i < dest->num_memory; i++) + clone_retro_subsystem_memory_info(&memory[i], &src->memory[i]); +} + +static void free_retro_subsystem_info(struct retro_subsystem_info *dest) +{ + int i; + + if (!dest) + return; + + FREE(dest->desc); + FREE(dest->ident); + + for (i = 0; i < dest->num_roms; i++) + free_retro_subsystem_rom_info((struct + retro_subsystem_rom_info*)&dest->roms[i]); + + FREE(dest->roms); +} + +static retro_subsystem_info* clone_retro_subsystem_info(struct + const retro_subsystem_info *src) +{ + int i; + retro_subsystem_info *dest = NULL; + retro_subsystem_rom_info *roms = NULL; + + if (!src) + return NULL; + dest = (struct retro_subsystem_info*)calloc(1, + sizeof(struct retro_subsystem_info)); + dest->desc = strcpy_alloc(src->desc); + dest->ident = strcpy_alloc(src->ident); + dest->num_roms = src->num_roms; + dest->id = src->id; + roms = (struct retro_subsystem_rom_info*) + calloc(src->num_roms, sizeof(struct retro_subsystem_rom_info)); + dest->roms = roms; + + for (i = 0; i < src->num_roms; i++) + clone_retro_subsystem_rom_info(&roms[i], &src->roms[i]); + + return dest; +} +#endif + +static void free_retro_ctx_load_content_info(struct + retro_ctx_load_content_info *dest) +{ + if (!dest) + return; + + free_retro_game_info(dest->info); + free_string_list((struct string_list*)dest->content); + FREE(dest->info); + FREE(dest->content); + +#if 0 + free_retro_subsystem_info((retro_subsystem_info*)dest->special); + FREE(dest->special); +#endif +} + +static struct retro_ctx_load_content_info +*clone_retro_ctx_load_content_info( + const struct retro_ctx_load_content_info *src) +{ + struct retro_ctx_load_content_info *dest = NULL; + if (!src || src->special != NULL) + return NULL; /* refuse to deal with the Special field */ + + dest = (struct retro_ctx_load_content_info*) + calloc(1, sizeof(*dest)); + + if (!dest) + return NULL; + + dest->info = clone_retro_game_info(src->info); + dest->content = NULL; + dest->special = NULL; + + if (src->content) + dest->content = string_list_clone(src->content); +#if 0 + dest->special = clone_retro_subsystem_info(src->special); +#endif + return dest; +} + +void set_load_content_info(const retro_ctx_load_content_info_t *ctx) +{ + free_retro_ctx_load_content_info(load_content_info); + free(load_content_info); + load_content_info = clone_retro_ctx_load_content_info(ctx); +} + +void set_last_core_type(enum rarch_core_type type) +{ + last_core_type = type; +} diff --git a/runahead/copy_load_info.h b/runahead/copy_load_info.h new file mode 100644 index 0000000000..fced73a2d6 --- /dev/null +++ b/runahead/copy_load_info.h @@ -0,0 +1,19 @@ +#ifndef __COPY_LOAD_INFO_H__ +#define __COPY_LOAD_INFO_H__ + +#include +#include + +#include + +#include "../core.h" + +RETRO_BEGIN_DECLS + +void set_load_content_info(const retro_ctx_load_content_info_t *ctx); + +void set_last_core_type(enum rarch_core_type type); + +RETRO_END_DECLS + +#endif diff --git a/runahead/dirty_input.c b/runahead/dirty_input.c new file mode 100644 index 0000000000..5c2086a53a --- /dev/null +++ b/runahead/dirty_input.c @@ -0,0 +1,176 @@ +#include + +#include + +#include "../core.h" +#include "../dynamic.h" + +#include "mylist.h" +#include "mem_util.h" +#include "dirty_input.h" + +bool input_is_dirty = false; +static MyList *input_state_list = NULL; + +typedef struct InputListElement_t +{ + unsigned port; + unsigned device; + unsigned index; + int16_t state[36]; +} InputListElement; + +extern struct retro_core_t current_core; +extern struct retro_callbacks retro_ctx; + +typedef bool(*LoadStateFunction)(const void*, size_t); + +static function_t retro_reset_callback_original = NULL; +static LoadStateFunction retro_unserialize_callback_original = NULL; +static retro_input_state_t input_state_callback_original; + +static void reset_hook(void); +static bool unserialze_hook(const void *buf, size_t size); + +static void* InputListElementConstructor(void) +{ + const int size = sizeof(InputListElement); + void *ptr = calloc(1, size); + + return ptr; +} + +static void input_state_destory(void) +{ + mylist_destroy(&input_state_list); +} + +static void input_state_set_last(unsigned port, unsigned device, + unsigned index, unsigned id, int16_t value) +{ + unsigned i; + InputListElement *element = NULL; + + if (!input_state_list) + mylist_create(&input_state_list, 16, + InputListElementConstructor, free); + + /* find list item */ + for (i = 0; i < (unsigned)input_state_list->size; i++) + { + element = (InputListElement*)input_state_list->data[i]; + if ( element->port == port + && element->device == device && element->index == index) + { + element->state[id] = value; + return; + } + } + + element = (InputListElement*) + mylist_add_element(input_state_list); + element->port = port; + element->device = device; + element->index = index; + element->state[id] = value; +} + +static int16_t input_state_get_last(unsigned port, + unsigned device, unsigned index, unsigned id) +{ + unsigned i; + + if (!input_state_list) + return 0; + + /* find list item */ + for (i = 0; i < (unsigned)input_state_list->size; i++) + { + InputListElement *element = + (InputListElement*)input_state_list->data[i]; + + if ( (element->port == port) && + (element->device == device) && + (element->index == index) + ) + return element->state[id]; + } + return 0; +} + +static int16_t input_state_with_logging(unsigned port, + unsigned device, unsigned index, unsigned id) +{ + if (input_state_callback_original) + { + int16_t result = input_state_callback_original( + port, device, index, id); + int16_t last_input = input_state_get_last(port, device, index, id); + if (result != last_input) + input_is_dirty = true; + input_state_set_last(port, device, index, id, result); + return result; + } + return 0; +} + +static void reset_hook(void) +{ + input_is_dirty = true; + if (retro_reset_callback_original) + retro_reset_callback_original(); +} + +static bool unserialze_hook(const void *buf, size_t size) +{ + input_is_dirty = true; + if (retro_unserialize_callback_original) + return retro_unserialize_callback_original(buf, size); + return false; +} + +void add_input_state_hook(void) +{ + if (!input_state_callback_original) + { + input_state_callback_original = retro_ctx.state_cb; + retro_ctx.state_cb = input_state_with_logging; + current_core.retro_set_input_state(retro_ctx.state_cb); + } + + if (!retro_reset_callback_original) + { + retro_reset_callback_original = current_core.retro_reset; + current_core.retro_reset = reset_hook; + } + + if (!retro_unserialize_callback_original) + { + retro_unserialize_callback_original = current_core.retro_unserialize; + current_core.retro_unserialize = unserialze_hook; + } +} + +void remove_input_state_hook(void) +{ + if (input_state_callback_original) + { + retro_ctx.state_cb = input_state_callback_original; + current_core.retro_set_input_state(retro_ctx.state_cb); + input_state_callback_original = NULL; + input_state_destory(); + } + + if (retro_reset_callback_original) + { + current_core.retro_reset = retro_reset_callback_original; + retro_reset_callback_original = NULL; + } + + if (retro_unserialize_callback_original) + { + current_core.retro_unserialize = retro_unserialize_callback_original; + retro_unserialize_callback_original = NULL; + } +} + diff --git a/runahead/dirty_input.h b/runahead/dirty_input.h new file mode 100644 index 0000000000..12623d2b02 --- /dev/null +++ b/runahead/dirty_input.h @@ -0,0 +1,15 @@ +#ifndef __DIRTY_INPUT_H___ +#define __DIRTY_INPUT_H___ + +#include "retro_common_api.h" +#include "boolean.h" + +RETRO_BEGIN_DECLS + +extern bool input_is_dirty; +void add_input_state_hook(void); +void remove_input_state_hook(void); + +RETRO_END_DECLS + +#endif diff --git a/runahead/mem_util.c b/runahead/mem_util.c new file mode 100644 index 0000000000..d04e3097d9 --- /dev/null +++ b/runahead/mem_util.c @@ -0,0 +1,50 @@ +#include + +#include "mem_util.h" + +char *strcpy_alloc(const char *sourceStr) +{ + size_t len = 0; + char *result = NULL; + + if (sourceStr) + len = strlen(sourceStr); + + if (len == 0) + return NULL; + + result = (char*)malloc(len + 1); + strcpy(result, sourceStr); + return result; +} + +char *strcpy_alloc_force(const char *sourceStr) +{ + char *result = strcpy_alloc(sourceStr); + if (!result) + result = (char*)calloc(1, 1); + return result; +} + +void strcat_alloc(char ** destStr_p, const char *appendStr) +{ + size_t len1, len2, newLen; + char *destStr = *destStr_p; + + if (!destStr) + { + destStr = strcpy_alloc_force(appendStr); + *destStr_p = destStr; + return; + } + + if (!appendStr) + return; + + len1 = strlen(destStr); + len2 = strlen(appendStr); + newLen = len1 + len2 + 1; + destStr = (char*)realloc(destStr, newLen); + *destStr_p = destStr; + strcpy(destStr + len1, appendStr); +} diff --git a/runahead/mem_util.h b/runahead/mem_util.h new file mode 100644 index 0000000000..4ddbe21521 --- /dev/null +++ b/runahead/mem_util.h @@ -0,0 +1,21 @@ +#ifndef __MEM_UTIL__ +#define __MEM_UTIL__ + +#include +#include + +#include + +#include + +#define FREE(xxxx) if ((xxxx) != NULL) { free((void*)(xxxx)); } (xxxx) = NULL + +RETRO_BEGIN_DECLS + +char *strcpy_alloc(const char *sourceStr); +char *strcpy_alloc_force(const char *sourceStr); +void strcat_alloc(char ** destStr_p, const char *appendStr); + +RETRO_END_DECLS + +#endif diff --git a/runahead/mylist.c b/runahead/mylist.c new file mode 100644 index 0000000000..11b3f3d6b4 --- /dev/null +++ b/runahead/mylist.c @@ -0,0 +1,162 @@ +#include +#include + +#include "mylist.h" +#include "mem_util.h" + +void mylist_resize(MyList *list, int newSize, bool runConstructor) +{ + int newCapacity; + int oldSize; + int i; + void *element = NULL; + if (newSize < 0) + newSize = 0; + if (!list) + return; + newCapacity = newSize; + oldSize = list->size; + + if (newSize == oldSize) + return; + + if (newSize > list->capacity) + { + if (newCapacity < list->capacity * 2) + newCapacity = list->capacity * 2; + + /* try to realloc */ + list->data = (void**)realloc((void*)list->data, newCapacity * sizeof(void*)); + + for (i = list->capacity; i < newCapacity; i++) + list->data[i] = NULL; + + list->capacity = newCapacity; + } + if (newSize <= list->size) + { + for (i = newSize; i < list->size; i++) + { + element = list->data[i]; + + if (element) + { + list->Destructor(element); + list->data[i] = NULL; + } + } + } + else + { + for (i = list->size; i < newSize; i++) + { + if (runConstructor) + list->data[i] = list->Constructor(); + else + list->data[i] = NULL; + } + } + list->size = newSize; +} + +void *mylist_add_element(MyList *list) +{ + int oldSize; + + if (!list) + return NULL; + + oldSize = list->size; + mylist_resize(list, oldSize + 1, true); + return list->data[oldSize]; +} + +void mylist_create(MyList **list_p, int initialCapacity, + constructor_t constructor, destructor_t destructor) +{ + MyList *list = NULL; + if (!list_p) + return; + if (initialCapacity < 0) + initialCapacity = 0; + list = *list_p; + if (list) + mylist_destroy(list_p); + + list = (MyList*)malloc(sizeof(MyList)); + *list_p = list; + list->size = 0; + list->Constructor = constructor; + list->Destructor = destructor; + + if (initialCapacity > 0) + { + list->data = (void**)calloc(initialCapacity, sizeof(void*)); + list->capacity = initialCapacity; + } + else + { + list->data = NULL; + list->capacity = 0; + } +} + +void mylist_destroy(MyList **list_p) +{ + MyList *list = NULL; + if (!list_p) + return; + + list = *list_p; + + if (list) + { + mylist_resize(list, 0, false); + free(list->data); + free(list); + *list_p = NULL; + } +} + +void mylist_assign(MyList *list, int index, void *value) +{ + void *oldElement = NULL; + + if (index < 0 || index >= list->size) + return; + + oldElement = list->data[index]; + list->Destructor(oldElement); + list->data[index] = value; +} + +void mylist_remove_at(MyList *list, int index) +{ + int i; + + if (index < 0 || index >= list->size) + return; + + mylist_assign(list, index, NULL); + + for (i = index + 1; i < list->size; i++) + list->data[i - 1] = list->data[i]; + + list->size--; + list->data[list->size] = NULL; +} + +void mylist_pop_front(MyList *list) +{ + mylist_remove_at(list, 0); +} + +void mylist_push_back(MyList *list, void *value) +{ + int oldSize; + if (!list) + return; + oldSize = list->size; + mylist_resize(list, oldSize + 1, false); + list->data[oldSize] = value; +} diff --git a/runahead/mylist.h b/runahead/mylist.h new file mode 100644 index 0000000000..1ec3e9c325 --- /dev/null +++ b/runahead/mylist.h @@ -0,0 +1,40 @@ +#ifndef __MYLIST_H__ +#define __MYLIST_H__ + +#include +#include +#include + +RETRO_BEGIN_DECLS + +typedef void* (*constructor_t)(void); +typedef void(*destructor_t)(void*); + +typedef struct MyList_t +{ + void **data; + int capacity; + int size; + constructor_t Constructor; + destructor_t Destructor; +} MyList; + +void *mylist_add_element(MyList *list); + +void mylist_resize(MyList *list, int newSize, bool runConstructor); + +void mylist_create(MyList **list_p, int initialCapacity, + constructor_t constructor, destructor_t destructor); + +void mylist_destroy(MyList **list_p); + +void mylist_assign(MyList *list, int index, void *value); + +void mylist_remove_at(MyList *list, int index); + +void mylist_pop_front(MyList *list); + +RETRO_END_DECLS + +#endif + diff --git a/runahead/run_ahead.c b/runahead/run_ahead.c new file mode 100644 index 0000000000..b5e84de396 --- /dev/null +++ b/runahead/run_ahead.c @@ -0,0 +1,491 @@ +#include +#include +#include + +#include + +#include "dirty_input.h" +#include "mylist.h" +#include "secondary_core.h" +#include "run_ahead.h" + +#include "../core.h" +#include "../dynamic.h" +#include "../audio/audio_driver.h" +#include "../gfx/video_driver.h" + +static bool runahead_create(void); +static bool runahead_save_state(void); +static bool runahead_load_state(void); +static bool runahead_load_state_secondary(void); +static bool runahead_run_secondary(void); +static void runahead_suspend_audio(void); +static void runahead_resume_audio(void); +static void runahead_suspend_video(void); +static void runahead_resume_video(void); +static void set_fast_savestate(void); +static void unset_fast_savestate(void); +static void set_hard_disable_audio(void); +static void unset_hard_disable_audio(void); + +/* TODO/FIXME - shouldn't this be signed size_t? */ +static size_t runahead_save_state_size = -1; + +/* Save State List for Run Ahead */ +static MyList *runahead_save_state_list; + +static void *runahead_save_state_alloc(void) +{ + retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*) + malloc(sizeof(retro_ctx_serialize_info_t)); + + if (!savestate) + return NULL; + + savestate->data = NULL; + savestate->data_const = NULL; + savestate->size = 0; + + if (runahead_save_state_size > 0 && runahead_save_state_size != -1) + { + savestate->data = malloc(runahead_save_state_size); + savestate->data_const = savestate->data; + savestate->size = runahead_save_state_size; + } + + return savestate; +} + +static void runahead_save_state_free(void *state) +{ + retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*)state; + if (!savestate) + return; + free(savestate->data); + free(savestate); +} + +static void runahead_save_state_list_init(size_t saveStateSize) +{ + runahead_save_state_size = saveStateSize; + mylist_create(&runahead_save_state_list, 16, + runahead_save_state_alloc, runahead_save_state_free); +} + +static void runahead_save_state_list_destroy(void) +{ + mylist_destroy(&runahead_save_state_list); +} + +#if 0 +static void runahead_save_state_list_rotate(void) +{ + int i; + void *element; + void *firstElement; + firstElement = runahead_save_state_list->data[0]; + for (i = 1; i < runahead_save_state_list->size; i++) + runahead_save_state_list->data[i - 1] = + runahead_save_state_list->data[i]; + runahead_save_state_list->data[runahead_save_state_list->size - 1] = + firstElement; +} +#endif + +/* Hooks - Hooks to cleanup, and add dirty input hooks */ + +static function_t originalRetroDeinit = NULL; +static function_t originalRetroUnload = NULL; + +extern struct retro_core_t current_core; +extern struct retro_callbacks retro_ctx; + +static void remove_hooks(void) +{ + if (originalRetroDeinit) + { + current_core.retro_deinit = originalRetroDeinit; + originalRetroDeinit = NULL; + } + + if (originalRetroUnload) + { + current_core.retro_unload_game = originalRetroUnload; + originalRetroUnload = NULL; + } + current_core.retro_set_environment(rarch_environment_cb); + remove_input_state_hook(); +} + +static void unload_hook(void) +{ + remove_hooks(); + runahead_destroy(); + secondary_core_destroy(); + if (current_core.retro_unload_game) + current_core.retro_unload_game(); +} + + +static void deinit_hook(void) +{ + remove_hooks(); + runahead_destroy(); + secondary_core_destroy(); + if (current_core.retro_deinit) + current_core.retro_deinit(); +} + +static bool env_hook(unsigned cmd, void *data) +{ + bool result = rarch_environment_cb(cmd, data); + if (cmd == RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE && result) + { + bool *bool_p = (bool*)data; + if (*bool_p == true) + secondary_core_set_variable_update(); + } + return result; +} + +static void add_hooks(void) +{ + if (!originalRetroDeinit) + { + originalRetroDeinit = current_core.retro_deinit; + current_core.retro_deinit = deinit_hook; + } + + if (!originalRetroUnload) + { + originalRetroUnload = current_core.retro_unload_game; + current_core.retro_unload_game = unload_hook; + } + current_core.retro_set_environment(env_hook); + add_input_state_hook(); +} + + +/* Runahead Code */ + +static bool runahead_video_driver_is_active = true; +static bool runahead_available = true; +static bool runahead_secondary_core_available = true; +static bool runahead_force_input_dirty = true; +static uint64_t runahead_last_frame_count = 0; + +static void runahead_clear_variables(void) +{ + runahead_save_state_size = -1; + runahead_video_driver_is_active = true; + runahead_available = true; + runahead_secondary_core_available = true; + runahead_force_input_dirty = true; + runahead_last_frame_count = 0; +} + +static void runahead_check_for_gui(void) +{ + /* Hack: If we were in the GUI, force a resync. */ + bool is_alive, is_focused = false; + uint64_t frame_count = 0; + + video_driver_get_status(&frame_count, &is_alive, &is_focused); + + if (frame_count != runahead_last_frame_count + 1) + runahead_force_input_dirty = true; + + runahead_last_frame_count = frame_count; +} + +void run_ahead(int runahead_count, bool useSecondary) +{ + int frame_number = 0; + bool last_frame = false; + bool suspended_frame = false; +#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) + const bool have_dynamic = true; +#else + const bool have_dynamic = false; +#endif + + if (runahead_count <= 0 || !runahead_available) + { + core_run(); + runahead_force_input_dirty = true; + return; + } + + if (runahead_save_state_size == -1) + { + if (!runahead_create()) + { + /* RunAhead has been disabled because the core + * does not support savestates. */ + core_run(); + runahead_force_input_dirty = true; + return; + } + } + + runahead_check_for_gui(); + + if (!useSecondary || !have_dynamic || !runahead_secondary_core_available) + { + /* TODO: multiple savestates for higher performance + * when not using secondary core */ + for (frame_number = 0; frame_number <= runahead_count; frame_number++) + { + last_frame = frame_number == runahead_count; + suspended_frame = !last_frame; + + if (suspended_frame) + { + runahead_suspend_audio(); + runahead_suspend_video(); + } + + if (frame_number == 0) + core_run(); + else + core_run_no_input_polling(); + + if (suspended_frame) + { + runahead_resume_video(); + runahead_resume_audio(); + } + + if (frame_number == 0) + { + /* RunAhead has been disabled due + * to save state failure */ + if (!runahead_save_state()) + return; + } + + if (last_frame) + { + /* RunAhead has been disabled due + * to load state failure */ + if (!runahead_load_state()) + return; + } + } + } + else + { +#if HAVE_DYNAMIC + bool okay = false; + + /* run main core with video suspended */ + runahead_suspend_video(); + core_run(); + runahead_resume_video(); + + if (input_is_dirty || runahead_force_input_dirty) + { + unsigned frame_count; + + input_is_dirty = false; + + if (!runahead_save_state()) + return; + + /* Could not create a secondary core. + * RunAhead wll only use the main core now. */ + if (!runahead_load_state_secondary()) + return; + + for (frame_count = 0; frame_count < + (unsigned)(runahead_count - 1); frame_count++) + { + runahead_suspend_video(); + runahead_suspend_audio(); + set_hard_disable_audio(); + okay = runahead_run_secondary(); + unset_hard_disable_audio(); + runahead_resume_audio(); + runahead_resume_video(); + + /* Could not create a secondary core. RunAhead + * will only use the main core now. */ + if (!okay) + return; + } + } + runahead_suspend_audio(); + set_hard_disable_audio(); + okay = runahead_run_secondary(); + unset_hard_disable_audio(); + runahead_resume_audio(); + + /* Could not create a secondary core. RunAhead + * will only use the main core now. */ + if (!okay) + return; +#endif + } + runahead_force_input_dirty = false; +} + +static void runahead_error(void) +{ + runahead_available = false; + runahead_save_state_list_destroy(); + remove_hooks(); + runahead_save_state_size = 0; +} + +static bool runahead_create(void) +{ + /* get savestate size and allocate buffer */ + retro_ctx_size_info_t info; + core_serialize_size(&info); + + runahead_save_state_list_init(info.size); + runahead_video_driver_is_active = video_driver_is_active(); + + if (runahead_save_state_size == 0 || runahead_save_state_size == -1) + { + runahead_error(); + return false; + } + + add_hooks(); + runahead_force_input_dirty = true; + mylist_resize(runahead_save_state_list, 1, true); + return true; +} + +static bool runahead_save_state(void) +{ + bool okay = false; + retro_ctx_serialize_info_t *serialize_info = + (retro_ctx_serialize_info_t*)runahead_save_state_list->data[0]; + set_fast_savestate(); + okay = core_serialize(serialize_info); + unset_fast_savestate(); + if (!okay) + { + runahead_error(); + return false; + } + return true; +} + +static bool runahead_load_state(void) +{ + bool okay = false; + retro_ctx_serialize_info_t *serialize_info = (retro_ctx_serialize_info_t*) + runahead_save_state_list->data[0]; + bool last_dirty = input_is_dirty; + + set_fast_savestate(); + /* calling core_unserialize has side effects with + * netplay (it triggers transmitting your save state) + call retro_unserialize directly from the core instead */ + okay = current_core.retro_unserialize( + serialize_info->data_const, serialize_info->size); + unset_fast_savestate(); + input_is_dirty = last_dirty; + + if (!okay) + runahead_error(); + + return okay; +} + +static bool runahead_load_state_secondary(void) +{ + bool okay = false; + retro_ctx_serialize_info_t *serialize_info = + (retro_ctx_serialize_info_t*)runahead_save_state_list->data[0]; + + set_fast_savestate(); + okay = secondary_core_deserialize( + serialize_info->data_const, (int)serialize_info->size); + unset_fast_savestate(); + + if (!okay) + { + runahead_secondary_core_available = false; + return false; + } + + return true; +} + +static bool runahead_run_secondary(void) +{ + if (!secondary_core_run_no_input_polling()) + { + runahead_secondary_core_available = false; + return false; + } + return true; +} + +static void runahead_suspend_audio(void) +{ + audio_driver_suspend(); +} + +static void runahead_resume_audio(void) +{ + audio_driver_resume(); +} + +static void runahead_suspend_video(void) +{ + video_driver_unset_active(); +} + +static void runahead_resume_video(void) +{ + if (runahead_video_driver_is_active) + video_driver_set_active(); + else + video_driver_unset_active(); +} + +void runahead_destroy(void) +{ + runahead_save_state_list_destroy(); + remove_hooks(); + runahead_clear_variables(); +} + +static bool request_fast_savestate; +static bool hard_disable_audio; + + +bool want_fast_savestate(void) +{ + return request_fast_savestate; +} + +static void set_fast_savestate(void) +{ + request_fast_savestate = true; +} + +static void unset_fast_savestate(void) +{ + request_fast_savestate = false; +} + +bool get_hard_disable_audio(void) +{ + return hard_disable_audio; +} + +static void set_hard_disable_audio(void) +{ + hard_disable_audio = true; +} + +static void unset_hard_disable_audio(void) +{ + hard_disable_audio = false; +} diff --git a/runahead/run_ahead.h b/runahead/run_ahead.h new file mode 100644 index 0000000000..8868ce345b --- /dev/null +++ b/runahead/run_ahead.h @@ -0,0 +1,20 @@ +#ifndef __RUN_AHEAD_H__ +#define __RUN_AHEAD_H__ + +#include +#include + +#include + +RETRO_BEGIN_DECLS + +void runahead_destroy(void); + +void run_ahead(int runAheadCount, bool useSecondary); + +bool want_fast_savestate(void); +bool get_hard_disable_audio(void); + +RETRO_END_DECLS + +#endif diff --git a/runahead/secondary_core.c b/runahead/secondary_core.c new file mode 100644 index 0000000000..016f53ca2e --- /dev/null +++ b/runahead/secondary_core.c @@ -0,0 +1,384 @@ +#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) + +#include +#include + +#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX) +#ifndef LEGACY_WIN32 +#define LEGACY_WIN32 +#endif +#endif + +#include +#include +#include +#include +#include + +#include "mem_util.h" + +#include "../core.h" +#include "../dynamic.h" +#include "../paths.h" +#include "../content.h" + +#include "secondary_core.h" + +static int port_map[16]; + +static char *secondary_library_path; +static dylib_t secondary_module; +static struct retro_core_t secondary_core; +static struct retro_callbacks secondary_callbacks; + +extern retro_ctx_load_content_info_t *load_content_info; +extern enum rarch_core_type last_core_type; +extern struct retro_callbacks retro_ctx; + +static char* get_temp_directory_alloc(void); + +static char* copy_core_to_temp_file(void); + +static bool write_file_with_random_name(char **tempDllPath, + const char *retroarchTempPath, const void* data, ssize_t dataSize); + +static bool secondary_core_create(void); + +bool secondary_core_run_no_input_polling(void); + +bool secondary_core_deserialize(const void *buffer, int size); + +static bool rarch_environment_secondary_core_hook(unsigned cmd, void *data); + +void secondary_core_destroy(void); + +void set_last_core_type(enum rarch_core_type type); + +void remember_controller_port_device(long port, long device); + +void clear_controller_port_map(void); + +char* get_temp_directory_alloc(void) +{ +#ifdef _WIN32 +#ifdef LEGACY_WIN32 + DWORD pathLength = GetTempPath(0, NULL) + 1; + char *path = (char*)malloc(pathLength * sizeof(char)); + + path[pathLength - 1] = 0; + GetTempPath(pathLength, path); + return path; +#else + char *path; + DWORD pathLength = GetTempPathW(0, NULL) + 1; + wchar_t *wideStr = (wchar_t*)malloc(pathLength * sizeof(wchar_t)); + wideStr[pathLength - 1] = 0; + GetTempPathW(pathLength, wideStr); + + path = utf16_to_utf8_string_alloc(wideStr); + free(wideStr); + return path; +#endif +#else + char *path = strcpy_alloc_force(getenv("TMPDIR")); + return path; +#endif +} + +char* copy_core_to_temp_file(void) +{ + char *tempDirectory = NULL; + char *retroarchTempPath = NULL; + char *tempDllPath = NULL; + void *dllFileData = NULL; + int64_t dllFileSize = 0; + const char *corePath = path_get(RARCH_PATH_CORE); + const char *coreBaseName = path_basename(corePath); + + if (strlen(coreBaseName) == 0) + goto failed; + + tempDirectory = get_temp_directory_alloc(); + if (!tempDirectory) + goto failed; + + strcat_alloc(&retroarchTempPath, tempDirectory); + strcat_alloc(&retroarchTempPath, path_default_slash()); + strcat_alloc(&retroarchTempPath, "retroarch_temp"); + strcat_alloc(&retroarchTempPath, path_default_slash()); + + if (!path_mkdir(retroarchTempPath)) + goto failed; + + if (!filestream_read_file(corePath, &dllFileData, &dllFileSize)) + goto failed; + + strcat_alloc(&tempDllPath, retroarchTempPath); + strcat_alloc(&tempDllPath, coreBaseName); + + if (!filestream_write_file(tempDllPath, dllFileData, dllFileSize)) + { + /* try other file names */ + if (!write_file_with_random_name(&tempDllPath, retroarchTempPath, dllFileData, dllFileSize)) + goto failed; + } + + FREE(tempDirectory); + FREE(retroarchTempPath); + FREE(dllFileData); + return tempDllPath; + +failed: + FREE(tempDirectory); + FREE(retroarchTempPath); + FREE(tempDllPath); + FREE(dllFileData); + return NULL; +} + +bool write_file_with_random_name(char **tempDllPath, + const char *retroarchTempPath, const void* data, ssize_t dataSize) +{ + bool okay = false; + unsigned i; + char number_buf[32]; + const char *prefix = "tmp"; + time_t time_value = time(NULL); + unsigned int number_value= (unsigned int)time_value; + int number = 0; + char *ext = strcpy_alloc_force(path_get_extension(*tempDllPath)); + int ext_len = (int)strlen(ext); + + if (ext_len > 0) + { + strcat_alloc(&ext, "."); + memmove(ext + 1, ext, ext_len); + ext[0] = '.'; + ext_len++; + } + + /* Try up to 30 'random' filenames before giving up */ + for (i = 0; i < 30; i++) + { + number_value = number_value * 214013 + 2531011; + number = (number_value >> 14) % 100000; + + snprintf(number_buf, sizeof(number_buf), "%05d", number); + + FREE(*tempDllPath); + strcat_alloc(tempDllPath, retroarchTempPath); + strcat_alloc(tempDllPath, prefix); + strcat_alloc(tempDllPath, number_buf); + strcat_alloc(tempDllPath, ext); + if (filestream_write_file(*tempDllPath, data, dataSize)) + { + okay = true; + break; + } + } + + FREE(ext); + return okay; +} + +bool secondary_core_create(void) +{ + long port, device; + bool contentless, is_inited; + + if ( last_core_type != CORE_TYPE_PLAIN || + !load_content_info || + load_content_info->special) + return false; + + FREE(secondary_library_path); + secondary_library_path = copy_core_to_temp_file(); + + if (!secondary_library_path) + return false; + + /* Load Core */ + if (init_libretro_sym_custom(CORE_TYPE_PLAIN, &secondary_core, secondary_library_path, &secondary_module)) + { + secondary_core.symbols_inited = true; + secondary_core.retro_set_environment(rarch_environment_secondary_core_hook); + secondary_core_set_variable_update(); + + secondary_core.retro_init(); + + content_get_status(&contentless, &is_inited); + secondary_core.inited = is_inited; + + /* Load Content */ + if (!load_content_info || load_content_info->special) + { + /* disabled due to crashes */ + return false; +#if 0 + secondary_core.game_loaded = secondary_core.retro_load_game_special( + loadContentInfo.special->id, loadContentInfo.info, loadContentInfo.content->size); + if (!secondary_core.game_loaded) + { + secondary_core_destroy(); + return false; + } +#endif + } + else if (load_content_info->content->size > 0 && load_content_info->content->elems[0].data) + { + secondary_core.game_loaded = secondary_core.retro_load_game(load_content_info->info); + if (!secondary_core.game_loaded) + { + secondary_core_destroy(); + return false; + } + } + else if (contentless) + { + secondary_core.game_loaded = secondary_core.retro_load_game(NULL); + if (!secondary_core.game_loaded) + { + secondary_core_destroy(); + return false; + } + } + else + { + secondary_core.game_loaded = false; + } + if (!secondary_core.inited) + { + secondary_core_destroy(); + return false; + } + + core_set_default_callbacks(&secondary_callbacks); + secondary_core.retro_set_video_refresh(secondary_callbacks.frame_cb); + secondary_core.retro_set_audio_sample(secondary_callbacks.sample_cb); + secondary_core.retro_set_audio_sample_batch(secondary_callbacks.sample_batch_cb); + secondary_core.retro_set_input_state(secondary_callbacks.state_cb); + secondary_core.retro_set_input_poll(secondary_callbacks.poll_cb); + + for (port = 0; port < 16; port++) + { + device = port_map[port]; + if (device >= 0) + secondary_core.retro_set_controller_port_device((unsigned)port, (unsigned)device); + } + clear_controller_port_map(); + } + else + return false; + + return true; +} + +static bool has_variable_update; + +static bool rarch_environment_secondary_core_hook(unsigned cmd, void *data) +{ + bool result = rarch_environment_cb(cmd, data); + if (cmd == RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE && has_variable_update) + { + bool *bool_p = (bool*)data; + *bool_p = true; + has_variable_update = false; + return true; + } + return result; +} + +void secondary_core_set_variable_update(void) +{ + has_variable_update = true; +} + +bool secondary_core_run_no_input_polling(void) +{ + if (!secondary_module) + { + if (!secondary_core_create()) + return false; + } + secondary_core.retro_run(); + return true; +} + +bool secondary_core_deserialize(const void *buffer, int size) +{ + if (!secondary_module) + { + if (!secondary_core_create()) + { + secondary_core_destroy(); + return false; + } + } + return secondary_core.retro_unserialize(buffer, size); +} + +void secondary_core_destroy(void) +{ + if (secondary_module) + { + /* unload game from core */ + if (secondary_core.retro_unload_game) + secondary_core.retro_unload_game(); + /* deinit */ + if (secondary_core.retro_deinit) + secondary_core.retro_deinit(); + memset(&secondary_core, 0, sizeof(struct retro_core_t)); + + dylib_close(secondary_module); + secondary_module = NULL; + filestream_delete(secondary_library_path); + FREE(secondary_library_path); + } +} + +void remember_controller_port_device(long port, long device) +{ + if (port >= 0 && port < 16) + port_map[port] = (int)device; + if (secondary_module && secondary_core.retro_set_controller_port_device) + secondary_core.retro_set_controller_port_device((unsigned)port, (unsigned)device); +} + +void clear_controller_port_map(void) +{ + unsigned port; + for (port = 0; port < 16; port++) + port_map[port] = -1; +} + +#else +#include + +#include "../core.h" + +bool secondary_core_run_no_input_polling(void) +{ + return false; +} +bool secondary_core_deserialize(const void *buffer, int size) +{ + return false; +} +void secondary_core_destroy(void) +{ + /* do nothing */ +} +void remember_controller_port_device(long port, long device) +{ + /* do nothing */ +} +void secondary_core_set_variable_update(void) +{ + /* do nothing */ +} +void clear_controller_port_map(void) +{ + /* do nothing */ +} +#endif + diff --git a/runahead/secondary_core.h b/runahead/secondary_core.h new file mode 100644 index 0000000000..9eb4190d09 --- /dev/null +++ b/runahead/secondary_core.h @@ -0,0 +1,23 @@ +#ifndef __SECONDARY_CORE_H__ +#define __SECONDARY_CORE_H__ + +#include +#include + +#include + +#include "../core_type.h" + +RETRO_BEGIN_DECLS + +bool secondary_core_run_no_input_polling(void); +bool secondary_core_deserialize(const void *buffer, int size); +void secondary_core_destroy(void); +void set_last_core_type(enum rarch_core_type type); +void remember_controller_port_device(long port, long device); +void clear_controller_port_map(void); +void secondary_core_set_variable_update(void); + +RETRO_END_DECLS + +#endif diff --git a/samples/tasks/database/Makefile b/samples/tasks/database/Makefile new file mode 100644 index 0000000000..d526f03358 --- /dev/null +++ b/samples/tasks/database/Makefile @@ -0,0 +1,136 @@ +compiler := gcc +extra_flags := +use_neon := 0 +release := release +EXE_EXT := +TARGET := database_task + +ifeq ($(platform),) +platform = unix +ifeq ($(shell uname -a),) + platform = win +else ifneq ($(findstring MINGW,$(shell uname -a)),) + platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx + arch = intel +ifeq ($(shell uname -p),powerpc) + arch = ppc +endif +else ifneq ($(findstring win,$(shell uname -a)),) + platform = win +endif +endif + +ifeq ($(compiler),gcc) +extra_rules_gcc := $(shell $(compiler) -dumpmachine) +endif + +ifneq (,$(findstring armv7,$(extra_rules_gcc))) +extra_flags += -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon +use_neon := 1 +endif + +ifneq (,$(findstring hardfloat,$(extra_rules_gcc))) +extra_flags += -mfloat-abi=hard +endif + +ifeq (release,$(build)) +extra_flags += -O2 +endif + +ifeq (debug,$(build)) +extra_flags += -O0 -g +endif + +ldflags := + +EXE_EXT := +ifeq ($(platform), unix) +else ifeq ($(platform), osx) +compiler := $(CC) +else +EXE_EXT = .exe +endif + +CORE_DIR = ../../.. +LIBRETRO_COMM_DIR = $(CORE_DIR)/libretro-common + +CC := $(compiler) +CXX := $(subst CC,++,$(compiler)) +flags := -I$(LIBRETRO_COMM_DIR)/include +asflags := $(extra_flags) +LDFLAGS := +flags += -std=c99 +INCFLAGS := -I$(LIBRETRO_COMM_DIR)/include + +SOURCES_C := \ + $(CORE_DIR)/samples/tasks/database/main.c \ + $(CORE_DIR)/tasks/task_database.c \ + $(CORE_DIR)/tasks/task_database_cue.c \ + $(CORE_DIR)/database_info.c \ + $(CORE_DIR)/core_info.c \ + $(CORE_DIR)/file_path_str.c \ + $(CORE_DIR)/msg_hash.c \ + $(CORE_DIR)/intl/msg_hash_us.c \ + $(CORE_DIR)/playlist.c \ + $(CORE_DIR)/verbosity.c \ + $(CORE_DIR)/libretro-db/bintree.c \ + $(CORE_DIR)/libretro-db/libretrodb.c \ + $(CORE_DIR)/libretro-db/query.c \ + $(CORE_DIR)/libretro-db/rmsgpack.c \ + $(CORE_DIR)/libretro-db/rmsgpack_dom.c \ + $(LIBRETRO_COMM_DIR)/file/archive_file.c \ + $(LIBRETRO_COMM_DIR)/file/config_file.c \ + $(LIBRETRO_COMM_DIR)/file/file_path.c \ + $(LIBRETRO_COMM_DIR)/file/retro_dirent.c \ + $(LIBRETRO_COMM_DIR)/hash/rhash.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_fnmatch.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ + $(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ + $(LIBRETRO_COMM_DIR)/queues/task_queue.c \ + $(LIBRETRO_COMM_DIR)/lists/dir_list.c \ + $(LIBRETRO_COMM_DIR)/lists/string_list.c \ + $(LIBRETRO_COMM_DIR)/streams/interface_stream.c \ + $(LIBRETRO_COMM_DIR)/streams/memory_stream.c \ + $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c + +DEFINES = -DHAVE_LIBRETRODB -DHAVE_COMPRESSION + +CFLAGS += $(DEFINES) +CXXFLAGS += $(DEFINES) + +OBJECTS = $(SOURCES_C:.c=.o) + +OBJOUT = -o +LINKOUT = -o + +ifneq (,$(findstring msvc,$(platform))) + OBJOUT = -Fo +LINKOUT = -out: +ifeq ($(STATIC_LINKING),1) + LD ?= lib.exe +else + LD = link.exe +endif +else + LD = $(CC) +endif + +all: $(TARGET)$(EXE_EXT) +$(TARGET)$(EXE_EXT): $(OBJECTS) + $(LD) $(LINKOUT)$@ $(SHARED) $(OBJECTS) $(LDFLAGS) $(LIBS) + +%.o: %.c + $(CC) $(INCFLAGS) $(CFLAGS) -c $(OBJOUT)$@ $< + +%.o: %.cpp + $(CXX) $(INCFLAGS) $(CXXFLAGS) -c $(OBJOUT)$@ $< + +clean: + rm -f $(OBJECTS) diff --git a/samples/tasks/database/main.c b/samples/tasks/database/main.c new file mode 100644 index 0000000000..49b6274a3e --- /dev/null +++ b/samples/tasks/database/main.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include + +#include "../../../core_info.h" +#include "../../../tasks/tasks_internal.h" + +static bool loop_active = true; + +static void main_msg_queue_push(const char *msg, + unsigned prio, unsigned duration, + bool flush) +{ + fprintf(stderr, "MSGQ: %s\n", msg); +} + +/* + * return codes - + * graceful exit: 1 + * normal exit: 0 + * error exit: -1 + */ + +static void main_db_cb(void *task_data, void *user_data, const char *err) +{ + fprintf(stderr, "DB CB: %s\n", err); + loop_active = false; +} + +int main(int argc, char *argv[]) +{ + const char *db_dir = NULL; + const char *core_info_dir = NULL; + const char *core_dir = NULL; + const char *input_dir = NULL; + const char *playlist_dir = NULL; +#if defined(_WIN32) + const char *exts = "dll"; +#elif defined(__MACH__) + const char *exts = "dylib"; +#else + const char *exts = "so"; +#endif + + if (argc < 6) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + db_dir = argv[1]; + core_dir = argv[2]; + core_info_dir = argv[3]; + input_dir = argv[4]; + playlist_dir = argv[5]; + + fprintf(stderr, "RDB database dir: %s\n", db_dir); + fprintf(stderr, "Core dir: %s\n", core_dir); + fprintf(stderr, "Core info dir: %s\n", core_info_dir); + fprintf(stderr, "Input dir: %s\n", input_dir); + fprintf(stderr, "Playlist dir: %s\n", playlist_dir); + + task_queue_init(false /* threaded enable */, main_msg_queue_push); + + core_info_init_list(core_info_dir, core_dir, exts, true); + + task_push_dbscan(playlist_dir, db_dir, input_dir, true, + true, main_db_cb); + + while (loop_active) + task_queue_check(); + + fprintf(stderr, "Exit loop\n"); + + core_info_deinit_list(); + task_queue_deinit(); + + return 0; +} diff --git a/tasks/task_audio_mixer.c b/tasks/task_audio_mixer.c index f0b95dfadb..69772849fe 100644 --- a/tasks/task_audio_mixer.c +++ b/tasks/task_audio_mixer.c @@ -73,7 +73,7 @@ static int cb_nbio_audio_mixer_load(void *data, size_t len) image->buffer = buffer; image->buffer->buf = ptr; - image->buffer->bufsize = len; + image->buffer->bufsize = (unsigned)len; image->copy_data_over = true; nbio->is_finished = true; @@ -102,6 +102,50 @@ static void task_audio_mixer_handle_upload_ogg(void *task_data, free(user_data); } +static void task_audio_mixer_handle_upload_flac(void *task_data, + void *user_data, const char *err) +{ + audio_mixer_stream_params_t params; + nbio_buf_t *img = (nbio_buf_t*)task_data; + + if (!img) + return; + + params.volume = 1.0f; + params.type = AUDIO_MIXER_TYPE_FLAC; + params.state = AUDIO_STREAM_STATE_PLAYING; + params.buf = img->buf; + params.bufsize = img->bufsize; + params.cb = NULL; + + audio_driver_mixer_add_stream(¶ms); + + free(img); + free(user_data); +} + +static void task_audio_mixer_handle_upload_mp3(void *task_data, + void *user_data, const char *err) +{ + audio_mixer_stream_params_t params; + nbio_buf_t *img = (nbio_buf_t*)task_data; + + if (!img) + return; + + params.volume = 1.0f; + params.type = AUDIO_MIXER_TYPE_MP3; + params.state = AUDIO_STREAM_STATE_PLAYING; + params.buf = img->buf; + params.bufsize = img->bufsize; + params.cb = NULL; + + audio_driver_mixer_add_stream(¶ms); + + free(img); + free(user_data); +} + static void task_audio_mixer_handle_upload_mod(void *task_data, void *user_data, const char *err) { @@ -216,6 +260,18 @@ bool task_push_audio_mixer_load(const char *fullpath, retro_task_callback_t cb, nbio->type = NBIO_TYPE_OGG; t->callback = task_audio_mixer_handle_upload_ogg; } + else if (strstr(fullpath, file_path_str(FILE_PATH_MP3_EXTENSION))) + { + image->type = AUDIO_MIXER_TYPE_MP3; + nbio->type = NBIO_TYPE_MP3; + t->callback = task_audio_mixer_handle_upload_mp3; + } + else if (strstr(fullpath, file_path_str(FILE_PATH_FLAC_EXTENSION))) + { + image->type = AUDIO_MIXER_TYPE_FLAC; + nbio->type = NBIO_TYPE_FLAC; + t->callback = task_audio_mixer_handle_upload_flac; + } else if ( strstr(fullpath, file_path_str(FILE_PATH_MOD_EXTENSION)) || strstr(fullpath, file_path_str(FILE_PATH_S3M_EXTENSION)) || strstr(fullpath, file_path_str(FILE_PATH_XM_EXTENSION))) diff --git a/tasks/task_content.c b/tasks/task_content.c index 982f9dd54c..3676308d73 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -144,14 +144,14 @@ static uint32_t content_rom_crc = 0; static bool pending_subsystem_init = false; static int pending_subsystem_rom_num = 0; static int pending_subsystem_id = 0; -static int pending_subsystem_rom_id = 0; +static unsigned pending_subsystem_rom_id = 0; static char pending_subsystem_ident[255]; static char pending_subsystem_extensions[PATH_MAX_LENGTH]; static char *pending_subsystem_roms[RARCH_MAX_SUBSYSTEM_ROMS]; -static int content_file_read(const char *path, void **buf, ssize_t *length) +static int64_t content_file_read(const char *path, void **buf, int64_t *length) { #ifdef HAVE_COMPRESSION if (path_contains_compressed_file(path)) @@ -324,7 +324,7 @@ end: static bool load_content_into_memory( content_information_ctx_t *content_ctx, unsigned i, const char *path, void **buf, - ssize_t *length) + int64_t *length) { uint8_t *ret_buf = NULL; @@ -359,7 +359,7 @@ static bool load_content_into_memory( (uint8_t**)&ret_buf, (void*)length); - content_rom_crc = encoding_crc32(0, ret_buf, *length); + content_rom_crc = encoding_crc32(0, ret_buf, (size_t)*length); RARCH_LOG("CRC32: 0x%x .\n", (unsigned)content_rom_crc); } @@ -383,7 +383,7 @@ static bool load_content_from_compressed_archive( char **error_string) { union string_list_elem_attr attributes; - ssize_t new_path_len = 0; + int64_t new_path_len = 0; size_t path_size = PATH_MAX_LENGTH * sizeof(char); char *new_basedir = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *new_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); @@ -582,7 +582,7 @@ static bool content_file_load( { /* Load the content into memory. */ - ssize_t len = 0; + int64_t len = 0; if (!load_content_into_memory( content_ctx, @@ -1009,6 +1009,7 @@ static bool firmware_update_status( content_information_ctx_t *content_ctx) { core_info_ctx_firmware_t firmware_info; + bool set_missing_firmware = false; core_info_t *core_info = NULL; size_t s_size = PATH_MAX_LENGTH * sizeof(char); char *s = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); @@ -1032,7 +1033,13 @@ static bool firmware_update_status( RARCH_LOG("Updating firmware status for: %s on %s\n", core_info->path, firmware_info.directory.system); - core_info_list_update_missing_firmware(&firmware_info); + + rarch_ctl(RARCH_CTL_UNSET_MISSING_BIOS, NULL); + + core_info_list_update_missing_firmware(&firmware_info, &set_missing_firmware); + + if (set_missing_firmware) + rarch_ctl(RARCH_CTL_SET_MISSING_BIOS, NULL); if( content_ctx->bios_is_missing && @@ -1734,9 +1741,11 @@ void content_get_status( /* Clears the pending subsystem rom buffer*/ void content_clear_subsystem(void) { - int i; + unsigned i; + pending_subsystem_rom_id = 0; - pending_subsystem_init = false; + pending_subsystem_init = false; + for (i = 0; i < RARCH_MAX_SUBSYSTEM_ROMS; i++) { if (pending_subsystem_roms[i]) @@ -1756,15 +1765,17 @@ int content_get_subsystem() /* Set the current subsystem*/ void content_set_subsystem(unsigned idx) { - rarch_system_info_t *system = runloop_get_system_info(); - const struct retro_subsystem_info* subsystem = NULL; + rarch_system_info_t *system = runloop_get_system_info(); + const struct retro_subsystem_info *subsystem = system ? + system->subsystem.data + pending_subsystem_id : NULL; - subsystem = system->subsystem.data + pending_subsystem_id; + pending_subsystem_id = idx; - pending_subsystem_id = idx; + strlcpy(pending_subsystem_ident, + subsystem->ident, sizeof(pending_subsystem_ident)); + + pending_subsystem_rom_num = subsystem->num_roms; - strlcpy(pending_subsystem_ident, subsystem->ident, sizeof(pending_subsystem_ident)); - pending_subsystem_rom_num = subsystem->num_roms; RARCH_LOG("[subsystem] settings current subsytem to: %d(%s) roms: %d\n", pending_subsystem_id, pending_subsystem_ident, pending_subsystem_rom_num); } @@ -1783,7 +1794,7 @@ void content_add_subsystem(const char* path) } /* Get the current subsystem rom id */ -int content_get_subsystem_rom_id(void) +unsigned content_get_subsystem_rom_id(void) { return pending_subsystem_rom_id; } @@ -1820,7 +1831,7 @@ void content_deinit(void) RARCH_LOG("%s: %s.\n", msg_hash_to_str(MSG_REMOVING_TEMPORARY_CONTENT_FILE), path); - if (!filestream_delete(path)) + if (filestream_delete(path) != 0) RARCH_ERR("%s: %s.\n", msg_hash_to_str(MSG_FAILED_TO_REMOVE_TEMPORARY_FILE), path); diff --git a/tasks/task_database.c b/tasks/task_database.c index d1cda3293f..2bbe1c4591 100644 --- a/tasks/task_database.c +++ b/tasks/task_database.c @@ -28,15 +28,16 @@ #include #include "tasks_internal.h" +#include "../core_info.h" #include "../database_info.h" #include "../file_path_special.h" -#include "../list_special.h" #include "../msg_hash.h" #include "../playlist.h" +#ifdef RARCH_INTERNAL #include "../retroarch.h" +#endif #include "../verbosity.h" -#include "../core_info.h" #ifndef COLLECTION_SIZE #define COLLECTION_SIZE 99999 @@ -59,6 +60,7 @@ typedef struct db_handle { bool is_directory; bool scan_started; + bool show_hidden_files; unsigned status; char *playlist_directory; char *content_database_path; @@ -68,17 +70,17 @@ typedef struct db_handle } db_handle_t; int cue_find_track(const char *cue_path, bool first, - size_t *offset, size_t *size, - char *track_path, size_t max_len); + uint64_t *offset, uint64_t *size, + char *track_path, uint64_t max_len); bool cue_next_file(intfstream_t *fd, const char *cue_path, - char *path, size_t max_len); + char *path, uint64_t max_len); int gdi_find_track(const char *gdi_path, bool first, - char *track_path, size_t max_len); + char *track_path, uint64_t max_len); bool gdi_next_file(intfstream_t *fd, const char *gdi_path, - char *path, size_t max_len); + char *path, uint64_t max_len); int detect_system(intfstream_t *fd, const char** system_name); @@ -144,12 +146,13 @@ static int task_database_iterate_start(database_info_handle_t *db, name); if (!string_is_empty(msg)) + { +#ifdef RARCH_INTERNAL runloop_msg_queue_push(msg, 1, 180, true); - -#if 0 - RARCH_LOG("msg: %s\n", msg); +#else + fprintf(stderr, "msg: %s\n", msg); #endif - + } db->status = DATABASE_STATUS_ITERATE; @@ -201,11 +204,11 @@ static int intfstream_get_serial(intfstream_t *fd, char *serial) } static bool intfstream_file_get_serial(const char *name, - size_t offset, size_t size, char *serial) + uint64_t offset, uint64_t size, char *serial) { int rv; uint8_t *data = NULL; - ssize_t file_size = -1; + int64_t file_size = -1; intfstream_t *fd = intfstream_open_file(name, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); @@ -223,14 +226,14 @@ static bool intfstream_file_get_serial(const char *name, if (file_size < 0) goto error; - if (offset != 0 || size < (size_t) file_size) + if (offset != 0 || size < (uint64_t) file_size) { - if (intfstream_seek(fd, offset, SEEK_SET) == -1) + if (intfstream_seek(fd, (int64_t)offset, SEEK_SET) == -1) goto error; - data = (uint8_t*)malloc(size); + data = (uint8_t*)malloc((size_t)size); - if (intfstream_read(fd, data, size) != (ssize_t) size) + if (intfstream_read(fd, data, size) != (int64_t) size) { free(data); goto error; @@ -265,8 +268,8 @@ static int task_database_cue_get_serial(const char *name, char* serial) char *track_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); int ret = 0; - size_t offset = 0; - size_t size = 0; + uint64_t offset = 0; + uint64_t size = 0; int rv = 0; track_path[0] = '\0'; @@ -337,12 +340,12 @@ static int task_database_chd_get_serial(const char *name, char* serial) static int intfstream_get_crc(intfstream_t *fd, uint32_t *crc) { - ssize_t read = 0; + int64_t read = 0; uint32_t acc = 0; uint8_t buffer[4096]; while ((read = intfstream_read(fd, buffer, sizeof(buffer))) > 0) - acc = encoding_crc32(acc, buffer, read); + acc = encoding_crc32(acc, buffer, (size_t)read); if (read < 0) return 0; @@ -353,13 +356,13 @@ static int intfstream_get_crc(intfstream_t *fd, uint32_t *crc) } static bool intfstream_file_get_crc(const char *name, - size_t offset, size_t size, uint32_t *crc) + uint64_t offset, size_t size, uint32_t *crc) { int rv; intfstream_t *fd = intfstream_open_file(name, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); uint8_t *data = NULL; - ssize_t file_size = -1; + int64_t file_size = -1; if (!fd) return 0; @@ -375,14 +378,14 @@ static bool intfstream_file_get_crc(const char *name, if (file_size < 0) goto error; - if (offset != 0 || size < (size_t) file_size) + if (offset != 0 || size < (uint64_t) file_size) { - if (intfstream_seek(fd, offset, SEEK_SET) == -1) + if (intfstream_seek(fd, (int64_t)offset, SEEK_SET) == -1) goto error; data = (uint8_t*)malloc(size); - if (intfstream_read(fd, data, size) != (ssize_t) size) + if (intfstream_read(fd, data, size) != (int64_t) size) goto error; intfstream_close(fd); @@ -414,8 +417,8 @@ error: static int task_database_cue_get_crc(const char *name, uint32_t *crc) { char *track_path = (char *)malloc(PATH_MAX_LENGTH); - size_t offset = 0; - size_t size = 0; + uint64_t offset = 0; + uint64_t size = 0; int rv = 0; track_path[0] = '\0'; @@ -432,11 +435,11 @@ static int task_database_cue_get_crc(const char *name, uint32_t *crc) return 0; } - RARCH_LOG("CUE '%s' primary track: %s\n (%lu, %lu)\n", name, track_path, (unsigned long) offset, (unsigned long) size); + RARCH_LOG("CUE '%s' primary track: %s\n (%lu, %lu)\n",name, track_path, (unsigned long) offset, (unsigned long) size); RARCH_LOG("%s\n", msg_hash_to_str(MSG_READING_FIRST_DATA_TRACK)); - rv = intfstream_file_get_crc(track_path, offset, size, crc); + rv = intfstream_file_get_crc(track_path, offset, (size_t)size, crc); if (rv == 1) { RARCH_LOG("CUE '%s' crc: %x\n", name, *crc); @@ -561,11 +564,50 @@ end: free(path); } +static enum msg_file_type extension_to_file_type(const char *ext) +{ + if ( + string_is_equal(ext, "7z") || + string_is_equal(ext, "7Z") || + string_is_equal(ext, "zip") || + string_is_equal(ext, "ZIP") || + string_is_equal(ext, "apk") || + string_is_equal(ext, "APK") + ) + return FILE_TYPE_COMPRESSED; + if ( + string_is_equal(ext, "cue") || + string_is_equal(ext, "CUE") + ) + return FILE_TYPE_CUE; + if ( + string_is_equal(ext, "gdi") || + string_is_equal(ext, "GDI") + ) + return FILE_TYPE_GDI; + if ( + string_is_equal(ext, "iso") || + string_is_equal(ext, "ISO") + ) + return FILE_TYPE_ISO; + if ( + string_is_equal(ext, "chd") || + string_is_equal(ext, "CHD") + ) + return FILE_TYPE_CHD; + if ( + string_is_equal(ext, "lutro") || + string_is_equal(ext, "LUTRO") + ) + return FILE_TYPE_LUTRO; + return FILE_TYPE_NONE; +} + static int task_database_iterate_playlist( database_state_handle_t *db_state, database_info_handle_t *db, const char *name) { - switch (msg_hash_to_file_type(msg_hash_calculate(path_get_extension(name)))) + switch (extension_to_file_type(path_get_extension(name))) { case FILE_TYPE_COMPRESSED: #ifdef HAVE_COMPRESSION @@ -699,8 +741,8 @@ static int database_info_list_iterate_new(database_state_handle_t *db_state, { const char *new_database = database_info_get_current_name(db_state); -#if 0 - RARCH_LOG("Check database [%d/%d] : %s\n", (unsigned)db_state->list_index, +#ifndef RARCH_INTERNAL + fprintf(stderr, "Check database [%d/%d] : %s\n", (unsigned)db_state->list_index, (unsigned)db_state->list->size, new_database); #endif if (db_state->info) @@ -766,6 +808,7 @@ static int database_info_list_iterate_found_match( (hash = strchr(entry_path_str, '#'))) *hash = '\0'; +#if defined(RARCH_INTERNAL) #if 0 RARCH_LOG("Found match in database !\n"); @@ -777,6 +820,17 @@ static int database_info_list_iterate_found_match( RARCH_LOG("ZIP entry: %s\n", archive_name); RARCH_LOG("entry path str: %s\n", entry_path_str); #endif +#else + fprintf(stderr, "Found match in database !\n"); + + fprintf(stderr, "Path: %s\n", db_path); + fprintf(stderr, "CRC : %s\n", db_crc); + fprintf(stderr, "Playlist Path: %s\n", db_playlist_path); + fprintf(stderr, "Entry Path: %s\n", entry_path); + fprintf(stderr, "Playlist not NULL: %d\n", playlist != NULL); + fprintf(stderr, "ZIP entry: %s\n", archive_name); + fprintf(stderr, "entry path str: %s\n", entry_path_str); +#endif if(!playlist_entry_exists(playlist, entry_path_str, db_crc)) { @@ -1100,7 +1154,7 @@ static void task_database_handler(retro_task_t *task) if (!string_is_empty(db->fullpath)) { if (db->is_directory) - db->handle = database_info_dir_init(db->fullpath, DATABASE_TYPE_ITERATE, task); + db->handle = database_info_dir_init(db->fullpath, DATABASE_TYPE_ITERATE, task, db->show_hidden_files); else db->handle = database_info_file_init(db->fullpath, DATABASE_TYPE_ITERATE, task); } @@ -1123,9 +1177,11 @@ static void task_database_handler(retro_task_t *task) if (dbstate && !dbstate->list) { if (!string_is_empty(db->content_database_path)) - dbstate->list = dir_list_new_special( + dbstate->list = dir_list_new( db->content_database_path, - DIR_LIST_DATABASES, NULL); + "rdb", false, + db->show_hidden_files, + false, false); /* If the scan path matches a database path exactly then * save time by only processing that database. */ @@ -1191,14 +1247,16 @@ static void task_database_handler(retro_task_t *task) } else { + const char *msg = NULL; if (db->is_directory) - runloop_msg_queue_push( - msg_hash_to_str(MSG_SCANNING_OF_DIRECTORY_FINISHED), - 0, 180, true); + msg = msg_hash_to_str(MSG_SCANNING_OF_DIRECTORY_FINISHED); else - runloop_msg_queue_push( - msg_hash_to_str(MSG_SCANNING_OF_FILE_FINISHED), - 0, 180, true); + msg = msg_hash_to_str(MSG_SCANNING_OF_FILE_FINISHED); +#ifdef RARCH_INTERNAL + runloop_msg_queue_push(msg, 0, 180, true); +#else + fprintf(stderr, "msg: %s\n", msg); +#endif goto task_finished; } break; @@ -1243,7 +1301,9 @@ bool task_push_dbscan( const char *playlist_directory, const char *content_database, const char *fullpath, - bool directory, retro_task_callback_t cb) + bool directory, + bool show_hidden_files, + retro_task_callback_t cb) { retro_task_t *t = (retro_task_t*)calloc(1, sizeof(*t)); db_handle_t *db = (db_handle_t*)calloc(1, sizeof(db_handle_t)); @@ -1256,6 +1316,7 @@ bool task_push_dbscan( t->callback = cb; t->title = strdup(msg_hash_to_str(MSG_PREPARING_FOR_CONTENT_SCAN)); + db->show_hidden_files = show_hidden_files; db->is_directory = directory; db->playlist_directory = NULL; db->fullpath = strdup(fullpath); diff --git a/tasks/task_database_cue.c b/tasks/task_database_cue.c index 94db29ed40..b36cb4421c 100644 --- a/tasks/task_database_cue.c +++ b/tasks/task_database_cue.c @@ -36,7 +36,6 @@ #include "tasks_internal.h" -#include "../driver.h" #include "../list_special.h" #include "../msg_hash.h" #include "../verbosity.h" @@ -65,15 +64,15 @@ static struct magic_entry MAGIC_NUMBERS[] = { { 0, NULL, NULL} }; -static ssize_t get_token(intfstream_t *fd, char *token, size_t max_len) +static int64_t get_token(intfstream_t *fd, char *token, uint64_t max_len) { char *c = token; - ssize_t len = 0; + int64_t len = 0; int in_string = 0; while (1) { - int rv = (int)intfstream_read(fd, c, 1); + int64_t rv = (int64_t)intfstream_read(fd, c, 1); if (rv == 0) return 0; @@ -117,7 +116,7 @@ static ssize_t get_token(intfstream_t *fd, char *token, size_t max_len) len++; c++; - if (len == (ssize_t)max_len) + if (len == (int64_t)max_len) { *c = '\0'; return len; @@ -363,7 +362,7 @@ int detect_system(intfstream_t *fd, const char **system_name) int rv; char magic[MAGIC_LEN]; int i; - ssize_t read; + int64_t read; RARCH_LOG("%s\n", msg_hash_to_str(MSG_COMPARING_WITH_KNOWN_MAGIC_NUMBERS)); for (i = 0; MAGIC_NUMBERS[i].system_name != NULL; i++) @@ -382,7 +381,7 @@ int detect_system(intfstream_t *fd, const char **system_name) if (read < MAGIC_LEN) continue; - if (string_is_equal(MAGIC_NUMBERS[i].magic, magic)) + if (memcmp(MAGIC_NUMBERS[i].magic, magic, MAGIC_LEN) == 0) { *system_name = MAGIC_NUMBERS[i].system_name; rv = 0; @@ -410,9 +409,9 @@ clean: return rv; } -static ssize_t intfstream_get_file_size(const char *path) +static int64_t intfstream_get_file_size(const char *path) { - ssize_t rv; + int64_t rv; intfstream_t *fd = intfstream_open_file(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!fd) @@ -423,40 +422,40 @@ static ssize_t intfstream_get_file_size(const char *path) return rv; } -static bool update_cand(ssize_t *cand_index, ssize_t *last_index, - size_t *largest, char *last_file, size_t *offset, - size_t *size, char *track_path, size_t max_len) +static bool update_cand(int64_t *cand_index, int64_t *last_index, + uint64_t *largest, char *last_file, uint64_t *offset, + uint64_t *size, char *track_path, uint64_t max_len) { - if (*cand_index != -1) - { - if ((unsigned)(*last_index - *cand_index) > *largest) - { - *largest = *last_index - *cand_index; - strlcpy(track_path, last_file, max_len); - *offset = *cand_index; - *size = *largest; + if (*cand_index != -1) + { + if ((uint64_t)(*last_index - *cand_index) > *largest) + { + *largest = *last_index - *cand_index; + strlcpy(track_path, last_file, (size_t)max_len); + *offset = *cand_index; + *size = *largest; + *cand_index = -1; + return true; + } *cand_index = -1; - return true; - } - *cand_index = -1; - } - return false; + } + return false; } int cue_find_track(const char *cue_path, bool first, - size_t *offset, size_t *size, char *track_path, size_t max_len) + uint64_t *offset, uint64_t *size, char *track_path, uint64_t max_len) { int rv; intfstream_info_t info; char *tmp_token = (char*)malloc(MAX_TOKEN_LEN); char *last_file = (char*)malloc(PATH_MAX_LENGTH + 1); intfstream_t *fd = NULL; - ssize_t last_index = -1; - ssize_t cand_index = -1; + int64_t last_index = -1; + int64_t cand_index = -1; int32_t cand_track = -1; int32_t track = 0; - size_t largest = 0; - ssize_t volatile file_size = -1; + uint64_t largest = 0; + int64_t volatile file_size = -1; bool is_data = false; char *cue_dir = (char*)malloc(PATH_MAX_LENGTH); cue_dir[0] = '\0'; @@ -488,17 +487,16 @@ int cue_find_track(const char *cue_path, bool first, if (string_is_equal(tmp_token, "FILE")) { /* Set last index to last EOF */ - if (file_size != -1) { + if (file_size != -1) last_index = file_size; - } /* We're changing files since the candidate, update it */ if (update_cand(&cand_index, &last_index, &largest, last_file, offset, - size, track_path, max_len)) { + size, track_path, max_len)) + { rv = 0; - if (first) { + if (first) goto clean; - } } get_token(fd, tmp_token, MAX_TOKEN_LEN); @@ -515,7 +513,9 @@ int cue_find_track(const char *cue_path, bool first, get_token(fd, tmp_token, MAX_TOKEN_LEN); is_data = !string_is_equal(tmp_token, "AUDIO"); ++track; - } else if (string_is_equal(tmp_token, "INDEX")) { + } + else if (string_is_equal(tmp_token, "INDEX")) + { int m, s, f; get_token(fd, tmp_token, MAX_TOKEN_LEN); get_token(fd, tmp_token, MAX_TOKEN_LEN); @@ -531,32 +531,30 @@ int cue_find_track(const char *cue_path, bool first, /* If we've changed tracks since the candidate, update it */ if (cand_track != -1 && track != cand_track && update_cand(&cand_index, &last_index, &largest, last_file, offset, - size, track_path, max_len)) { + size, track_path, max_len)) + { rv = 0; - if (first) { + if (first) goto clean; - } } - if (!is_data) { + if (!is_data) continue; - } - if (cand_index == -1) { + if (cand_index == -1) + { cand_index = last_index; cand_track = track; } } } - if (file_size != -1) { + if (file_size != -1) last_index = file_size; - } if (update_cand(&cand_index, &last_index, &largest, last_file, offset, - size, track_path, max_len)) { + size, track_path, max_len)) rv = 0; - } clean: free(cue_dir); @@ -578,7 +576,8 @@ error: return -errno; } -bool cue_next_file(intfstream_t *fd, const char *cue_path, char *path, size_t max_len) +bool cue_next_file(intfstream_t *fd, + const char *cue_path, char *path, uint64_t max_len) { bool rv = false; char *tmp_token = (char*)malloc(MAX_TOKEN_LEN); @@ -594,7 +593,7 @@ bool cue_next_file(intfstream_t *fd, const char *cue_path, char *path, size_t ma if (string_is_equal(tmp_token, "FILE")) { get_token(fd, tmp_token, MAX_TOKEN_LEN); - fill_pathname_join(path, cue_dir, tmp_token, max_len); + fill_pathname_join(path, cue_dir, tmp_token, (size_t)max_len); rv = true; break; } @@ -606,16 +605,16 @@ bool cue_next_file(intfstream_t *fd, const char *cue_path, char *path, size_t ma } int gdi_find_track(const char *gdi_path, bool first, - char *track_path, size_t max_len) + char *track_path, uint64_t max_len) { int rv; intfstream_info_t info; char *tmp_token = (char*)malloc(MAX_TOKEN_LEN); intfstream_t *fd = NULL; - size_t largest = 0; + uint64_t largest = 0; int size = -1; int mode = -1; - ssize_t file_size = -1; + int64_t file_size = -1; info.type = INTFSTREAM_FILE; @@ -694,11 +693,13 @@ int gdi_find_track(const char *gdi_path, bool first, goto error; } - if ((unsigned)file_size > largest) + if ((uint64_t)file_size > largest) { - strlcpy(track_path, last_file, max_len); - rv = 0; + strlcpy(track_path, last_file, (size_t)max_len); + + rv = 0; largest = file_size; + if (first) { free(gdi_dir); @@ -735,11 +736,11 @@ error: } bool gdi_next_file(intfstream_t *fd, const char *gdi_path, - char *path, size_t max_len) + char *path, uint64_t max_len) { bool rv = false; char *tmp_token = (char*)malloc(MAX_TOKEN_LEN); - ssize_t offset = -1; + int64_t offset = -1; tmp_token[0] = '\0'; @@ -769,7 +770,7 @@ bool gdi_next_file(intfstream_t *fd, const char *gdi_path, fill_pathname_basedir(gdi_dir, gdi_path, PATH_MAX_LENGTH); - fill_pathname_join(path, gdi_dir, tmp_token, max_len); + fill_pathname_join(path, gdi_dir, tmp_token, (size_t)max_len); rv = true; /* Disc offset */ diff --git a/tasks/task_file_transfer.c b/tasks/task_file_transfer.c index 9d8ed3976a..2249681508 100644 --- a/tasks/task_file_transfer.c +++ b/tasks/task_file_transfer.c @@ -103,6 +103,8 @@ void task_file_load_handler(retro_task_t *task) if (!task_image_load_handler(task)) task_set_finished(task, true); break; + case NBIO_TYPE_MP3: + case NBIO_TYPE_FLAC: case NBIO_TYPE_OGG: case NBIO_TYPE_MOD: case NBIO_TYPE_WAV: diff --git a/tasks/task_overlay.c b/tasks/task_overlay.c index 036b869030..7f755f6ef9 100644 --- a/tasks/task_overlay.c +++ b/tasks/task_overlay.c @@ -329,8 +329,9 @@ static bool task_overlay_resolve_targets(struct overlay *ol, for (i = 0; i < current->size; i++) { - ssize_t next_idx = 0; - const char *next = current->descs[i].next_index_name; + struct overlay_desc *desc = (struct overlay_desc*)¤t->descs[i]; + const char *next = desc->next_index_name; + ssize_t next_idx = (idx + 1) & size; if (!string_is_empty(next)) { @@ -343,10 +344,8 @@ static bool task_overlay_resolve_targets(struct overlay *ol, return false; } } - else - next_idx = (idx + 1) & size; - current->descs[i].next_index = (unsigned)next_idx; + desc->next_index = (unsigned)next_idx; } return true; diff --git a/tasks/task_patch.c b/tasks/task_patch.c index 3df074c171..51579453ec 100644 --- a/tasks/task_patch.c +++ b/tasks/task_patch.c @@ -93,8 +93,8 @@ struct ups_data unsigned target_checksum; }; -typedef enum patch_error (*patch_func_t)(const uint8_t*, size_t, - const uint8_t*, size_t, uint8_t*, size_t*); +typedef enum patch_error (*patch_func_t)(const uint8_t*, uint64_t, + const uint8_t*, uint64_t, uint8_t*, uint64_t*); static uint8_t bps_read(struct bps_data *bps) { @@ -128,9 +128,9 @@ static void bps_write(struct bps_data *bps, uint8_t data) } static enum patch_error bps_apply_patch( - const uint8_t *modify_data, size_t modify_length, - const uint8_t *source_data, size_t source_length, - uint8_t *target_data, size_t *target_length) + const uint8_t *modify_data, uint64_t modify_length, + const uint8_t *source_data, uint64_t source_length, + uint8_t *target_data, uint64_t *target_length) { size_t i; uint32_t checksum; @@ -309,9 +309,9 @@ static uint64_t ups_decode(struct ups_data *data) } static enum patch_error ups_apply_patch( - const uint8_t *patchdata, size_t patchlength, - const uint8_t *sourcedata, size_t sourcelength, - uint8_t *targetdata, size_t *targetlength) + const uint8_t *patchdata, uint64_t patchlength, + const uint8_t *sourcedata, uint64_t sourcelength, + uint8_t *targetdata, uint64_t *targetlength) { size_t i; struct ups_data data; @@ -417,9 +417,9 @@ static enum patch_error ups_apply_patch( } static enum patch_error ips_apply_patch( - const uint8_t *patchdata, size_t patchlen, - const uint8_t *sourcedata, size_t sourcelength, - uint8_t *targetdata, size_t *targetlength) + const uint8_t *patchdata, uint64_t patchlen, + const uint8_t *sourcedata, uint64_t sourcelength, + uint8_t *targetdata, uint64_t *targetlength) { uint32_t offset = 5; @@ -431,7 +431,7 @@ static enum patch_error ips_apply_patch( patchdata[4] != 'H') return PATCH_PATCH_INVALID; - memcpy(targetdata, sourcedata, sourcelength); + memcpy(targetdata, sourcedata, (size_t)sourcelength); *targetlength = sourcelength; @@ -501,13 +501,13 @@ static enum patch_error ips_apply_patch( static bool apply_patch_content(uint8_t **buf, ssize_t *size, const char *patch_desc, const char *patch_path, - patch_func_t func, void *patch_data, ssize_t patch_size) + patch_func_t func, void *patch_data, int64_t patch_size) { enum patch_error err = PATCH_UNKNOWN; ssize_t ret_size = *size; uint8_t *ret_buf = *buf; - size_t target_size = ret_size * 4; /* Just to be sure. */ - uint8_t *patched_content = (uint8_t*)malloc(target_size); + uint64_t target_size = ret_size * 4; /* Just to be sure. */ + uint8_t *patched_content = (uint8_t*)malloc((size_t)target_size); RARCH_LOG("Found %s file in \"%s\", attempting to patch ...\n", patch_desc, patch_path); @@ -551,7 +551,7 @@ static bool try_bps_patch(bool allow_bps, const char *name_bps, if (allow_bps && !string_is_empty(name_bps)) if (path_is_valid(name_bps) && filestream_exists(name_bps)) { - ssize_t patch_size; + int64_t patch_size; bool ret = false; void *patch_data = NULL; @@ -578,7 +578,7 @@ static bool try_ups_patch(bool allow_ups, const char *name_ups, if (allow_ups && !string_is_empty(name_ups)) if (path_is_valid(name_ups) && filestream_exists(name_ups)) { - ssize_t patch_size; + int64_t patch_size; bool ret = false; void *patch_data = NULL; @@ -605,7 +605,7 @@ static bool try_ips_patch(bool allow_ips, if (allow_ips && !string_is_empty(name_ips)) if (path_is_valid(name_ips) && filestream_exists(name_ips)) { - ssize_t patch_size; + int64_t patch_size; bool ret = false; void *patch_data = NULL; diff --git a/tasks/task_save.c b/tasks/task_save.c index 2dbca2c94d..08bfbf947e 100644 --- a/tasks/task_save.c +++ b/tasks/task_save.c @@ -1347,7 +1347,7 @@ static bool content_get_memory(retro_ctx_memory_info_t *mem_info, */ bool content_load_ram_file(unsigned slot) { - ssize_t rc; + int64_t rc; struct ram_type ram; retro_ctx_memory_info_t mem_info; void *buf = NULL; @@ -1370,7 +1370,7 @@ bool content_load_ram_file(unsigned slot) (unsigned)mem_info.size); rc = mem_info.size; } - memcpy(mem_info.data, buf, rc); + memcpy(mem_info.data, buf, (size_t)rc); } if (buf) diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index bbb11866ad..766f593d14 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -32,7 +32,6 @@ #include "../content.h" #include "../core_type.h" #include "../msg_hash.h" -#include "../frontend/frontend_driver.h" RETRO_BEGIN_DECLS @@ -74,6 +73,8 @@ enum nbio_type NBIO_TYPE_TGA, NBIO_TYPE_BMP, NBIO_TYPE_OGG, + NBIO_TYPE_FLAC, + NBIO_TYPE_MP3, NBIO_TYPE_MOD, NBIO_TYPE_WAV }; @@ -134,7 +135,8 @@ bool task_push_dbscan( const char *playlist_directory, const char *content_database, const char *fullpath, - bool directory, retro_task_callback_t cb); + bool directory, bool show_hidden_files, + retro_task_callback_t cb); #endif #ifdef HAVE_OVERLAY diff --git a/ui/drivers/ui_win32.c b/ui/drivers/ui_win32.c index 4b5dfb21f6..ec7c2265cc 100644 --- a/ui/drivers/ui_win32.c +++ b/ui/drivers/ui_win32.c @@ -74,6 +74,7 @@ typedef struct ui_companion_win32 void *empty; } ui_companion_win32_t; +#ifdef HAVE_SHADERPIPELINE enum shader_param_ctrl_type { SHADER_PARAM_CTRL_NONE = 0, @@ -221,6 +222,7 @@ static void shader_dlg_params_clear(void) control->type = SHADER_PARAM_CTRL_NONE; } } +#endif void shader_dlg_params_reload(void) { @@ -329,6 +331,7 @@ void shader_dlg_params_reload(void) #endif } +#ifdef HAVE_SHADERPIPELINE static void shader_dlg_update_on_top_state(void) { bool on_top = SendMessage(g_shader_dlg.on_top_checkbox.hwnd, @@ -339,7 +342,7 @@ static void shader_dlg_update_on_top_state(void) SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } -void shader_dlg_show(HWND parent_hwnd) +static void shader_dlg_show(HWND parent_hwnd) { const ui_window_t *window = ui_companion_driver_get_window_ptr(); @@ -364,6 +367,7 @@ void shader_dlg_show(HWND parent_hwnd) window->set_focused(&g_shader_dlg.window); } +#endif #if 0 static LRESULT CALLBACK ShaderDlgWndProc(HWND hwnd, UINT message, @@ -443,7 +447,7 @@ static LRESULT CALLBACK ShaderDlgWndProc(HWND hwnd, UINT message, return DefWindowProc(hwnd, message, wparam, lparam); } -bool win32_shader_dlg_init(void) +static bool win32_shader_dlg_init(void) { static bool inited = false; int pos_y; @@ -687,11 +691,11 @@ LRESULT win32_menu_loop(HWND owner, WPARAM wparam) case ID_M_FULL_SCREEN: cmd = CMD_EVENT_FULLSCREEN_TOGGLE; break; -#ifndef _XBOX case ID_M_SHADER_PARAMETERS: +#if !defined(_XBOX) && defined(HAVE_SHADERPIPELINE) shader_dlg_show(owner); - break; #endif + break; case ID_M_MOUSE_GRAB: cmd = CMD_EVENT_GRAB_MOUSE_TOGGLE; break; diff --git a/verbosity.c b/verbosity.c index 4f3548af97..6102669a78 100644 --- a/verbosity.c +++ b/verbosity.c @@ -101,7 +101,7 @@ void retro_main_log_file_init(const char *path) if (path == NULL) return; - log_file_fp = fopen_utf8(path, "wb"); + log_file_fp = (FILE*)fopen_utf8(path, "wb"); log_file_initialized = true; /* TODO: this is only useful for a few platforms, find which and add ifdef */ @@ -121,17 +121,12 @@ void retro_main_log_file_deinit(void) #if !defined(HAVE_LOGGER) void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap) { -#if TARGET_OS_IPHONE - static int asl_initialized = 0; -#if !TARGET_IPHONE_SIMULATOR - static aslclient asl_client; -#endif -#endif - #if TARGET_OS_IPHONE #if TARGET_IPHONE_SIMULATOR vprintf(fmt, ap); #else + static aslclient asl_client; + static int asl_initialized = 0; if (!asl_initialized) { asl_client = asl_open( @@ -193,6 +188,37 @@ void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap) #endif } +void RARCH_LOG_BUFFER(uint8_t *data, size_t size) +{ + int i, offset; + int padding = size % 16; + uint8_t buf[16]; + + RARCH_LOG("== %d-byte buffer ==================\n", size); + for(i = 0, offset = 0; i < size; i++) + { + buf[offset] = data[i]; + offset++; + + if(offset == 16) + { + offset = 0; + RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); + } + } + if(padding) + { + for(i = padding; i < 16; i++) + buf[i] = 0xff; + RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); + } + RARCH_LOG("==================================\n"); +} + void RARCH_LOG(const char *fmt, ...) { va_list ap; diff --git a/verbosity.h b/verbosity.h index 5f5cdcf30a..42ae964f58 100644 --- a/verbosity.h +++ b/verbosity.h @@ -86,7 +86,7 @@ void logger_send_v(const char *__format, va_list args); logger_send_v(fmt, vp); \ } while (0) -#else +#else /* IS_SALAMANDER */ #define RARCH_LOG(...) do { \ logger_send("" __VA_ARGS__); \ @@ -123,11 +123,14 @@ void logger_send_v(const char *__format, va_list args); logger_send("[OUTPUT] " tag); \ logger_send_v(fmt, vp); \ } while (0) - #endif -#else + +#define RARCH_LOG_BUFFER(...) do { } while(0) + +#else /* HAVE_LOGGER */ void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap); void RARCH_LOG(const char *fmt, ...); +void RARCH_LOG_BUFFER(uint8_t *buffer, size_t size); void RARCH_LOG_OUTPUT(const char *msg, ...); void RARCH_WARN(const char *fmt, ...); void RARCH_ERR(const char *fmt, ...); @@ -135,7 +138,7 @@ void RARCH_ERR(const char *fmt, ...); #define RARCH_LOG_OUTPUT_V RARCH_LOG_V #define RARCH_WARN_V RARCH_LOG_V #define RARCH_ERR_V RARCH_LOG_V -#endif +#endif /* HAVE_LOGGER */ RETRO_END_DECLS diff --git a/wiiu/include/wiiu/os/atomic.h b/wiiu/include/wiiu/os/atomic.h new file mode 100644 index 0000000000..a5e5dfbcf4 --- /dev/null +++ b/wiiu/include/wiiu/os/atomic.h @@ -0,0 +1,14 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint8_t SwapAtomic8(uint8_t *ptr, uint8_t value); +uint16_t SwapAtomic16(uint16_t *ptr, uint16_t value); +uint32_t SwapAtomic32(uint32_t *ptr, uint32_t value); + +#ifdef __cplusplus +} +#endif diff --git a/wiiu/include/wiiu/pad_driver.h b/wiiu/include/wiiu/pad_driver.h deleted file mode 100644 index 376b899f43..0000000000 --- a/wiiu/include/wiiu/pad_driver.h +++ /dev/null @@ -1,183 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2014-2017 - Ali Bouhlel - * Copyright (C) 2011-2017 - Daniel De Matteis - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#ifndef __PAD_DRIVER__H -#define __PAD_DRIVER__H - -#ifdef HAVE_CONFIG_H -#include "../../config.h" -#endif /* HAVE_CONFIG_H */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../input/input_driver.h" -#include "../../input/connect/joypad_connection.h" -#include "../../tasks/tasks_internal.h" -#include "../../retroarch.h" -#include "../../verbosity.h" -#include "../../command.h" -#include "../../gfx/video_driver.h" - -/** - * Magic button sequence that triggers an exit. Useful for if the visuals are - * corrupted, but won't work in the case of a hard lock. - */ -#define PANIC_BUTTON_MASK (VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_STICK_R | VPAD_BUTTON_STICK_L) - -/** - * Applies a standard transform to the Wii U gamepad's analog stick. - * No idea where 0x7ff0 comes from. - */ - -#define WIIU_ANALOG_FACTOR 0x7ff0 -#define WIIU_READ_STICK(stick) ((stick) * WIIU_ANALOG_FACTOR) - -/** - * the wiimote driver uses these to delimit which pads correspond to the - * wiimotes. - */ -#define PAD_GAMEPAD 0 -#define WIIU_WIIMOTE_CHANNELS 4 - -/** - * These are used by the wiimote driver to identify the wiimote configuration - * attached to the channel. - */ -/* wiimote with Wii U Pro controller */ -#define WIIMOTE_TYPE_PRO 0x1f -/* wiimote with Classic Controller */ -#define WIIMOTE_TYPE_CLASSIC 0x02 -/* wiimote with nunchuk */ -#define WIIMOTE_TYPE_NUNCHUK 0x01 -/* wiimote plus (no accessory attached) */ -#define WIIMOTE_TYPE_WIIPLUS 0x00 -/* wiimote not attached on this channel */ -#define WIIMOTE_TYPE_NONE 0xFD - -/** - * These are used to map pad names to controller mappings. You can - * change these relatively free-form. - */ - -#define PAD_NAME_WIIU_GAMEPAD "WiiU Gamepad" -#define PAD_NAME_WIIU_PRO "WiiU Pro Controller" -#define PAD_NAME_WIIMOTE "Wiimote Controller" -#define PAD_NAME_NUNCHUK "Wiimote+Nunchuk Controller" -#define PAD_NAME_CLASSIC "Classic Controller" -#define PAD_NAME_HID "HID Controller" - -/** - * The Wii U gamepad and wiimotes have 3 sets of x/y axes. The third - * is used by the gamepad for the touchpad driver; the wiimotes is - * currently unimplemented, but could be used for future IR pointer - * support. - */ -#define WIIU_DEVICE_INDEX_TOUCHPAD 2 - -typedef struct _axis_data axis_data; - -struct _axis_data { - int32_t axis; - bool is_negative; -}; - -typedef struct _wiiu_pad_functions wiiu_pad_functions_t; - -struct _wiiu_pad_functions { - int16_t (*get_axis_value)(int32_t axis, int16_t state[3][2], bool is_negative); - void (*set_axis_value)(int16_t state[3][2], int16_t left_x, int16_t left_y, - int16_t right_x, int16_t right_y, int16_t touch_x, int16_t touch_y); - void (*read_axis_data)(uint32_t axis, axis_data *data); - void (*connect)(unsigned pad, input_device_driver_t *driver); -}; - -/** - * HID driver data structures - */ - -typedef struct wiiu_hid { - /* used to register for HID notifications */ - HIDClient *client; - /* list of HID pads */ - joypad_connection_t *connections; - /* size of connections list */ - unsigned connections_size; - /* thread state data for HID polling thread */ - OSThread *polling_thread; - /* stack space for polling thread */ - void *polling_thread_stack; - /* watch variable to tell the polling thread to terminate */ - volatile bool polling_thread_quit; -} wiiu_hid_t; - -typedef struct wiiu_adapter wiiu_adapter_t; - -struct wiiu_adapter { - wiiu_adapter_t *next; - wiiu_hid_t *hid; - uint8_t state; - uint8_t *rx_buffer; - int32_t rx_size; - uint8_t *tx_buffer; - int32_t tx_size; - int32_t slot; - uint32_t handle; - uint8_t interface_index; -}; - -typedef struct wiiu_attach wiiu_attach_event; - -struct wiiu_attach { - wiiu_attach_event *next; - uint32_t type; - uint32_t handle; - uint16_t vendor_id; - uint16_t product_id; - uint8_t interface_index; - uint8_t is_keyboard; - uint8_t is_mouse; - uint16_t max_packet_size_rx; - uint16_t max_packet_size_tx; -}; - -typedef struct _wiiu_event_list wiiu_event_list; -typedef struct _wiiu_adapter_list wiiu_adapter_list; - -struct _wiiu_event_list { - OSFastMutex lock; - wiiu_attach_event *list; -}; - -struct _wiiu_adapter_list { - OSFastMutex lock; - wiiu_adapter_t *list; -}; - -extern wiiu_pad_functions_t pad_functions; -extern input_device_driver_t wiiu_joypad; -extern input_device_driver_t wpad_driver; -extern input_device_driver_t kpad_driver; -extern input_device_driver_t hidpad_driver; -extern hid_driver_t wiiu_hid; - -#endif /* __PAD_DRIVER__H */ diff --git a/wiiu/include/wiiu/pad_strings.h b/wiiu/include/wiiu/pad_strings.h new file mode 100644 index 0000000000..e28a9036e6 --- /dev/null +++ b/wiiu/include/wiiu/pad_strings.h @@ -0,0 +1,32 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2014-2017 - Ali Bouhlel + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef __PAD_DRIVER__H +#define __PAD_DRIVER__H + +/** + * These are used to map pad names to controller mappings. You can + * change these relatively free-form. + */ + +#define PAD_NAME_WIIU_GAMEPAD "WiiU Gamepad" +#define PAD_NAME_WIIU_PRO "WiiU Pro Controller" +#define PAD_NAME_WIIMOTE "Wiimote Controller" +#define PAD_NAME_NUNCHUK "Wiimote+Nunchuk Controller" +#define PAD_NAME_CLASSIC "Classic Controller" +#define PAD_NAME_HID "HID Controller" + +#endif /* __PAD_DRIVER__H */ diff --git a/wiiu/include/wiiu/syshid.h b/wiiu/include/wiiu/syshid.h index 1f55718dd9..664e52eef6 100644 --- a/wiiu/include/wiiu/syshid.h +++ b/wiiu/include/wiiu/syshid.h @@ -1,15 +1,6 @@ #pragma once #include -/* - * Report types for the report_type parameter in HIDSetReport() - */ - -/* what is 1? */ -#define HID_REPORT_OUTPUT 2 -#define HID_REPORT_FEATURE 3 -/* are there more? */ - typedef struct { uint32_t handle; diff --git a/wiiu/input/hidpad_driver.c b/wiiu/input/hidpad_driver.c index 5cae6d710f..03efe64d5c 100644 --- a/wiiu/input/hidpad_driver.c +++ b/wiiu/input/hidpad_driver.c @@ -14,64 +14,31 @@ * If not, see . */ -#include +#include "wiiu_input.h" +#include "wiiu_hid.h" static bool hidpad_init(void *data); static bool hidpad_query_pad(unsigned pad); static void hidpad_destroy(void); static bool hidpad_button(unsigned pad, uint16_t button); -static void hidpad_get_buttons(unsigned pad, retro_bits_t *state); +static void hidpad_get_buttons(unsigned pad, input_bits_t *state); static int16_t hidpad_axis(unsigned pad, uint32_t axis); static void hidpad_poll(void); static const char *hidpad_name(unsigned pad); static bool ready = false; -static wiiu_hid_t *hid_data; -static hid_driver_t *hid_driver; - -static unsigned to_slot(unsigned pad) +static bool init_hid_driver(void) { - return pad - (WIIU_WIIMOTE_CHANNELS+1); -} - -const void *get_hid_data(void) -{ - return hid_data; -} - -static hid_driver_t *init_hid_driver(void) -{ - joypad_connection_t *connections = NULL; - unsigned connections_size = MAX_USERS - (WIIU_WIIMOTE_CHANNELS+1); - - hid_data = (wiiu_hid_t *)wiiu_hid.init(); - connections = pad_connection_init(connections_size); - - if (!hid_data || !connections) - goto error; - - hid_data->connections = connections; - hid_data->connections_size = connections_size; - return &wiiu_hid; - -error: - if (connections) - free(connections); - if (hid_data) - { - wiiu_hid.free(hid_data); - hid_data = NULL; - } - return NULL; + return hid_init(&hid_instance, &wiiu_hid, &hidpad_driver, MAX_USERS); } static bool hidpad_init(void *data) { (void *)data; + int i; - hid_driver = init_hid_driver(); - if (!hid_driver) + if(!init_hid_driver()) { RARCH_ERR("Failed to initialize HID driver.\n"); return false; @@ -85,23 +52,14 @@ static bool hidpad_init(void *data) static bool hidpad_query_pad(unsigned pad) { - return ready && (pad > WIIU_WIIMOTE_CHANNELS && pad < MAX_USERS); + return ready && pad < MAX_USERS; } static void hidpad_destroy(void) { ready = false; - if(hid_driver) { - hid_driver->free(hid_data); - hid_data = NULL; - hid_driver = NULL; - } - - if(hid_data) { - free(hid_data); - hid_data = NULL; - } + hid_deinit(&hid_instance); } static bool hidpad_button(unsigned pad, uint16_t button) @@ -109,42 +67,29 @@ static bool hidpad_button(unsigned pad, uint16_t button) if (!hidpad_query_pad(pad)) return false; -#if 0 - return hid_driver->button(hid_data, to_slot(pad), button); -#else - return false; -#endif + return HID_BUTTON(pad, button); } -static void hidpad_get_buttons(unsigned pad, retro_bits_t *state) +static void hidpad_get_buttons(unsigned pad, input_bits_t *state) { if (!hidpad_query_pad(pad)) BIT256_CLEAR_ALL_PTR(state); -#if 0 - hid_driver->get_buttons(hid_data, to_slot(pad), state); -#endif - BIT256_CLEAR_ALL_PTR(state); + HID_GET_BUTTONS(pad, state); } static int16_t hidpad_axis(unsigned pad, uint32_t axis) { - if (!hidpad_query_pad(pad)); - return 0; + if (!hidpad_query_pad(pad)) + return 0; -#if 0 - return hid_driver->axis(hid_data, to_slot(pad), axis); -#else - return 0; -#endif + return HID_AXIS(pad, axis); } static void hidpad_poll(void) { -#if 0 if (ready) - hid_driver->poll(hid_data); -#endif + HID_POLL(); } static const char *hidpad_name(unsigned pad) @@ -152,11 +97,7 @@ static const char *hidpad_name(unsigned pad) if (!hidpad_query_pad(pad)) return "N/A"; -#if 1 - return PAD_NAME_HID; -#else - return hid_driver->name(hid_data, to_slot(pad)); -#endif + return HID_PAD_NAME(pad); } input_device_driver_t hidpad_driver = diff --git a/wiiu/input/kpad_driver.c b/wiiu/input/kpad_driver.c index 48a7f428c3..a3c7078357 100644 --- a/wiiu/input/kpad_driver.c +++ b/wiiu/input/kpad_driver.c @@ -20,16 +20,17 @@ * controllers. */ -#include +#include "wiiu_input.h" static bool kpad_init(void *data); static bool kpad_query_pad(unsigned pad); static void kpad_destroy(void); static bool kpad_button(unsigned pad, uint16_t button); -static void kpad_get_buttons(unsigned pad, retro_bits_t *state); +static void kpad_get_buttons(unsigned pad, input_bits_t *state); static int16_t kpad_axis(unsigned pad, uint32_t axis); static void kpad_poll(void); static const char *kpad_name(unsigned pad); +static void kpad_deregister(unsigned channel); typedef struct _wiimote_state wiimote_state; @@ -52,17 +53,30 @@ wiimote_state wiimotes[WIIU_WIIMOTE_CHANNELS] = { { 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE }, }; -static unsigned to_wiimote_channel(unsigned pad) -{ - if (pad == PAD_GAMEPAD || pad > WIIU_WIIMOTE_CHANNELS) - return 0xffffffff; +static int channel_slot_map[] = { -1, -1, -1, -1 }; - return pad-1; +static int to_wiimote_channel(unsigned pad) +{ + int i; + + for(i = 0; i < WIIU_WIIMOTE_CHANNELS; i++) + if(channel_slot_map[i] == pad) + return i; + + return -1; } -static unsigned to_retro_pad(unsigned channel) +static int get_slot_for_channel(unsigned channel) { - return channel+1; + int slot = pad_connection_find_vacant_pad(hid_instance.pad_list); + if(slot >= 0) + { + RARCH_LOG("[kpad]: got slot %d\n", slot); + channel_slot_map[channel] = slot; + hid_instance.pad_list[slot].connected = true; + } + + return slot; } static bool kpad_init(void *data) @@ -75,7 +89,7 @@ static bool kpad_init(void *data) static bool kpad_query_pad(unsigned pad) { - return ready && pad <= WIIU_WIIMOTE_CHANNELS && pad > PAD_GAMEPAD; + return ready && pad < MAX_USERS; } static void kpad_destroy(void) @@ -88,27 +102,34 @@ static bool kpad_button(unsigned pad, uint16_t button_bit) if (!kpad_query_pad(pad)) return false; - return wiimotes[to_wiimote_channel(pad)].button_state + int channel = to_wiimote_channel(pad); + if(channel < 0) + return false; + + return wiimotes[channel].button_state & (UINT64_C(1) << button_bit); } -static void kpad_get_buttons(unsigned pad, retro_bits_t *state) +static void kpad_get_buttons(unsigned pad, input_bits_t *state) { - if (!kpad_query_pad(pad)) + int channel = to_wiimote_channel(pad); + + if (!kpad_query_pad(pad) || channel < 0) BIT256_CLEAR_ALL_PTR(state); else - BITS_COPY16_PTR(state, wiimotes[to_wiimote_channel(pad)].button_state); + BITS_COPY16_PTR(state, wiimotes[channel].button_state); } static int16_t kpad_axis(unsigned pad, uint32_t axis) { + int channel = to_wiimote_channel(pad); axis_data data; - if (!kpad_query_pad(pad) || axis == AXIS_NONE) + if (!kpad_query_pad(pad) || channel < 0 || axis == AXIS_NONE) return 0; pad_functions.read_axis_data(axis, &data); return pad_functions.get_axis_value(data.axis, - wiimotes[to_wiimote_channel(pad)].analog_state, + wiimotes[channel].analog_state, data.is_negative); } @@ -116,8 +137,19 @@ static void kpad_register(unsigned channel, uint8_t device_type) { if (wiimotes[channel].type != device_type) { + int slot; + + kpad_deregister(channel); + slot = get_slot_for_channel(channel); + + if(slot < 0) + { + RARCH_ERR("Couldn't get a slot for this remote.\n"); + return; + } + wiimotes[channel].type = device_type; - pad_functions.connect(to_retro_pad(channel), &kpad_driver); + input_pad_connect(slot, &kpad_driver); } } @@ -161,6 +193,21 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad) } } +static void kpad_deregister(unsigned channel) +{ + int slot = channel_slot_map[channel]; + + if(slot >= 0) + { + input_autoconfigure_disconnect(slot, kpad_driver.name(slot)); + wiimotes[channel].type = WIIMOTE_TYPE_NONE; + hid_instance.pad_list[slot].connected = false; + channel_slot_map[channel] = -1; + } +} + +static int poll_failures[WIIU_WIIMOTE_CHANNELS] = { 0, 0, 0, 0 }; + static void kpad_poll(void) { unsigned channel; @@ -172,9 +219,16 @@ static void kpad_poll(void) memset(&kpad, 0, sizeof(kpad)); result = KPADRead(channel, &kpad, 1); + /* this is a hack to prevent spurious disconnects */ + /* TODO: use KPADSetConnectCallback and use callbacks to detect */ + /* pad disconnects properly. */ if (result == 0) { + poll_failures[channel]++; + if(poll_failures[channel] > 5) + kpad_deregister(channel); continue; } + poll_failures[channel] = 0; kpad_poll_one_channel(channel, &kpad); } @@ -182,11 +236,11 @@ static void kpad_poll(void) static const char *kpad_name(unsigned pad) { - pad = to_wiimote_channel(pad); - if (pad >= WIIU_WIIMOTE_CHANNELS) + int channel = to_wiimote_channel(pad); + if (channel < 0) return "unknown"; - switch(wiimotes[pad].type) + switch(wiimotes[channel].type) { case WIIMOTE_TYPE_PRO: return PAD_NAME_WIIU_PRO; diff --git a/wiiu/input/pad_functions.c b/wiiu/input/pad_functions.c index fe352e5da4..5aefbaf23c 100644 --- a/wiiu/input/pad_functions.c +++ b/wiiu/input/pad_functions.c @@ -14,7 +14,7 @@ * If not, see . */ -#include +#include "wiiu_input.h" enum wiiu_pad_axes { AXIS_LEFT_ANALOG_X, @@ -75,29 +75,8 @@ void wiiu_pad_set_axis_value(int16_t state[3][2], int16_t left_x, int16_t left_y state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y] = touch_y; } - -void wiiu_pad_read_axis_data(uint32_t axis, axis_data *data) -{ - data->axis = AXIS_POS_GET(axis); - data->is_negative = false; - - if(data->axis >= AXIS_INVALID) - { - data->axis = AXIS_NEG_GET(axis); - data->is_negative = true; - } -} - -void wiiu_pad_connect(unsigned pad, input_device_driver_t *driver) -{ - if(!input_autoconfigure_connect(driver->name(pad), NULL, driver->ident, - pad, VID_NONE, PID_NONE)) - input_config_set_device_name(pad, driver->name(pad)); -} - wiiu_pad_functions_t pad_functions = { wiiu_pad_get_axis_value, wiiu_pad_set_axis_value, - wiiu_pad_read_axis_data, - wiiu_pad_connect + gamepad_read_axis_data, }; diff --git a/wiiu/input/wiiu_hid.c b/wiiu/input/wiiu_hid.c index db0fcd074b..962e9323d8 100644 --- a/wiiu/input/wiiu_hid.c +++ b/wiiu/input/wiiu_hid.c @@ -15,64 +15,82 @@ */ #include "wiiu_hid.h" +#include static wiiu_event_list events; static wiiu_adapter_list adapters; +static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t error); + static bool wiiu_hid_joypad_query(void *data, unsigned slot) { wiiu_hid_t *hid = (wiiu_hid_t *)data; if (!hid) return false; - return slot < hid->connections_size; + return slot < HID_MAX_SLOT(); +} + +static joypad_connection_t *get_pad(wiiu_hid_t *hid, unsigned slot) +{ + if(!wiiu_hid_joypad_query(hid, slot)) + return NULL; + + joypad_connection_t *result = HID_PAD_CONNECTION_PTR(slot); + if(!result || !result->connected || !result->iface || !result->data) + return NULL; + + return result; } static const char *wiiu_hid_joypad_name(void *data, unsigned slot) { - if (!wiiu_hid_joypad_query(data, slot)) + joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); + + if(!pad) return NULL; - wiiu_hid_t *hid = (wiiu_hid_t *)data; - - return hid->connections[slot].iface->get_name(data); + return pad->iface->get_name(pad->data); } -static void wiiu_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_t *state) +static void wiiu_hid_joypad_get_buttons(void *data, unsigned slot, input_bits_t *state) { - (void)data; - (void)port; + joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); - BIT256_CLEAR_ALL_PTR(state); + if(pad) + pad->iface->get_buttons(pad->data, state); } -static bool wiiu_hid_joypad_button(void *data, unsigned port, uint16_t joykey) +static bool wiiu_hid_joypad_button(void *data, unsigned slot, uint16_t joykey) { - (void)data; - (void)port; - (void)joykey; + joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); - return false; + if(!pad) + return false; + + return pad->iface->button(pad->data, joykey); } -static bool wiiu_hid_joypad_rumble(void *data, unsigned pad, +static bool wiiu_hid_joypad_rumble(void *data, unsigned slot, enum retro_rumble_effect effect, uint16_t strength) { - (void)data; - (void)pad; - (void)effect; - (void)strength; + joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); + if(!pad) + return false; + + pad->iface->set_rumble(pad->data, effect, strength); return false; } -static int16_t wiiu_hid_joypad_axis(void *data, unsigned port, uint32_t joyaxis) +static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis) { - (void)data; - (void)port; - (void)joyaxis; + joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); - return 0; + if(!pad) + return 0; + + return pad->iface->get_axis(pad->data, joyaxis); } static void *wiiu_hid_init(void) @@ -89,7 +107,6 @@ static void *wiiu_hid_init(void) if (!hid->polling_thread) goto error; - RARCH_LOG("[hid]: Registering HIDClient\n"); HIDAddClient(client, wiiu_attach_callback); hid->client = client; @@ -98,6 +115,7 @@ static void *wiiu_hid_init(void) error: RARCH_LOG("[hid]: initialization failed. cleaning up.\n"); + stop_polling_thread(hid); delete_hid(hid); delete_hidclient(client); @@ -129,7 +147,11 @@ static void wiiu_hid_free(const void *data) static void wiiu_hid_poll(void *data) { - (void)data; + wiiu_hid_t *hid = (wiiu_hid_t *)data; + if(hid == NULL) + return; + + synchronized_process_adapters(hid); } static void wiiu_hid_send_control(void *data, uint8_t *buf, size_t size) @@ -162,14 +184,17 @@ static int32_t wiiu_hid_set_report(void *data, uint8_t report_type, uint8_t report_id, void *report_data, uint32_t report_length) { wiiu_adapter_t *adapter = (wiiu_adapter_t *)data; - if (!adapter) + if (!adapter || report_length > adapter->tx_size) return -1; + memset(adapter->tx_buffer, 0, adapter->tx_size); + memcpy(adapter->tx_buffer, report_data, report_length); + return HIDSetReport(adapter->handle, report_type, report_id, - report_data, - report_length, + adapter->tx_buffer, + adapter->tx_size, NULL, NULL); } @@ -197,6 +222,25 @@ static int32_t wiiu_hid_set_protocol(void *data, uint8_t protocol) NULL, NULL); } +static int32_t wiiu_hid_read(void *data, void *buffer, size_t size) +{ + wiiu_adapter_t *adapter = (wiiu_adapter_t *)data; + int32_t result; + + if(!adapter) + return -1; + + if(size > adapter->rx_size) + return -1; + + result = HIDRead(adapter->handle, buffer, size, NULL, NULL); + if(result < 0) + report_hid_error("read failed", adapter, result); + + return result; +} + + static void start_polling_thread(wiiu_hid_t *hid) { OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2; @@ -285,23 +329,88 @@ static void log_device(HIDDevice *device) } +static uint8_t try_init_driver(wiiu_adapter_t *adapter) +{ + adapter->driver_handle = adapter->driver->init(adapter); + if(adapter->driver_handle == NULL) { + RARCH_ERR("[hid]: Failed to initialize driver: %s\n", + adapter->driver->name); + return ADAPTER_STATE_DONE; + } + + return ADAPTER_STATE_READY; +} + +static void synchronized_process_adapters(wiiu_hid_t *hid) +{ + wiiu_adapter_t *adapter = NULL; + wiiu_adapter_t *prev = NULL, *adapter_next = NULL; + bool keep_prev = false; + + OSFastMutex_Lock(&(adapters.lock)); + for(adapter = adapters.list; adapter != NULL; adapter = adapter_next) + { + adapter_next = adapter->next; + + switch(adapter->state) + { + case ADAPTER_STATE_NEW: + adapter->state = try_init_driver(adapter); + break; + case ADAPTER_STATE_READY: + case ADAPTER_STATE_READING: + case ADAPTER_STATE_DONE: + break; + case ADAPTER_STATE_GC: + /* remove from the list */ + if(prev == NULL) + adapters.list = adapter->next; + else + prev->next = adapter->next; + + /* adapter is no longer valid after this point */ + delete_adapter(adapter); + /* signal not to update prev ptr since adapter is now invalid */ + keep_prev = true; + break; + default: + RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state); + break; + } + prev = keep_prev ? prev : adapter; + keep_prev = false; + } + OSFastMutex_Unlock(&(adapters.lock)); +} + static void synchronized_add_event(wiiu_attach_event *event) { - OSFastMutex_Lock(&(events.lock)); - event->next = events.list; - events.list = event; - OSFastMutex_Unlock(&(events.lock)); + wiiu_attach_event *head = (wiiu_attach_event *)SwapAtomic32((uint32_t *)&events.list, 0); + + event->next = head; + head = event; + + SwapAtomic32((uint32_t *)&events.list, (uint32_t)head); } static wiiu_attach_event *synchronized_get_events_list(void) { - wiiu_attach_event *list; - OSFastMutex_Lock(&(events.lock)); - list = events.list; - events.list = NULL; - OSFastMutex_Unlock(&(events.lock)); + return (wiiu_attach_event *)SwapAtomic32((uint32_t *)&events.list, 0); +} - return list; +static wiiu_adapter_t *synchronized_lookup_adapter(uint32_t handle) +{ + OSFastMutex_Lock(&(adapters.lock)); + wiiu_adapter_t *iterator; + + for(iterator = adapters.list; iterator != NULL; iterator = iterator->next) + { + if(iterator->handle == handle) + break; + } + OSFastMutex_Unlock(&(adapters.lock)); + + return iterator; } static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter) @@ -317,25 +426,24 @@ static int32_t wiiu_attach_callback(HIDClient *client, { wiiu_attach_event *event = NULL; - log_device(device); - - switch(attach) - { - case HID_DEVICE_ATTACH: - case HID_DEVICE_DETACH: - if (device) - event = new_attach_event(device); - - if(!event) - goto error; - - event->type = attach; - synchronized_add_event(event); - return DEVICE_USED; - default: - break; + if(attach) { + RARCH_LOG("[hid]: Device attach event generated.\n"); + log_device(device); + } else { + RARCH_LOG("[hid]: Device detach event generated.\n"); } + if (device) + event = new_attach_event(device); + + if(!event) + goto error; + + event->type = attach; + synchronized_add_event(event); + + return DEVICE_USED; + error: delete_attach_event(event); return DEVICE_UNUSED; @@ -343,6 +451,13 @@ error: static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event) { + wiiu_adapter_t *adapter = synchronized_lookup_adapter(event->handle); + + /* this will signal the read loop to stop for this adapter + * the read loop method will update this to ADAPTER_STATE_GC + * so the adapter poll method can clean it up. */ + if(adapter) + adapter->connected = false; } @@ -357,127 +472,92 @@ static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event) } adapter->hid = hid; - adapter->slot = pad_connection_pad_init(hid->connections, - "hid", event->vendor_id, event->product_id, adapter, - &wiiu_hid); + adapter->driver = event->driver; + adapter->state = ADAPTER_STATE_NEW; - if(adapter->slot < 0) - { - RARCH_ERR("[hid]: No available slots.\n"); - goto error; - } - - RARCH_LOG("[hid]: got slot %d\n", adapter->slot); - - if(!pad_connection_has_interface(hid->connections, adapter->slot)) - { - RARCH_ERR("[hid]: Interface not found for HID device with vid=0x%04x pid=0x%04x\n", - event->vendor_id, event->product_id); - goto error; - } - - RARCH_LOG("[hid]: adding to adapter list\n"); synchronized_add_to_adapters_list(adapter); - RARCH_LOG("[hid]: starting read loop\n"); - wiiu_start_read_loop(adapter); - return; error: delete_adapter(adapter); } -void wiiu_start_read_loop(wiiu_adapter_t *adapter) -{ - adapter->state = ADAPTER_STATE_READING; -#if 0 - RARCH_LOG("HIDRead(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", - adapter->handle, adapter->rx_buffer, adapter->rx_size, - wiiu_hid_read_loop_callback, adapter); -#endif - HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size, wiiu_hid_read_loop_callback, adapter); -} - -/** - * Takes a buffer and formats it for the log file, 16 bytes per line. - * - * When the end of the buffer is reached, it is padded out with 0xff. So e.g. - * a 5-byte buffer might look like: - * - * 5 bytes read fro HIDRead: - * 0102030405ffffff ffffffffffffffff - * ================================== - */ -static void log_buffer(uint8_t *data, uint32_t len) -{ - int i, o; - int padding = len % 16; - uint8_t buf[16]; - - (uint8_t *)data; - (uint32_t)len; - - RARCH_LOG("%d bytes read from HIDRead:\n", len); - - for(i = 0, o = 0; i < len; i++) - { - buf[o] = data[i]; - o++; - if(o == 16) - { - o = 0; - RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); - } - } - - if(padding) - { - for(i = padding; i < 16; i++) - buf[i] = 0xff; - - RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); - } - RARCH_LOG("==================================\n"); - -} - -static void wiiu_hid_do_read(wiiu_adapter_t *adapter, - uint8_t *data, uint32_t length) -{ -#if 0 - log_buffer(data, length); -#endif - - /* TODO: get this data to the connect_xxx driver somehow. */ -} - static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error, uint8_t *buffer, uint32_t buffer_size, void *userdata) { - wiiu_adapter_t *adapter = (wiiu_adapter_t *)userdata; - if(!adapter) - { - RARCH_ERR("read_loop_callback: bad userdata\n"); - return; - } + wiiu_adapter_t *adapter = (wiiu_adapter_t *)userdata; + if(!adapter) + { + RARCH_ERR("read_loop_callback: bad userdata\n"); + return; + } - if(adapter->hid->polling_thread_quit) - { - RARCH_LOG("Shutting down read loop for slot %d\n", adapter->slot); - adapter->state = ADAPTER_STATE_DONE; - return; - } + if(error < 0) + { + report_hid_error("async read failed", adapter, error); + } - wiiu_hid_do_read(adapter, buffer, buffer_size); + if(adapter->state == ADAPTER_STATE_READING) { + adapter->state = ADAPTER_STATE_READY; - adapter->state = ADAPTER_STATE_READING; - HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size, - wiiu_hid_read_loop_callback, adapter); + if(error == 0) { + adapter->driver->handle_packet(adapter->driver_handle, + buffer, buffer_size); + } + } +} + +static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t error) +{ + if(error >= 0) + return; + + int16_t hid_error_code = error & 0xffff; + int16_t error_category = (error >> 16) & 0xffff; + const char *device = (adapter && adapter->driver) ? adapter->driver->name : "unknown"; + + switch(hid_error_code) + { + case -100: + RARCH_ERR("[hid]: Invalid RM command (%s)\n", device); + break; + case -102: + RARCH_ERR("[hid]: Invalid IOCTL command (%s)\n", device); + break; + case -103: + RARCH_ERR("[hid]: bad vector count (%s)\n", device); + break; + case -104: + RARCH_ERR("[hid]: invalid memory bank (%s)\n", device); + break; + case -105: + RARCH_ERR("[hid]: invalid memory alignment (%s)\n", device); + break; + case -106: + RARCH_ERR("[hid]: invalid data size (%s)\n", device); + break; + case -107: + RARCH_ERR("[hid]: request cancelled (%s)\n", device); + break; + case -108: + RARCH_ERR("[hid]: request timed out (%s)\n", device); + break; + case -109: + RARCH_ERR("[hid]: request aborted (%s)\n", device); + break; + case -110: + RARCH_ERR("[hid]: client priority error (%s)\n", device); + break; + case -111: + RARCH_ERR("[hid]: invalid device handle (%s)\n", device); + break; +#if 0 + default: + RARCH_ERR("[hid]: Unknown error (%d:%d: %s)\n", + error_category, hid_error_code, device); +#endif + } } /** @@ -491,27 +571,29 @@ static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack) RARCH_LOG("Waiting for in-flight reads to finish.\n"); + /* We don't need to protect the adapter list here because nothing else + will access it during this method (the HID system is shut down, and + the only other access is the polling thread that just stopped */ do { - OSFastMutex_Lock(&(adapters.lock)); incomplete = 0; for(adapter = adapters.list; adapter != NULL; adapter = adapter->next) { if(adapter->state == ADAPTER_STATE_READING) incomplete++; } - /* We are clear for shutdown. Clean up the list - * while we are holding the lock. */ + if(incomplete == 0) { + RARCH_LOG("All in-flight reads complete.\n"); while(adapters.list != NULL) { + RARCH_LOG("[hid]: shutting down adapter..\n"); adapter = adapters.list; adapters.list = adapter->next; delete_adapter(adapter); } } - OSFastMutex_Unlock(&(adapters.lock)); if(incomplete) usleep(5000); @@ -521,9 +603,7 @@ static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack) RARCH_WARN("[hid]: timed out waiting for in-flight read to finish.\n"); incomplete = 0; } - }while(incomplete); - - RARCH_LOG("All in-flight reads complete.\n"); + } while(incomplete); } static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list) @@ -544,20 +624,45 @@ static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list) } } +static void wiiu_poll_adapter(wiiu_adapter_t *adapter) +{ + if(!adapter->connected) { + adapter->state = ADAPTER_STATE_DONE; + return; + } + + adapter->state = ADAPTER_STATE_READING; + HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size, + wiiu_hid_read_loop_callback, adapter); +} + +static void wiiu_poll_adapters(wiiu_hid_t *hid) +{ + wiiu_adapter_t *it; + OSFastMutex_Lock(&(adapters.lock)); + + for(it = adapters.list; it != NULL; it = it->next) + { + if(it->state == ADAPTER_STATE_READY) + wiiu_poll_adapter(it); + + if(it->state == ADAPTER_STATE_DONE) + it->state = ADAPTER_STATE_GC; + } + + OSFastMutex_Unlock(&(adapters.lock)); +} + static int wiiu_hid_polling_thread(int argc, const char **argv) { wiiu_hid_t *hid = (wiiu_hid_t *)argv; - int i = 0; RARCH_LOG("[hid]: polling thread is starting\n"); while(!hid->polling_thread_quit) { wiiu_handle_attach_events(hid, synchronized_get_events_list()); - usleep(10000); - i += 10000; - if(i >= (1000 * 1000 * 3)) - i = 0; + wiiu_poll_adapters(hid); } RARCH_LOG("[hid]: polling thread is stopping\n"); @@ -612,6 +717,13 @@ static void delete_hidclient(HIDClient *client) free(client); } +static void init_cachealigned_buffer(int32_t min_size, uint8_t **out_buf_ptr, int32_t *actual_size) +{ + *actual_size = (min_size + 0x3f) & ~0x3f; + + *out_buf_ptr = alloc_zeroed(64, *actual_size); +} + static wiiu_adapter_t *new_adapter(wiiu_attach_event *event) { wiiu_adapter_t *adapter = alloc_zeroed(32, sizeof(wiiu_adapter_t)); @@ -621,10 +733,9 @@ static wiiu_adapter_t *new_adapter(wiiu_attach_event *event) adapter->handle = event->handle; adapter->interface_index = event->interface_index; - adapter->rx_size = event->max_packet_size_rx; - adapter->rx_buffer = alloc_zeroed(32, adapter->rx_size); - adapter->tx_size = event->max_packet_size_tx; - adapter->tx_buffer = alloc_zeroed(32, adapter->tx_size); + init_cachealigned_buffer(event->max_packet_size_rx, &adapter->rx_buffer, &adapter->rx_size); + init_cachealigned_buffer(event->max_packet_size_tx, &adapter->tx_buffer, &adapter->tx_size); + adapter->connected = true; return adapter; } @@ -644,15 +755,29 @@ static void delete_adapter(wiiu_adapter_t *adapter) free(adapter->tx_buffer); adapter->tx_buffer = NULL; } + if(adapter->driver && adapter->driver_handle) { + adapter->driver->free(adapter->driver_handle); + adapter->driver_handle = NULL; + adapter->driver = NULL; + } + free(adapter); } static wiiu_attach_event *new_attach_event(HIDDevice *device) { + hid_device_t *driver = hid_device_driver_lookup(device->vid, device->pid); + if(!driver) + { + RARCH_ERR("[hid]: Failed to locate driver for device vid=%04x pid=%04x\n", + device->vid, device->pid); + return NULL; + } wiiu_attach_event *event = alloc_zeroed(4, sizeof(wiiu_attach_event)); if(!event) return NULL; + event->driver = driver; event->handle = device->handle; event->vendor_id = device->vid; event->product_id = device->pid; @@ -698,6 +823,7 @@ hid_driver_t wiiu_hid = { wiiu_hid_send_control, wiiu_hid_set_report, wiiu_hid_set_idle, - wiiu_hid_set_protocol + wiiu_hid_set_protocol, + wiiu_hid_read, }; diff --git a/wiiu/input/wiiu_hid.h b/wiiu/input/wiiu_hid.h index 1c2ede6f73..0c96c9599c 100644 --- a/wiiu/input/wiiu_hid.h +++ b/wiiu/input/wiiu_hid.h @@ -17,14 +17,89 @@ #ifndef __WIIU_HID__H #define __WIIU_HID__H -#include +#include "wiiu_hid_types.h" + +#include "wiiu_input.h" #define DEVICE_UNUSED 0 #define DEVICE_USED 1 +/* Adapter has been detected and needs to be initialized */ #define ADAPTER_STATE_NEW 0 -#define ADAPTER_STATE_READING 1 -#define ADAPTER_STATE_DONE 2 +/* Adapter has been initialized successfully */ +#define ADAPTER_STATE_READY 1 +/* The read loop has been started */ +#define ADAPTER_STATE_READING 2 +/* The read loop is shutting down */ +#define ADAPTER_STATE_DONE 3 +/* The read loop has fully stopped and the adapter can be freed */ +#define ADAPTER_STATE_GC 4 + +struct wiiu_hid { + /* used to register for HID notifications */ + HIDClient *client; + /* thread state data for the HID input polling thread */ + OSThread *polling_thread; + /* stack space for polling thread */ + void *polling_thread_stack; + /* watch variable for telling the polling thread to terminate */ + volatile bool polling_thread_quit; +}; + +/** + * Each HID device attached to the WiiU gets its own adapter, which + * connects the HID subsystem with the HID device driver. + */ +struct wiiu_adapter { + wiiu_adapter_t *next; + hid_device_t *driver; + void *driver_handle; + wiiu_hid_t *hid; + uint8_t state; + uint8_t *rx_buffer; + int32_t rx_size; + uint8_t *tx_buffer; + int32_t tx_size; + uint32_t handle; + uint8_t interface_index; + bool connected; +}; + +/** + * When a HID device is connected, the OS generates an attach + * event; the attach event handler translate them into these + * structures. + */ +struct wiiu_attach { + wiiu_attach_event *next; + hid_device_t *driver; + uint32_t type; + uint32_t handle; + uint16_t vendor_id; + uint16_t product_id; + uint8_t interface_index; + uint8_t is_keyboard; + uint8_t is_mouse; + uint16_t max_packet_size_rx; + uint16_t max_packet_size_tx; +}; + +struct _wiiu_event_list { + OSFastMutex lock; + wiiu_attach_event *list; +}; + +struct _wiiu_adapter_list { + OSFastMutex lock; + wiiu_adapter_t *list; +}; + +extern wiiu_pad_functions_t pad_functions; +extern input_device_driver_t wiiu_joypad; +extern input_device_driver_t wpad_driver; +extern input_device_driver_t kpad_driver; +extern input_device_driver_t hidpad_driver; +extern hid_driver_t wiiu_hid; static void *alloc_zeroed(size_t alignment, size_t size); static OSThread *new_thread(void); @@ -46,7 +121,9 @@ static wiiu_attach_event *synchronized_get_events_list(void); static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list); static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event); static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event); +static void synchronized_process_adapters(wiiu_hid_t *hid); static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter); +static wiiu_adapter_t *synchronized_remove_from_adapters_list(uint32_t handle); static void synchronized_add_event(wiiu_attach_event *event); static void wiiu_start_read_loop(wiiu_adapter_t *adapter); static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error, diff --git a/wiiu/input/wiiu_hid_types.h b/wiiu/input/wiiu_hid_types.h new file mode 100644 index 0000000000..b73fcf3a6d --- /dev/null +++ b/wiiu/input/wiiu_hid_types.h @@ -0,0 +1,27 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef __WIIU_HID_TYPES__H +#define __WIIU_HID_TYPES__H + +typedef struct wiiu_hid wiiu_hid_t; +typedef struct wiiu_adapter wiiu_adapter_t; +typedef struct wiiu_attach wiiu_attach_event; +typedef struct _wiiu_event_list wiiu_event_list; +typedef struct _wiiu_adapter_list wiiu_adapter_list; +typedef struct _wiiu_pad_functions wiiu_pad_functions_t; + +#endif /* __WIIU_HID_TYPES__H */ diff --git a/wiiu/input/wiiu_input.h b/wiiu/input/wiiu_input.h new file mode 100644 index 0000000000..37416bc7e6 --- /dev/null +++ b/wiiu/input/wiiu_input.h @@ -0,0 +1,68 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef __WIIU_INPUT__H +#define __WIIU_INPUT__H + +#include "wiiu_hid_types.h" +#include "../../input/include/gamepad.h" + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../input/input_driver.h" +#include "../../input/common/hid/hid_device_driver.h" +#include "../../tasks/tasks_internal.h" +#include "../../input/connect/joypad_connection.h" +#include "../../retroarch.h" +#include "../../verbosity.h" +#include "../../command.h" +#include "../../gfx/video_driver.h" +#include "wiiu_hid.h" + +#define WIIMOTE_TYPE_WIIPLUS 0x00 +#define WIIMOTE_TYPE_NUNCHUK 0x01 +#define WIIMOTE_TYPE_CLASSIC 0x02 +#define WIIMOTE_TYPE_PRO 0x1f +#define WIIMOTE_TYPE_NONE 0xfd + +#define WIIU_DEVICE_INDEX_TOUCHPAD 2 + +#define PAD_GAMEPAD 0 +#define WIIU_WIIMOTE_CHANNELS 4 + +#define WIIU_ANALOG_FACTOR 0x7ff0 +#define WIIU_READ_STICK(stick) ((stick) * WIIU_ANALOG_FACTOR) + +struct _wiiu_pad_functions { + int16_t (*get_axis_value)(int32_t axis, int16_t state[3][2], bool is_negative); + void (*set_axis_value)(int16_t state[3][2], int16_t left_x, int16_t left_y, + int16_t right_x, int16_t right_y, int16_t touch_x, int16_t touch_y); + void (*read_axis_data)(uint32_t axis, axis_data *data); + void (*connect)(unsigned pad, input_device_driver_t *driver); +}; + +#endif /* __WIIU_INPUT__H */ diff --git a/wiiu/input/wpad_driver.c b/wiiu/input/wpad_driver.c index b707c63cb5..4933a2dc3e 100644 --- a/wiiu/input/wpad_driver.c +++ b/wiiu/input/wpad_driver.c @@ -21,7 +21,9 @@ * - For HID controllers, see hid_driver.c */ -#include +#include "wiiu_input.h" + +#define PANIC_BUTTON_MASK (VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_STICK_R | VPAD_BUTTON_STICK_L) static bool ready = false; static uint64_t button_state = 0; @@ -184,7 +186,12 @@ static void wpad_poll(void) static bool wpad_init(void *data) { - pad_functions.connect(PAD_GAMEPAD, &wpad_driver); + int slot = pad_connection_find_vacant_pad(hid_instance.pad_list); + if(slot < 0) + return false; + + hid_instance.pad_list[slot].connected = true; + input_pad_connect(slot, &wpad_driver); wpad_poll(); ready = true; @@ -193,7 +200,7 @@ static bool wpad_init(void *data) static bool wpad_query_pad(unsigned pad) { - return ready && pad == PAD_GAMEPAD; + return ready && pad < MAX_USERS; } static void wpad_destroy(void) @@ -209,7 +216,7 @@ static bool wpad_button(unsigned pad, uint16_t button_bit) return button_state & (UINT64_C(1) << button_bit); } -static void wpad_get_buttons(unsigned pad, retro_bits_t *state) +static void wpad_get_buttons(unsigned pad, input_bits_t *state) { if (!wpad_query_pad(pad)) BIT256_CLEAR_ALL_PTR(state); diff --git a/wiiu/system/atomic.c b/wiiu/system/atomic.c new file mode 100644 index 0000000000..ec16f75876 --- /dev/null +++ b/wiiu/system/atomic.c @@ -0,0 +1,36 @@ +/* devkitPPC is missing a few functions that are kinda needed for some cores. + * This should add them back in. + */ + +#include + +/** + * Performs an atomic swap of a single piece of data. In each function, + * value is written to ptr, and the previous value is returned. + * + * From GCC docs: + * + * "This builtin is not a full barrier, but rather a *release* barrier. This + * means that references after the builtin cannot move to (or be speculated + * to) before the builtin, but previous memory stores may not be globally + * visible yet, and previous memory loads may not yet be satisfied." + * + * https://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Atomic-Builtins.html + * + * This builtin seems to be implemented in the Wii U GCC toolchain. But since + * this is GCC-specific, I'm not going to put it into a more general-use + * location. + */ +uint8_t SwapAtomic8(uint8_t *ptr, uint8_t value) +{ + return __sync_lock_test_and_set(ptr, value); +} +uint16_t SwapAtomic16(uint16_t *ptr, uint16_t value) +{ + return __sync_lock_test_and_set(ptr, value); +} +uint32_t SwapAtomic32(uint32_t *ptr, uint32_t value) +{ + return __sync_lock_test_and_set(ptr, value); +} + diff --git a/wiiu/system/exception_handler.c b/wiiu/system/exception_handler.c index d6138fac00..2caa0779c7 100644 --- a/wiiu/system/exception_handler.c +++ b/wiiu/system/exception_handler.c @@ -22,6 +22,8 @@ #include #include "wiiu_dbg.h" #include "exception_handler.h" +#include "version.h" +#include "version_git.h" /* Settings */ #define NUM_STACK_TRACE_LINES 5 @@ -182,6 +184,11 @@ void __attribute__((__noreturn__)) exception_cb(OSContext* ctx, OSExceptionType else buf_add("Stack pointer invalid. Could not trace further.\n"); +#ifdef HAVE_GIT_VERSION + buf_add("RetroArch " PACKAGE_VERSION " (%s) built " __DATE__, retroarch_git_version); +#else + buf_add("RetroArch " PACKAGE_VERSION " built " __DATE__); +#endif OSFatal(exception_msgbuf); for (;;) {} }