Skip to content

Use the libretro VFS interface in libretro builds - #3489

Open
white-axe wants to merge 20 commits into
EasyRPG:masterfrom
white-axe:vfs
Open

Use the libretro VFS interface in libretro builds#3489
white-axe wants to merge 20 commits into
EasyRPG:masterfrom
white-axe:vfs

Conversation

@white-axe

Copy link
Copy Markdown

The libretro API provides a virtual filesystem interface that libretro cores can use to perform filesystem operations. It allows the libretro frontend to expose filesystem functionality that's not available through the native filesystem calls, such as the Storage Access Framework filesystem driver I added to the Android builds of RetroArch in libretro/RetroArch#18336.

This pull request changes the libretro builds of EasyRPG Player to request the libretro VFS interface from the libretro frontend, and then, if it's available, replace NativeFilesystem with a new LibretroFilesystem that uses the libretro VFS interface instead of the native filesystem calls.

@github-actions github-actions Bot added FileFinder Building libretro Libretro port related, including RetroArch, RetroPie and related projects labels Nov 8, 2025
@Ghabry

Ghabry commented Nov 8, 2025

Copy link
Copy Markdown
Member

Great to see that RetroArch is finally getting SAF support on Android.

Also interesting to see the implementation being completely different to our SAF approach. We use wrapper classes in Java to do all the heavy lifting and you call everything via JNI and use C code.

Code looks solid. Will do some testing on Android soon.

@Ghabry

Ghabry commented Nov 8, 2025

Copy link
Copy Markdown
Member

Jenkins: test this please

(ignore the lint error, is unrelated)

@Ghabry

Ghabry commented Dec 17, 2025

Copy link
Copy Markdown
Member

Made now some tests and their are some behaviours in the player code that break the Android side. Will try to fix them myself as they are also affecting other components on other platforms:

  • The Player code removes the saf:// prefix for whatever reason. Just deleting that code makes it work 🤷
  • MakeDirectory must actually create them recursively. That needs documentation and a helper function
  • When inside a ZIP the save directory discovery fails (not sure why)

Besides this it appears to work inside a saf document tree. Good job.

Ghabry added 6 commits July 13, 2026 16:50
libretro requires them for correct functionality
Our code assumes that this works at far too many places
It goes downwards instead of upwards

This prevents issues when path-like components are in the path that are not considered directories by the system.
@Ghabry

Ghabry commented Jul 14, 2026

Copy link
Copy Markdown
Member

@white-axe btw is their a simple way to test the core from Android Studio? (including debugger support)

Currently I just use adb + root permissions to manually copy the so-file in the retroarch data folder but their must be a better way

@white-axe

white-axe commented Jul 14, 2026

Copy link
Copy Markdown
Author

You don't have to copy the core file into the directory where RetroArch normally looks for the cores. Instead, copy it anywhere and then specify the core path when launching RetroArch:

adb push <path to the core on your computer> /data/local/tmp/libretro_android.so
adb shell am start -n com.retroarch/com.retroarch.browser.debug.CoreSideloadActivity -e LIBRETRO /data/local/tmp/libretro_android.so -e ROM <path to the game on your Android device>

SAF paths are supported for the ROM path, either in the form of the saf:// paths that appear in RetroArch's history when you run the game from the GUI or in the form of a SAF content:// URI (only for nightly builds of RetroArch currently in the latter case).

Ghabry added 2 commits July 29, 2026 15:13
Code is now simpler and works for the namespaced paths libretro uses
@Ghabry

Ghabry commented Jul 29, 2026

Copy link
Copy Markdown
Member

Jenkins: test this please

wow this was surprisingly complecated as we had too many assumptions how paths are supposed to look like... works now

The only problem I see is that MakeDirectory fails but this seems to be a libretro bug in the saf code:

07-29 15:28:28.120 30447 30474 I RetroArch: Tree: MAP0001
07-29 15:28:32.401 30447 30474 I RetroArch: MakeDirectory saf://content:%2F%2Fcom.android.externalstorage.documents%2Ftree%2Fprimary%253AEasyRPG%252Fgames/string-var.zip.save/string-var/Text failed
07-29 15:28:32.401 30447 30474 I RetroArch: Maniac String Op ToFile failed. Cannot create directory Text

The same code works when using the "real path" (/storage/0 etc.) instead of SAF.

As this isn't fixable I don't think its relevant for us.


Guess libretro should URI encode the path here?

@Ghabry Ghabry added the Android label Jul 29, 2026
@Ghabry

Ghabry commented Jul 29, 2026

Copy link
Copy Markdown
Member

Jenkins: Test this please

EDIT: Tested and confirmed working by Mimigris and me.

@Ghabry
Ghabry requested a review from carstene1ns July 29, 2026 19:07
Comment thread tests/filefinder.cpp
Comment on lines +136 to +139
components = FileFinder::SplitPathPrefixes("saf://content:%2F%2Fgames/File.zip");
CHECK(components[0] == "saf://");
CHECK(components[1] == "saf://content:%2F%2Fgames");
CHECK(components[2] == "saf://content:%2F%2Fgames/File.zip");

@white-axe white-axe Jul 29, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RetroArch's current implementation of libretro VFS for SAF returns -1 if you try to call mkdir on the root path of a SAF tree: https://github.com/libretro/RetroArch/blob/556283a6689ab5502ceec86f4e83e8b8d796bbd8/libretro-common/vfs/saf/src/com/libretro/common/vfs/VfsImplementationSaf.java#L304-L306 (i.e. calling mkdir on saf://content:%2F%2Fgames is always going to fail). It's also going to return -1 if you call it on saf://. Maybe the implementation of FileFinder::SplitPathPrefixes() should be changed to not return these first two prefixes if the path contains a namespace so that the recursive mkdir implementation will work correctly.

I will fix the RetroArch SAF VFS implementation to return -2 for calling mkdir on the root path of a saf tree (to indicate that the directory already exists) but I feel like returning -1 for saf:// is the correct behaviour. Feel free to dispute this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, my bad. It actually already returns -2 when you call mkdir on the root directory of a SAF tree. So the only change that needs to be made here is to not return the initial saf:// prefix when calling FileFinder::SplitPathPrefixes().

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recursive mkdir goes already top to bottom.

When the path is something like saf://content:%2F%2Fgames/dir/a it will start with saf://content:%2F%2Fgames/dir and then saf://content:%2F%2Fgames to find the first existing directory. Usually it won't reach saf://

And then it constructs the folders in reverse. In the native app this works.

It's not bottom up. This already fails on some homebrew systems where romfs:/ is not considered a directory

The problem is the / in games/dir which must be %2F. Would be useful when the VFS layer URI encodes this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SAF VFS implementation in RetroArch already handles URI encoding so that you can just use normal forward slashes to access files and directories inside of the SAF tree. So saf://content:%2F%2Fgames/dir/a should be fine. The problem is probably still in RetroArch, though. I'll take a look at it later.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be fixed by libretro/RetroArch#19342.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great. thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Android Building FileFinder libretro Libretro port related, including RetroArch, RetroPie and related projects

Development

Successfully merging this pull request may close these issues.

2 participants