diff --git a/.gitignore b/.gitignore index 0fe81b9..8127ff0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ sdl/gen_sdl2 sdl/build_sdl sdl/build_sdl2 +/libretro/msvc/msvc-2017/msvc-2017.vcxproj.user diff --git a/Makefile.libretro b/Makefile.libretro index 312024b..bd91682 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -6,6 +6,15 @@ HAVE_SYS_PARAM = 1 CORE_DIR := . +SPACE := +SPACE := $(SPACE) $(SPACE) +BACKSLASH := +BACKSLASH := \$(BACKSLASH) +filter_out1 = $(filter-out $(firstword $1),$1) +filter_out2 = $(call filter_out1,$(call filter_out1,$1)) +unixpath = $(subst \,/,$1) +unixcygpath = /$(subst :,,$(call unixpath,$1)) + # system platform ifeq ($(platform),) platform = unix @@ -223,6 +232,14 @@ else ifneq (,$(filter $(platform), ngc wii wiiu)) PLATFORM_DEFINES += -DHW_DOL -mrvl endif +# Nintendo Switch (libtransistor) +else ifeq ($(platform), switch) + TARGET := $(TARGET_NAME)_libretro_$(platform).a + include $(LIBTRANSISTOR_HOME)/libtransistor.mk + CFLAGS += -fomit-frame-pointer -ffast-math + STATIC_LINKING=1 + STATIC_LINKING_LINK=1 + # emscripten else ifeq ($(platform), emscripten) TARGET := $(TARGET_NAME)_libretro_$(platform).bc @@ -243,13 +260,14 @@ else ifeq ($(platform), gcw0) # Windows MSVC 2003 Xbox 1 else ifeq ($(platform), xbox1_msvc2003) TARGET := $(TARGET_NAME)_libretro_xdk1.lib -MSVCBINDIRPREFIX = $(XDK)/xbox/bin/vc71 -CC = "$(MSVCBINDIRPREFIX)/CL.exe" -CXX = "$(MSVCBINDIRPREFIX)/CL.exe" -LD = "$(MSVCBINDIRPREFIX)/lib.exe" +CC = CL.exe +CXX = CL.exe +LD = lib.exe export INCLUDE := $(XDK)/xbox/include export LIB := $(XDK)/xbox/lib +PATH := $(call unixcygpath,$(XDK)/xbox/bin/vc71):$(PATH) + ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN PSS_STYLE :=2 CFLAGS += -D_XBOX -D_XBOX1 @@ -282,23 +300,115 @@ HAVE_SYS_PARAM = 0 PATH := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin/amd64"):$(PATH) PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../IDE") -LIB := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/lib/amd64") -INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/include") +LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS100COMNTOOLS)../../VC/lib/amd64") +INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VS100COMNTOOLS)../../VC/include") -WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib/x64 -WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib/x64 - -WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include -WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include +WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*') +WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*') +WindowsSdkDirInc := $(WindowsSdkDir)Include +WindowsSdkDirInc ?= $(WindowsSdkDir)Include INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)" export INCLUDE := $(INCLUDE) -export LIB := $(LIB);$(WindowsSdkDir) +export LIB := $(LIB);$(WindowsSdkDir)\Lib\x64 TARGET := $(TARGET_NAME)_libretro.dll PSS_STYLE :=2 LDFLAGS += -DLL LIBS = + +# Windows MSVC 2017 all architectures +else ifneq (,$(findstring windows_msvc2017,$(platform))) + + PlatformSuffix = $(subst windows_msvc2017_,,$(platform)) + ifneq (,$(findstring desktop,$(PlatformSuffix))) + WinPartition = desktop + MSVC2017CompileFlags = -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -FS + LDFLAGS += -MANIFEST -LTCG:incremental -NXCOMPAT -DYNAMICBASE -DEBUG -OPT:REF -INCREMENTAL:NO -SUBSYSTEM:WINDOWS -MANIFESTUAC:"level='asInvoker' uiAccess='false'" -OPT:ICF -ERRORREPORT:PROMPT -NOLOGO -TLBID:1 + LIBS := kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib + else ifneq (,$(findstring uwp,$(PlatformSuffix))) + WinPartition = uwp + MSVC2017CompileFlags = -DWINAPI_FAMILY=WINAPI_FAMILY_APP -D_WINDLL -D_UNICODE -DUNICODE -D__WRL_NO_DEFAULT_LIB__ -EHsc -FS + LDFLAGS += -APPCONTAINER -NXCOMPAT -DYNAMICBASE -MANIFEST:NO -LTCG -OPT:REF -SUBSYSTEM:CONSOLE -MANIFESTUAC:NO -OPT:ICF -ERRORREPORT:PROMPT -NOLOGO -TLBID:1 -DEBUG:FULL -WINMD:NO + LIBS := WindowsApp.lib + endif + + CFLAGS += $(MSVC2017CompileFlags) + CXXFLAGS += $(MSVC2017CompileFlags) + + TargetArchMoniker = $(subst $(WinPartition)_,,$(PlatformSuffix)) + + CC = cl.exe + CXX = cl.exe + LD = link.exe + + HAVE_SYS_PARAM = 0 + + reg_query = $(call filter_out2,$(subst $2,,$(shell reg query "$2" -v "$1" 2>nul))) + fix_path = $(subst $(SPACE),\ ,$(subst \,/,$1)) + + ProgramFiles86w := $(shell cmd /c "echo %PROGRAMFILES(x86)%") + ProgramFiles86 := $(shell cygpath "$(ProgramFiles86w)") + + WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0) + WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0) + WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0) + WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0) + WindowsSdkDir := $(WindowsSdkDir) + + WindowsSDKVersion ?= $(firstword $(foreach folder,$(subst $(subst \,/,$(WindowsSdkDir)Include/),,$(wildcard $(call fix_path,$(WindowsSdkDir)Include\*))),$(if $(wildcard $(call fix_path,$(WindowsSdkDir)Include/$(folder)/um/Windows.h)),$(folder),)))$(BACKSLASH) + WindowsSDKVersion := $(WindowsSDKVersion) + + VsInstallBuildTools = $(ProgramFiles86)/Microsoft Visual Studio/2017/BuildTools + VsInstallEnterprise = $(ProgramFiles86)/Microsoft Visual Studio/2017/Enterprise + VsInstallProfessional = $(ProgramFiles86)/Microsoft Visual Studio/2017/Professional + VsInstallCommunity = $(ProgramFiles86)/Microsoft Visual Studio/2017/Community + + VsInstallRoot ?= $(shell if [ -d "$(VsInstallBuildTools)" ]; then echo "$(VsInstallBuildTools)"; fi) + ifeq ($(VsInstallRoot), ) + VsInstallRoot = $(shell if [ -d "$(VsInstallEnterprise)" ]; then echo "$(VsInstallEnterprise)"; fi) + endif + ifeq ($(VsInstallRoot), ) + VsInstallRoot = $(shell if [ -d "$(VsInstallProfessional)" ]; then echo "$(VsInstallProfessional)"; fi) + endif + ifeq ($(VsInstallRoot), ) + VsInstallRoot = $(shell if [ -d "$(VsInstallCommunity)" ]; then echo "$(VsInstallCommunity)"; fi) + endif + VsInstallRoot := $(VsInstallRoot) + + VcCompilerToolsVer := $(shell cat "$(VsInstallRoot)/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt" | grep -o '[0-9\.]*') + VcCompilerToolsDir := $(VsInstallRoot)/VC/Tools/MSVC/$(VcCompilerToolsVer) + + WindowsSDKSharedIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\shared") + WindowsSDKUCRTIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\ucrt") + WindowsSDKUMIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\um") + WindowsSDKUCRTLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib\$(WindowsSDKVersion)\ucrt\$(TargetArchMoniker)") + WindowsSDKUMLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib\$(WindowsSDKVersion)\um\$(TargetArchMoniker)") + + # For some reason the HostX86 compiler doesn't like compiling for x64 + # ("no such file" opening a shared library), and vice-versa. + # Work around it for now by using the strictly x86 compiler for x86, and x64 for x64. + # NOTE: What about ARM? + ifneq (,$(findstring x64,$(TargetArchMoniker))) + VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX64 + else + VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX86 + endif + + PATH := $(shell IFS=$$'\n'; cygpath "$(VCCompilerToolsBinDir)/$(TargetArchMoniker)"):$(PATH) + PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VsInstallRoot)/Common7/IDE") + INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/include") + LIB := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/lib/$(TargetArchMoniker)") + ifneq (,$(findstring uwp,$(PlatformSuffix))) + LIB := $(shell IFS=$$'\n'; cygpath -w "$(LIB)/store") + endif + + export INCLUDE := $(INCLUDE);$(WindowsSDKSharedIncludeDir);$(WindowsSDKUCRTIncludeDir);$(WindowsSDKUMIncludeDir) + export LIB := $(LIB);$(WindowsSDKUCRTLibDir);$(WindowsSDKUMLibDir) + TARGET := $(TARGET_NAME)_libretro.dll + PSS_STYLE :=2 + LDFLAGS += -DLL + # Windows MSVC 2010 x86 else ifeq ($(platform), windows_msvc2010_x86) CC = cl.exe @@ -309,18 +419,17 @@ else ifeq ($(platform), windows_msvc2010_x86) PATH := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin"):$(PATH) PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../IDE") LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS100COMNTOOLS)../../VC/lib") -INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/include") - -WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib -WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib - -WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include -WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include +INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VS100COMNTOOLS)../../VC/include") +WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*') +WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*') + +WindowsSdkDirInc := $(WindowsSdkDir)Include +WindowsSdkDirInc ?= $(WindowsSdkDir)Include INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)" export INCLUDE := $(INCLUDE) -export LIB := $(LIB);$(WindowsSdkDir) +export LIB := $(LIB);$(WindowsSdkDir)\Lib TARGET := $(TARGET_NAME)_libretro.dll PSS_STYLE :=2 LDFLAGS += -DLL @@ -347,6 +456,29 @@ PSS_STYLE :=2 LDFLAGS += -DLL CFLAGS += -D_CRT_SECURE_NO_DEPRECATE LIBS = + +# Windows MSVC 2003 x86 +else ifeq ($(platform), windows_msvc2003_x86) + CC = cl.exe + CXX = cl.exe + +PATH := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin"):$(PATH) +PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../IDE") +INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/include") +LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS71COMNTOOLS)../../Vc7/lib") +BIN := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin") + +WindowsSdkDir := $(INETSDK) + +export INCLUDE := $(INCLUDE);$(INETSDK)/Include;src/drivers/libretro/msvc/msvc-2005 +export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib +TARGET := $(TARGET_NAME)_libretro.dll +PSS_STYLE :=2 +LDFLAGS += -DLL +HAVE_SYS_PARAM = 0 +CFLAGS += -D_CRT_SECURE_NO_DEPRECATE + LIBS = + # Windows else TARGET := $(TARGET_NAME)_libretro.dll @@ -494,3 +626,6 @@ clean: .PHONY: clean clean-objs endif + +print-%: + @echo '$*=$($*)' diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..e7741cc --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,31 @@ +version: 0.1.{build} + +image: Visual Studio 2017 + +environment: + matrix: + - generator: "Visual Studio 15" + config: Release + platform: x86 + arch: win32 + output: win32\genesis_plus_gx_libretro.dll + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + + - generator: "Visual Studio 15" + config: Release + platform: x64 + arch: win32-x64 + output: win32\genesis_plus_gx_libretro.dll + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + +init: + - git config --global core.autocrlf input + +before_build: + - git submodule update --init --recursive + +build_script: + - msbuild libretro\msvc\msvc-2017.sln /t:build /p:Configuration="%config%";Platform="%platform%" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + +artifacts: + - path: 'libretro\**\*.dll' diff --git a/libretro/Makefile.common b/libretro/Makefile.common index caa76b0..232e04c 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -56,7 +56,11 @@ SOURCES_C += $(foreach dir,$(GENPLUS_SRC_DIR),$(wildcard $(dir)/*.c)) ifneq ($(STATIC_LINKING), 1) SOURCES_C += \ $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ - $(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c + $(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \ + $(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c SOURCES_C += $(CHDLIBDIR)/deps/zlib/adler32.c \ $(CHDLIBDIR)/deps/zlib/inffast.c \ diff --git a/libretro/jni/Android.mk b/libretro/jni/Android.mk index 72fb2f6..200f4bb 100644 --- a/libretro/jni/Android.mk +++ b/libretro/jni/Android.mk @@ -1,40 +1,29 @@ LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -GIT_VERSION ?= " $(shell git rev-parse --short HEAD || echo unknown)" -ifneq ($(GIT_VERSION)," unknown") - LOCAL_CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" -endif +CORE_DIR := $(LOCAL_PATH)/../.. +TREMOR_SRC_DIR := $(CORE_DIR)/core/tremor +SOURCES_C := WANT_CRC32 := 1 -HAVE_CHD := 1 +HAVE_CHD := 1 -CORE_DIR := ../.. +include $(CORE_DIR)/libretro/Makefile.common -TREMOR_SRC_DIR := $(CORE_DIR)/core/tremor -LIBRETRO_DIR := .. - -LOCAL_MODULE := retro +COREFLAGS := -ffast-math -funroll-loops -DINLINE="static inline" -DUSE_LIBTREMOR -DUSE_16BPP_RENDERING -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN -D__LIBRETRO__ -DFRONTEND_SUPPORTS_RGB565 -DALIGN_LONG -DALIGN_WORD -DM68K_OVERCLOCK_SHIFT=20 -DZ80_OVERCLOCK_SHIFT=20 -DUSE_LIBCHDR -DPACKAGE_VERSION=\"1.3.2\" -DFLAC_API_EXPORTS -DFLAC__HAS_OGG=0 -DHAVE_LROUND -DHAVE_STDINT_H -D_7ZIP_ST -DHAVE_SYS_PARAM_H $(INCFLAGS) ifeq ($(TARGET_ARCH),arm) -LOCAL_CFLAGS += -DANDROID_ARM -D_ARM_ASSEM_ -LOCAL_ARM_MODE := arm + COREFLAGS += -D_ARM_ASSEM_ endif -include $(LIBRETRO_DIR)/Makefile.common +GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" +ifneq ($(GIT_VERSION)," unknown") + COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" +endif +include $(CLEAR_VARS) +LOCAL_MODULE := retro LOCAL_SRC_FILES := $(SOURCES_C) - -LOCAL_C_INCLUDES = $(foreach dir,$(GENPLUS_SRC_DIR),$(LOCAL_PATH)/$(dir)) \ - $(CORE_DIR)/libretro/libretro-common/include \ - $(LOCAL_PATH)/$(TREMOR_SRC_DIR) \ - $(LOCAL_PATH)/$(LIBRETRO_DIR) \ - $(CHDLIBDIR)/src \ - $(CHDLIBDIR)/deps/libFLAC/include \ - $(CHDLIBDIR)/deps/lzma \ - $(CHDLIBDIR)/deps/zlib - -LOCAL_CFLAGS += -ffast-math -O2 -funroll-loops -DINLINE="static inline" -DUSE_LIBTREMOR -DUSE_16BPP_RENDERING -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN -D__LIBRETRO__ -DFRONTEND_SUPPORTS_RGB565 -DALIGN_LONG -DALIGN_WORD -DM68K_OVERCLOCK_SHIFT=20 -DZ80_OVERCLOCK_SHIFT=20 -DUSE_LIBCHDR -DPACKAGE_VERSION=\"1.3.2\" -DFLAC_API_EXPORTS -DFLAC__HAS_OGG=0 -DHAVE_LROUND -DHAVE_STDINT_H -D_7ZIP_ST -DHAVE_SYS_PARAM_H - +LOCAL_CFLAGS := $(COREFLAGS) +LOCAL_LDFLAGS := -Wl,-version-script=$(LIBRETRO_DIR)/link.T +LOCAL_ARM_MODE := arm include $(BUILD_SHARED_LIBRARY) diff --git a/libretro/libretro-common/compat/compat_strl.c b/libretro/libretro-common/compat/compat_strl.c new file mode 100644 index 0000000..94cb39b --- /dev/null +++ b/libretro/libretro-common/compat/compat_strl.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (compat_strl.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 + +/* Implementation of strlcpy()/strlcat() based on OpenBSD. */ + +#ifndef __MACH__ + +size_t strlcpy(char *dest, const char *source, size_t size) +{ + size_t src_size = 0; + size_t n = size; + + if (n) + while (--n && (*dest++ = *source++)) src_size++; + + if (!n) + { + if (size) *dest = '\0'; + while (*source++) src_size++; + } + + return src_size; +} + +size_t strlcat(char *dest, const char *source, size_t size) +{ + size_t len = strlen(dest); + + dest += len; + + if (len > size) + size = 0; + else + size -= len; + + return len + strlcpy(dest, source, size); +} +#endif + +char *strldup(const char *s, size_t n) +{ + char *dst = (char*)malloc(sizeof(char) * (n + 1)); + strlcpy(dst, s, n); + return dst; +} diff --git a/libretro/libretro-common/compat/fopen_utf8.c b/libretro/libretro-common/compat/fopen_utf8.c new file mode 100644 index 0000000..52b481e --- /dev/null +++ b/libretro/libretro-common/compat/fopen_utf8.c @@ -0,0 +1,60 @@ +/* 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) +#ifndef LEGACY_WIN32 +#define LEGACY_WIN32 +#endif +#endif + +#ifdef _WIN32 +#undef fopen + +void *fopen_utf8(const char * filename, const char * mode) +{ +#if defined(_XBOX) + return fopen(filename, mode); +#elif defined(LEGACY_WIN32) + FILE *ret = NULL; + char * filename_local = utf8_to_local_string_alloc(filename); + + if (!filename_local) + return NULL; + ret = fopen(filename_local, mode); + if (filename_local) + free(filename_local); + return ret; +#else + wchar_t * filename_w = utf8_to_utf16_string_alloc(filename); + wchar_t * mode_w = utf8_to_utf16_string_alloc(mode); + FILE* ret = _wfopen(filename_w, mode_w); + free(filename_w); + free(mode_w); + return ret; +#endif +} +#endif diff --git a/libretro/libretro-common/encodings/encoding_utf.c b/libretro/libretro-common/encodings/encoding_utf.c new file mode 100644 index 0000000..f7c533f --- /dev/null +++ b/libretro/libretro-common/encodings/encoding_utf.c @@ -0,0 +1,516 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (encoding_utf.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 +#include + +#include + +#if defined(_WIN32) && !defined(_XBOX) +#include +#elif defined(_XBOX) +#include +#endif + +static unsigned leading_ones(uint8_t c) +{ + unsigned ones = 0; + while (c & 0x80) + { + ones++; + c <<= 1; + } + + return ones; +} + +/* Simple implementation. Assumes the sequence is + * properly synchronized and terminated. */ + +size_t utf8_conv_utf32(uint32_t *out, size_t out_chars, + const char *in, size_t in_size) +{ + unsigned i; + size_t ret = 0; + while (in_size && out_chars) + { + unsigned extra, shift; + uint32_t c; + uint8_t first = *in++; + unsigned ones = leading_ones(first); + + if (ones > 6 || ones == 1) /* Invalid or desync. */ + break; + + extra = ones ? ones - 1 : ones; + if (1 + extra > in_size) /* Overflow. */ + break; + + shift = (extra - 1) * 6; + c = (first & ((1 << (7 - ones)) - 1)) << (6 * extra); + + for (i = 0; i < extra; i++, in++, shift -= 6) + c |= (*in & 0x3f) << shift; + + *out++ = c; + in_size -= 1 + extra; + out_chars--; + ret++; + } + + return ret; +} + +bool utf16_conv_utf8(uint8_t *out, size_t *out_chars, + const uint16_t *in, size_t in_size) +{ + static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + size_t out_pos = 0; + size_t in_pos = 0; + + for (;;) + { + unsigned numAdds; + uint32_t value; + + if (in_pos == in_size) + { + *out_chars = out_pos; + return true; + } + value = in[in_pos++]; + if (value < 0x80) + { + if (out) + out[out_pos] = (char)value; + out_pos++; + continue; + } + + if (value >= 0xD800 && value < 0xE000) + { + uint32_t c2; + + if (value >= 0xDC00 || in_pos == in_size) + break; + c2 = in[in_pos++]; + if (c2 < 0xDC00 || c2 >= 0xE000) + break; + value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + } + + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((uint32_t)1) << (numAdds * 5 + 6))) + break; + if (out) + out[out_pos] = (char)(kUtf8Limits[numAdds - 1] + + (value >> (6 * numAdds))); + out_pos++; + do + { + numAdds--; + if (out) + out[out_pos] = (char)(0x80 + + ((value >> (6 * numAdds)) & 0x3F)); + out_pos++; + }while (numAdds != 0); + } + + *out_chars = out_pos; + return false; +} + +/* Acts mostly like strlcpy. + * + * Copies the given number of UTF-8 characters, + * but at most d_len bytes. + * + * Always NULL terminates. + * Does not copy half a character. + * + * Returns number of bytes. 's' is assumed valid UTF-8. + * Use only if 'chars' is considerably less than 'd_len'. */ +size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars) +{ + const uint8_t *sb = (const uint8_t*)s; + const uint8_t *sb_org = sb; + + if (!s) + return 0; + + while (*sb && chars-- > 0) + { + sb++; + while ((*sb & 0xC0) == 0x80) sb++; + } + + if ((size_t)(sb - sb_org) > d_len-1 /* NUL */) + { + sb = sb_org + d_len-1; + while ((*sb & 0xC0) == 0x80) sb--; + } + + memcpy(d, sb_org, sb-sb_org); + d[sb-sb_org] = '\0'; + + return sb-sb_org; +} + +const char *utf8skip(const char *str, size_t chars) +{ + const uint8_t *strb = (const uint8_t*)str; + if (!chars) + return str; + do + { + strb++; + while ((*strb & 0xC0)==0x80) strb++; + chars--; + } while(chars); + return (const char*)strb; +} + +size_t utf8len(const char *string) +{ + size_t ret = 0; + + if (!string) + return 0; + + while (*string) + { + if ((*string & 0xC0) != 0x80) + ret++; + string++; + } + return ret; +} + +static uint8_t utf8_walkbyte(const char **string) +{ + return *((*string)++); +} + +/* Does not validate the input, returns garbage if it's not UTF-8. */ +uint32_t utf8_walk(const char **string) +{ + uint8_t first = utf8_walkbyte(string); + uint32_t ret = 0; + + if (first < 128) + return first; + + ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F); + if (first >= 0xE0) + ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F); + if (first >= 0xF0) + ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F); + + if (first >= 0xF0) + return ret | (first & 7) << 18; + if (first >= 0xE0) + return ret | (first & 15) << 12; + return ret | (first & 31) << 6; +} + +static bool utf16_to_char(uint8_t **utf_data, + size_t *dest_len, const uint16_t *in) +{ + unsigned len = 0; + + while (in[len] != '\0') + len++; + + utf16_conv_utf8(NULL, dest_len, in, len); + *dest_len += 1; + *utf_data = (uint8_t*)malloc(*dest_len); + if (*utf_data == 0) + return false; + + return utf16_conv_utf8(*utf_data, dest_len, in, len); +} + +bool utf16_to_char_string(const uint16_t *in, char *s, size_t len) +{ + size_t dest_len = 0; + uint8_t *utf16_data = NULL; + bool ret = utf16_to_char(&utf16_data, &dest_len, in); + + if (ret) + { + utf16_data[dest_len] = 0; + strlcpy(s, (const char*)utf16_data, len); + } + + free(utf16_data); + utf16_data = NULL; + + return ret; +} + +/* Returned pointer MUST be freed by the caller if non-NULL. */ +static char* mb_to_mb_string_alloc(const char *str, + enum CodePage cp_in, enum CodePage cp_out) +{ + char *path_buf = NULL; + wchar_t *path_buf_wide = NULL; + int path_buf_len = 0; + int path_buf_wide_len = 0; + + if (!str || !*str) + return NULL; + + (void)path_buf; + (void)path_buf_wide; + (void)path_buf_len; + (void)path_buf_wide_len; + +#if !defined(_WIN32) || defined(_XBOX) + /* assume string needs no modification if not on Windows */ + return strdup(str); +#else +#ifdef UNICODE + /* TODO/FIXME: Not implemented. */ + return strdup(str); +#else + + /* Windows 95 will return 0 from these functions with a UTF8 codepage set without MSLU. From an unknown MSDN version (others omit this info): + * - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-8. When this is set, dwFlags must be zero. + * - Windows 95: Under the Microsoft Layer for Unicode, MultiByteToWideChar also supports CP_UTF7 and CP_UTF8. + */ + path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0); + + if (path_buf_wide_len) + { + path_buf_wide = (wchar_t*) + calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t)); + + if (path_buf_wide) + { + MultiByteToWideChar(cp_in, 0, + str, -1, path_buf_wide, path_buf_wide_len); + + if (*path_buf_wide) + { + path_buf_len = WideCharToMultiByte(cp_out, 0, + path_buf_wide, -1, NULL, 0, NULL, NULL); + + if (path_buf_len) + { + path_buf = (char*) + calloc(path_buf_len + sizeof(char), sizeof(char)); + + if (path_buf) + { + WideCharToMultiByte(cp_out, 0, + path_buf_wide, -1, path_buf, + path_buf_len, NULL, NULL); + + free(path_buf_wide); + + if (*path_buf) + return path_buf; + + free(path_buf); + return NULL; + } + } + else + { + free(path_buf_wide); + return strdup(str); + } + } + } + } + else + return strdup(str); + + if (path_buf_wide) + free(path_buf_wide); + + return NULL; +#endif +#endif +} + +/* Returned pointer MUST be freed by the caller if non-NULL. */ +char* utf8_to_local_string_alloc(const char *str) +{ + return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL); +} + +/* Returned pointer MUST be freed by the caller if non-NULL. */ +char* local_to_utf8_string_alloc(const char *str) +{ + return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8); +} + +/* Returned pointer MUST be freed by the caller if non-NULL. */ +wchar_t* utf8_to_utf16_string_alloc(const char *str) +{ +#ifdef _WIN32 + int len = 0; + int out_len = 0; +#else + size_t len = 0; + size_t out_len = 0; +#endif + wchar_t *buf = NULL; + + if (!str || !*str) + return NULL; + +#ifdef _WIN32 + len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + + if (len) + { + buf = (wchar_t*)calloc(len, sizeof(wchar_t)); + + if (!buf) + return NULL; + + out_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len); + } + else + { + /* fallback to ANSI codepage instead */ + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + + if (len) + { + buf = (wchar_t*)calloc(len, sizeof(wchar_t)); + + if (!buf) + return NULL; + + out_len = MultiByteToWideChar(CP_ACP, 0, str, -1, buf, len); + } + } + + if (out_len < 0) + { + free(buf); + return NULL; + } +#else + /* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */ + len = mbstowcs(NULL, str, 0) + 1; + + if (len) + { + buf = (wchar_t*)calloc(len, sizeof(wchar_t)); + + if (!buf) + return NULL; + + out_len = mbstowcs(buf, str, len); + } + + if (out_len == (size_t)-1) + { + free(buf); + return NULL; + } +#endif + + return buf; +} + +/* Returned pointer MUST be freed by the caller if non-NULL. */ +char* utf16_to_utf8_string_alloc(const wchar_t *str) +{ +#ifdef _WIN32 + int len = 0; + int out_len = 0; +#else + size_t len = 0; + size_t out_len = 0; +#endif + char *buf = NULL; + + if (!str || !*str) + return NULL; + +#ifdef _WIN32 + len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); + + if (len) + { + buf = (char*)calloc(len, sizeof(char)); + + if (!buf) + return NULL; + + out_len = WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL); + } + else + { + /* fallback to ANSI codepage instead */ + len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL); + + if (len) + { + buf = (char*)calloc(len, sizeof(char)); + + if (!buf) + return NULL; + + out_len = WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL); + } + } + + if (out_len < 0) + { + free(buf); + return NULL; + } +#else + /* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */ + len = wcstombs(NULL, str, 0) + 1; + + if (len) + { + buf = (char*)calloc(len, sizeof(char)); + + if (!buf) + return NULL; + + out_len = wcstombs(buf, str, len); + } + + if (out_len == (size_t)-1) + { + free(buf); + return NULL; + } +#endif + + return buf; +} diff --git a/libretro/libretro-common/include/boolean.h b/libretro/libretro-common/include/boolean.h index 2c18ef7..f06ac5a 100644 --- a/libretro/libretro-common/include/boolean.h +++ b/libretro/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). @@ -25,7 +25,7 @@ #ifndef __cplusplus -#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) +#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3) /* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */ #define bool unsigned char #define true 1 diff --git a/libretro/libretro-common/include/compat/apple_compat.h b/libretro/libretro-common/include/compat/apple_compat.h index f656546..819b39e 100644 --- a/libretro/libretro-common/include/compat/apple_compat.h +++ b/libretro/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/libretro-common/include/compat/fnmatch.h b/libretro/libretro-common/include/compat/fnmatch.h index 3f3c025..cede1ca 100644 --- a/libretro/libretro-common/include/compat/fnmatch.h +++ b/libretro/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/libretro-common/include/compat/fopen_utf8.h b/libretro/libretro-common/include/compat/fopen_utf8.h new file mode 100644 index 0000000..f59822a --- /dev/null +++ b/libretro/libretro-common/include/compat/fopen_utf8.h @@ -0,0 +1,34 @@ +/* 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. + */ + +#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 */ +/* TODO: enable */ +/* #define fopen (use fopen_utf8 instead) */ +void *fopen_utf8(const char * filename, const char * mode); +#else +#define fopen_utf8 fopen +#endif +#endif diff --git a/libretro/libretro-common/include/compat/getopt.h b/libretro/libretro-common/include/compat/getopt.h index fd5300a..74287b6 100644 --- a/libretro/libretro-common/include/compat/getopt.h +++ b/libretro/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). @@ -28,13 +28,13 @@ #endif /* Custom implementation of the GNU getopt_long for portability. - * Not designed to be fully compatible, but compatible with + * Not designed to be fully compatible, but compatible with * the features RetroArch uses. */ #ifdef HAVE_GETOPT_LONG #include #else -/* Avoid possible naming collisions during link since we +/* Avoid possible naming collisions during link since we * prefer to use the actual name. */ #define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_retro(argc, argv, optstring, longopts, longindex) @@ -51,7 +51,7 @@ struct option }; /* argv[] is declared with char * const argv[] in GNU, - * but this makes no sense, as non-POSIX getopt_long + * but this makes no sense, as non-POSIX getopt_long * mutates argv (non-opts are moved to the end). */ int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex); diff --git a/libretro/libretro-common/include/compat/intrinsics.h b/libretro/libretro-common/include/compat/intrinsics.h index d4aa3c1..3fc7d92 100644 --- a/libretro/libretro-common/include/compat/intrinsics.h +++ b/libretro/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). @@ -61,12 +61,12 @@ static INLINE int compat_ctz(unsigned x) { #if defined(__GNUC__) && !defined(RARCH_CONSOLE) return __builtin_ctz(x); -#elif _MSC_VER >= 1400 +#elif _MSC_VER >= 1400 && !defined(_XBOX) unsigned long r = 0; _BitScanReverse((unsigned long*)&r, x); return (int)r; #else -/* Only checks at nibble granularity, +/* Only checks at nibble granularity, * because that's what we need. */ if (x & 0x000f) return 0; diff --git a/libretro/libretro-common/include/compat/msvc.h b/libretro/libretro-common/include/compat/msvc.h index 76bc2e4..822c973 100644 --- a/libretro/libretro-common/include/compat/msvc.h +++ b/libretro/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). @@ -35,12 +35,12 @@ extern "C" { #ifndef snprintf #define snprintf c99_snprintf_retro__ #endif - + int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...); #endif /* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ -#if _MSC_VER < 1600 +#if _MSC_VER < 1600 #include #include #ifndef vsnprintf @@ -86,9 +86,33 @@ typedef int ssize_t; #pragma warning(disable : 4723) #pragma warning(disable : 4996) -/* roundf is available since MSVC 2013 */ +/* roundf and va_copy is available since MSVC 2013 */ #if _MSC_VER < 1800 #define roundf(in) (in >= 0.0f ? floorf(in + 0.5f) : ceilf(in - 0.5f)) +#define va_copy(x, y) ((x) = (y)) +#endif + +#if _MSC_VER <= 1310 + #ifndef __cplusplus + /* VC6 math.h doesn't define some functions when in C mode. + * Trying to define a prototype gives "undefined reference". + * But providing an implementation then gives "function already has body". + * So the equivalent of the implementations from math.h are used as + * defines here instead, and it seems to work. + */ + #define cosf(x) ((float)cos((double)x)) + #define powf(x, y) ((float)pow((double)x, (double)y)) + #define sinf(x) ((float)sin((double)x)) + #define ceilf(x) ((float)ceil((double)x)) + #define floorf(x) ((float)floor((double)x)) + #define sqrtf(x) ((float)sqrt((double)x)) + #define fabsf(x) ((float)fabs((double)(x))) + #endif + + #ifndef _strtoui64 + #define _strtoui64(x, y, z) (_atoi64(x)) + #endif + #endif #ifndef PATH_MAX diff --git a/libretro/libretro-common/include/compat/posix_string.h b/libretro/libretro-common/include/compat/posix_string.h index 380e1a1..9f56322 100644 --- a/libretro/libretro-common/include/compat/posix_string.h +++ b/libretro/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/libretro-common/include/compat/strcasestr.h b/libretro/libretro-common/include/compat/strcasestr.h index a8676a5..f849593 100644 --- a/libretro/libretro-common/include/compat/strcasestr.h +++ b/libretro/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). @@ -35,7 +35,7 @@ RETRO_BEGIN_DECLS -/* Avoid possible naming collisions during link +/* Avoid possible naming collisions during link * since we prefer to use the actual name. */ #define strcasestr(haystack, needle) strcasestr_retro__(haystack, needle) diff --git a/libretro/libretro-common/include/compat/strl.h b/libretro/libretro-common/include/compat/strl.h index a68005a..290498d 100644 --- a/libretro/libretro-common/include/compat/strl.h +++ b/libretro/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). @@ -26,7 +26,7 @@ #include #include -#ifdef HAVE_CONFIG_H +#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H) #include "../../../config.h" #endif @@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS #endif #ifndef HAVE_STRL -/* Avoid possible naming collisions during link since +/* Avoid possible naming collisions during link since * we prefer to use the actual name. */ #define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size) @@ -52,6 +52,8 @@ size_t strlcat(char *dest, const char *source, size_t size); #endif +char *strldup(const char *s, size_t n); + RETRO_END_DECLS #endif diff --git a/libretro/libretro-common/include/encodings/utf.h b/libretro/libretro-common/include/encodings/utf.h new file mode 100644 index 0000000..b513f28 --- /dev/null +++ b/libretro/libretro-common/include/encodings/utf.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (utf.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. + */ + +#ifndef _LIBRETRO_ENCODINGS_UTF_H +#define _LIBRETRO_ENCODINGS_UTF_H + +#include +#include + +#include + +#include + +RETRO_BEGIN_DECLS + +enum CodePage +{ + CODEPAGE_LOCAL = 0, /* CP_ACP */ + CODEPAGE_UTF8 = 65001 /* CP_UTF8 */ +}; + +size_t utf8_conv_utf32(uint32_t *out, size_t out_chars, + const char *in, size_t in_size); + +bool utf16_conv_utf8(uint8_t *out, size_t *out_chars, + const uint16_t *in, size_t in_size); + +size_t utf8len(const char *string); + +size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars); + +const char *utf8skip(const char *str, size_t chars); + +uint32_t utf8_walk(const char **string); + +bool utf16_to_char_string(const uint16_t *in, char *s, size_t len); + +char* utf8_to_local_string_alloc(const char *str); + +char* local_to_utf8_string_alloc(const char *str); + +wchar_t* utf8_to_utf16_string_alloc(const char *str); + +char* utf16_to_utf8_string_alloc(const wchar_t *str); + +RETRO_END_DECLS + +#endif diff --git a/libretro/libretro.h b/libretro/libretro-common/include/libretro.h similarity index 79% rename from libretro/libretro.h rename to libretro/libretro-common/include/libretro.h index 2579e8b..804a6c2 100644 --- a/libretro/libretro.h +++ b/libretro/libretro-common/include/libretro.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 libretro API header (libretro.h). @@ -32,7 +32,7 @@ extern "C" { #endif #ifndef __cplusplus -#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) +#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3) /* Hack applied for MSVC when compiling in C89 mode * as it isn't C99-compliant. */ #define bool unsigned char @@ -77,7 +77,7 @@ extern "C" { # endif #endif -/* Used for checking API/ABI mismatches that can break libretro +/* Used for checking API/ABI mismatches that can break libretro * implementations. * It is not incremented for compatible changes to the API. */ @@ -87,13 +87,13 @@ extern "C" { * Libretro's fundamental device abstractions. * * Libretro's input system consists of some standardized device types, - * such as a joypad (with/without analog), mouse, keyboard, lightgun + * such as a joypad (with/without analog), mouse, keyboard, lightgun * and a pointer. * - * The functionality of these devices are fixed, and individual cores + * The functionality of these devices are fixed, and individual cores * map their own concept of a controller to libretro's abstractions. - * This makes it possible for frontends to map the abstract types to a - * real input device, and not having to worry about binding input + * This makes it possible for frontends to map the abstract types to a + * real input device, and not having to worry about binding input * correctly to arbitrary controller layouts. */ @@ -104,43 +104,50 @@ extern "C" { /* Input disabled. */ #define RETRO_DEVICE_NONE 0 -/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo - * controller, but with additional L2/R2/L3/R3 buttons, similar to a +/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo + * controller, but with additional L2/R2/L3/R3 buttons, similar to a * PS1 DualShock. */ #define RETRO_DEVICE_JOYPAD 1 /* The mouse is a simple mouse, similar to Super Nintendo's mouse. * X and Y coordinates are reported relatively to last poll (poll callback). - * It is up to the libretro implementation to keep track of where the mouse + * It is up to the libretro implementation to keep track of where the mouse * pointer is supposed to be on the screen. - * The frontend must make sure not to interfere with its own hardware + * The frontend must make sure not to interfere with its own hardware * mouse pointer. */ #define RETRO_DEVICE_MOUSE 2 /* KEYBOARD device lets one poll for raw key pressed. - * It is poll based, so input callback will return with the current + * It is poll based, so input callback will return with the current * pressed state. * For event/text based keyboard input, see * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. */ #define RETRO_DEVICE_KEYBOARD 3 -/* Lightgun X/Y coordinates are reported relatively to last poll, - * similar to mouse. */ +/* LIGHTGUN device is similar to Guncon-2 for PlayStation 2. + * It reports X/Y coordinates in screen space (similar to the pointer) + * in the range [-0x8000, 0x7fff] in both axes, with zero being center. + * As well as reporting on/off screen state. It features a trigger, + * start/select buttons, auxiliary action buttons and a + * directional pad. A forced off-screen shot can be requested for + * auto-reloading function in some games. + */ #define RETRO_DEVICE_LIGHTGUN 4 /* The ANALOG device is an extension to JOYPAD (RetroPad). - * Similar to DualShock it adds two analog sticks. - * This is treated as a separate device type as it returns values in the - * full analog range of [-0x8000, 0x7fff]. Positive X axis is right. - * Positive Y axis is down. - * Only use ANALOG type when polling for analog values of the axes. + * Similar to DualShock2 it adds two analog sticks and all buttons can + * be analog. This is treated as a separate device type as it returns + * axis values in the full analog range of [-0x8000, 0x7fff]. + * Positive X axis is right. Positive Y axis is down. + * Buttons are returned in the range [0, 0x7fff]. + * Only use ANALOG type when polling for analog values. */ #define RETRO_DEVICE_ANALOG 5 /* Abstracts the concept of a pointing mechanism, e.g. touch. - * This allows libretro to query in absolute coordinates where on the + * This allows libretro to query in absolute coordinates where on the * screen a mouse (or something similar) is being placed. * For a touch centric device, coordinates reported are the coordinates * of the press. @@ -148,33 +155,34 @@ extern "C" { * Coordinates in X and Y are reported as: * [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, * and 0x7fff corresponds to the far right/bottom of the screen. - * The "screen" is here defined as area that is passed to the frontend and + * The "screen" is here defined as area that is passed to the frontend and * later displayed on the monitor. * * The frontend is free to scale/resize this screen as it sees fit, however, - * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the + * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the * game image, etc. * - * To check if the pointer coordinates are valid (e.g. a touch display + * To check if the pointer coordinates are valid (e.g. a touch display * actually being touched), PRESSED returns 1 or 0. * - * If using a mouse on a desktop, PRESSED will usually correspond to the + * If using a mouse on a desktop, PRESSED will usually correspond to the * left mouse button, but this is a frontend decision. * PRESSED will only return 1 if the pointer is inside the game screen. * - * For multi-touch, the index variable can be used to successively query + * For multi-touch, the index variable can be used to successively query * more presses. * If index = 0 returns true for _PRESSED, coordinates can be extracted - * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with + * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with * index = 1, and so on. - * Eventually _PRESSED will return false for an index. No further presses + * Eventually _PRESSED will return false for an index. No further presses * are registered at this point. */ #define RETRO_DEVICE_POINTER 6 /* Buttons for the RetroPad (JOYPAD). - * The placement of these is equivalent to placements on the + * The placement of these is equivalent to placements on the * Super Nintendo controller. - * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */ + * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. + * Also used as id values for RETRO_DEVICE_INDEX_ANALOG_BUTTON */ #define RETRO_DEVICE_ID_JOYPAD_B 0 #define RETRO_DEVICE_ID_JOYPAD_Y 1 #define RETRO_DEVICE_ID_JOYPAD_SELECT 2 @@ -193,10 +201,11 @@ extern "C" { #define RETRO_DEVICE_ID_JOYPAD_R3 15 /* Index / Id values for ANALOG device. */ -#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 -#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 -#define RETRO_DEVICE_ID_ANALOG_X 0 -#define RETRO_DEVICE_ID_ANALOG_Y 1 +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_INDEX_ANALOG_BUTTON 2 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 /* Id values for MOUSE. */ #define RETRO_DEVICE_ID_MOUSE_X 0 @@ -208,15 +217,30 @@ extern "C" { #define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 #define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 #define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 +#define RETRO_DEVICE_ID_MOUSE_BUTTON_4 9 +#define RETRO_DEVICE_ID_MOUSE_BUTTON_5 10 -/* Id values for LIGHTGUN types. */ -#define RETRO_DEVICE_ID_LIGHTGUN_X 0 -#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 -#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 -#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 -#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 -#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 -#define RETRO_DEVICE_ID_LIGHTGUN_START 6 +/* Id values for LIGHTGUN. */ +#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X 13 /*Absolute Position*/ +#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y 14 /*Absolute*/ +#define RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN 15 /*Status Check*/ +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_RELOAD 16 /*Forced off-screen shot*/ +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_A 3 +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_B 4 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 +#define RETRO_DEVICE_ID_LIGHTGUN_SELECT 7 +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_C 8 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP 9 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN 10 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT 11 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT 12 +/* deprecated */ +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 /*Relative Position*/ +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 /*Relative*/ +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 /*Use Aux:A*/ +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 /*Use Aux:B*/ +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 /*Use Start*/ /* Id values for POINTER. */ #define RETRO_DEVICE_ID_POINTER_X 0 @@ -230,28 +254,31 @@ extern "C" { /* Id values for LANGUAGE */ enum retro_language { - RETRO_LANGUAGE_ENGLISH = 0, - RETRO_LANGUAGE_JAPANESE = 1, - RETRO_LANGUAGE_FRENCH = 2, - RETRO_LANGUAGE_SPANISH = 3, - RETRO_LANGUAGE_GERMAN = 4, - RETRO_LANGUAGE_ITALIAN = 5, - RETRO_LANGUAGE_DUTCH = 6, - RETRO_LANGUAGE_PORTUGUESE = 7, - RETRO_LANGUAGE_RUSSIAN = 8, - RETRO_LANGUAGE_KOREAN = 9, - RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, - RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, - RETRO_LANGUAGE_ESPERANTO = 12, - RETRO_LANGUAGE_POLISH = 13, + RETRO_LANGUAGE_ENGLISH = 0, + RETRO_LANGUAGE_JAPANESE = 1, + RETRO_LANGUAGE_FRENCH = 2, + RETRO_LANGUAGE_SPANISH = 3, + RETRO_LANGUAGE_GERMAN = 4, + RETRO_LANGUAGE_ITALIAN = 5, + RETRO_LANGUAGE_DUTCH = 6, + RETRO_LANGUAGE_PORTUGUESE_BRAZIL = 7, + RETRO_LANGUAGE_PORTUGUESE_PORTUGAL = 8, + RETRO_LANGUAGE_RUSSIAN = 9, + RETRO_LANGUAGE_KOREAN = 10, + RETRO_LANGUAGE_CHINESE_TRADITIONAL = 11, + RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 12, + RETRO_LANGUAGE_ESPERANTO = 13, + RETRO_LANGUAGE_POLISH = 14, + RETRO_LANGUAGE_VIETNAMESE = 15, + RETRO_LANGUAGE_ARABIC = 16, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ - RETRO_LANGUAGE_DUMMY = INT_MAX + RETRO_LANGUAGE_DUMMY = INT_MAX }; /* Passed to retro_get_memory_data/size(). - * If the memory type doesn't apply to the + * If the memory type doesn't apply to the * implementation NULL/0 can be returned. */ #define RETRO_MEMORY_MASK 0xff @@ -349,6 +376,10 @@ enum retro_key RETROK_x = 120, RETROK_y = 121, RETROK_z = 122, + RETROK_LEFTBRACE = 123, + RETROK_BAR = 124, + RETROK_RIGHTBRACE = 125, + RETROK_TILDE = 126, RETROK_DELETE = 127, RETROK_KP0 = 256, @@ -441,7 +472,7 @@ enum retro_mod RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ }; -/* If set, this call is not part of the public libretro API yet. It can +/* If set, this call is not part of the public libretro API yet. It can * change or be removed at any time. */ #define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 /* Environment callback to be used internally in frontend. */ @@ -451,11 +482,11 @@ enum retro_mod #define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- * Sets screen rotation of graphics. * Is only implemented if rotation can be accelerated by hardware. - * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, + * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, * 270 degrees counter-clockwise respectively. */ #define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- - * Boolean value whether or not the implementation should use overscan, + * Boolean value whether or not the implementation should use overscan, * or crop away overscan. */ #define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- @@ -463,15 +494,15 @@ enum retro_mod * passing NULL to video frame callback. */ - /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), + /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), * and reserved to avoid possible ABI clash. */ #define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- - * Sets a message to be displayed in implementation-specific manner + * Sets a message to be displayed in implementation-specific manner * for a certain amount of 'frames'. - * Should not be used for trivial messages, which should simply be - * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a + * Should not be used for trivial messages, which should simply be + * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a * fallback, stderr). */ #define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- @@ -499,15 +530,15 @@ enum retro_mod #define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 /* const char ** -- * Returns the "system" directory of the frontend. - * This directory can be used to store system specific + * This directory can be used to store system specific * content such as BIOSes, configuration data, etc. * The returned value can be NULL. * If so, no such directory is defined, * and it's up to the implementation to find a suitable directory. * - * NOTE: Some cores used this folder also for "save" data such as + * NOTE: Some cores used this folder also for "save" data such as * memory cards, etc, for lack of a better place to put it. - * This is now discouraged, and if possible, cores should try to + * This is now discouraged, and if possible, cores should try to * use the new GET_SAVE_DIRECTORY. */ #define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 @@ -515,19 +546,19 @@ enum retro_mod * Sets the internal pixel format used by the implementation. * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. * This pixel format however, is deprecated (see enum retro_pixel_format). - * If the call returns false, the frontend does not support this pixel + * If the call returns false, the frontend does not support this pixel * format. * - * This function should be called inside retro_load_game() or + * This function should be called inside retro_load_game() or * retro_get_system_av_info(). */ #define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 /* const struct retro_input_descriptor * -- * Sets an array of retro_input_descriptors. * It is up to the frontend to present this in a usable way. - * The array is terminated by retro_input_descriptor::description + * The array is terminated by retro_input_descriptor::description * being set to NULL. - * This function can be called at any time, but it is recommended + * This function can be called at any time, but it is recommended * to call it as early as possible. */ #define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 @@ -536,52 +567,52 @@ enum retro_mod */ #define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 /* const struct retro_disk_control_callback * -- - * Sets an interface which frontend can use to eject and insert + * Sets an interface which frontend can use to eject and insert * disk images. - * This is used for games which consist of multiple images and + * This is used for games which consist of multiple images and * must be manually swapped out by the user (e.g. PSX). */ #define RETRO_ENVIRONMENT_SET_HW_RENDER 14 /* struct retro_hw_render_callback * -- - * Sets an interface to let a libretro core render with + * Sets an interface to let a libretro core render with * hardware acceleration. * Should be called in retro_load_game(). - * If successful, libretro cores will be able to render to a + * If successful, libretro cores will be able to render to a * frontend-provided framebuffer. - * The size of this framebuffer will be at least as large as + * The size of this framebuffer will be at least as large as * max_width/max_height provided in get_av_info(). - * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or + * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or * NULL to retro_video_refresh_t. */ #define RETRO_ENVIRONMENT_GET_VARIABLE 15 /* struct retro_variable * -- * Interface to acquire user-defined information from environment * that cannot feasibly be supported in a multi-system way. - * 'key' should be set to a key which has already been set by + * 'key' should be set to a key which has already been set by * SET_VARIABLES. * 'data' will be set to a value or NULL. */ #define RETRO_ENVIRONMENT_SET_VARIABLES 16 /* const struct retro_variable * -- * Allows an implementation to signal the environment - * which variables it might want to check for later using + * which variables it might want to check for later using * GET_VARIABLE. - * This allows the frontend to present these variables to + * This allows the frontend to present these variables to * a user dynamically. - * This should be called as early as possible (ideally in + * This should be called as early as possible (ideally in * retro_set_environment). * - * 'data' points to an array of retro_variable structs + * 'data' points to an array of retro_variable structs * terminated by a { NULL, NULL } element. - * retro_variable::key should be namespaced to not collide - * with other implementations' keys. E.g. A core called + * retro_variable::key should be namespaced to not collide + * with other implementations' keys. E.g. A core called * 'foo' should use keys named as 'foo_option'. - * retro_variable::value should contain a human readable - * description of the key as well as a '|' delimited list + * retro_variable::value should contain a human readable + * description of the key as well as a '|' delimited list * of expected values. * - * The number of possible options should be very limited, - * i.e. it should be feasible to cycle through options + * The number of possible options should be very limited, + * i.e. it should be feasible to cycle through options * without a keyboard. * * First entry should be treated as a default. @@ -589,11 +620,11 @@ enum retro_mod * Example entry: * { "foo_option", "Speed hack coprocessor X; false|true" } * - * Text before first ';' is description. This ';' must be - * followed by a space, and followed by a list of possible + * Text before first ';' is description. This ';' must be + * followed by a space, and followed by a list of possible * values split up with '|'. * - * Only strings are operated on. The possible values will + * Only strings are operated on. The possible values will * generally be displayed and stored as-is by the frontend. */ #define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 @@ -604,72 +635,72 @@ enum retro_mod */ #define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 /* const bool * -- - * If true, the libretro implementation supports calls to + * If true, the libretro implementation supports calls to * retro_load_game() with NULL as argument. * Used by cores which can run without particular game data. * This should be called within retro_set_environment() only. */ #define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 /* const char ** -- - * Retrieves the absolute path from where this libretro + * Retrieves the absolute path from where this libretro * implementation was loaded. - * NULL is returned if the libretro was loaded statically - * (i.e. linked statically to frontend), or if the path cannot be + * NULL is returned if the libretro was loaded statically + * (i.e. linked statically to frontend), or if the path cannot be * determined. - * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can + * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can * be loaded without ugly hacks. */ - - /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. + + /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. * It was not used by any known core at the time, * and was removed from the API. */ #define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 /* const struct retro_audio_callback * -- - * Sets an interface which is used to notify a libretro core about audio + * Sets an interface which is used to notify a libretro core about audio * being available for writing. - * The callback can be called from any thread, so a core using this must + * The callback can be called from any thread, so a core using this must * have a thread safe audio implementation. - * It is intended for games where audio and video are completely + * It is intended for games where audio and video are completely * asynchronous and audio can be generated on the fly. - * This interface is not recommended for use with emulators which have + * This interface is not recommended for use with emulators which have * highly synchronous audio. * - * The callback only notifies about writability; the libretro core still + * The callback only notifies about writability; the libretro core still * has to call the normal audio callbacks - * to write audio. The audio callbacks must be called from within the + * to write audio. The audio callbacks must be called from within the * notification callback. * The amount of audio data to write is up to the implementation. * Generally, the audio callback will be called continously in a loop. * - * Due to thread safety guarantees and lack of sync between audio and - * video, a frontend can selectively disallow this interface based on - * internal configuration. A core using this interface must also + * Due to thread safety guarantees and lack of sync between audio and + * video, a frontend can selectively disallow this interface based on + * internal configuration. A core using this interface must also * implement the "normal" audio interface. * - * A libretro core using SET_AUDIO_CALLBACK should also make use of + * A libretro core using SET_AUDIO_CALLBACK should also make use of * SET_FRAME_TIME_CALLBACK. */ #define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 /* const struct retro_frame_time_callback * -- - * Lets the core know how much time has passed since last + * Lets the core know how much time has passed since last * invocation of retro_run(). - * The frontend can tamper with the timing to fake fast-forward, + * The frontend can tamper with the timing to fake fast-forward, * slow-motion, frame stepping, etc. - * In this case the delta time will use the reference value + * In this case the delta time will use the reference value * in frame_time_callback.. */ #define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 /* struct retro_rumble_interface * -- - * Gets an interface which is used by a libretro core to set + * Gets an interface which is used by a libretro core to set * state of rumble motors in controllers. - * A strong and weak motor is supported, and they can be + * A strong and weak motor is supported, and they can be * controlled indepedently. */ #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 /* uint64_t * -- - * Gets a bitmask telling which device type are expected to be + * Gets a bitmask telling which device type are expected to be * handled properly in a call to retro_input_state_t. - * Devices which are not handled or recognized always return + * Devices which are not handled or recognized always return * 0 in retro_input_state_t. * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). * Should only be called in retro_run(). @@ -678,56 +709,56 @@ enum retro_mod /* struct retro_sensor_interface * -- * Gets access to the sensor interface. * The purpose of this interface is to allow - * setting state related to sensors such as polling rate, + * setting state related to sensors such as polling rate, * enabling/disable it entirely, etc. - * Reading sensor state is done via the normal + * Reading sensor state is done via the normal * input_state_callback API. */ #define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* struct retro_camera_callback * -- * Gets an interface to a video camera driver. - * A libretro core can use this interface to get access to a + * A libretro core can use this interface to get access to a * video camera. - * New video frames are delivered in a callback in same + * New video frames are delivered in a callback in same * thread as retro_run(). * * GET_CAMERA_INTERFACE should be called in retro_load_game(). * - * Depending on the camera implementation used, camera frames + * Depending on the camera implementation used, camera frames * will be delivered as a raw framebuffer, * or as an OpenGL texture directly. * - * The core has to tell the frontend here which types of + * The core has to tell the frontend here which types of * buffers can be handled properly. - * An OpenGL texture can only be handled when using a + * An OpenGL texture can only be handled when using a * libretro GL core (SET_HW_RENDER). - * It is recommended to use a libretro GL core when + * It is recommended to use a libretro GL core when * using camera interface. * - * The camera is not started automatically. The retrieved start/stop + * The camera is not started automatically. The retrieved start/stop * functions must be used to explicitly * start and stop the camera driver. */ #define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 /* struct retro_log_callback * -- - * Gets an interface for logging. This is useful for + * Gets an interface for logging. This is useful for * logging in a cross-platform way - * as certain platforms cannot use use stderr for logging. + * as certain platforms cannot use stderr for logging. * It also allows the frontend to * show logging information in a more suitable way. - * If this interface is not used, libretro cores should + * If this interface is not used, libretro cores should * log to stderr as desired. */ #define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 /* struct retro_perf_callback * -- - * Gets an interface for performance counters. This is useful - * for performance logging in a cross-platform way and for detecting + * Gets an interface for performance counters. This is useful + * for performance logging in a cross-platform way and for detecting * architecture-specific features, such as SIMD support. */ #define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 /* struct retro_location_callback * -- * Gets access to the location interface. - * The purpose of this interface is to be able to retrieve + * The purpose of this interface is to be able to retrieve * location-based information from the host device, * such as current latitude / longitude. */ @@ -735,7 +766,7 @@ enum retro_mod #define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 /* const char ** -- * Returns the "core assets" directory of the frontend. - * This directory can be used to store specific assets that the + * This directory can be used to store specific assets that the * core relies upon, such as art assets, * input data, etc etc. * The returned value can be NULL. @@ -745,75 +776,75 @@ enum retro_mod #define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 /* const char ** -- * Returns the "save" directory of the frontend. - * This directory can be used to store SRAM, memory cards, + * This directory can be used to store SRAM, memory cards, * high scores, etc, if the libretro core * cannot use the regular memory interface (retro_get_memory_data()). * - * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for + * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for * similar things before. - * They should still check GET_SYSTEM_DIRECTORY if they want to + * They should still check GET_SYSTEM_DIRECTORY if they want to * be backwards compatible. - * The path here can be NULL. It should only be non-NULL if the + * The path here can be NULL. It should only be non-NULL if the * frontend user has set a specific save path. */ #define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 /* const struct retro_system_av_info * -- - * Sets a new av_info structure. This can only be called from + * Sets a new av_info structure. This can only be called from * within retro_run(). - * This should *only* be used if the core is completely altering the + * This should *only* be used if the core is completely altering the * internal resolutions, aspect ratios, timings, sampling rate, etc. - * Calling this can require a full reinitialization of video/audio + * Calling this can require a full reinitialization of video/audio * drivers in the frontend, * - * so it is important to call it very sparingly, and usually only with + * so it is important to call it very sparingly, and usually only with * the users explicit consent. - * An eventual driver reinitialize will happen so that video and + * An eventual driver reinitialize will happen so that video and * audio callbacks - * happening after this call within the same retro_run() call will + * happening after this call within the same retro_run() call will * target the newly initialized driver. * - * This callback makes it possible to support configurable resolutions + * This callback makes it possible to support configurable resolutions * in games, which can be useful to * avoid setting the "worst case" in max_width/max_height. * - * ***HIGHLY RECOMMENDED*** Do not call this callback every time + * ***HIGHLY RECOMMENDED*** Do not call this callback every time * resolution changes in an emulator core if it's - * expected to be a temporary change, for the reasons of possible + * expected to be a temporary change, for the reasons of possible * driver reinitialization. - * This call is not a free pass for not trying to provide - * correct values in retro_get_system_av_info(). If you need to change - * things like aspect ratio or nominal width/height, - * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant + * This call is not a free pass for not trying to provide + * correct values in retro_get_system_av_info(). If you need to change + * things like aspect ratio or nominal width/height, + * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant * of SET_SYSTEM_AV_INFO. * - * If this returns false, the frontend does not acknowledge a + * If this returns false, the frontend does not acknowledge a * changed av_info struct. */ #define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 /* const struct retro_get_proc_address_interface * -- - * Allows a libretro core to announce support for the + * Allows a libretro core to announce support for the * get_proc_address() interface. - * This interface allows for a standard way to extend libretro where + * This interface allows for a standard way to extend libretro where * use of environment calls are too indirect, * e.g. for cases where the frontend wants to call directly into the core. * - * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK + * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK * **MUST** be called from within retro_set_environment(). */ #define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 /* const struct retro_subsystem_info * -- * This environment call introduces the concept of libretro "subsystems". - * A subsystem is a variant of a libretro core which supports + * A subsystem is a variant of a libretro core which supports * different kinds of games. - * The purpose of this is to support e.g. emulators which might + * The purpose of this is to support e.g. emulators which might * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. - * It can also be used to pick among subsystems in an explicit way + * It can also be used to pick among subsystems in an explicit way * if the libretro implementation is a multi-system emulator itself. * * Loading a game via a subsystem is done with retro_load_game_special(), - * and this environment call allows a libretro core to expose which + * and this environment call allows a libretro core to expose which * subsystems are supported for use with retro_load_game_special(). - * A core passes an array of retro_game_special_info which is terminated + * A core passes an array of retro_game_special_info which is terminated * with a zeroed out retro_game_special_info struct. * * If a core wants to use this functionality, SET_SUBSYSTEM_INFO @@ -821,15 +852,15 @@ enum retro_mod */ #define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 /* const struct retro_controller_info * -- - * This environment call lets a libretro core tell the frontend - * which controller types are recognized in calls to + * This environment call lets a libretro core tell the frontend + * which controller types are recognized in calls to * retro_set_controller_port_device(). * * Some emulators such as Super Nintendo - * support multiple lightgun types which must be specifically + * support multiple lightgun types which must be specifically * selected from. - * It is therefore sometimes necessary for a frontend to be able - * to tell the core about a special kind of input device which is + * It is therefore sometimes necessary for a frontend to be able + * to tell the core about a special kind of input device which is * not covered by the libretro input API. * * In order for a frontend to understand the workings of an input device, @@ -837,52 +868,52 @@ enum retro_mod * of the generic device types already defined in the libretro API. * * Which devices are supported can vary per input port. - * The core must pass an array of const struct retro_controller_info which - * is terminated with a blanked out struct. Each element of the struct - * corresponds to an ascending port index to + * The core must pass an array of const struct retro_controller_info which + * is terminated with a blanked out struct. Each element of the struct + * corresponds to an ascending port index to * retro_set_controller_port_device(). - * Even if special device types are set in the libretro core, + * Even if special device types are set in the libretro core, * libretro should only poll input based on the base input device types. */ #define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* const struct retro_memory_map * -- - * This environment call lets a libretro core tell the frontend + * This environment call lets a libretro core tell the frontend * about the memory maps this core emulates. * This can be used to implement, for example, cheats in a core-agnostic way. * - * Should only be used by emulators; it doesn't make much sense for + * Should only be used by emulators; it doesn't make much sense for * anything else. - * It is recommended to expose all relevant pointers through + * It is recommended to expose all relevant pointers through * retro_get_memory_* as well. * * Can be called from retro_init and retro_load_game. */ #define RETRO_ENVIRONMENT_SET_GEOMETRY 37 /* const struct retro_game_geometry * -- - * This environment call is similar to SET_SYSTEM_AV_INFO for changing - * video parameters, but provides a guarantee that drivers will not be + * This environment call is similar to SET_SYSTEM_AV_INFO for changing + * video parameters, but provides a guarantee that drivers will not be * reinitialized. * This can only be called from within retro_run(). * - * The purpose of this call is to allow a core to alter nominal - * width/heights as well as aspect ratios on-the-fly, which can be + * The purpose of this call is to allow a core to alter nominal + * width/heights as well as aspect ratios on-the-fly, which can be * useful for some emulators to change in run-time. * * max_width/max_height arguments are ignored and cannot be changed - * with this call as this could potentially require a reinitialization or a + * with this call as this could potentially require a reinitialization or a * non-constant time operation. * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. * - * A frontend must guarantee that this environment call completes in + * A frontend must guarantee that this environment call completes in * constant time. */ -#define RETRO_ENVIRONMENT_GET_USERNAME 38 +#define RETRO_ENVIRONMENT_GET_USERNAME 38 /* const char ** * Returns the specified username of the frontend, if specified by the user. - * This username can be used as a nickname for a core that has online facilities + * This username can be used as a nickname for a core that has online facilities * or any other mode where personalization of the user is desirable. * The returned value can be NULL. - * If this environ callback is used by a core that requires a valid username, + * If this environ callback is used by a core that requires a valid username, * a default username should be specified by the core. */ #define RETRO_ENVIRONMENT_GET_LANGUAGE 39 @@ -921,10 +952,148 @@ enum retro_mod * writeable (and readable). */ +#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* N/A (null) * -- + * The frontend will try to use a 'shared' hardware context (mostly applicable + * to OpenGL) when a hardware context is being set up. + * + * Returns true if the frontend supports shared hardware contexts and false + * if the frontend does not support shared hardware contexts. + * + * This will do nothing on its own until SET_HW_RENDER env callbacks are + * being used. + */ + +#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_vfs_interface_info * -- + * Gets access to the VFS interface. + * VFS presence needs to be queried prior to load_game or any + * get_system/save/other_directory being called to let front end know + * core supports VFS before it starts handing out paths. + * It is recomended to do so in retro_set_environment */ + +/* VFS functionality */ + +/* File paths: + * File paths passed as parameters when using this api shall be well formed unix-style, + * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator. + * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead). + * Other than the directory separator, cores shall not make assumptions about path format: + * "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths. + * Cores may replace the basename or remove path components from the end, and/or add new components; + * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end. + * The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much. + * Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable). + * Cores are allowed to try using them, but must remain functional if the front rejects such requests. + * Cores are encouraged to use the libretro-common filestream functions for file I/O, + * as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate + * and provide platform-specific fallbacks in cases where front ends do not support VFS. */ + +/* Opaque file handle + * Introduced in VFS API v1 */ +struct retro_vfs_file_handle; + +/* File open flags + * Introduced in VFS API v1 */ +#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */ +#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */ +#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/ +#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */ + +/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use, + and how they react to unlikely external interference (for example someone else writing to that file, + or the file's server going down), behavior will not change. */ +#define RETRO_VFS_FILE_ACCESS_HINT_NONE (0) +/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */ +#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0) + +/* Seek positions */ +#define RETRO_VFS_SEEK_POSITION_START 0 +#define RETRO_VFS_SEEK_POSITION_CURRENT 1 +#define RETRO_VFS_SEEK_POSITION_END 2 + +/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle + * Introduced in VFS API v1 */ +typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream); + +/* Open a file for reading or writing. If path points to a directory, this will + * fail. Returns the opaque file handle, or NULL for error. + * Introduced in VFS API v1 */ +typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints); + +/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on succes, -1 on failure. + * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream); + +/* Return the size of the file in bytes, or -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream); + +/* Get the current read / write position for the file. Returns - 1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream); + +/* Set the current read/write position for the file. Returns the new position, -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position); + +/* Read data from a file. Returns the number of bytes read, or -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len); + +/* Write data to a file. Returns the number of bytes written, or -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len); + +/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure. + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream); + +/* Delete the specified file. Returns 0 on success, -1 on failure + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path); + +/* Rename the specified file. Returns 0 on success, -1 on failure + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path); + +struct retro_vfs_interface +{ + retro_vfs_get_path_t get_path; + retro_vfs_open_t open; + retro_vfs_close_t close; + retro_vfs_size_t size; + retro_vfs_tell_t tell; + retro_vfs_seek_t seek; + retro_vfs_read_t read; + retro_vfs_write_t write; + retro_vfs_flush_t flush; + retro_vfs_remove_t remove; + retro_vfs_rename_t rename; +}; + +struct retro_vfs_interface_info +{ + /* Set by core: should this be higher than the version the front end supports, + * front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call + * Introduced in VFS API v1 */ + uint32_t required_interface_version; + + /* Frontend writes interface pointer here. The frontend also sets the actual + * version, must be at least required_interface_version. + * Introduced in VFS API v1 */ + struct retro_vfs_interface *iface; +}; + enum retro_hw_render_interface_type { - RETRO_HW_RENDER_INTERFACE_VULKAN = 0, - RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX + RETRO_HW_RENDER_INTERFACE_VULKAN = 0, + RETRO_HW_RENDER_INTERFACE_D3D9 = 1, + RETRO_HW_RENDER_INTERFACE_D3D10 = 2, + RETRO_HW_RENDER_INTERFACE_D3D11 = 3, + RETRO_HW_RENDER_INTERFACE_D3D12 = 4, + RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX }; /* Base struct. All retro_hw_render_interface_* types @@ -934,6 +1103,62 @@ struct retro_hw_render_interface enum retro_hw_render_interface_type interface_type; unsigned interface_version; }; + + +#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_led_interface * -- + * Gets an interface which is used by a libretro core to set + * state of LEDs. + */ + +typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state); +struct retro_led_interface +{ + retro_set_led_state_t set_led_state; +}; + +#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* int * -- + * 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) /* const struct retro_hw_render_interface ** -- * Returns an API specific rendering interface for accessing API specific data. @@ -1006,7 +1231,6 @@ struct retro_hw_render_context_negotiation_interface * recognize or support. Should be set in either retro_init or retro_load_game, but not both. */ - #define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ #define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ #define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ @@ -1020,56 +1244,56 @@ struct retro_memory_descriptor uint64_t flags; /* Pointer to the start of the relevant ROM or RAM chip. - * It's strongly recommended to use 'offset' if possible, rather than + * It's strongly recommended to use 'offset' if possible, rather than * doing math on the pointer. * - * If the same byte is mapped my multiple descriptors, their descriptors + * If the same byte is mapped my multiple descriptors, their descriptors * must have the same pointer. - * If 'start' does not point to the first byte in the pointer, put the + * If 'start' does not point to the first byte in the pointer, put the * difference in 'offset' instead. * - * May be NULL if there's nothing usable here (e.g. hardware registers and + * May be NULL if there's nothing usable here (e.g. hardware registers and * open bus). No flags should be set if the pointer is NULL. * It's recommended to minimize the number of descriptors if possible, * but not mandatory. */ void *ptr; size_t offset; - /* This is the location in the emulated address space + /* This is the location in the emulated address space * where the mapping starts. */ size_t start; /* Which bits must be same as in 'start' for this mapping to apply. - * The first memory descriptor to claim a certain byte is the one + * The first memory descriptor to claim a certain byte is the one * that applies. * A bit which is set in 'start' must also be set in this. - * Can be zero, in which case each byte is assumed mapped exactly once. + * Can be zero, in which case each byte is assumed mapped exactly once. * In this case, 'len' must be a power of two. */ size_t select; - /* If this is nonzero, the set bits are assumed not connected to the + /* If this is nonzero, the set bits are assumed not connected to the * memory chip's address pins. */ size_t disconnect; /* This one tells the size of the current memory area. - * If, after start+disconnect are applied, the address is higher than + * If, after start+disconnect are applied, the address is higher than * this, the highest bit of the address is cleared. * * If the address is still too high, the next highest bit is cleared. - * Can be zero, in which case it's assumed to be infinite (as limited + * Can be zero, in which case it's assumed to be infinite (as limited * by 'select' and 'disconnect'). */ size_t len; - /* To go from emulated address to physical address, the following + /* To go from emulated address to physical address, the following * order applies: * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ - /* The address space name must consist of only a-zA-Z0-9_-, + /* The address space name must consist of only a-zA-Z0-9_-, * should be as short as feasible (maximum length is 8 plus the NUL), - * and may not be any other address space plus one or more 0-9A-F + * and may not be any other address space plus one or more 0-9A-F * at the end. - * However, multiple memory descriptors for the same address space is - * allowed, and the address space name can be empty. NULL is treated + * However, multiple memory descriptors for the same address space is + * allowed, and the address space name can be empty. NULL is treated * as empty. * * Address space names are case sensitive, but avoid lowercase if possible. @@ -1083,11 +1307,11 @@ struct retro_memory_descriptor * 'a'+blank - valid ('a' is not in 0-9A-F) * 'a'+'A' - valid (neither is a prefix of each other) * 'AR'+blank - valid ('R' is not in 0-9A-F) - * 'ARB'+blank - valid (the B can't be part of the address either, because + * 'ARB'+blank - valid (the B can't be part of the address either, because * there is no namespace 'AR') - * blank+'B' - not valid, because it's ambigous which address space B1234 + * blank+'B' - not valid, because it's ambigous which address space B1234 * would refer to. - * The length can't be used for that purpose; the frontend may want + * The length can't be used for that purpose; the frontend may want * to append arbitrary data to an address, without a separator. */ const char *addrspace; @@ -1109,32 +1333,32 @@ struct retro_memory_descriptor * the most recent addition and continue on the next bit. * TODO: Can the above be optimized? Is "remove the lowest bit set in both * pointer and 'len'" equivalent? */ - + /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing * the emulated memory in 32-bit chunks, native endian. But that's nothing * compared to Darek Mihocka * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE * RAM backwards! I'll want to represent both of those, via some flags. - * + * * I suspect MAME either didn't think of that idea, or don't want the #ifdef. * Not sure which, nor do I really care. */ - + /* TODO: Some of those flags are unused and/or don't really make sense. Clean * them up. */ }; -/* The frontend may use the largest value of 'start'+'select' in a +/* The frontend may use the largest value of 'start'+'select' in a * certain namespace to infer the size of the address space. * - * If the address space is larger than that, a mapping with .ptr=NULL - * should be at the end of the array, with .select set to all ones for + * If the address space is larger than that, a mapping with .ptr=NULL + * should be at the end of the array, with .select set to all ones for * as long as the address space is big. * * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): * SNES WRAM: * .start=0x7E0000, .len=0x20000 - * (Note that this must be mapped before the ROM in most cases; some of the - * ROM mappers + * (Note that this must be mapped before the ROM in most cases; some of the + * ROM mappers * try to claim $7E0000, or at least $7E8000.) * SNES SPC700 RAM: * .addrspace="S", .len=0x10000 @@ -1143,7 +1367,7 @@ struct retro_memory_descriptor * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 * SNES WRAM mirrors, alternate equivalent descriptor: * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF - * (Various similar constructions can be created by combining parts of + * (Various similar constructions can be created by combining parts of * the above two.) * SNES LoROM (512KB, mirrored a couple of times): * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 @@ -1169,13 +1393,13 @@ struct retro_memory_map struct retro_controller_description { - /* Human-readable description of the controller. Even if using a generic - * input device type, this can be set to the particular device type the + /* Human-readable description of the controller. Even if using a generic + * input device type, this can be set to the particular device type the * core uses. */ const char *desc; - /* Device type passed to retro_set_controller_port_device(). If the device - * type is a sub-class of a generic input device type, use the + /* Device type passed to retro_set_controller_port_device(). If the device + * type is a sub-class of a generic input device type, use the * RETRO_DEVICE_SUBCLASS macro to create an ID. * * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ @@ -1193,8 +1417,8 @@ struct retro_subsystem_memory_info /* The extension associated with a memory type, e.g. "psram". */ const char *extension; - /* The memory type for retro_get_memory(). This should be at - * least 0x100 to avoid conflict with standardized + /* The memory type for retro_get_memory(). This should be at + * least 0x100 to avoid conflict with standardized * libretro memory types. */ unsigned type; }; @@ -1213,11 +1437,11 @@ struct retro_subsystem_rom_info /* Same definition as retro_get_system_info(). */ bool block_extract; - /* This is set if the content is required to load a game. + /* This is set if the content is required to load a game. * If this is set to false, a zeroed-out retro_game_info can be passed. */ bool required; - /* Content can have multiple associated persistent + /* Content can have multiple associated persistent * memory types (retro_get_memory()). */ const struct retro_subsystem_memory_info *memory; unsigned num_memory; @@ -1235,17 +1459,17 @@ struct retro_subsystem_info */ const char *ident; - /* Infos for each content file. The first entry is assumed to be the + /* Infos for each content file. The first entry is assumed to be the * "most significant" content for frontend purposes. - * E.g. with Super GameBoy, the first content should be the GameBoy ROM, + * E.g. with Super GameBoy, the first content should be the GameBoy ROM, * as it is the most "significant" content to a user. - * If a frontend creates new file paths based on the content used + * If a frontend creates new file paths based on the content used * (e.g. savestates), it should use the path for the first ROM to do so. */ const struct retro_subsystem_rom_info *roms; /* Number of content files associated with a subsystem. */ unsigned num_roms; - + /* The type passed to retro_load_game_special(). */ unsigned id; }; @@ -1256,13 +1480,13 @@ typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); * (None here so far). * * Get a symbol from a libretro core. - * Cores should only return symbols which are actual + * Cores should only return symbols which are actual * extensions to the libretro API. * - * Frontends should not use this to obtain symbols to standard + * Frontends should not use this to obtain symbols to standard * libretro entry points (static linking or dlsym). * - * The symbol name must be equal to the function name, + * The symbol name must be equal to the function name, * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". * The returned function pointer must be cast to the corresponding type. */ @@ -1316,6 +1540,7 @@ struct retro_log_callback #define RETRO_SIMD_POPCNT (1 << 18) #define RETRO_SIMD_MOVBE (1 << 19) #define RETRO_SIMD_CMOV (1 << 20) +#define RETRO_SIMD_ASIMD (1 << 21) typedef uint64_t retro_perf_tick_t; typedef int64_t retro_time_t; @@ -1336,7 +1561,7 @@ struct retro_perf_counter typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void); /* A simple counter. Usually nanoseconds, but can also be CPU cycles. - * Can be used directly if desired (when creating a more sophisticated + * Can be used directly if desired (when creating a more sophisticated * performance counter system). * */ typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); @@ -1350,9 +1575,9 @@ typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void); typedef void (RETRO_CALLCONV *retro_perf_log_t)(void); /* Register a performance counter. - * ident field must be set with a discrete value and other values in + * ident field must be set with a discrete value and other values in * retro_perf_counter must be 0. - * Registering can be called multiple times. To avoid calling to + * Registering can be called multiple times. To avoid calling to * frontend redundantly, you can check registered field first. */ typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); @@ -1423,7 +1648,7 @@ enum retro_sensor_action #define RETRO_SENSOR_ACCELEROMETER_Y 1 #define RETRO_SENSOR_ACCELEROMETER_Z 2 -typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, +typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate); typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); @@ -1448,7 +1673,7 @@ typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); /* Stops the camera driver. Can only be called in retro_run(). */ typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); -/* Callback which signals when the camera driver is initialized +/* Callback which signals when the camera driver is initialized * and/or deinitialized. * retro_camera_start_t can be called in initialized callback. */ @@ -1458,36 +1683,36 @@ typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); * Width, height and pitch are similar to retro_video_refresh_t. * First pixel is top-left origin. */ -typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, +typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch); /* A callback for when OpenGL textures are used. * * texture_id is a texture owned by camera driver. - * Its state or content should be considered immutable, except for things like + * Its state or content should be considered immutable, except for things like * texture filtering and clamping. * * texture_target is the texture target for the GL texture. - * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly + * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly * more depending on extensions. * - * affine points to a packed 3x3 column-major matrix used to apply an affine + * affine points to a packed 3x3 column-major matrix used to apply an affine * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) - * After transform, normalized texture coord (0, 0) should be bottom-left + * After transform, normalized texture coord (0, 0) should be bottom-left * and (1, 1) should be top-right (or (width, height) for RECTANGLE). * - * GL-specific typedefs are avoided here to avoid relying on gl.h in + * GL-specific typedefs are avoided here to avoid relying on gl.h in * the API definition. */ -typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, +typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine); struct retro_camera_callback { - /* Set by libretro core. + /* Set by libretro core. * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). */ - uint64_t caps; + uint64_t caps; /* Desired resolution for camera. Is only used as a hint. */ unsigned width; @@ -1501,22 +1726,22 @@ struct retro_camera_callback retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; /* Set by libretro core if OpenGL texture callbacks will be used. */ - retro_camera_frame_opengl_texture_t frame_opengl_texture; + retro_camera_frame_opengl_texture_t frame_opengl_texture; - /* Set by libretro core. Called after camera driver is initialized and + /* Set by libretro core. Called after camera driver is initialized and * ready to be started. * Can be NULL, in which this callback is not called. */ retro_camera_lifetime_status_t initialized; - /* Set by libretro core. Called right before camera driver is + /* Set by libretro core. Called right before camera driver is * deinitialized. * Can be NULL, in which this callback is not called. */ retro_camera_lifetime_status_t deinitialized; }; -/* Sets the interval of time and/or distance at which to update/poll +/* Sets the interval of time and/or distance at which to update/poll * location-based data. * * To ensure compatibility with all location-based implementations, @@ -1529,20 +1754,20 @@ typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_m unsigned interval_distance); /* Start location services. The device will start listening for changes to the - * current location at regular intervals (which are defined with + * current location at regular intervals (which are defined with * retro_location_set_interval_t). */ typedef bool (RETRO_CALLCONV *retro_location_start_t)(void); -/* Stop location services. The device will stop listening for changes +/* Stop location services. The device will stop listening for changes * to the current location. */ typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); -/* Get the position of the current location. Will set parameters to +/* Get the position of the current location. Will set parameters to * 0 if no new location update has happened since the last time. */ typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy, double *vert_accuracy); -/* Callback which signals when the location driver is initialized +/* Callback which signals when the location driver is initialized * and/or deinitialized. * retro_location_start_t can be called in initialized callback. */ @@ -1567,14 +1792,14 @@ enum retro_rumble_effect RETRO_RUMBLE_DUMMY = INT_MAX }; -/* Sets rumble state for joypad plugged in port 'port'. +/* Sets rumble state for joypad plugged in port 'port'. * Rumble effects are controlled independently, * and setting e.g. strong rumble does not override weak rumble. * Strength has a range of [0, 0xffff]. * - * Returns true if rumble state request was honored. + * Returns true if rumble state request was honored. * Calling this before first retro_run() is likely to return false. */ -typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, +typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength); struct retro_rumble_interface @@ -1585,10 +1810,10 @@ struct retro_rumble_interface /* Notifies libretro that audio data should be written. */ typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); -/* True: Audio driver in frontend is active, and callback is +/* True: Audio driver in frontend is active, and callback is * expected to be called regularily. - * False: Audio driver in frontend is paused or inactive. - * Audio callback will not be called until set_state has been + * False: Audio driver in frontend is paused or inactive. + * Audio callback will not be called until set_state has been * called with true. * Initial state is false (inactive). */ @@ -1600,11 +1825,11 @@ struct retro_audio_callback retro_audio_set_state_callback_t set_state; }; -/* Notifies a libretro core of time spent since last invocation +/* Notifies a libretro core of time spent since last invocation * of retro_run() in microseconds. * * It will be called right before retro_run() every frame. - * The frontend can tamper with timing to support cases like + * The frontend can tamper with timing to support cases like * fast-forward, slow-motion and framestepping. * * In those scenarios the reference frame time value will be used. */ @@ -1613,8 +1838,8 @@ typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); struct retro_frame_time_callback { retro_frame_time_callback_t callback; - /* Represents the time of one frame. It is computed as - * 1000000 / fps, but the implementation will resolve the + /* Represents the time of one frame. It is computed as + * 1000000 / fps, but the implementation will resolve the * rounding to ensure that framestepping, etc is exact. */ retro_usec_t reference; }; @@ -1630,7 +1855,7 @@ struct retro_frame_time_callback * it should implement context_destroy callback. * If called, all GPU resources must be reinitialized. * Usually called when frontend reinits video driver. - * Also called first time video driver is initialized, + * Also called first time video driver is initialized, * allowing libretro core to initialize resources. */ typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); @@ -1647,7 +1872,7 @@ enum retro_hw_context_type { RETRO_HW_CONTEXT_NONE = 0, /* OpenGL 2.x. Driver can choose to use latest compatibility context. */ - RETRO_HW_CONTEXT_OPENGL = 1, + RETRO_HW_CONTEXT_OPENGL = 1, /* OpenGL ES 2.0. */ RETRO_HW_CONTEXT_OPENGLES2 = 2, /* Modern desktop core GL context. Use version_major/ @@ -1662,6 +1887,10 @@ enum retro_hw_context_type /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ RETRO_HW_CONTEXT_VULKAN = 6, + /* Direct3D, set version_major to select the type of interface + * returned by RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */ + RETRO_HW_CONTEXT_DIRECT3D = 7, + RETRO_HW_CONTEXT_DUMMY = INT_MAX }; @@ -1673,10 +1902,10 @@ struct retro_hw_render_callback /* Called when a context has been created or when it has been reset. * An OpenGL context is only valid after context_reset() has been called. * - * When context_reset is called, OpenGL resources in the libretro + * When context_reset is called, OpenGL resources in the libretro * implementation are guaranteed to be invalid. * - * It is possible that context_reset is called multiple times during an + * It is possible that context_reset is called multiple times during an * application lifecycle. * If context_reset is called without any notification (context_destroy), * the OpenGL context was lost and resources should just be recreated @@ -1689,7 +1918,8 @@ struct retro_hw_render_callback * be providing preallocated framebuffers. */ retro_hw_get_current_framebuffer_t get_current_framebuffer; - /* Set by frontend. */ + /* Set by frontend. + * Can return all relevant functions, including glClear on Windows. */ retro_hw_get_proc_address_t get_proc_address; /* Set if render buffers should have depth component attached. @@ -1700,48 +1930,48 @@ struct retro_hw_render_callback * TODO: Obsolete. */ bool stencil; - /* If depth and stencil are true, a packed 24/8 buffer will be added. + /* If depth and stencil are true, a packed 24/8 buffer will be added. * Only attaching stencil is invalid and will be ignored. */ - /* Use conventional bottom-left origin convention. If false, + /* Use conventional bottom-left origin convention. If false, * standard libretro top-left origin semantics are used. * TODO: Move to GL specific interface. */ bool bottom_left_origin; - + /* Major version number for core GL context or GLES 3.1+. */ unsigned version_major; /* Minor version number for core GL context or GLES 3.1+. */ unsigned version_minor; - /* If this is true, the frontend will go very far to avoid + /* If this is true, the frontend will go very far to avoid * resetting context in scenarios like toggling fullscreen, etc. * TODO: Obsolete? Maybe frontend should just always assume this ... */ bool cache_context; - /* The reset callback might still be called in extreme situations + /* The reset callback might still be called in extreme situations * such as if the context is lost beyond recovery. * - * For optimal stability, set this to false, and allow context to be + * For optimal stability, set this to false, and allow context to be * reset at any time. */ - - /* A callback to be called before the context is destroyed in a + + /* A callback to be called before the context is destroyed in a * controlled way by the frontend. */ retro_hw_context_reset_t context_destroy; /* OpenGL resources can be deinitialized cleanly at this step. - * context_destroy can be set to NULL, in which resources will + * context_destroy can be set to NULL, in which resources will * just be destroyed without any notification. * - * Even when context_destroy is non-NULL, it is possible that + * Even when context_destroy is non-NULL, it is possible that * context_reset is called without any destroy notification. - * This happens if context is lost by external factors (such as + * This happens if context is lost by external factors (such as * notified by GL_ARB_robustness). * * In this case, the context is assumed to be already dead, - * and the libretro implementation must not try to free any OpenGL + * and the libretro implementation must not try to free any OpenGL * resources in the subsequent context_reset. */ @@ -1749,7 +1979,7 @@ struct retro_hw_render_callback bool debug_context; }; -/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. +/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. * Called by the frontend in response to keyboard events. * down is set if the key is being pressed, or false if it is being released. * keycode is the RETROK value of the char. @@ -1757,16 +1987,16 @@ struct retro_hw_render_callback * key_modifiers is a set of RETROKMOD values or'ed together. * * The pressed/keycode state can be indepedent of the character. - * It is also possible that multiple characters are generated from a + * It is also possible that multiple characters are generated from a * single keypress. * Keycode events should be treated separately from character events. * However, when possible, the frontend should try to synchronize these. * If only a character is posted, keycode should be RETROK_UNKNOWN. * - * Similarily if only a keycode event is generated with no corresponding + * Similarily if only a keycode event is generated with no corresponding * character, character should be 0. */ -typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, +typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); struct retro_keyboard_callback @@ -1775,15 +2005,15 @@ struct retro_keyboard_callback }; /* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. - * Should be set for implementations which can swap out multiple disk + * Should be set for implementations which can swap out multiple disk * images in runtime. * * If the implementation can do this automatically, it should strive to do so. * However, there are cases where the user must manually do so. * - * Overview: To swap a disk image, eject the disk image with + * Overview: To swap a disk image, eject the disk image with * set_eject_state(true). - * Set the disk index with set_image_index(index). Insert the disk again + * Set the disk index with set_image_index(index). Insert the disk again * with set_eject_state(false). */ @@ -1801,7 +2031,7 @@ typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); /* Sets image index. Can only be called when disk is ejected. - * The implementation supports setting "no disk" by using an + * The implementation supports setting "no disk" by using an * index >= get_num_images(). */ typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); @@ -1815,11 +2045,11 @@ struct retro_game_info; * Arguments to pass in info have same requirements as retro_load_game(). * Virtual disk tray must be ejected when calling this. * - * Replacing a disk image with info = NULL will remove the disk image + * Replacing a disk image with info = NULL will remove the disk image * from the internal list. * As a result, calls to get_image_index() can change. * - * E.g. replace_image_index(1, NULL), and previous get_image_index() + * E.g. replace_image_index(1, NULL), and previous get_image_index() * returned 4 before. * Index 1 will be removed, and the new index is 3. */ @@ -1828,7 +2058,7 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, /* Adds a new valid index (get_num_images()) to the internal disk list. * This will increment subsequent return values from get_num_images() by 1. - * This image index cannot be used until a disk image has been set + * This image index cannot be used until a disk image has been set * with replace_image_index. */ typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); @@ -1859,7 +2089,7 @@ enum retro_pixel_format /* RGB565, native endian. * This pixel format is the recommended format to use if a 15/16-bit - * format is desired as it is the pixel format that is typically + * format is desired as it is the pixel format that is typically * available on a wide range of low-power devices. * * It is also natively supported in APIs like OpenGL ES. */ @@ -1889,43 +2119,43 @@ struct retro_input_descriptor /* Human readable description for parameters. * The pointer must remain valid until * retro_unload_game() is called. */ - const char *description; + const char *description; }; struct retro_system_info { - /* All pointers are owned by libretro implementation, and pointers must + /* All pointers are owned by libretro implementation, and pointers must * remain valid until retro_deinit() is called. */ - const char *library_name; /* Descriptive name of library. Should not + const char *library_name; /* Descriptive name of library. Should not * contain any version numbers, etc. */ const char *library_version; /* Descriptive version of core. */ - const char *valid_extensions; /* A string listing probably content - * extensions the core will be able to + const char *valid_extensions; /* A string listing probably content + * extensions the core will be able to * load, separated with pipe. * I.e. "bin|rom|iso". - * Typically used for a GUI to filter + * Typically used for a GUI to filter * out extensions. */ - /* If true, retro_load_game() is guaranteed to provide a valid pathname + /* If true, retro_load_game() is guaranteed to provide a valid pathname * in retro_game_info::path. * ::data and ::size are both invalid. * - * If false, ::data and ::size are guaranteed to be valid, but ::path + * If false, ::data and ::size are guaranteed to be valid, but ::path * might not be valid. * - * This is typically set to true for libretro implementations that must + * This is typically set to true for libretro implementations that must * load from file. - * Implementations should strive for setting this to false, as it allows + * Implementations should strive for setting this to false, as it allows * the frontend to perform patching, etc. */ - bool need_fullpath; + bool need_fullpath; - /* If true, the frontend is not allowed to extract any archives before + /* If true, the frontend is not allowed to extract any archives before * loading the real content. - * Necessary for certain libretro implementations that load games + * Necessary for certain libretro implementations that load games * from zipped archives. */ - bool block_extract; + bool block_extract; }; struct retro_game_geometry @@ -1957,14 +2187,14 @@ struct retro_system_av_info struct retro_variable { /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. - * If NULL, obtains the complete environment string if more + * If NULL, obtains the complete environment string if more * complex parsing is necessary. - * The environment string is formatted as key-value pairs + * The environment string is formatted as key-value pairs * delimited by semicolons as so: * "key1=value1;key2=value2;..." */ const char *key; - + /* Value to be obtained. If key does not exist, it is set to NULL. */ const char *value; }; @@ -1972,12 +2202,14 @@ struct retro_variable struct retro_game_info { const char *path; /* Path to game, UTF-8 encoded. - * Usually used as a reference. - * May be NULL if rom was loaded from stdin - * or similar. - * retro_system_info::need_fullpath guaranteed + * Sometimes used as a reference for building other paths. + * May be NULL if game was loaded from stdin or similar, + * but in this case some cores will be unable to load `data`. + * So, it is preferable to fabricate something here instead + * of passing NULL, which will help more cores to succeed. + * retro_system_info::need_fullpath requires * that this path is valid. */ - const void *data; /* Memory buffer of loaded game. Will be NULL + const void *data; /* Memory buffer of loaded game. Will be NULL * if need_fullpath was set. */ size_t size; /* Size of memory buffer. */ const char *meta; /* String of implementation specific meta-data. */ @@ -2015,25 +2247,25 @@ struct retro_framebuffer /* Callbacks */ -/* Environment callback. Gives implementations a way of performing +/* Environment callback. Gives implementations a way of performing * uncommon tasks. Extensible. */ typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); -/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian +/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). * * Width and height specify dimensions of buffer. * Pitch specifices length in bytes between two lines in buffer. * - * For performance reasons, it is highly recommended to have a frame + * For performance reasons, it is highly recommended to have a frame * that is packed in memory, i.e. pitch == width * byte_per_pixel. - * Certain graphic APIs, such as OpenGL ES, do not like textures + * Certain graphic APIs, such as OpenGL ES, do not like textures * that are not packed in memory. */ typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); -/* Renders a single audio frame. Should only be used if implementation +/* Renders a single audio frame. Should only be used if implementation * generates a single sample at a time. * Format is signed 16-bit native endian. */ @@ -2051,20 +2283,20 @@ typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, /* Polls input. */ typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); -/* Queries for input for player 'port'. device will be masked with +/* Queries for input for player 'port'. device will be masked with * RETRO_DEVICE_MASK. * - * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that + * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that * have been set with retro_set_controller_port_device() * will still use the higher level RETRO_DEVICE_JOYPAD to request input. */ -typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, +typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); -/* Sets callbacks. retro_set_environment() is guaranteed to be called +/* Sets callbacks. retro_set_environment() is guaranteed to be called * before retro_init(). * - * The rest of the set_* functions are guaranteed to have been called + * The rest of the set_* functions are guaranteed to have been called * before the first call to retro_run() is made. */ RETRO_API void retro_set_environment(retro_environment_t); RETRO_API void retro_set_video_refresh(retro_video_refresh_t); @@ -2081,26 +2313,26 @@ RETRO_API void retro_deinit(void); * when the API is revised. */ RETRO_API unsigned retro_api_version(void); -/* Gets statically known system info. Pointers provided in *info +/* Gets statically known system info. Pointers provided in *info * must be statically allocated. * Can be called at any time, even before retro_init(). */ RETRO_API void retro_get_system_info(struct retro_system_info *info); /* Gets information about system audio/video timings and geometry. * Can be called only after retro_load_game() has successfully completed. - * NOTE: The implementation of this function might not initialize every + * NOTE: The implementation of this function might not initialize every * variable if needed. - * E.g. geom.aspect_ratio might not be initialized if core doesn't + * E.g. geom.aspect_ratio might not be initialized if core doesn't * desire a particular aspect ratio. */ RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); /* Sets device to be used for player 'port'. - * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all + * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all * available ports. - * Setting a particular device type is not a guarantee that libretro cores - * will only poll input based on that particular device type. It is only a - * hint to the libretro core when a core cannot automatically detect the - * appropriate input device type on its own. It is also relevant when a + * Setting a particular device type is not a guarantee that libretro cores + * will only poll input based on that particular device type. It is only a + * hint to the libretro core when a core cannot automatically detect the + * appropriate input device type on its own. It is also relevant when a * core can change its behavior depending on device type. */ RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); @@ -2109,18 +2341,18 @@ RETRO_API void retro_reset(void); /* Runs the game for one video frame. * During retro_run(), input_poll callback must be called at least once. - * + * * If a frame is not rendered for reasons where a game "dropped" a frame, - * this still counts as a frame, and retro_run() should explicitly dupe + * this still counts as a frame, and retro_run() should explicitly dupe * a frame if GET_CAN_DUPE returns true. * In this case, the video callback can take a NULL argument for data. */ RETRO_API void retro_run(void); -/* Returns the amount of data the implementation requires to serialize +/* Returns the amount of data the implementation requires to serialize * internal state (save states). - * Between calls to retro_load_game() and retro_unload_game(), the - * returned size is never allowed to be larger than a previous returned + * Between calls to retro_load_game() and retro_unload_game(), the + * returned size is never allowed to be larger than a previous returned * value, to ensure that the frontend can allocate a save state buffer once. */ RETRO_API size_t retro_serialize_size(void); diff --git a/libretro/libretro-common/include/memmap.h b/libretro/libretro-common/include/memmap.h index 5dc1a89..2bedd5c 100644 --- a/libretro/libretro-common/include/memmap.h +++ b/libretro/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). @@ -23,7 +23,10 @@ #ifndef _LIBRETRO_MEMMAP_H #define _LIBRETRO_MEMMAP_H -#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) +#include +#include + +#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) /* No mman available */ #elif defined(_WIN32) && !defined(_XBOX) #include diff --git a/libretro/libretro-common/include/retro_common.h b/libretro/libretro-common/include/retro_common.h index 3385723..e4804fa 100644 --- a/libretro/libretro-common/include/retro_common.h +++ b/libretro/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). @@ -26,7 +26,7 @@ /* This file is designed to normalize the libretro-common compiling environment. It is not to be used in public API headers, as they should be designed as leanly as possible. -Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable, +Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable, in a public API, you may need this. */ diff --git a/libretro/libretro-common/include/retro_common_api.h b/libretro/libretro-common/include/retro_common_api.h index 38b6773..c3b3f49 100644 --- a/libretro/libretro-common/include/retro_common_api.h +++ b/libretro/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). @@ -25,14 +25,14 @@ /* This file is designed to normalize the libretro-common compiling environment -for public API headers. This should be leaner than a normal compiling environment, +for public API headers. This should be leaner than a normal compiling environment, since it gets #included into other project's sources. */ /* ------------------------------------ */ /* -Ordinarily we want to put #ifdef __cplusplus extern "C" in C library +Ordinarily we want to put #ifdef __cplusplus extern "C" in C library headers to enable them to get used by c++ sources. However, we want to support building this library as C++ as well, so a special technique is called for. @@ -75,19 +75,29 @@ typedef int ssize_t; #include #endif -#ifdef _WIN32 -#define STRING_REP_INT64 "%I64u" -#define STRING_REP_UINT64 "%I64u" -#define STRING_REP_ULONG "%Iu" -#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L && !defined(VITA) && !defined(WIIU) -#define STRING_REP_INT64 "%llu" -#define STRING_REP_UINT64 "%llu" -#define STRING_REP_ULONG "%zu" +#ifdef _MSC_VER +#if _MSC_VER >= 1800 +#include #else -#define STRING_REP_INT64 "%llu" -#define STRING_REP_UINT64 "%llu" -#define STRING_REP_ULONG "%lu" +#ifndef PRId64 +#define PRId64 "I64d" +#define PRIu64 "I64u" +#define PRIuPTR "Iu" #endif +#endif +#else +/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */ +/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */ +/* https://github.com/libretro/RetroArch/issues/6009 */ +#define __STDC_FORMAT_MACROS +#include +#endif +#ifndef PRId64 +#error "inttypes.h is being screwy" +#endif +#define STRING_REP_INT64 "%" PRId64 +#define STRING_REP_UINT64 "%" PRIu64 +#define STRING_REP_USIZE "%" PRIuPTR /* I would like to see retro_inline.h moved in here; possibly boolean too. diff --git a/libretro/libretro-common/include/retro_inline.h b/libretro/libretro-common/include/retro_inline.h index ffdaa4a..e4a21f6 100644 --- a/libretro/libretro-common/include/retro_inline.h +++ b/libretro/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/libretro-common/include/retro_miscellaneous.h b/libretro/libretro-common/include/retro_miscellaneous.h deleted file mode 100644 index 790f6e8..0000000 --- a/libretro/libretro-common/include/retro_miscellaneous.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (C) 2010-2017 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (retro_miscellaneous.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. - */ - -#ifndef __RARCH_MISCELLANEOUS_H -#define __RARCH_MISCELLANEOUS_H - -#include - -#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) -#include -#elif defined(XENON) -#include