feat: automate PortMaster save directory

This commit is contained in:
Alexander Sellite 2026-08-16 20:57:54 -04:00
parent 7aaed6393b
commit 01e534e278
5 changed files with 53 additions and 6 deletions

View file

@ -365,7 +365,10 @@ rm -rf -- "$test_root"
```
Do not point `NETFISHING_DATA_DIR` at an arbitrary empty directory; it is an
explicit portable-data override and must identify a valid data root.
explicit portable-data override and must identify a valid data root. The
PortMaster launcher is the narrow exception: it also sets
`NETFISHING_CREATE_DATA_DIR=1`, allowing the game to initialize its known empty
external save directory on first launch.
Headless tests cannot prove visual alignment, mouse routing, shader appearance,
controller feel, or resize behavior. Presentation changes require graphical

View file

@ -38,8 +38,12 @@ directory. The templates in `scripts/portmaster/` are authoritative.
mapping manager handle gameplay input.
- The launcher calls `pm_platform_helper` for the game executable after
starting GPTOKEYB and calls `pm_finish` after the game exits.
- Persistent device data remains under `netfishing/conf/data`,
`netfishing/conf/config`, and `netfishing/conf/cache`.
- New installations automatically create player data under
`ports/saves/netfishing/` and do not present the in-game folder picker.
- Existing installations with a selected data root keep that location when
upgraded. Device-local data, configuration, and cache remain under
`netfishing/conf/data`, `netfishing/conf/config`, and
`netfishing/conf/cache`.
- The archive must not contain `conf/`, saves, identities, logs, source files,
`.git`, or `.godot` content.
- Release downloads must publish only the canonical `netfishing.zip` for this
@ -95,13 +99,15 @@ device directory and run:
```
Before upgrading an existing installation, preserve
`/mnt/mmc/ports/netfishing/conf/` on the device. After installation:
`/mnt/mmc/ports/netfishing/conf/` and `/mnt/mmc/ports/saves/netfishing/` on the
device. After installation:
1. Confirm the installed executable and PCK hashes match the staged release.
2. Confirm the installed launcher contains the canonical PortMaster header,
starts GPTOKEYB with `netfishing.gptk`, and calls
`pm_platform_helper` for the game executable.
3. Confirm `conf/` was not replaced or removed.
3. Confirm `conf/` and the external save directory were not replaced or
removed.
4. Launch the installed port through the normal muOS menu.
5. Verify the displayed game version and controller face-button mapping.
6. Verify PortMaster's force-quit chord exits the game. This is Start+Select on

View file

@ -12,6 +12,7 @@ const LAYOUT_VERSION := 1
const MANIFEST_FILENAME := "netfishing_data.json"
const README_FILENAME := "README.txt"
const ENVIRONMENT_VARIABLE := "NETFISHING_DATA_DIR"
const CREATE_ENVIRONMENT_VARIABLE := "NETFISHING_CREATE_DATA_DIR"
const APPLICATION_ID := "netfishing"
const APP_DATA_PORTABLE_PATH := "user://portable-data"
const PATH_ALLOWED: StringName = &"allowed"
@ -48,6 +49,15 @@ func resolve() -> bool:
var environment_path: String = OS.get_environment(ENVIRONMENT_VARIABLE)
if not environment_path.is_absolute_path():
return _fail("NETFISHING_DATA_DIR must be an absolute path.")
if (
OS.get_environment(CREATE_ENVIRONMENT_VARIABLE) == "1"
and not FileAccess.file_exists(
environment_path.path_join(MANIFEST_FILENAME)
)
):
var created: Dictionary = create_unbound_root(environment_path)
if not bool(created.get("ok", false)):
return false
return _activate_existing(environment_path, "", false)
var bootstrap: Dictionary = _read_json(BOOTSTRAP_PATH, 64 * 1024)
if bootstrap.is_empty() and FileAccess.file_exists(BOOTSTRAP_PATH + ".backup"):

