-- ROM extraction, off the main thread. The extractor's require closure needs -- only love.filesystem, love.image, love.math and love.system, none of which -- are main-thread-only, so it runs here instead of as a coroutine the frame -- loop resumed for 8ms out of every 16.7ms. -- -- The caller clears the stale cache and writes the completion marker itself; -- this only fills the tree between those two steps, so the "marker appears -- last" order isReady() depends on stays on one thread. pcall(require, "love.filesystem") pcall(require, "love.image") pcall(require, "love.math") pcall(require, "love.system") pcall(require, "love.timer") pcall(require, "love.data") pcall(require, "love.thread") -- Ensure fresh thread Lua state resolves "src.*" via love.filesystem on all platforms: table.insert(package.searchers or package.loaders, 1, function(modname) local path = modname:gsub("%.", "/") .. ".lua" if love and love.filesystem and love.filesystem.getInfo and love.filesystem.getInfo(path) then return assert(love.filesystem.load(path)) end local initPath = modname:gsub("%.", "/") .. "/init.lua" if love and love.filesystem and love.filesystem.getInfo and love.filesystem.getInfo(initPath) then return assert(love.filesystem.load(initPath)) end end) local version, prefix, romData, progressName, resultName, romSha1 = ... local progressChannel = love.thread and love.thread.getChannel and love.thread.getChannel(progressName) local resultChannel = love.thread and love.thread.getChannel and love.thread.getChannel(resultName) -- RomExtractor:tick fires per item, thousands of times per import; a channel -- push each would cost more than the work it reports. local PROGRESS_HZ = 20 local ok, err = pcall(function() local CacheFs = require("src.import.CacheFs") CacheFs.prefix = prefix local manifest = require("src.import.RomManifest").decode(version) local GameVersion = require("src.core.GameVersion") local gen = GameVersion.generation(version) local RomExtractor = gen == 3 and require("src.import.RomExtractorGen3") or gen == 2 and require("src.import.RomExtractorGen2") or require("src.import.RomExtractor") local lastPush, lastStage = 0, nil local extractor = RomExtractor.new(romData, manifest, function(progress, total, stage, current, stageTotal) local now = love.timer.getTime() -- Stage changes always go through, or the caption goes stale. if stage ~= lastStage or now - lastPush >= 1 / PROGRESS_HZ then lastPush, lastStage = now, stage progressChannel:push({ progress = progress, total = total, stage = stage, current = current, stageTotal = stageTotal, }) end end, romSha1) extractor:run() end) resultChannel:push({ ok = ok, error = ok and nil or tostring(err) })