Default Wii saves to SD card, store saves next to dusk.dsk/EBOOT.PBP

Wii NAND save storage is blocked by Dolphin's IOS ticket-rights check for
homebrew (documented earlier this session as a known, non-code limitation),
so Wii now defaults DUSK_SAVE_WII_METHOD to SD instead of NAND.

Also: asset_t gains ASSET.baseDirectory, populated by each platform's asset
loader with the real directory dusk.dsk was opened from (or, on PSP, the
directory EBOOT.PBP itself lives in, since dusk.dsk is embedded inside it).
Wii SD and PSP now write their single combined save file directly into
that directory instead of a separate hardcoded path, and no longer need to
create it (it's already known to exist). Linux now uses a `saves/`
subdirectory of that same directory instead of ~/.dusk/saves, since it
keeps multiple files (settings + one per slot). Wii NAND and GameCube/Wii
memory-card storage are unaffected - neither has a real filesystem-path
concept this applies to.

Built and verified on Linux, PSP (Docker), GameCube (Docker) and Wii
(Docker) - confirmed via the compiler invocation that Wii now compiles
with DUSK_SAVE_WII_METHOD_SD.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
YourWishesandClaude Sonnet 5 committed 2026-09-04 09:43:00 -05:00
1 parent f9820bd226
commit 3c3dc35e1d
11 files changed
+70 -49

No files matched your search

+5
View File
@@ -41,6 +41,11 @@ errorret_t assetInitDolphinFAT(void) {
*dolphinSearchPath,
ASSET_FILE_NAME
);
// Save devices with a real filesystem path (Wii SD) reuse this as
// their base directory - see ASSET.baseDirectory's own comment.
stringCopy(
ASSET.baseDirectory, *dolphinSearchPath, ASSET_BASE_DIRECTORY_MAX
);
break;
}
+8 -20
View File
@@ -7,12 +7,12 @@
#include "save/savedevice.h"
#include "save/savedevicedolphinsd.h"
#include "asset/asset.h"
#include "assert/assert.h"
#include "util/memory.h"
#include "util/string.h"
#include <fat.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#define SAVE_DEVICE_DOLPHIN_SD_PATH_MAX 128
@@ -39,29 +39,15 @@ void saveDeviceDolphinSDCheckAvailability(savedevice_t *device) {
"Device state incorrect?"
);
// Safe to call more than once - returns true if already mounted.
// Safe to call more than once - returns true if already mounted. No
// directory to create here - ASSET.baseDirectory is already known to
// exist, since dusk.dsk was just successfully opened from it.
if(!fatInitDefault()) {
device->state = SAVE_DEVICE_STATE_UNAVAILABLE;
device->reasonKey = "save.dolphin.sd_fat_init_failed";
return saveDeviceFireCallback(device);
}
// mkdir() only ever creates one level at a time - create the parent
// ("/dusk") before the save directory itself.
if(mkdir("/dusk", 0700) != 0 && errno != EEXIST) {
device->state = SAVE_DEVICE_STATE_UNAVAILABLE;
device->reasonKey = "save.dolphin.sd_mkdir_failed";
return saveDeviceFireCallback(device);
}
if(
mkdir(SAVE_DEVICE_DOLPHIN_SD_DIRECTORY, 0700) != 0 && errno != EEXIST
) {
device->state = SAVE_DEVICE_STATE_UNAVAILABLE;
device->reasonKey = "save.dolphin.sd_mkdir_failed";
return saveDeviceFireCallback(device);
}
device->state = SAVE_DEVICE_STATE_AVAILABLE;
device->reasonKey = NULL;
saveDeviceFireCallback(device);
@@ -75,7 +61,7 @@ errorret_t saveDeviceDolphinSDGetDataPath(
stringFormat(
dest, destSize, "%s/%s",
SAVE_DEVICE_DOLPHIN_SD_DIRECTORY, SAVE_DEVICE_DOLPHIN_SD_DATA_FILENAME
ASSET.baseDirectory, SAVE_DEVICE_DOLPHIN_SD_DATA_FILENAME
);
errorOk();
@@ -96,7 +82,9 @@ errorret_t saveDeviceDolphinSDDataWrite(
stringFormat(tempPath, sizeof(tempPath), "%s.tmp", finalPath);
FILE *file = fopen(tempPath, "wb");
if(file == NULL) errorThrow("Failed to open save data for writing: %s", tempPath);
if(file == NULL) {
errorThrow("Failed to open save data for writing: %s", tempPath);
}
size_t written = fwrite(buffer, 1, size, file);
fclose(file);
+6 -8
View File
@@ -8,12 +8,10 @@
#pragma once
#include "error/error.h"
// Root directory on whichever device libfat's fatInitDefault() picks as the
// default (SD slot on Wii, SD Gecko/Slot2 on GameCube) - same mechanism
// already used for Dolphin asset loading, see assetdolphinfat.c.
#ifndef SAVE_DEVICE_DOLPHIN_SD_DIRECTORY
#define SAVE_DEVICE_DOLPHIN_SD_DIRECTORY "/dusk/save"
#endif
// Data file lives directly in ASSET.baseDirectory (the same directory
// dusk.dsk was found in - see its own comment) rather than a separate
// fixed directory, so it doesn't need creating: that directory is already
// known to exist, since dusk.dsk was just successfully opened from it.
#ifndef SAVE_DEVICE_DOLPHIN_SD_DATA_FILENAME
#define SAVE_DEVICE_DOLPHIN_SD_DATA_FILENAME "save.dat"
#endif
@@ -42,8 +40,8 @@ errorret_t saveDeviceDolphinSDUpdate(savedevice_t *device);
/**
* Requests the device to check its availability, this will call the callback
* whence completed. Initializes libfat and confirms the save directory
* exists (creating it on first run).
* whence completed. Initializes libfat - the save directory itself is
* ASSET.baseDirectory, already known to exist.
*
* @param device The save device platform to check availability.
*/