View file

@ -181,7 +181,10 @@ Install the complete \`netfishing.zip\` archive with PortMaster or HarbourMaster
The package requires an ARM64 device, two analog sticks, GLIBC 2.28 or newer,
and the \`weston_pkg_0.2\` runtime.
Save data and device-local configuration remain under \`netfishing/conf/\`.
New installations store player data under \`ports/saves/netfishing/\` without
opening a folder picker. Existing installations preserve their previously
selected data root. Device-local configuration remains under
\`netfishing/conf/\`.
PortMaster launches use the light performance profile by default. Put the word
\`normal\` in \`netfishing/conf/performance_profile\` to opt a capable device
into the normal rendering profile. See \`netfishing/licenses/\` for bundled
@ -223,6 +226,12 @@ grep -Fq 'NETFISHING_PERFORMANCE_PROFILE=light' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'CONTROLLER_MAPPING_FILE="$CONFDIR/cache/controller_mapping.txt"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'SAVEDIR="$PORTS_ROOT/saves/netfishing"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq '"NETFISHING_DATA_DIR=$SAVEDIR"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq '"NETFISHING_CREATE_DATA_DIR=1"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'printf '\''%s\n'\'' "$netfishing_controllerconfig" > "$CONTROLLER_MAPPING_FILE"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq '"$GAME_LAUNCHER"' "${STAGE_ROOT}/NETfishing.sh"

View file

@ -28,6 +28,9 @@ if [ ! -d "$GAMEDIR" ] && [ -d "/mnt/mmc/ports/netfishing" ]; then
fi
CONFDIR="$GAMEDIR/conf"
PORTS_ROOT="${GAMEDIR%/netfishing}"
SAVEDIR="$PORTS_ROOT/saves/netfishing"
DATA_BOOTSTRAP_DIR="$CONFDIR/data/godot/app_userdata/NETFISHING"
GAME_EXECUTABLE="$GAMEDIR/NETfishing.aarch64"
GAME_LAUNCHER="$GAMEDIR/launch-netfishing.sh"
GPTOKEYB_CONFIG="$GAMEDIR/netfishing.gptk"
@ -42,6 +45,21 @@ fi
mkdir -p "$CONFDIR/data" "$CONFDIR/config" "$CONFDIR/cache" "$WESTON_DIR"
chmod +x "$GAME_EXECUTABLE"
# New PortMaster installs use a predictable save directory beside the port
# instead of presenting a folder picker on a small screen. Preserve an
# established data-root choice when upgrading an existing installation.
NETFISHING_DATA_ENVIRONMENT=()
if [ -f "$SAVEDIR/netfishing_data.json" ] || {
[ ! -f "$DATA_BOOTSTRAP_DIR/data_root_bootstrap.json" ] &&
[ ! -f "$DATA_BOOTSTRAP_DIR/data_root_bootstrap.json.backup" ]
}; then
mkdir -p "$SAVEDIR"
NETFISHING_DATA_ENVIRONMENT+=(
"NETFISHING_DATA_DIR=$SAVEDIR"
"NETFISHING_CREATE_DATA_DIR=1"
)
fi
> "$GAMEDIR/log.txt" && exec > >(tee "$GAMEDIR/log.txt") 2>&1
if [ ! -f "$controlfolder/libs/${WESTON_RUNTIME}.squashfs" ]; then
@ -134,6 +152,7 @@ $ESUDO env CRUSTY_RESOLUTION="${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" \
XDG_CONFIG_HOME="$CONFDIR/config" \
XDG_CACHE_HOME="$CONFDIR/cache" \
GODOT_SILENCE_ROOT_WARNING=1 \
"${NETFISHING_DATA_ENVIRONMENT[@]}" \
"${NETFISHING_GAME_ENVIRONMENT[@]}" \
"$GAME_LAUNCHER" \
"$CONTROLLER_MAPPING_FILE" \