-- 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. require("love.filesystem") require("love.image") require("love.math") require("love.system") require("love.timer") local version, prefix, romData, progressName, resultName, romSha1 = ... local progressChannel = love.thread.getChannel(progressName) local resultChannel = 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 RomExtractor = require("src.core.GameVersion").generation(version) == 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) })