This commit is contained in:
bryanthaboi
2026-08-18 09:20:07 -04:00
parent 675971068e
commit 55616fc03d
14 changed files with 194 additions and 31 deletions
+5 -5
View File
@@ -120,11 +120,11 @@ local function visibleBaseState(stack)
end
local function loadGenerated(path)
local chunk = love.filesystem.load(path)
if not chunk then return nil end
local ok, data = pcall(chunk)
if ok then return data end
return nil
-- CacheFs.loadActive, not love.filesystem.load: Gold's cache lives under
-- gold/ and fused NX often cannot mount that tree onto data/generated/.
local CacheFs = require("src.import.CacheFs")
local data = CacheFs.loadActive(path)
return data
end
-- NewGame (engine/menus/intro_menu.asm) calls OakSpeech, and OakSpeech's first
+24 -10
View File
@@ -1,10 +1,10 @@
-- NX-only asset overlay: fused love-nx cannot reliably mount
-- blue|yellow/assets/generated onto the un-prefixed assets/generated, so
-- blue|yellow|gold/{assets,data}/generated onto the un-prefixed paths, so
-- instead of teaching every call site about versioned caches, this module
-- wraps EVERY read-side love entry point that accepts a filesystem path
-- once at boot: any string path under assets/generated/ that does not
-- resolve falls back to the active version's prefixed copy
-- (yellow|blue/assets/generated/...). Covering the whole read surface --
-- once at boot: any string path under assets/generated/ or data/generated/
-- that does not resolve falls back to the active version's prefixed copy
-- (yellow|blue|gold/... ). Covering the whole read surface --
-- not just the loaders we happened to need -- is what keeps future states
-- and mods inside the fallback without anyone updating this file.
--
@@ -18,24 +18,38 @@
-- * the chip-audio worker (src/core/chip_worker.lua) is a separate Lua
-- state without these wrappers; ChipAudio.slimAudio hands it the prefix
-- explicitly as audio.programPrefix.
-- * data/generated module loads go through CacheFs.readActive, which
-- already implements the same fallback for require bytes.
-- * Gen 1 Data:load and Gold Game2/World go through CacheFs.readActive /
-- CacheFs.loadActive, which implement the same fallback for Lua bytes.
-- data/generated is still rewritten here so any leftover
-- love.filesystem.load("data/generated/...") call (the Gold intro /
-- naming / maps hole on 0.2.4) stays inside the overlay.
local GameVersion = require("src.core.GameVersion")
local GENERATED = "assets/generated/"
local GENERATED_PREFIXES = {
"assets/generated/",
"data/generated/",
}
local NxAssetOverlay = {}
local originals -- raw love functions, non-nil while installed
-- Resolve `path` to the versioned copy when the un-prefixed file is missing
-- and the active version (Blue/Yellow) carries it. Returns nil when the
-- caller's path should be used untouched (non-generated path, Red, the real
-- and the active version (Blue/Yellow/Gold) carries it. Returns nil when the
-- caller's path should be used untouched (non-generated path, the real
-- file exists, or no versioned copy).
local function versioned(path)
if type(path) ~= "string" then return nil end
if path:sub(1, #GENERATED) ~= GENERATED then return nil end
local generated = false
for i = 1, #GENERATED_PREFIXES do
local gen = GENERATED_PREFIXES[i]
if path:sub(1, #gen) == gen then
generated = true
break
end
end
if not generated then return nil end
local prefix = GameVersion.cachePrefix()
if prefix == "" then return nil end
if originals.getInfo(path) then return nil end
+19 -7
View File
@@ -220,6 +220,9 @@ function SwitchDiagnostics.probeAssets(version)
"assets/generated/tilesets/reds_house.png",
"assets/generated/sprites/red.png",
"assets/generated/sprites/monster.png",
"data/generated/maps.lua",
"data/generated/oak_speech.lua",
"data/generated/font.lua",
}
for _, path in ipairs(samples) do
local versioned = prefix ~= "" and (prefix .. path) or path
@@ -230,17 +233,26 @@ function SwitchDiagnostics.probeAssets(version)
lines[#lines + 1] = "versioned=" .. probeInfo(filesystem, versioned)
end
lines[#lines + 1] = "resolve=" .. tostring(resolved)
lines[#lines + 1] = "newImage=" .. probeOpen("image", resolved)
lines[#lines + 1] = "newImageData=" .. probeOpen("imageData", resolved)
if prefix ~= "" and resolved ~= versioned then
lines[#lines + 1] = "newImage_versioned=" .. probeOpen("image", versioned)
lines[#lines + 1] = "newImageData_versioned=" .. probeOpen("imageData", versioned)
if path:sub(-4) == ".lua" then
local CacheFs = require("src.import.CacheFs")
local loaded, err = CacheFs.loadActive(path)
lines[#lines + 1] = "loadActive=" .. (loaded ~= nil and "ok"
or ("FAIL " .. tostring(err):gsub("%s+", " "):sub(1, 160)))
else
lines[#lines + 1] = "newImage=" .. probeOpen("image", resolved)
lines[#lines + 1] = "newImageData=" .. probeOpen("imageData", resolved)
if prefix ~= "" and resolved ~= versioned then
lines[#lines + 1] = "newImage_versioned=" .. probeOpen("image", versioned)
lines[#lines + 1] = "newImageData_versioned=" .. probeOpen("imageData", versioned)
end
end
end
-- Shallow listing so we can see if the extract tree exists at all.
local roots = { "yellow", "blue", "assets", "yellow/assets/generated",
"yellow/assets/generated/sprites", "blue/assets/generated/sprites" }
local roots = { "yellow", "blue", "gold", "assets", "yellow/assets/generated",
"yellow/assets/generated/sprites", "blue/assets/generated/sprites",
"gold/assets/generated", "gold/assets/generated/sprites",
"gold/data/generated" }
for _, dir in ipairs(roots) do
local info = filesystem.getInfo(dir)
if info and info.type == "directory" and filesystem.getDirectoryItems then
+27 -1
View File
@@ -305,7 +305,7 @@ function CacheFs.read(rel)
end
-- Read cache-relative `rel` for the active GameVersion when PhysFS may hide
-- prefixed Blue/Yellow trees (fused NX mount hole). Same order Data:load
-- prefixed Blue/Yellow/Gold trees (fused NX mount hole). Same order Data:load
-- already used: active version prefix with CacheFs.prefix cleared, then
-- `rel` under the caller's CacheFs.prefix. Returns the bytes or nil.
function CacheFs.readActive(rel)
@@ -322,6 +322,32 @@ function CacheFs.readActive(rel)
return nil
end
-- Load a generated Lua table the way Data:load does: versioned save-dir
-- bytes first (gold/data/generated/maps.lua), then the un-prefixed path.
-- Game2/World used love.filesystem.load("data/generated/...") which misses
-- on fused NX when the gold/ overlay mount fails -- intro art still loads
-- via NxAssetOverlay, but oak_speech.lua / font.lua / maps.lua do not.
function CacheFs.loadActive(rel)
local bytes = CacheFs.readActive(rel)
if type(bytes) == "string" then
local GameVersion = require("src.core.GameVersion")
local loader = loadstring or load
local chunk, err = loader(bytes, "@" .. GameVersion.cachePrefix() .. rel)
if not chunk then return nil, err end
local ok, value = pcall(chunk)
if not ok then return nil, value end
return value
end
if love and love.filesystem and love.filesystem.load then
local chunk, err = love.filesystem.load(rel)
if not chunk then return nil, err end
local ok, value = pcall(chunk)
if not ok then return nil, value end
return value
end
return nil, "Could not open file " .. rel .. ". Does not exist."
end
-- does cache-relative `rel` exist as a file?
function CacheFs.exists(rel)
rel = withPrefix(rel)
+4 -5
View File
@@ -396,11 +396,10 @@ local function givePokeMon(data, speciesIndex, level, itemIndex)
end
local function loadGenerated(path)
local chunk, err = love.filesystem.load(path)
if not chunk then return nil, err end
local ok, value = pcall(chunk)
if not ok then return nil, value end
return value
-- Same NX gold/ fallback Game2 uses. World:load is what surfaces
-- "Gold cache incomplete" when maps.lua is invisible at the unprefixed path.
local CacheFs = require("src.import.CacheFs")
return CacheFs.loadActive(path)
end
-- Paste the 9-tile roof sheet over atlas tiles $0a-$12.