diff --git a/libgambatte/libretro-common/compat/fopen_utf8.c b/libgambatte/libretro-common/compat/fopen_utf8.c index b61c53e..d9fe35f 100644 --- a/libgambatte/libretro-common/compat/fopen_utf8.c +++ b/libgambatte/libretro-common/compat/fopen_utf8.c @@ -1,5 +1,6 @@ #include #include +#include #include #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX) @@ -11,14 +12,19 @@ #ifdef _WIN32 #undef fopen -FILE* fopen_utf8(const char * filename, const char * mode) +void *fopen_utf8(const char * filename, const char * mode) { #if defined(_XBOX) return fopen(filename, mode); #elif defined(LEGACY_WIN32) + FILE *ret = NULL; char * filename_local = utf8_to_local_string_alloc(filename); - FILE* ret = fopen(filename_local, mode); - free(filename_local); + + 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); diff --git a/libgambatte/libretro-common/include/boolean.h b/libgambatte/libretro-common/include/boolean.h index 2c18ef7..8a5482c 100644 --- a/libgambatte/libretro-common/include/boolean.h +++ b/libgambatte/libretro-common/include/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/libgambatte/libretro-common/include/compat/fopen_utf8.h b/libgambatte/libretro-common/include/compat/fopen_utf8.h index 67cc289..1fe6a8a 100644 --- a/libgambatte/libretro-common/include/compat/fopen_utf8.h +++ b/libgambatte/libretro-common/include/compat/fopen_utf8.h @@ -1,13 +1,11 @@ #ifndef __FOPEN_UTF8_H #define __FOPEN_UTF8_H -#include - #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) */ -FILE* fopen_utf8(const char * filename, const char * mode); +void *fopen_utf8(const char * filename, const char * mode); #else #define fopen_utf8 fopen #endif diff --git a/libgambatte/libretro-common/include/compat/msvc.h b/libgambatte/libretro-common/include/compat/msvc.h index 7302f64..fea4b53 100644 --- a/libgambatte/libretro-common/include/compat/msvc.h +++ b/libgambatte/libretro-common/include/compat/msvc.h @@ -109,11 +109,6 @@ typedef int ssize_t; #define fabsf(x) ((float)fabs((double)(x))) #endif - #ifndef _vscprintf - #define _vscprintf c89_vscprintf_retro__ - int c89_vscprintf_retro__(const char *format, va_list pargs); - #endif - #ifndef _strtoui64 #define _strtoui64(x, y, z) (_atoi64(x)) #endif diff --git a/libgambatte/libretro-common/include/libretro.h b/libgambatte/libretro-common/include/libretro.h index 7148f47..7d01185 100644 --- a/libgambatte/libretro-common/include/libretro.h +++ b/libgambatte/libretro-common/include/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 @@ -270,6 +270,7 @@ enum retro_language RETRO_LANGUAGE_ESPERANTO = 13, RETRO_LANGUAGE_POLISH = 14, RETRO_LANGUAGE_VIETNAMESE = 15, + RETRO_LANGUAGE_ARABIC = 16, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ @@ -375,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, @@ -1083,8 +1088,12 @@ struct retro_vfs_interface_info 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 @@ -1098,7 +1107,7 @@ struct retro_hw_render_interface #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 + * Gets an interface which is used by a libretro core to set * state of LEDs. */ @@ -1108,6 +1117,47 @@ 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 ** -- @@ -1837,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 }; diff --git a/libgambatte/libretro-common/include/retro_common_api.h b/libgambatte/libretro-common/include/retro_common_api.h index c2eeac0..ff38f98 100644 --- a/libgambatte/libretro-common/include/retro_common_api.h +++ b/libgambatte/libretro-common/include/retro_common_api.h @@ -76,11 +76,15 @@ typedef int ssize_t; #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 */ diff --git a/libgambatte/libretro-common/include/retro_miscellaneous.h b/libgambatte/libretro-common/include/retro_miscellaneous.h index e526d6e..23f9ef0 100644 --- a/libgambatte/libretro-common/include/retro_miscellaneous.h +++ b/libgambatte/libretro-common/include/retro_miscellaneous.h @@ -23,6 +23,9 @@ #ifndef __RARCH_MISCELLANEOUS_H #define __RARCH_MISCELLANEOUS_H +#define RARCH_MAX_SUBSYSTEMS 10 +#define RARCH_MAX_SUBSYSTEM_ROMS 10 + #include #include #include diff --git a/libgambatte/libretro-common/include/streams/file_stream.h b/libgambatte/libretro-common/include/streams/file_stream.h index fba803c..1ae545d 100644 --- a/libgambatte/libretro-common/include/streams/file_stream.h +++ b/libgambatte/libretro-common/include/streams/file_stream.h @@ -60,19 +60,19 @@ int64_t filestream_get_size(RFILE *stream); **/ RFILE *filestream_open(const char *path, unsigned mode, unsigned hints); -ssize_t filestream_seek(RFILE *stream, ssize_t offset, int seek_position); +int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position); -ssize_t filestream_read(RFILE *stream, void *data, int64_t len); +int64_t filestream_read(RFILE *stream, void *data, int64_t len); -ssize_t filestream_write(RFILE *stream, const void *data, int64_t len); +int64_t filestream_write(RFILE *stream, const void *data, int64_t len); -ssize_t filestream_tell(RFILE *stream); +int64_t filestream_tell(RFILE *stream); void filestream_rewind(RFILE *stream); int filestream_close(RFILE *stream); -int filestream_read_file(const char *path, void **buf, ssize_t *len); +int64_t filestream_read_file(const char *path, void **buf, int64_t *len); char *filestream_gets(RFILE *stream, char *s, size_t len); @@ -80,7 +80,7 @@ int filestream_getc(RFILE *stream); int filestream_eof(RFILE *stream); -bool filestream_write_file(const char *path, const void *data, ssize_t size); +bool filestream_write_file(const char *path, const void *data, int64_t size); int filestream_putc(RFILE *stream, int c); diff --git a/libgambatte/libretro-common/streams/file_stream.c b/libgambatte/libretro-common/streams/file_stream.c index 2e72402..a73b78f 100644 --- a/libgambatte/libretro-common/streams/file_stream.c +++ b/libgambatte/libretro-common/streams/file_stream.c @@ -31,6 +31,7 @@ #endif #include +#define VFS_FRONTEND #include static const int64_t vfs_error_return_value = -1; @@ -190,7 +191,7 @@ int filestream_getc(RFILE *stream) return EOF; } -ssize_t filestream_seek(RFILE *stream, ssize_t offset, int seek_position) +int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position) { int64_t output; @@ -212,9 +213,9 @@ int filestream_eof(RFILE *stream) } -ssize_t filestream_tell(RFILE *stream) +int64_t filestream_tell(RFILE *stream) { - ssize_t output; + int64_t output; if (filestream_size_cb != NULL) output = filestream_tell_cb(stream->hfile); @@ -236,7 +237,7 @@ void filestream_rewind(RFILE *stream) stream->eof_flag = false; } -ssize_t filestream_read(RFILE *stream, void *s, int64_t len) +int64_t filestream_read(RFILE *stream, void *s, int64_t len) { int64_t output; @@ -293,7 +294,7 @@ const char *filestream_get_path(RFILE *stream) return retro_vfs_file_get_path_impl((libretro_vfs_implementation_file*)stream->hfile); } -ssize_t filestream_write(RFILE *stream, const void *s, int64_t len) +int64_t filestream_write(RFILE *stream, const void *s, int64_t len) { int64_t output; @@ -319,14 +320,14 @@ int filestream_putc(RFILE *stream, int c) int filestream_vprintf(RFILE *stream, const char* format, va_list args) { static char buffer[8 * 1024]; - int num_chars = vsprintf(buffer, format, args); + int64_t num_chars = vsprintf(buffer, format, args); if (num_chars < 0) return -1; else if (num_chars == 0) return 0; - return filestream_write(stream, buffer, num_chars); + return (int)filestream_write(stream, buffer, num_chars); } int filestream_printf(RFILE *stream, const char* format, ...) @@ -372,9 +373,9 @@ int filestream_close(RFILE *stream) * * Returns: number of items read, -1 on error. */ -int filestream_read_file(const char *path, void **buf, ssize_t *len) +int64_t filestream_read_file(const char *path, void **buf, int64_t *len) { - ssize_t ret = 0; + int64_t ret = 0; int64_t content_buf_size = 0; void *content_buf = NULL; RFILE *file = filestream_open(path, @@ -396,7 +397,7 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len) if (!content_buf) goto error; - if ((int64_t)(size_t)(content_buf_size + 1) != (content_buf_size + 1)) + if ((int64_t)(uint64_t)(content_buf_size + 1) != (content_buf_size + 1)) goto error; ret = filestream_read(file, content_buf, (int64_t)content_buf_size); @@ -440,9 +441,9 @@ error: * * Returns: true (1) on success, false (0) otherwise. */ -bool filestream_write_file(const char *path, const void *data, ssize_t size) +bool filestream_write_file(const char *path, const void *data, int64_t size) { - ssize_t ret = 0; + int64_t ret = 0; RFILE *file = filestream_open(path, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); @@ -460,21 +461,27 @@ bool filestream_write_file(const char *path, const void *data, ssize_t size) char *filestream_getline(RFILE *stream) { - char* newline = (char*)malloc(9); - char* newline_tmp = NULL; - size_t cur_size = 8; - size_t idx = 0; - int in = filestream_getc(stream); + char* newline_tmp = NULL; + size_t cur_size = 8; + size_t idx = 0; + int in = 0; + char* newline = (char*)malloc(9); - if (!newline) + if (!stream || !newline) + { + if (newline) + free(newline); return NULL; + } + + in = filestream_getc(stream); while (in != EOF && in != '\n') { if (idx == cur_size) { - cur_size *= 2; - newline_tmp = (char*)realloc(newline, cur_size + 1); + cur_size *= 2; + newline_tmp = (char*)realloc(newline, cur_size + 1); if (!newline_tmp) { @@ -482,13 +489,13 @@ char *filestream_getline(RFILE *stream) return NULL; } - newline = newline_tmp; + newline = newline_tmp; } newline[idx++] = in; in = filestream_getc(stream); } - newline[idx] = '\0'; + newline[idx] = '\0'; return newline; } diff --git a/libgambatte/libretro-common/vfs/vfs_implementation.c b/libgambatte/libretro-common/vfs/vfs_implementation.c index ba96284..ce6fa5b 100644 --- a/libgambatte/libretro-common/vfs/vfs_implementation.c +++ b/libgambatte/libretro-common/vfs/vfs_implementation.c @@ -75,6 +75,12 @@ #endif +#if defined(_WIN32) && !defined(_XBOX) +#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400) +#define ATLEAST_VC2005 +#endif +#endif + #ifdef RARCH_INTERNAL #ifndef VFS_FRONTEND #define VFS_FRONTEND @@ -114,7 +120,14 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i goto error; if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) +/* VC2005 and up have a special 64-bit fseek */ +#ifdef ATLEAST_VC2005 + return _fseeki64(stream->fp, offset, whence); +#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310 return fseek(stream->fp, (long)offset, whence); +#else + return fseeko(stream->fp, (off_t)offset, whence); +#endif #ifdef HAVE_MMAP /* Need to check stream->mapped because this function is @@ -251,12 +264,9 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) { - if (!mode_str) - goto error; + FILE *fp = (FILE*)fopen_utf8(path, mode_str); - stream->fp = fopen_utf8(path, mode_str); - - if (!stream->fp) + if (!fp) goto error; /* Regarding setvbuf: @@ -269,6 +279,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns * Since C89 does not support specifying a null buffer with a non-zero size, we create and track our own buffer for it. */ /* TODO: this is only useful for a few platforms, find which and add ifdef */ + stream->fp = fp; stream->buf = (char*)calloc(1, 0x4000); setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000); } @@ -375,7 +386,12 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream) return -1; if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) +/* VC2005 and up have a special 64-bit ftell */ +#ifdef ATLEAST_VC2005 + return _ftelli64(stream->fp); +#else return ftell(stream->fp); +#endif #ifdef HAVE_MMAP /* Need to check stream->mapped because this function diff --git a/libgambatte/libretro/libretro.cpp b/libgambatte/libretro/libretro.cpp index 173d395..0741d1d 100644 --- a/libgambatte/libretro/libretro.cpp +++ b/libgambatte/libretro/libretro.cpp @@ -82,20 +82,23 @@ bool file_present_in_system(std::string fname) bool get_bootloader_from_file(void* userdata, bool isgbc, uint8_t* data, uint32_t buf_size) { + std::string path; + unsigned int size; + RFILE *fp = NULL; + int64_t n = 0; + bool worked = false; + const char *systemdirtmp = NULL; if (!use_official_bootloader) return false; // get path - const char *systemdirtmp = NULL; - bool worked = environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemdirtmp); + worked = environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemdirtmp); if (!worked) return false; - std::string path = systemdirtmp; + path = systemdirtmp; path += "/"; //retroarch/libretro does not add a slash at the end of directory names - unsigned int size; - if (isgbc) { path += "gbc_bios.bin"; @@ -111,17 +114,14 @@ bool get_bootloader_from_file(void* userdata, bool isgbc, uint8_t* data, uint32_ return false; // open file - int n = 0; - RFILE *fp = filestream_open(path.c_str(), RETRO_VFS_FILE_ACCESS_READ, + fp = filestream_open(path.c_str(), RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if (fp) - { - n = filestream_read(fp, data, size); - filestream_close(fp); - } - else + if (!fp) return false; + + n = filestream_read(fp, data, size); + filestream_close(fp); if (n != size) return false;