mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Android: route native file creation through Java, and scope patch state per game
Two fixes that both live in the JNI layer. Folder memory cards on a user-chosen data folder crashed on the first new save. FUSE-backed shared storage denies libc file CREATION even though mkdir is already routed through Java, so SaveYAMLToFile opened a not-yet-existing _pcsx2_index with an unchecked OpenCFile and then dereferenced null. Existing saves reuse that file, which is exactly why only new saves crashed. Null-check the write, and add a CreateFileViaJava fallback in OpenCFile so a denied create is retried through the Java file API - the same libc/Java asymmetry that CreateDirectoryPath already relies on. Patch and cheat enable-state was written to the base settings layer, keyed only by patch name, so enabling e.g. "Widescreen 16:9" for one game switched on the identically named patch in every other game. LayeredSettingsInterface returns the first non-empty layer with the game layer ahead of the base one, so upstream keys this per serial and CRC; do the same, and strip the migrated names from the base list so an empty per-game list cannot fall back through to it. The per-game INI exporter also rebuilt the file from scratch, dropping every key it does not own - the patch lists above, and per-game MemoryCards and Gamefixes overrides. Load the existing file and clear only the sections the exporter actually writes.
This commit is contained in:
@@ -1020,6 +1020,18 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error*
|
||||
#endif
|
||||
|
||||
std::FILE* fp = std::fopen(filename, mode);
|
||||
#if defined(__ANDROID__)
|
||||
// libc fopen(O_CREAT) is denied on the FUSE-emulated external storage Android
|
||||
// hands out for a user-chosen data folder — the same split that forces
|
||||
// CreateDirectoryViaJava for mkdir(). Pre-create the empty file via the Java
|
||||
// File API and retry: opening the now-existing file for a truncating write
|
||||
// ("w"/"wb") IS permitted on FUSE (which is why writing EXISTING folder-card
|
||||
// saves already works), so the FIRST save to a folder card on a custom data
|
||||
// folder can now create its _pcsx2_index / save-data files instead of failing.
|
||||
// Write/create modes only — never "r"/"r+b" (those must fail on a missing file).
|
||||
if (!fp && (errno == EACCES || errno == EPERM) && mode[0] != 'r' && CreateFileViaJava(filename))
|
||||
fp = std::fopen(filename, mode);
|
||||
#endif
|
||||
if (!fp)
|
||||
Error::SetErrno(error, errno);
|
||||
return fp;
|
||||
|
||||
@@ -132,6 +132,12 @@ namespace FileSystem
|
||||
/// (user-picked custom data folders) despite all-files access. Returns true if
|
||||
/// the directory exists afterwards.
|
||||
bool CreateDirectoryViaJava(const char* path);
|
||||
/// Create an empty file via the Java File API (NativeApp.createFilePath).
|
||||
/// Fallback for when libc fopen(O_CREAT) is denied on FUSE-emulated external
|
||||
/// storage (user-picked custom data folders) despite all-files access; once the
|
||||
/// file exists the native truncating write that follows succeeds. Makes NEW
|
||||
/// folder-card saves work on a custom data folder. Returns true if it exists after.
|
||||
bool CreateFileViaJava(const char* path);
|
||||
#endif
|
||||
|
||||
/// Sharing modes for OpenSharedCFile().
|
||||
|
||||
Reference in New Issue
Block a user