Add PSP/GameCube/Wii save-device availability checks

PSP checks memory-stick reachability via sceIoGetstat. GameCube gets two
devices (CARD_SLOTA/CARD_SLOTB), each mounted via CARD_Init/CARD_Mount and
checked for free space via CARD_GetDirectory/CARD_GetBlockCount. Wii picks
between three storage methods at compile time (DUSK_SAVE_WII_METHOD =
NAND/CARD/SD in wii.cmake, default NAND via ISFS) since real hardware
behavior for the default is unverified.

Also fixes two pre-existing bugs found while build/runtime-testing this
across PPSSPP and Dolphin: wrong libogc language macros in
systemGetLocaleDolphin, and a missing SYS_STDIO_Report(true) call that
silently swallowed all guest console output in Dolphin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-14 16:20:28 -05:00
parent 45331c2a60
commit d7223d7387
16 changed files with 670 additions and 2 deletions
@@ -0,0 +1,60 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
#include <ogc/isfs.h>
// A private namespace under /title on the Wii's internal NAND, used purely
// as ISFS storage - not a real installed title/ticket. Only reachable
// because the Homebrew Channel's <ahb_access/> grants full hardware access,
// which also disables IOS's normal ES rights checking for the running app;
// this hasn't been confirmed against real hardware yet (see project memory
// for the caveat - Dolphin's NAND emulation may not reproduce the same
// rights-check behavior as a real Wii/vWii).
#ifndef SAVE_DEVICE_DOLPHIN_NAND_DIR
#define SAVE_DEVICE_DOLPHIN_NAND_DIR "/title/00010001/44555348/data"
#endif
typedef struct {
bool_t initialized;
} savedeviceplatform_t;
typedef struct savedevice_s savedevice_t;
/**
* Initializes the save device platform.
*
* @param device The save device platform to initialize.
* @return Error state if any.
*/
errorret_t saveDeviceDolphinNandInit(savedevice_t *device);
/**
* Updates the save device platform.
*
* @param device The save device platform to update.
* @return Error state if any.
*/
errorret_t saveDeviceDolphinNandUpdate(savedevice_t *device);
/**
* Requests the device to check its availability, this will call the callback
* whence completed. Brings up ISFS and confirms our private save directory
* exists (creating it on first run).
*
* @param device The save device platform to check availability.
*/
void saveDeviceDolphinNandCheckAvailability(savedevice_t *device);
/**
* Disposes of the save device platform.
*
* @param device The save device platform to dispose.
* @return Error state if any.
*/
errorret_t saveDeviceDolphinNandDispose(savedevice_t *device);