From 270c6dd14f876b8a67929aa22abefc47f4588324 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Tue, 20 Apr 2021 20:00:18 +0800 Subject: [PATCH] Selectively replace fopen() with fopen_utf8() This selectively replace fopen calls with fopen_utf8, to handle paths that uses special characters in Windows. The replacement covers these: - opening of bios file - opening, writting and creating memcard2 - opening and handling of disk images Related: https://github.com/libretro/libretro-fceumm/issues/448 --- Makefile | 1 + frontend/libretro.c | 5 +- libpcsxcore/cdriso.c | 26 +++-- libpcsxcore/psxmem.c | 4 +- libpcsxcore/sio.c | 10 +- libretro-common/compat/fopen_utf8.c | 63 +++++++++++ libretro-common/include/boolean.h | 39 +++++++ libretro-common/include/compat/fopen_utf8.h | 34 ++++++ libretro-common/include/encodings/utf.h | 67 +++++++++++ libretro-common/include/libretro.h | 86 +++++++++++++- libretro-common/include/retro_common_api.h | 119 ++++++++++++++++++++ libretro-common/include/retro_inline.h | 2 +- plugins/cdrcimg/cdrcimg.c | 8 +- 13 files changed, 440 insertions(+), 24 deletions(-) create mode 100644 libretro-common/compat/fopen_utf8.c create mode 100644 libretro-common/include/boolean.h create mode 100644 libretro-common/include/compat/fopen_utf8.h create mode 100644 libretro-common/include/encodings/utf.h create mode 100644 libretro-common/include/retro_common_api.h diff --git a/Makefile b/Makefile index 1015cf2b..52761dc0 100644 --- a/Makefile +++ b/Makefile @@ -295,6 +295,7 @@ CFLAGS += `pkg-config --cflags glib-2.0 libosso dbus-1 hildon-fm-2` LDFLAGS += `pkg-config --libs glib-2.0 libosso dbus-1 hildon-fm-2` endif ifeq "$(PLATFORM)" "libretro" +OBJS += libretro-common/compat/fopen_utf8.o OBJS += frontend/libretro.o CFLAGS += -Ilibretro-common/include CFLAGS += -DFRONTEND_SUPPORTS_RGB565 diff --git a/frontend/libretro.c b/frontend/libretro.c index 9aadb32f..f94bcc68 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -39,6 +39,7 @@ #include "revision.h" #include +#include #include "libretro_core_options.h" #ifdef _3DS @@ -1112,7 +1113,7 @@ static bool read_m3u(const char *file) { char line[1024]; char name[PATH_MAX]; - FILE *f = fopen(file, "r"); + FILE *f = fopen_utf8(file, "r"); if (!f) return false; @@ -2572,7 +2573,7 @@ static bool try_use_bios(const char *path) long size; const char *name; - f = fopen(path, "rb"); + f = fopen_utf8(path, "rb"); if (f == NULL) return false; diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index 9e70ddf0..c36c1961 100644 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -19,6 +19,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ +#include + #include "psxcommon.h" #include "plugins.h" #include "cdrom.h" @@ -334,16 +336,16 @@ static int parsetoc(const char *isofile) { return -1; } - if ((fi = fopen(tocname, "r")) == NULL) { + if ((fi = fopen_utf8(tocname, "r")) == NULL) { // try changing extension to .cue (to satisfy some stupid tutorials) strcpy(tocname + strlen(tocname) - 4, ".cue"); - if ((fi = fopen(tocname, "r")) == NULL) { + if ((fi = fopen_utf8(tocname, "r")) == NULL) { // if filename is image.toc.bin, try removing .bin (for Brasero) strcpy(tocname, isofile); t = strlen(tocname); if (t >= 8 && strcmp(tocname + t - 8, ".toc.bin") == 0) { tocname[t - 4] = '\0'; - if ((fi = fopen(tocname, "r")) == NULL) { + if ((fi = fopen_utf8(tocname, "r")) == NULL) { return -1; } } @@ -486,7 +488,7 @@ static int parsecue(const char *isofile) { return -1; } - if ((fi = fopen(cuename, "r")) == NULL) { + if ((fi = fopen_utf8(cuename, "r")) == NULL) { return -1; } @@ -590,7 +592,7 @@ static int parsecue(const char *isofile) { else tmp = tmpb; strncpy(incue_fname, tmp, incue_max_len); - ti[numtracks + 1].handle = fopen(filepath, "rb"); + ti[numtracks + 1].handle = fopen_utf8(filepath, "rb"); // update global offset if this is not first file in this .cue if (numtracks + 1 > 1) { @@ -611,7 +613,7 @@ static int parsecue(const char *isofile) { strncasecmp(isofile + strlen(isofile) - 4, ".cd", 3) == 0)) { // user selected .cue/.cdX as image file, use it's data track instead fclose(cdHandle); - cdHandle = fopen(filepath, "rb"); + cdHandle = fopen_utf8(filepath, "rb"); } } } @@ -645,7 +647,7 @@ static int parseccd(const char *isofile) { return -1; } - if ((fi = fopen(ccdname, "r")) == NULL) { + if ((fi = fopen_utf8(ccdname, "r")) == NULL) { return -1; } @@ -704,7 +706,7 @@ static int parsemds(const char *isofile) { return -1; } - if ((fi = fopen(mdsname, "rb")) == NULL) { + if ((fi = fopen_utf8(mdsname, "rb")) == NULL) { return -1; } @@ -1144,7 +1146,7 @@ static int opensubfile(const char *isoname) { return -1; } - subHandle = fopen(subname, "rb"); + subHandle = fopen_utf8(subname, "rb"); if (subHandle == NULL) { return -1; } @@ -1623,7 +1625,7 @@ static long CALLBACK ISOopen(void) { return 0; // it's already open } - cdHandle = fopen(GetIsoFile(), "rb"); + cdHandle = fopen_utf8(GetIsoFile(), "rb"); if (cdHandle == NULL) { SysPrintf(_("Could't open '%s' for reading: %s\n"), GetIsoFile(), strerror(errno)); @@ -1695,7 +1697,7 @@ static long CALLBACK ISOopen(void) { p = alt_bin_filename + strlen(alt_bin_filename) - 4; for (i = 0; i < sizeof(exts) / sizeof(exts[0]); i++) { strcpy(p, exts[i]); - tmpf = fopen(alt_bin_filename, "rb"); + tmpf = fopen_utf8(alt_bin_filename, "rb"); if (tmpf != NULL) break; } @@ -1731,7 +1733,7 @@ static long CALLBACK ISOopen(void) { // make sure we have another handle open for cdda if (numtracks > 1 && ti[1].handle == NULL) { - ti[1].handle = fopen(bin_filename, "rb"); + ti[1].handle = fopen_utf8(bin_filename, "rb"); } cdda_cur_sector = 0; cdda_file_offset = 0; diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 11a01adc..53edfabc 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -23,6 +23,8 @@ // TODO: Implement caches & cycle penalty. +#include + #include "psxmem.h" #include "psxmem_map.h" #include "r3000a.h" @@ -217,7 +219,7 @@ void psxMemReset() { if (strcmp(Config.Bios, "HLE") != 0) { sprintf(bios, "%s/%s", Config.BiosDir, Config.Bios); - f = fopen(bios, "rb"); + f = fopen_utf8(bios, "rb"); if (f == NULL) { SysMessage(_("Could not open BIOS:\"%s\". Enabling HLE Bios!\n"), bios); diff --git a/libpcsxcore/sio.c b/libpcsxcore/sio.c index c2390bf0..ae3e634a 100644 --- a/libpcsxcore/sio.c +++ b/libpcsxcore/sio.c @@ -17,6 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * ***************************************************************************/ +#include + /* * SIO functions. */ @@ -436,11 +438,11 @@ void LoadMcd(int mcd, char *str) { if (*str == 0) return; - f = fopen(str, "rb"); + f = fopen_utf8(str, "rb"); if (f == NULL) { SysPrintf(_("The memory card %s doesn't exist - creating it\n"), str); CreateMcd(str); - f = fopen(str, "rb"); + f = fopen_utf8(str, "rb"); if (f != NULL) { struct stat buf; @@ -481,7 +483,7 @@ void SaveMcd(char *mcd, char *data, uint32_t adr, int size) { if (mcd == NULL || *mcd == 0 || strcmp(mcd, "none") == 0) return; - f = fopen(mcd, "r+b"); + f = fopen_utf8(mcd, "r+b"); if (f != NULL) { struct stat buf; @@ -518,7 +520,7 @@ void CreateMcd(char *mcd) { int s = MCD_SIZE; int i = 0, j; - f = fopen(mcd, "wb"); + f = fopen_utf8(mcd, "wb"); if (f == NULL) return; diff --git a/libretro-common/compat/fopen_utf8.c b/libretro-common/compat/fopen_utf8.c new file mode 100644 index 00000000..85abb59e --- /dev/null +++ b/libretro-common/compat/fopen_utf8.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2010-2020 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(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 = NULL; + + if (filename_w && mode_w) + ret = _wfopen(filename_w, mode_w); + if (filename_w) + free(filename_w); + if (mode_w) + free(mode_w); + return ret; +#endif +} +#endif diff --git a/libretro-common/include/boolean.h b/libretro-common/include/boolean.h new file mode 100644 index 00000000..9d0d7c12 --- /dev/null +++ b/libretro-common/include/boolean.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2010-2020 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (boolean.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_BOOLEAN_H +#define __LIBRETRO_SDK_BOOLEAN_H + +#ifndef __cplusplus + +#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 +#define false 0 +#else +#include +#endif + +#endif + +#endif diff --git a/libretro-common/include/compat/fopen_utf8.h b/libretro-common/include/compat/fopen_utf8.h new file mode 100644 index 00000000..97d4404e --- /dev/null +++ b/libretro-common/include/compat/fopen_utf8.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2010-2020 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-common/include/encodings/utf.h b/libretro-common/include/encodings/utf.h new file mode 100644 index 00000000..bea4e145 --- /dev/null +++ b/libretro-common/include/encodings/utf.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2010-2020 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-common/include/libretro.h b/libretro-common/include/libretro.h index 833dfedd..8a5da864 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -279,6 +279,10 @@ enum retro_language RETRO_LANGUAGE_GREEK = 17, RETRO_LANGUAGE_TURKISH = 18, RETRO_LANGUAGE_SLOVAK = 19, + RETRO_LANGUAGE_PERSIAN = 20, + RETRO_LANGUAGE_HEBREW = 21, + RETRO_LANGUAGE_ASTURIAN = 22, + RETRO_LANGUAGE_FINNISH = 23, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ @@ -709,6 +713,9 @@ enum retro_mod * state of rumble motors in controllers. * A strong and weak motor is supported, and they can be * controlled indepedently. + * Should be called from either retro_init() or retro_load_game(). + * Should not be called from retro_set_environment(). + * Returns false if rumble functionality is unavailable. */ #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 /* uint64_t * -- @@ -1318,6 +1325,59 @@ enum retro_mod * fallback, stderr). */ +#define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61 + /* unsigned * -- + * Unsigned value is the number of active input devices + * provided by the frontend. This may change between + * frames, but will remain constant for the duration + * of each frame. + * If callback returns true, a core need not poll any + * input device with an index greater than or equal to + * the number of active devices. + * If callback returns false, the number of active input + * devices is unknown. In this case, all input devices + * should be considered active. + */ + +#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62 + /* const struct retro_audio_buffer_status_callback * -- + * Lets the core know the occupancy level of the frontend + * audio buffer. Can be used by a core to attempt frame + * skipping in order to avoid buffer under-runs. + * A core may pass NULL to disable buffer status reporting + * in the frontend. + */ + +#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63 + /* const unsigned * -- + * Sets minimum frontend audio latency in milliseconds. + * Resultant audio latency may be larger than set value, + * or smaller if a hardware limit is encountered. A frontend + * is expected to honour requests up to 512 ms. + * + * - If value is less than current frontend + * audio latency, callback has no effect + * - If value is zero, default frontend audio + * latency is set + * + * May be used by a core to increase audio latency and + * therefore decrease the probability of buffer under-runs + * (crackling) when performing 'intensive' operations. + * A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK + * to implement audio-buffer-based frame skipping may achieve + * optimal results by setting the audio latency to a 'high' + * (typically 6x or 8x) integer multiple of the expected + * frame time. + * + * WARNING: This can only be called from within retro_run(). + * Calling this can require a full reinitialization of audio + * drivers in the frontend, 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 audio + * callbacks happening after this call within the same retro_run() + * call will target the newly initialized driver. + */ + /* VFS functionality */ /* File paths: @@ -2207,6 +2267,30 @@ struct retro_frame_time_callback retro_usec_t reference; }; +/* Notifies a libretro core of the current occupancy + * level of the frontend audio buffer. + * + * - active: 'true' if audio buffer is currently + * in use. Will be 'false' if audio is + * disabled in the frontend + * + * - occupancy: Given as a value in the range [0,100], + * corresponding to the occupancy percentage + * of the audio buffer + * + * - underrun_likely: 'true' if the frontend expects an + * audio buffer underrun during the + * next frame (indicates that a core + * should attempt frame skipping) + * + * It will be called right before retro_run() every frame. */ +typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)( + bool active, unsigned occupancy, bool underrun_likely); +struct retro_audio_buffer_status_callback +{ + retro_audio_buffer_status_callback_t callback; +}; + /* Pass this to retro_video_refresh_t if rendering to hardware. * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. * */ @@ -2655,7 +2739,7 @@ struct retro_input_descriptor struct retro_system_info { /* All pointers are owned by libretro implementation, and pointers must - * remain valid until retro_deinit() is called. */ + * remain valid until it is unloaded. */ const char *library_name; /* Descriptive name of library. Should not * contain any version numbers, etc. */ diff --git a/libretro-common/include/retro_common_api.h b/libretro-common/include/retro_common_api.h new file mode 100644 index 00000000..0f68b7d9 --- /dev/null +++ b/libretro-common/include/retro_common_api.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2010-2020 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_common_api.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_COMMON_RETRO_COMMON_API_H +#define _LIBRETRO_COMMON_RETRO_COMMON_API_H + +/* +This file is designed to normalize the libretro-common 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 +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. +*/ + +#define RETRO_BEGIN_DECLS +#define RETRO_END_DECLS + +#ifdef __cplusplus + +#ifdef CXX_BUILD +/* build wants everything to be built as c++, so no extern "C" */ +#else +#undef RETRO_BEGIN_DECLS +#undef RETRO_END_DECLS +#define RETRO_BEGIN_DECLS extern "C" { +#define RETRO_END_DECLS } +#endif + +#else + +/* header is included by a C source file, so no extern "C" */ + +#endif + +/* +IMO, this non-standard ssize_t should not be used. +However, it's a good example of how to handle something like this. +*/ +#ifdef _MSC_VER +#ifndef HAVE_SSIZE_T +#define HAVE_SSIZE_T +#if defined(_WIN64) +typedef __int64 ssize_t; +#elif defined(_WIN32) +typedef int ssize_t; +#endif +#endif +#elif defined(__MACH__) +#include +#endif + +#ifdef _MSC_VER +#if _MSC_VER >= 1800 +#include +#else +#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 */ +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS 1 +#endif +#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. + +rationale: these are used in public APIs, and it is easier to find problems +and write code that works the first time portably when theyre included uniformly +than to do the analysis from scratch each time you think you need it, for each feature. + +Moreover it helps force you to make hard decisions: if you EVER bring in boolean.h, +then you should pay the price everywhere, so you can see how much grief it will cause. + +Of course, another school of thought is that you should do as little damage as possible +in as few places as possible... +*/ + +/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ +#endif diff --git a/libretro-common/include/retro_inline.h b/libretro-common/include/retro_inline.h index e4a21f6c..b27d6dd6 100644 --- a/libretro-common/include/retro_inline.h +++ b/libretro-common/include/retro_inline.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2020 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_inline.h). diff --git a/plugins/cdrcimg/cdrcimg.c b/plugins/cdrcimg/cdrcimg.c index f1e07773..007e96b9 100644 --- a/plugins/cdrcimg/cdrcimg.c +++ b/plugins/cdrcimg/cdrcimg.c @@ -8,6 +8,8 @@ * See the COPYING file in the top-level directory. */ +#include + #include #include #include @@ -321,7 +323,7 @@ static long handle_eboot(void) int i, ret; FILE *f; - f = fopen(cd_fname, "rb"); + f = fopen_utf8(cd_fname, "rb"); if (f == NULL) { err("missing file: %s: ", cd_fname); perror(NULL); @@ -460,7 +462,7 @@ static long CDRopen(void) return -1; } - f = fopen(table_fname, "rb"); + f = fopen_utf8(table_fname, "rb"); if (f == NULL) { err("missing file: %s: ", table_fname); perror(NULL); @@ -525,7 +527,7 @@ static long CDRopen(void) break; } - cd_file = fopen(cd_fname, "rb"); + cd_file = fopen_utf8(cd_fname, "rb"); if (cd_file == NULL) { err("failed to open: %s: ", table_fname); perror(NULL); -- 2.39.5