Selectively replace fopen() with fopen_utf8()
authornegativeExponent <negativeExponent@users.noreply.github.com>
Tue, 20 Apr 2021 12:00:18 +0000 (20:00 +0800)
committernegativeExponent <negativeExponent@users.noreply.github.com>
Tue, 20 Apr 2021 12:00:18 +0000 (20:00 +0800)
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

13 files changed:
Makefile
frontend/libretro.c
libpcsxcore/cdriso.c
libpcsxcore/psxmem.c
libpcsxcore/sio.c
libretro-common/compat/fopen_utf8.c [new file with mode: 0644]
libretro-common/include/boolean.h [new file with mode: 0644]
libretro-common/include/compat/fopen_utf8.h [new file with mode: 0644]
libretro-common/include/encodings/utf.h [new file with mode: 0644]
libretro-common/include/libretro.h
libretro-common/include/retro_common_api.h [new file with mode: 0644]
libretro-common/include/retro_inline.h
plugins/cdrcimg/cdrcimg.c

index 1015cf2..52761dc 100644 (file)
--- 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
index 9aadb32..f94bcc6 100644 (file)
@@ -39,6 +39,7 @@
 #include "revision.h"
 
 #include <libretro.h>
+#include <compat/fopen_utf8.h>
 #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;
 
index 9e70ddf..c36c196 100644 (file)
@@ -19,6 +19,8 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
  ***************************************************************************/
 
+#include <compat/fopen_utf8.h>
+
 #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;
index 11a01ad..53edfab 100644 (file)
@@ -23,6 +23,8 @@
 
 // TODO: Implement caches & cycle penalty.
 
+#include <compat/fopen_utf8.h>
+
 #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);
index c2390bf..ae3e634 100644 (file)
@@ -17,6 +17,8 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
  ***************************************************************************/
 
+#include <compat/fopen_utf8.h>
+
 /*
 * 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 (file)
index 0000000..85abb59
--- /dev/null
@@ -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 <compat/fopen_utf8.h>
+#include <encodings/utf.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..9d0d7c1
--- /dev/null
@@ -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 <stdbool.h>
+#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 (file)
index 0000000..97d4404
--- /dev/null
@@ -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 (file)
index 0000000..bea4e14
--- /dev/null
@@ -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 <stdint.h>
+#include <stddef.h>
+
+#include <boolean.h>
+
+#include <retro_common_api.h>
+
+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
index 833dfed..8a5da86 100644 (file)
@@ -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 (file)
index 0000000..0f68b7d
--- /dev/null
@@ -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 <sys/types.h>
+#endif
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1800
+#include <inttypes.h>
+#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 <inttypes.h>
+#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
index e4a21f6..b27d6dd 100644 (file)
@@ -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).
index f1e0777..007e96b 100644 (file)
@@ -8,6 +8,8 @@
  * See the COPYING file in the top-level directory.
  */
 
+#include <compat/fopen_utf8.h>
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -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);