Files
hizzlekizzle d2e771806a Rename .gitlab-ci.yaml to .gitlab-ci.yml
this was breaking the CI process -_-

simplify libretro makefile (#1)

only build the components needed by libretro

default to building with GCC

see if this can clear some CI hurdles

let runners override toolchain

libretro: build fixes (#2)

libretro: more apple build fixes (#4)

libretro: apple build fixes (#5)

buildfix for iOS/tvOS

libretro: frontend VFS support + Android/Windows/libnx build fixes (#3)

* libretro: route all file access through the frontend VFS

RetroArch can hand the core paths that don't exist on the real
filesystem - the common case being Android SAF content:// URIs, which
only the frontend can open. The core sets need_fullpath, so it opens the
content itself and every one of those loads currently fails.

All of the core's file I/O goes through utf8::ifstream/utf8::ofstream, so
routing those two through a VFS-backed streambuf covers ROMs, patches,
firmware, battery saves, save states, screenshots and recordings:

 - Utilities/VfsFile.{h,cpp}: VfsStreamBuf, a std::streambuf on top of
   retro_vfs_interface with a stdio fallback for when no frontend VFS is
   available, plus VfsIo helpers for stat/mkdir/opendir/remove/rename.
   Note that RetroArch's seek() returns 0 rather than the new offset, so
   the position is always read back with tell().
 - UTF8Util.h: in LIBRETRO builds utf8::ifstream/ofstream are backed by
   VfsStreamBuf (the _WIN32 wide-path classes stay for other builds).
 - retro_set_environment asks for VFS v3 and falls back to v2, so the
   directory calls are used when the frontend has them.
 - FolderUtilities uses the VFS for CreateFolder/GetFolders/
   GetFilesInFolder when v3 is available, std::filesystem otherwise.
 - ZipWriter builds archives in memory and writes them out through the
   stream layer - miniz's file API goes straight to stdio.
 - The remaining direct std::ifstream/std::ofstream/rename/remove calls
   in libretro.cpp and sha1.cpp now go through the same layer.

Verified with a harness that only accepts saf://-prefixed paths (a core
still on stdio fails to load): GB and SNES content loads, and the
RecentGames archive is written back through the VFS. A second harness
that refuses GET_VFS_INTERFACE checks the stdio fallback.

* libretro: fix the Android, Windows and libnx builds

Android (No rule to make target '.../Core/APU.cpp'): Libretro/jni/
Android.mk pulled its file list from Libretro/Makefile.common, a
leftover from the Mesen 1 libretro port that lists sources this tree
doesn't have. Android.mk now derives the sources the same way
Makefile.libretro does (and builds as C++17, not C++11); the two stale
Mesen 1 makefiles are removed.

Windows x64: two failures.
 - Lua/unixdgram.c needs sys/un.h. The unix-domain luasocket modules
   (unix.c, unixdgram.c, unixstream.c, serial.c) aren't registered by the
   core and aren't in the MSVC project either, so they're excluded.
 - The core is cross-compiled from Linux, so uname reported Linux and the
   build produced a .so with ELF-only link flags. The OS is now taken
   from the target triple, and the Windows build gets --no-undefined plus
   the winsock/UPnP import libraries.

libnx: the job builds with platform=libnx and then moves
mesen2_libretro_libnx.a, but Makefile.libretro had no such target, so it
built a host .so and the job died on the move. It now includes
switch_rules, compiles with the devkitA64 flags and archives a static
library. Untested - this needs a CI run on the libnx image to confirm the
core itself builds for the Switch.

Also fixes the compiler detection: `$(CXX) --version` matched 'gcc|g++'
by name, so a plain `make -f Makefile.libretro` (CXX=c++) took the clang
path and passed -flto=thin to GCC. It now looks for clang instead.

* libretro: use _wfopen_s in the MSVC build

The Mesen solution compiles with C4996 as an error, so the deprecated
_wfopen broke the standalone Windows build. The stdio fallback now has a
single open helper that uses _wfopen_s on MSVC.

* libretro: keep the core changes behind LIBRETRO, restore the old makefiles

Review feedback on libretro/MesenCE#3: the changes outside the libretro
glue should be conditional so this stays a soft fork, and the deleted
files should come back.

Everything the VFS work touches in shared code is now behind #ifdef
LIBRETRO - the WaveRecorder stream member, sha1's file hash, ZipWriter's
archive writing and FolderUtilities' directory calls all build exactly as
before without it. VfsFile.{h,cpp} is a libretro-only translation unit now
(empty otherwise), so it is out of Utilities.vcxproj again; Makefile.libretro
and Android.mk pick it up by globbing.

The macro is LIBRETRO, which is what Makefile.libretro and Android.mk
define, rather than __LIBRETRO__.

Libretro/Makefile and Libretro/Makefile.common are restored. Android.mk no
longer includes Makefile.common, so the stale Mesen 1 file list is only
dead weight rather than a broken build.

Re-verified after the change: linux-x64 core builds, the saf:// harness
loads GB and SNES content and writes the RecentGames archive through the
VFS, and the no-VFS harness still loads content through stdio.

* libretro: confine the VFS to the libretro layer

Review feedback on libretro/MesenCE#3: keep the VFS out of the core and
wrap the core's existing file access instead.

VfsFile.{h,cpp} moves to Libretro/, so it is not part of Utilities at all
any more. The interception point is utf8::ifstream/ofstream in
UTF8Util.h - the one place the core already routes file access through -
which is the only file in Core/ or Utilities/ that mentions the VFS.

The four sites that used to bypass utf8:: now go through it, which drops
their #ifdef LIBRETRO entirely (and incidentally fixes non-ASCII paths on
Windows, where utf8:: is what the rest of the codebase already uses):

- sha1.cpp opened a raw std::ifstream
- WaveRecorder held a std::ofstream, now a utf8::ofstream opened in place
  rather than move-assigned
- ZipWriter used miniz's stdio API; it now drives mz_zip_writer_init with
  a write callback backed by an ofstream, and reads added files through
  an ifstream. Still streamed, so no in-memory archive
- FolderUtilities keeps three guarded early-returns; the directory walk
  itself moved to VfsIo::GetEntries/CreateFolderIfSupported, which return
  false when the frontend has no v3 folder calls so the core falls back
  to std::filesystem

Makefile.libretro and Android.mk compile Libretro/VfsFile.cpp explicitly.

libretro: fix the Windows and libnx buildbot jobs (#6)

* libretro: lowercase the Windows headers for the MinGW cross-build

The buildbot's libretro-build-windows-x64 job is an MXE MinGW cross-build
running on Linux, where the include lookup is case-sensitive. mingw-w64
ships these headers all-lowercase, so <Windows.h> and <Ws2tcpip.h> are not
found and the job dies on Utilities/PlatformUtilities.cpp:

  fatal error: Windows.h: No such file or directory

MSVC is unaffected either way, since the Windows filesystem matches the
name regardless of case.

UTF8Util.cpp keeps its <Windows.h>: that include sits behind #ifdef
_MSC_VER, so the MinGW build never reaches it.

* libretro: don't require IN6ADDR_ANY_INIT on libnx

libretro-build-libnx-aarch64 dies on luasocket:

  Lua/inet.c:374:39: error: 'IN6ADDR_ANY_INIT' undeclared

devkitA64's newlib declares in6_addr, sockaddr_in6 and AF_INET6 - the
rest of the IPv6 code around it compiles - but not that macro. Fall back
to zeroing the address, which is what the wildcard address is by
definition and does not depend on how in6_addr is laid out.

libretro doesn't need upnp mapping

hopefully fix win64 builds

remove LUAOBJ from libnx

hopefully get it building on CI

fix typo in ifdef

libretro: fix the remaining Windows and libnx buildbot failures (#7)

* libretro: link winmm on Windows

PlatformUtilities asks for a 1ms timer resolution while a game runs, and
nothing in LIBS provides timeBeginPeriod/timeEndPeriod, so the MXE link ends
on __imp_timeBeginPeriod / __imp_timeEndPeriod. Those two are the only
symbols left unresolved in the buildbot's windows-x64 job.

* libretro: define _DEFAULT_SOURCE on libnx

Utilities/Socket.cpp does not compile there: u_long, fd_set, FD_ZERO,
FD_SET, select and struct timeval are all undeclared. They are all in
newlib, behind __MISC_VISIBLE and __BSD_VISIBLE - and newlib sets both from
_DEFAULT_SOURCE alone, which it auto-defines only when __STRICT_ANSI__ is
absent. CXXFLAGS passes --std=c++17, which defines it.

glibc turns _DEFAULT_SOURCE on whatever the dialect, so the same source
builds everywhere else and only the Switch job sees this.

re-add LUAOBJ to libnx

libretro: fix the windows-x64 link and get libnx past Lua (#8)

* libretro: give the VFS streams a key function

The windows-x64 job links with -flto and stops on multiple definitions of
the vtable, VTT and construction vtables for utf8::ifstream and
utf8::ofstream, one pair per translation unit that includes UTF8Util.h:

  BsxCart.o: multiple definition of `vtable for utf8::ifstream';
  libretro.o: first defined here

std::istream and std::ostream inherit virtually, so a class derived from
them gets construction vtables and a VTT as well as its own vtable. With no
key function all of it is emitted everywhere into .gnu.linkonce comdats, and
on PE/COFF the group keys come out inconsistent between objects - the same
section is keyed on the vtable in one and on the construction vtable in
another - so the linker keeps both instead of folding them.

Declaring the destructors in the header and defining them in the .cpp makes
those the key functions, so one object emits the lot. The VFS streams are the
only classes here that derive from a virtual base, which is why this is the
job that noticed.

* libretro: build libnx as gnu++17 instead of patching around __STRICT_ANSI__

declarations back for Utilities/Socket.cpp. That was the narrower of the two
options and it only covered newlib: the job now reaches Lua and stops there,
because gcc's own limits.h leaves LLONG_MAX undefined in C++ mode when
__STRICT_ANSI__ is set, and luaconf.h reads that as "no long long":

  Lua/luaconf.h:572: error: #error "Compiler does not support 'long long'.
    Use option '-DLUA_32BITS' or '-DLUA_C89_NUMBERS'"

Both come from the same place, so take the other option instead. MESENFLAGS
lands after the global --std=c++17 in CXXFLAGS, so this stays scoped to
libnx; every other target keeps the dialect it had.

* Delete mesen2_libretro.so

libretro: give libnx the ipv6_mreq luasocket needs (#9)

libretro-build-libnx-aarch64 is the last red job on the buildbot, and it
dies in luasocket:

  Lua/options.c: In function 'opt_ip6_setmembership':
  Lua/options.c:399:22: error: storage size of 'val' isn't known
    399 |     struct ipv6_mreq val;

devkitA64's newlib declares in6_addr, sockaddr_in6 and the
IPV6_ADD_MEMBERSHIP / IPV6_DROP_MEMBERSHIP constants - the two callers a
few lines up compile, and the IN6ADDR_ANY_INIT fallback in inet.c already
leans on in6_addr being there - but it never declares the struct those
two options take.

There is no macro to test a struct tag for, so the shim keys off
__SWITCH__, and it declares luasocket_ipv6_mreq rather than filling in
struct ipv6_mreq so that a devkitA64 that grows the real one later cannot
collide with it. socket.h is where it goes because options.c is built on
every platform and only reaches usocket.h off Windows.

The layout is the one RFC 3493 fixes; checked against glibc, both are 20
bytes with the fields at 0 and 16, so the buffer handed to setsockopt()
is unchanged. Whether the Switch network stack honours IPv6 multicast
joins at runtime is a separate question - this only stops the option from
breaking the build for every other libnx user.

set core option to default to 44.1 khz

this was making everything 55 FPS instead of 60

libretro: give libnx the LLONG_MAX luaconf.h expects (#10)

With the ipv6_mreq shim from #9 in, the libnx job gets past Lua/options.c
and dies further along, in the first C++ translation unit that pulls in
lua.hpp:

  In file included from Lua/lua.h:16,
                   from Lua/lua.hpp:6,
                   from Core/Debugger/LuaCallHelper.h:3,
                   from Core/Debugger/LuaCallHelper.cpp:2:
  Lua/luaconf.h:572:2: error: #error "Compiler does not support 'long long'."

luaconf.h includes <limits.h> itself and then gates its LUA_INT_LONGLONG
branch on LLONG_MAX. devkitA64's newlib does not make that macro visible to
C++ translation units, so the branch falls through to the #error - while the
C files in the same build, which the -std=gnu++17 in CFLAGS does not apply
to, see it and compile.

The error suggests LUA_32BITS or LUA_C89_NUMBERS, but both change Lua's
integer type, and only on the Switch. GCC always predefines
__LONG_LONG_MAX__, so fill LLONG_MAX, LLONG_MIN and ULLONG_MAX from it
instead, guarded on __SWITCH__ and on the macro actually being absent.

Checked against glibc's limits.h: all three expressions compare equal to the
real LLONG_MAX, LLONG_MIN and ULLONG_MAX, and luaconf.h still parses from
both C and C++ with the block inert off-Switch.
2026-08-29 10:21:13 -05:00
..
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2019-05-12 21:18:22 -04:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2019-05-12 21:18:22 -04:00
2019-05-12 21:18:22 -04:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2026-03-29 09:52:09 +02:00
2019-05-12 21:18:22 -04:00
2019-05-12 21:18:22 -04:00
2019-05-12 21:18:22 -04:00