mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
fix(switch): extend NX-only asset prefix to audio and title/intro art
The previous NX gate only rewrote image paths that go through Assets.resolve. Pokemon Yellow still had no sound and a blank title screen because: - ChipSynth reads programs.bin directly via love.filesystem.read, bypassing Assets. On NX the unprefixed path is missing when the mount overlay fails, so the engine never built and every song/SFX was silent. - Sound.playPikaCry loads pika_cries WAVs with love.audio.newSource, also bypassing Assets.resolve. - TitleState, YellowIntro, and IntroMovie call love.graphics.newImage directly on unprefixed assets/generated paths, so the Pikachu title and intro atlases failed to load. Fix: apply the same NX-only prefix rewrite in those four places. Desktop/Android keep the existing mountVersion overlay behavior. Also add ChipSynth._loadBanksForTest and tests covering the new paths. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+17
-1
@@ -123,7 +123,18 @@ local function loadBanks(data)
|
||||
if cachedProgramFile == audio.programFile and cachedBanks then
|
||||
return cachedBanks
|
||||
end
|
||||
local raw, readError = love.filesystem.read(audio.programFile)
|
||||
local raw, readError
|
||||
-- NX-only: Blue/Yellow live under a versioned save-dir prefix; desktop
|
||||
-- relies on mountVersion overlay. Read the prefixed path when present.
|
||||
if require("src.core.Platform").isNX() then
|
||||
local prefix = require("src.core.GameVersion").cachePrefix()
|
||||
if prefix ~= "" then
|
||||
raw, readError = love.filesystem.read(prefix .. audio.programFile)
|
||||
end
|
||||
end
|
||||
if not raw then
|
||||
raw, readError = love.filesystem.read(audio.programFile)
|
||||
end
|
||||
if not raw then error("could not read sound programs: " .. tostring(readError)) end
|
||||
local banks = {}
|
||||
for index, bank in ipairs(audio.bankOrder) do
|
||||
@@ -140,6 +151,11 @@ function ChipSynth.invalidateBanks()
|
||||
cachedProgramFile, cachedBanks = nil, nil
|
||||
end
|
||||
|
||||
-- test-only: exercise loadBanks without building a full engine
|
||||
function ChipSynth._loadBanksForTest(data)
|
||||
return loadBanks(data)
|
||||
end
|
||||
|
||||
-- A def-local program (ChipAsm output) is mounted as pseudo-bank 0 next to
|
||||
-- the ROM banks, so the 0x4000-window byte reader and every call/loop
|
||||
-- target work unchanged. The ROM's own cached bank table is never touched
|
||||
|
||||
@@ -269,6 +269,13 @@ function Sound.playPikaCry(data, n)
|
||||
if src == false then return nil end
|
||||
if not src then
|
||||
local path = ("assets/generated/audio/pika_cries/cry_%02d.wav"):format(n)
|
||||
-- NX-only: Blue/Yellow live under a versioned save-dir prefix.
|
||||
if require("src.core.Platform").isNX() then
|
||||
local prefix = require("src.core.GameVersion").cachePrefix()
|
||||
if prefix ~= "" and love.filesystem.getInfo(prefix .. path) then
|
||||
path = prefix .. path
|
||||
end
|
||||
end
|
||||
local ok, s = pcall(love.audio.newSource, path, "static")
|
||||
if not ok or not s then
|
||||
cache[key] = false
|
||||
|
||||
@@ -136,7 +136,7 @@ local FIGHT_SCRIPT = {
|
||||
|
||||
local function tryImage(path)
|
||||
if not path then return nil end
|
||||
local ok, img = pcall(love.graphics.newImage, path)
|
||||
local ok, img = pcall(love.graphics.newImage, require("src.render.Assets").resolve(path))
|
||||
return ok and img or nil
|
||||
end
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ local CYCLE_FRAMES = 240 -- the original waits ~4s between picks
|
||||
|
||||
local function tryImage(path)
|
||||
if not path then return nil end
|
||||
local ok, img = pcall(love.graphics.newImage, path)
|
||||
local ok, img = pcall(love.graphics.newImage, require("src.render.Assets").resolve(path))
|
||||
return ok and img or nil
|
||||
end
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ local function bobOffset(phase)
|
||||
end
|
||||
|
||||
local function tryImage(path)
|
||||
local ok, img = pcall(love.graphics.newImage, path)
|
||||
local ok, img = pcall(love.graphics.newImage, require("src.render.Assets").resolve(path))
|
||||
return ok and img or nil
|
||||
end
|
||||
|
||||
|
||||
@@ -95,6 +95,67 @@ local luaBytes = CacheFs.readActive("data/generated/maps.lua")
|
||||
check(type(luaBytes) == "string" and luaBytes:find("ok", 1, true),
|
||||
"readActive still finds yellow/data/generated when CacheFs.prefix is set")
|
||||
|
||||
-- ChipSynth.loadBanks: NX prefers the versioned prefix; desktop untouched
|
||||
setOS("NX")
|
||||
GameVersion.set("yellow")
|
||||
local PROG = "assets/generated/audio/programs.bin"
|
||||
local PROG_BYTES = string.rep("\0", 0x4000 * 2)
|
||||
love.filesystem.write("yellow/" .. PROG, PROG_BYTES)
|
||||
clearPath(PROG)
|
||||
local ChipSynth = require("src.core.ChipSynth")
|
||||
ChipSynth.invalidateBanks()
|
||||
local progData = { audio = { programFile = PROG, bankOrder = { 1, 2 } } }
|
||||
local okB, banks = pcall(ChipSynth._loadBanksForTest, progData)
|
||||
check(okB and banks ~= nil, "NX loadBanks reads yellow/programs.bin")
|
||||
if okB and banks then
|
||||
eq(banks[1], PROG_BYTES:sub(1, 0x4000), "loadBanks returns the bank 1 bytes")
|
||||
end
|
||||
|
||||
-- Sound.playPikaCry: NX rewrites the pika-cry path before newSource
|
||||
setOS("NX")
|
||||
GameVersion.set("yellow")
|
||||
local Sound = require("src.core.Sound")
|
||||
local CRY = "assets/generated/audio/pika_cries/cry_01.wav"
|
||||
love.filesystem.write("yellow/" .. CRY, "RIFF\x24\x00\x00\x00WAVEfmt ")
|
||||
clearPath(CRY)
|
||||
local lastNewSource
|
||||
local savedAudio = love.audio
|
||||
love.audio = {
|
||||
newSource = function(path, mode)
|
||||
lastNewSource = path
|
||||
return setmetatable({
|
||||
stop = function() end,
|
||||
play = function() end,
|
||||
setVolume = function() end,
|
||||
}, { __index = function() return function() end end })
|
||||
end,
|
||||
}
|
||||
Sound.invalidate("pikacry:1")
|
||||
local cryData = { audio = { pikaCries = 1 } }
|
||||
local src = Sound.playPikaCry(cryData, 1)
|
||||
love.audio = savedAudio
|
||||
eq(lastNewSource, "yellow/" .. CRY, "NX playPikaCry loads yellow/pika_cries")
|
||||
|
||||
-- TitleState/YellowIntro/IntroMovie use Assets.resolve (NX prefix); a static
|
||||
-- source check keeps them from regressing to raw newImage(path).
|
||||
local function srcHasResolve(path)
|
||||
local f = io.open(path, "r")
|
||||
if not f then return false end
|
||||
local body = f:read("*a")
|
||||
f:close()
|
||||
return body:find("Assets%.resolve", 1, false) ~= nil
|
||||
or body:find('require%("src%.render%.Assets"%)%.resolve', 1, false) ~= nil
|
||||
end
|
||||
check(srcHasResolve("src/ui/TitleState.lua"),
|
||||
"TitleState loads art via Assets.resolve")
|
||||
check(srcHasResolve("src/ui/YellowIntro.lua"),
|
||||
"YellowIntro loads art via Assets.resolve")
|
||||
check(srcHasResolve("src/ui/IntroMovie.lua"),
|
||||
"IntroMovie loads art via Assets.resolve")
|
||||
|
||||
clearPath("yellow/" .. PROG)
|
||||
clearPath("yellow/" .. CRY)
|
||||
|
||||
love.system = savedSystem
|
||||
Platform._resetForTests()
|
||||
CacheFs.prefix = savedPrefix
|
||||
|
||||
Reference in New Issue
Block a user