mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
186 lines
5.3 KiB
Lua
186 lines
5.3 KiB
Lua
local M = {}
|
|
|
|
local function readable(path)
|
|
local f = io.open(path, "rb")
|
|
if f then
|
|
f:close()
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function push(list, seen, path)
|
|
if path and path ~= "" and not seen[path] then
|
|
seen[path] = true
|
|
list[#list + 1] = path
|
|
end
|
|
end
|
|
|
|
local SUFFIX = "/firered/data/generated/gba"
|
|
local OWNER_IDENTITY = "pokemon-love2d"
|
|
|
|
local function candidates()
|
|
local list, seen, last = {}, {}, {}
|
|
local home = os.getenv("HOME")
|
|
local saveRoots = home and {
|
|
home .. "/Library/Application Support/LOVE",
|
|
home .. "/.local/share/love",
|
|
} or {}
|
|
|
|
local identity = os.getenv("POKEPORT_IDENTITY")
|
|
if identity and identity ~= "" and identity ~= OWNER_IDENTITY then
|
|
for _, saveRoot in ipairs(saveRoots) do
|
|
push(list, seen, saveRoot .. "/" .. identity .. SUFFIX)
|
|
end
|
|
end
|
|
push(list, seen, os.getenv("POKEPORT_GBA_CACHE"))
|
|
push(list, seen, "data/generated/gba")
|
|
|
|
for _, saveRoot in ipairs(saveRoots) do
|
|
local owner = saveRoot .. "/" .. OWNER_IDENTITY .. SUFFIX
|
|
local pipe = io.popen('ls -1t "' .. saveRoot .. '"/*' .. SUFFIX .. '/meta.json 2>/dev/null')
|
|
if pipe then
|
|
for line in pipe:lines() do
|
|
local root = line:match("^(.*)/meta%.json$")
|
|
if root and root ~= owner then push(list, seen, root) end
|
|
end
|
|
pipe:close()
|
|
end
|
|
last[#last + 1] = owner
|
|
end
|
|
return list, last
|
|
end
|
|
|
|
local function metaVersions(root)
|
|
local f = io.open(root .. "/meta.json", "rb")
|
|
if not f then return nil end
|
|
local src = f:read("*a") or ""
|
|
f:close()
|
|
return tonumber(src:match('"cache_version"%s*:%s*(%d+)')) or 0,
|
|
tonumber(src:match('"native_version"%s*:%s*(%d+)')) or 0
|
|
end
|
|
|
|
local function isCurrent(root, needNative)
|
|
local Versions = require("src.import.gba.versions")
|
|
local cacheV, nativeV = metaVersions(root)
|
|
if not cacheV then return false, "no meta.json" end
|
|
if cacheV ~= Versions.CACHE_VERSION then
|
|
return false, ("cache v%d, importer is v%d"):format(cacheV, Versions.CACHE_VERSION)
|
|
end
|
|
if needNative and nativeV ~= Versions.NATIVE_VERSION then
|
|
return false, ("native v%d, importer is v%d"):format(nativeV, Versions.NATIVE_VERSION)
|
|
end
|
|
return true
|
|
end
|
|
|
|
M._roots = {}
|
|
M.reason = nil
|
|
|
|
function M.root(marker, opts)
|
|
marker = marker or "meta.json"
|
|
local needNative = type(opts) == "table" and opts.native == true
|
|
local memoKey = marker .. (needNative and "|native" or "")
|
|
local memo = M._roots[memoKey]
|
|
if memo ~= nil then
|
|
if memo == false then return nil end
|
|
return memo
|
|
end
|
|
local list, last = candidates()
|
|
local stale = 0
|
|
local function pick(roots)
|
|
for _, root in ipairs(roots) do
|
|
if readable(root .. "/" .. marker) then
|
|
if isCurrent(root, needNative) then return root end
|
|
stale = stale + 1
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
local root = pick(list) or pick(last)
|
|
if root then
|
|
M._roots[memoKey] = root
|
|
M.reason = nil
|
|
return root
|
|
end
|
|
local Versions = require("src.import.gba.versions")
|
|
if stale > 0 then
|
|
M.reason = ("%d imported FireRed cache(s) found, none at cache v%d%s"):format(
|
|
stale, Versions.CACHE_VERSION,
|
|
needNative and (" / native v" .. tostring(Versions.NATIVE_VERSION)) or "")
|
|
else
|
|
M.reason = "no imported FireRed cache found"
|
|
end
|
|
M._roots[memoKey] = false
|
|
return nil
|
|
end
|
|
|
|
function M.cache()
|
|
return {
|
|
read = function(_, rel)
|
|
local f = io.open(rel, "rb")
|
|
if not f then return nil end
|
|
local data = f:read("*a")
|
|
f:close()
|
|
if type(data) == "string" and #data > 0 then return data end
|
|
return nil
|
|
end,
|
|
exists = function(_, rel)
|
|
return readable(rel)
|
|
end,
|
|
}
|
|
end
|
|
|
|
function M.mount(marker, opts)
|
|
local root = M.root(marker, opts)
|
|
if not root then return nil end
|
|
local Dataset = require("src.core.game3.dataset")
|
|
Dataset.cacheRootOverride = root
|
|
Dataset.mountExtractRoots()
|
|
return root
|
|
end
|
|
|
|
function M.mountOrSkip(label, marker, opts)
|
|
local root = M.mount(marker, opts)
|
|
if not root then
|
|
print("[skip] " .. tostring(label) .. ": " .. tostring(M.reason))
|
|
os.exit(0)
|
|
end
|
|
print("[info] FireRed cache at " .. root)
|
|
return root
|
|
end
|
|
|
|
local function datasetRoots()
|
|
local roots = { "." }
|
|
local home = os.getenv("HOME")
|
|
local identity = os.getenv("POKEPORT_IDENTITY") or ""
|
|
if home and identity ~= "" then
|
|
roots[#roots + 1] = home .. "/Library/Application Support/LOVE/" .. identity .. "/firered"
|
|
roots[#roots + 1] = home .. "/.local/share/love/" .. identity .. "/firered"
|
|
elseif home then
|
|
roots[#roots + 1] = home .. "/.local/share/love/" .. OWNER_IDENTITY .. "/firered"
|
|
end
|
|
return roots
|
|
end
|
|
|
|
function M.requireData(label, marker)
|
|
marker = marker or "meta.json"
|
|
if M.root(marker) then return end
|
|
for _, root in ipairs(datasetRoots()) do
|
|
if readable(root .. "/data/generated/gba/" .. marker) then return end
|
|
end
|
|
print("[skip] " .. tostring(label) .. ": " .. tostring(M.reason or "no imported FireRed cache found"))
|
|
os.exit(0)
|
|
end
|
|
|
|
function M.bundle(marker, opts)
|
|
local root = M.mount(marker, opts)
|
|
if not root then return nil end
|
|
local ExtractScripts = require("src.import.gba.extract_scripts")
|
|
local Space = require("src.core.game3.scripting.space")
|
|
local bundle = ExtractScripts.loadBundle(M.cache(), root, { allowIncomplete = true })
|
|
Space.bundle = bundle
|
|
return bundle, root
|
|
end
|
|
|
|
return M
|