Add UWP LocalState baserom discovery

This commit is contained in:
Caorthann
2026-08-06 14:27:25 +01:00
parent 506cd2c5c5
commit 9e3d487a08
6 changed files with 296 additions and 3 deletions
+16 -2
View File
@@ -541,11 +541,15 @@ local function romModel(imp, version, info, ready, locked)
label = Strings("Import unavailable"), enabled = false }
end
local dropHint = imp.isNX and Strings("Copy the .gb/.gbc via MTP into imports/.")
or (imp.android and Strings("Copy the .gb/.gbc via USB.")
or Strings("Or drop the .gb/.gbc file here."))
or (imp.baseRomDiscovery and Strings("Or copy the .gb/.gbc into baseroms/.")
or (imp.android and Strings("Copy the .gb/.gbc via USB.")
or Strings("Or drop the .gb/.gbc file here.")))
local importing = imp.importing == version
local erroring = imp.workState == "error" and imp.errorVersion == version
local notice = imp.notice and imp.notice.version == version and imp.notice
local baseRom = imp.baseRoms and imp.baseRoms[version]
local scanning = imp.baseRomDiscovery and imp.baseRomScan
and imp.baseRomScan.state ~= "done"
if importing and (imp.workState == "working" or imp.workState == "complete") then
return { state = imp.status or Strings("Importing"),
detail = imp.detail or "", progress = imp.progress or 0 }
@@ -564,6 +568,14 @@ local function romModel(imp, version, info, ready, locked)
detail = ((notice.status or "") .. " " .. (notice.detail or ""))
:gsub("^%s+", ""):gsub("%s+$", ""),
label = importLabel, enabled = true }
elseif baseRom then
return { state = Strings("Compatible ROM found"),
detail = Strings("Found in baseroms/: %s", baseRom.name),
label = Strings("Import detected ROM"), enabled = true }
elseif scanning then
return { state = Strings("Checking baseroms..."),
detail = Strings("Looking for compatible Red, Blue, and Yellow ROMs."),
label = Strings("Import ROM"), enabled = false }
elseif imp.returning[version] then
return { state = Strings("Update required"),
detail = Strings("This build needs a few more things from your ")
@@ -922,6 +934,8 @@ local function buildGamePanel(imp, x, y, w, availH, m, version)
Kit.text("title", Kit.ellipsize("title", gameName, w * 0.6), x, y, PAL.heading)
local tagText, tagCol
if ready then tagText, tagCol = Strings("GOOD TO GO"), PAL.green
elseif imp.baseRoms and imp.baseRoms[version] then
tagText, tagCol = Strings("ROM FOUND"), PAL.green
elseif locked then tagText, tagCol = Strings("COMING SOON"), PAL.steel
else tagText, tagCol = Strings("ROM REQUIRED"), PAL.yellow end
local tagW = Kit.textWidth("micro", tagText) + math.floor(18 * m.s)
+84
View File
@@ -341,6 +341,7 @@ local function commandOutput(command)
end
local IMPORTS_DIR = "imports"
local BASE_ROMS_DIR = "baseroms"
local MODS_INBOX_DIR = "imports/mods"
local SAVES_INBOX_DIR = "imports/saves"
local ROM_BYTES = 1024 * 1024
@@ -474,6 +475,65 @@ local function listRomPaths(dir)
return paths
end
local function baseRomScanSatisfied(self)
for _, version in ipairs(GameVersion.ORDER) do
if not self.ready[version] and not self.baseRoms[version] then
return false
end
end
return true
end
function RomImporter:_queueBaseRomScan()
if not self.baseRomDiscovery then return end
if baseRomScanSatisfied(self) then
self.baseRomScan = { state = "done" }
return
end
self.baseRomScan = { state = "queued", index = 1 }
end
function RomImporter:_stepBaseRomScan()
local scan = self.baseRomScan
if not scan or scan.state == "done" or self.workState == "working" then
return
end
if scan.state == "queued" then
local info = love.filesystem.getInfo(BASE_ROMS_DIR)
if not info and love.filesystem.createDirectory then
love.filesystem.createDirectory(BASE_ROMS_DIR)
end
scan.paths = listRomPaths(BASE_ROMS_DIR)
table.sort(scan.paths)
scan.state = "running"
end
local path = scan.paths[scan.index]
if not path then
scan.state = "done"
return
end
scan.index = scan.index + 1
local info = love.filesystem.getInfo(path, "file")
if info and info.size == ROM_BYTES then
local data = love.filesystem.read(path)
if type(data) == "string" and #data == ROM_BYTES then
local version = GameVersion.forSha1(sha1(data))
if version and not self.ready[version] and not self.baseRoms[version] then
self.baseRoms[version] = {
path = path,
name = path:match("[^/\\]+$") or path,
}
end
end
end
if baseRomScanSatisfied(self) or not scan.paths[scan.index] then
scan.state = "done"
end
end
local function listZipPaths(dir)
local paths = {}
for _, name in ipairs(love.filesystem.getDirectoryItems(dir) or {}) do
@@ -1050,6 +1110,9 @@ function RomImporter.new(onComplete, opts)
android = android,
ios = mobileOS == "iOS",
nativePicker = romImportMode == "native-picker",
baseRomDiscovery = opts.launcher and Platform.isUWP(),
baseRoms = {},
baseRomScan = nil,
-- One startup poll pass on both mobiles. iOS: files dropped through the
-- Files app are swept into the save dir before Lua boots (GRBootstrap) with
-- no love.focus event necessarily following. Android: the SAF picker is a
@@ -1149,6 +1212,7 @@ function RomImporter.new(onComplete, opts)
.. (info.id == "yellow" and ".gbc" or ".gb")
end
self:_applyLastVersionTab()
self:_queueBaseRomScan()
-- Android: import a save-dir .gb/.gbc that is not yet ready (USB drop or a
-- leftover SAF pick), routed by SHA-1. Already-imported carts are skipped
@@ -1755,6 +1819,21 @@ function RomImporter:choose(version)
self:rescanAction(self.chooseVersion)
return
end
local baseRom = self.baseRomDiscovery and self.baseRoms[self.chooseVersion]
if baseRom then
self.baseRoms[self.chooseVersion] = nil
local data = love.filesystem.read(baseRom.path)
if not data then
self.notice = {
version = self.chooseVersion,
status = "The detected ROM is no longer available.",
detail = "Choose Import ROM to select it another way.",
}
return
end
self:startData(data, baseRom.name)
return
end
if self.nativePicker and love.system.getPickedFile then
self.pickerPendingKind = "rom"
if not pickFile("rom") then
@@ -1877,6 +1956,7 @@ end
function RomImporter:update(dt)
self.pulse = self.pulse + dt
self:_updatePadCursor(dt)
self:_stepBaseRomScan()
-- Pump the FlexLove view (input polling + the queued click actions). The
-- flag is only set once draw() has built a tree, so headless runs and the
-- test tier never touch the toolkit.
@@ -2293,6 +2373,10 @@ function RomImporter:reimport(version)
self.ready[version] = false
self.returning[version] = false
self.chooseVersion = version
if self.baseRomDiscovery then
self.baseRoms[version] = nil
self:_queueBaseRomScan()
end
end
local function clamp(v, lo, hi)