Update libretro-common to latest upstream#106
Update libretro-common to latest upstream#106JoeMatt wants to merge 49 commits intolibretro:masterfrom
Conversation
The bit shifting and masking is expensive on ARM64 for some reason. The unions seem to greatly reduce the perfomance hit of these common calls.
The values for offset0 and offset1 were coming out to 63 when they should be no more than 3. I think the devide should have beena modulus? I wrote out the code with more vars to figure ouit what was going on
looking at the offical shamusworld repo the division was moved after the 0xFF checks
GPU_RUNNING running macro was pretty slow on ARM for some reason. Bitswise structs are faster in my testing
Signed-off-by: Joe Mattiello <mail@joemattiello.com>
Signed-off-by: Joe Mattiello <mail@joemattiello.com>
Signed-off-by: Joe Mattiello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
The bit shifting and masking is expensive on ARM64 for some reason. The unions seem to greatly reduce the perfomance hit of these common calls. byte pack struct Move memory structs to header Disable some of my speed hacks to test mem corruption Wrap more of my structs in ifdefs for testing Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
GPU_RUNNING running macro was pretty slow on ARM for some reason. Bitswise structs are faster in my testing Try some blitter optimizations blitter sign fixes Signed-off-by: Joe Mattiello <mail@joemattiello.com> Comment out unused simd import Signed-off-by: Joe Mattiello <mail@joemattiello.com> Try some GPU optimizations and clarity post rebase cleanup Signed-off-by: Joseph Mattello <mail@joemattiello.com> Remove USE_STRUCTS ifdef Signed-off-by: Joseph Mattello <mail@joemattiello.com> gpu.c Fix bad return Signed-off-by: Joseph Mattello <mail@joemattiello.com> Fix gpu opcode bad merge Signed-off-by: Joseph Mattello <mail@joemattiello.com> remove duplicate struct defs Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
GPU_RUNNING running macro was pretty slow on ARM for some reason. Bitswise structs are faster in my testing Try some blitter optimizations blitter sign fixes Signed-off-by: Joe Mattiello <mail@joemattiello.com> Comment out unused simd import Signed-off-by: Joe Mattiello <mail@joemattiello.com> Try some GPU optimizations and clarity post rebase cleanup Signed-off-by: Joseph Mattello <mail@joemattiello.com> Remove USE_STRUCTS ifdef Signed-off-by: Joseph Mattello <mail@joemattiello.com> gpu.c Fix bad return Signed-off-by: Joseph Mattello <mail@joemattiello.com> Fix gpu opcode bad merge Signed-off-by: Joseph Mattello <mail@joemattiello.com> remove duplicate struct defs Signed-off-by: Joseph Mattello <mail@joemattiello.com>
GPU_RUNNING running macro was pretty slow on ARM for some reason. Bitswise structs are faster in my testing Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com> # Conflicts: # src/blitter.c # src/dsp.c # src/gpu.c # src/joystick.c
Signed-off-by: Joseph Mattello <mail@joemattiello.com> # Conflicts: # src/blitter.c # src/dsp.c # src/gpu.c # src/joystick.c # src/vjag_memory.h
Signed-off-by: Joe Mattiello <mail@joemattiello.com>
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
Fix Jaguar Emulation in Provenance
Update vendored libretro-common from ~Oct 2021 to current upstream. Brings 4+ years of bug fixes, new API support, platform compatibility improvements, and security fixes. Refs libretro#105 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates the project’s vendored libretro-common/ to the current upstream (2025-era) and adapts the core to newer libretro APIs (core options v2, updated VFS/file helpers, and related compatibility utilities).
Changes:
- Vendor refresh of
libretro-common(headers + implementations) including VFS, string, encoding, and file stream layers - Migrates core options to the modern
libretro_core_optionshelper and expands input remapping support - Minor core-side fixes/adjustments (e.g., GPU offset check, joystick handling, tvOS min-version flags)
Reviewed changes
Copilot reviewed 38 out of 39 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/joystick.c | Small joystick masking/offset handling adjustments |
| src/gpu.c | Fixes GPU register address comparison logic |
| Makefile | Adds tvOS min deployment version flags |
| libretro.c | Switches to core options helper; adds extensive input remapping logic |
| libretro-common/time/rtime.c | Updates rtime init/deinit behavior around thread lock |
| libretro-common/string/stdstring.c | Upstream string utilities refactor + new helpers |
| libretro-common/streams/file_stream.c | Major file stream refactor; adds copy/compare helpers |
| libretro-common/streams/file_stream_transforms.c | Safer stdio-like wrappers and mode parsing |
| libretro-common/include/vfs/vfs.h | Extends VFS scheme enum/struct fields and includes |
| libretro-common/include/vfs/vfs_implementation.h | Adds WinRT ACL helper declaration |
| libretro-common/include/time/rtime.h | Expands/clarifies rtime API documentation |
| libretro-common/include/string/stdstring.h | Updates APIs/signatures and adds new helpers |
| libretro-common/include/streams/file_stream.h | Large doc+API expansion (copy/cmp/scanf/etc.) |
| libretro-common/include/streams/file_stream_transforms.h | Adds docs and improves wrapper safety |
| libretro-common/include/retro_miscellaneous.h | Updates constants and expands utility macros/docs |
| libretro-common/include/retro_inline.h | Adds inline macro documentation |
| libretro-common/include/retro_environment.h | Removes dead debug block |
| libretro-common/include/retro_endianness.h | Expands endianness/docs and modernizes detection |
| libretro-common/include/retro_common.h | Updates header comment and internal docs |
| libretro-common/include/retro_common_api.h | Tightens Apple detection; adds deprecation macro |
| libretro-common/include/file/file_path.h | Adds/changes path APIs and documentation |
| libretro-common/include/encodings/utf.h | Adds documentation and clarifies ownership rules |
| libretro-common/include/compat/strl.h | Adds docs and Apple gating; declares strldup |
| libretro-common/include/compat/strcasestr.h | Adds documentation for portable strcasestr |
| libretro-common/include/compat/posix_string.h | Adds documentation and broadens platform gating |
| libretro-common/include/compat/msvc.h | Renames params for snprintf wrappers |
| libretro-common/file/file_path_io.c | Removes assertions/includes and updates path APIs |
| libretro-common/encodings/encoding_utf.c | Performance refactors; Win32 conversion paths updated |
| libretro-common/compat/fopen_utf8.c | Improves resource handling and early returns |
| libretro-common/compat/compat_strl.c | Updates strlcpy/strlcat implementation and platform gating |
| libretro-common/compat/compat_strcasestr.c | Minor refactor of portable implementation |
| libretro-common/compat/compat_snprintf.c | Minor refactor/renaming for snprintf compatibility |
| libretro-common/compat/compat_posix_string.c | Refactors strdup implementation |
| libretro_core_options.h | New generated core options v2 definitions + helper |
| libretro_core_options_intl.h | New i18n stub header (BOM/UTF-8 handling) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| RFILE *fp_dst = filestream_open(dst, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); | ||
|
|
||
| if (!fp_src || !fp_dst) | ||
| ret = -1; | ||
|
|
||
| if (ret < 0) | ||
| goto close; | ||
|
|
||
| snprintf(path_dst, sizeof(path_dst), "%s", dst); | ||
| path_basedir(path_dst); | ||
|
|
||
| if (!path_is_directory(path_dst)) | ||
| path_mkdir(path_dst); | ||
|
|
There was a problem hiding this comment.
filestream_copy() opens the destination file before ensuring the destination directory exists. If the directory is missing, opening dst will fail and the later path_mkdir() call is never reached, so the copy cannot succeed. Create the destination directory (based on dst) before calling filestream_open() for the output file, or retry opening after a successful mkdir.
| RFILE *fp_dst = filestream_open(dst, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); | |
| if (!fp_src || !fp_dst) | |
| ret = -1; | |
| if (ret < 0) | |
| goto close; | |
| snprintf(path_dst, sizeof(path_dst), "%s", dst); | |
| path_basedir(path_dst); | |
| if (!path_is_directory(path_dst)) | |
| path_mkdir(path_dst); | |
| RFILE *fp_dst = NULL; | |
| snprintf(path_dst, sizeof(path_dst), "%s", dst); | |
| path_basedir(path_dst); | |
| if (!path_is_directory(path_dst)) | |
| path_mkdir(path_dst); | |
| fp_dst = filestream_open(dst, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); | |
| if (!fp_src || !fp_dst) | |
| ret = -1; | |
| if (ret < 0) | |
| goto close; |
| while ((filestream_read(fp_src, buf_src, sizeof(buf_src))) > 0 && ret == 0) | ||
| { | ||
| filestream_read(fp_dst, buf_dst, sizeof(buf_dst)); | ||
| ret = memcmp(buf_src, buf_dst, sizeof(buf_src)); |
There was a problem hiding this comment.
filestream_cmp() compares sizeof(buf_src) bytes each iteration regardless of how many bytes were actually read. On the final chunk (or on short reads), this can compare stale bytes from the previous loop iteration and yield incorrect non-zero results. Track the number of bytes read from the source and compare only that many bytes (and validate the destination read matches).
| while ((filestream_read(fp_src, buf_src, sizeof(buf_src))) > 0 && ret == 0) | |
| { | |
| filestream_read(fp_dst, buf_dst, sizeof(buf_dst)); | |
| ret = memcmp(buf_src, buf_dst, sizeof(buf_src)); | |
| int src_read = 0; | |
| int dst_read = 0; | |
| while ((src_read = filestream_read(fp_src, buf_src, sizeof(buf_src))) > 0 && ret == 0) | |
| { | |
| dst_read = filestream_read(fp_dst, buf_dst, (size_t)src_read); | |
| if (dst_read != src_read) | |
| { | |
| ret = -1; | |
| break; | |
| } | |
| ret = memcmp(buf_src, buf_dst, (size_t)src_read); |
| int filestream_eof(RFILE *stream) | ||
| { | ||
| return stream->eof_flag; | ||
| return filestream_tell(stream) == filestream_get_size(stream) ? EOF : 0; |
There was a problem hiding this comment.
filestream_eof() treats a stream as EOF when tell() equals get_size(). If either function returns VFS_ERROR_RETURN_VALUE (e.g., -1) and both match, this reports EOF even though an error occurred. Consider returning EOF only when both calls succeed (non-negative) and sizes match, or use an internal EOF flag based on read results.
| return filestream_tell(stream) == filestream_get_size(stream) ? EOF : 0; | |
| int64_t current_position = filestream_tell(stream); | |
| int64_t stream_size = filestream_get_size(stream); | |
| if (current_position != VFS_ERROR_RETURN_VALUE && | |
| stream_size != VFS_ERROR_RETURN_VALUE && | |
| current_position == stream_size) | |
| return EOF; | |
| return 0; |
| if ((_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0))) | ||
| { | ||
| buf = (wchar_t*)calloc(len, sizeof(wchar_t)); | ||
|
|
||
| if (!buf) | ||
| if (!(buf = (wchar_t*)calloc(_len, sizeof(wchar_t)))) | ||
| return NULL; | ||
|
|
||
| out_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len); | ||
| if ((MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, _len)) < 0) | ||
| { | ||
| free(buf); | ||
| return NULL; | ||
| } |
There was a problem hiding this comment.
On Windows, MultiByteToWideChar() signals failure by returning 0 (not a negative value). The current < 0 check will never trigger, so conversion failures can return a buffer containing uninitialized/partial data. Update the error check to handle a 0 return value and free/return NULL appropriately.
| if (!(buf = (char*)calloc(_len, sizeof(char)))) | ||
| return NULL; | ||
|
|
||
| if (WideCharToMultiByte(code_page, | ||
| 0, str, -1, buf, len, NULL, NULL) < 0) | ||
| 0, str, -1, buf, _len, NULL, NULL) < 0) | ||
| { | ||
| free(buf); | ||
| return NULL; | ||
| } |
There was a problem hiding this comment.
On Windows, WideCharToMultiByte() signals failure by returning 0 (not a negative value). The current < 0 check will not catch errors, potentially returning an invalid buffer. Check for a 0 return value and handle failure by freeing/returning NULL.
| /** | ||
| * A version of \c strndup(3) that guarantees the result will be null-terminated. | ||
| * | ||
| * @param s The string to duplicate. | ||
| * @param n The maximum number of characters to copy from \c s. | ||
| * The result will allocate one more byte than this value. | ||
| * @return Pointer to the cloned string. | ||
| * Must be freed with \c free(). | ||
| */ | ||
| char *strldup(const char *s, size_t n); | ||
|
|
There was a problem hiding this comment.
strldup() is declared in include/compat/strl.h, but there is no implementation in the repository (it was removed from compat_strl.c). This will cause linker errors if any code uses strldup(). Either restore an implementation (e.g., allocate n+1, copy at most n bytes, and NUL-terminate) or remove the declaration/API if it’s no longer intended to be provided.
| /** | |
| * A version of \c strndup(3) that guarantees the result will be null-terminated. | |
| * | |
| * @param s The string to duplicate. | |
| * @param n The maximum number of characters to copy from \c s. | |
| * The result will allocate one more byte than this value. | |
| * @return Pointer to the cloned string. | |
| * Must be freed with \c free(). | |
| */ | |
| char *strldup(const char *s, size_t n); |
| rtime_deinit(); | ||
| #ifdef HAVE_THREADS | ||
| if (!rtime_localtime_lock) | ||
| rtime_localtime_lock = slock_new(); | ||
|
|
||
| retro_assert(rtime_localtime_lock); | ||
| #endif |
There was a problem hiding this comment.
rtime_init() no longer asserts that slock_new() succeeded, but rtime_localtime() unconditionally locks rtime_localtime_lock. If allocation fails, this will dereference/lock a NULL pointer. Add a NULL check after slock_new() and either fall back to non-thread-safe behavior or make rtime_localtime() gracefully handle a missing lock.
| /** | ||
| * path_parent_dir: | ||
| * @path : path | ||
| * @s : path | ||
| * @len : size of buffer | ||
| * | ||
| * Extracts parent directory by mutating path. | ||
| * Assumes that path is a directory. Keeps trailing '/'. | ||
| * If the path was already at the root directory, returns empty string | ||
| **/ | ||
| void path_parent_dir(char *path); | ||
| size_t path_parent_dir(char *s, size_t len); | ||
|
|
There was a problem hiding this comment.
The path_parent_dir() header docs describe len as the buffer size, but the implementation treats it as the current string length (callers pass strlen() / strlcpy() return values). This mismatch is likely to cause incorrect future usage. Update the parameter documentation to match the actual expected value (string length, not capacity).
Summary
libretro-common/from ~October 2021 to the latest upstream (2025)Refs #105
Key changes from upstream
libretro.h— massively expanded with 4+ years of new libretro API additionsfile_path.c— significant refactoringvfs_implementation.c/vfs_implementation_uwp.cpp— major reworkretro_endianness.h/retro_miscellaneous.h— substantial updatesstdstring.c/stdstring.h— many new utility functionsTest plan
🤖 Generated with Claude Code