diff --git a/src/core/game3/asset_decode.lua b/src/core/game3/asset_decode.lua index 34bf6de4..fcf23f4f 100644 --- a/src/core/game3/asset_decode.lua +++ b/src/core/game3/asset_decode.lua @@ -2,6 +2,7 @@ local Pack = require("src.import.gba.native_pack") local Palette = require("src.core.game3.palette") local OwExtract = require("src.import.gba.ow_extract") +local CacheBlob = require("src.import.CacheBlob") local D = {} function D.imageData(rgba, w, h) @@ -111,12 +112,13 @@ function D.cache(spec, cancelSignal) if spec.directory then local f = io.open(spec.directory .. "/" .. path(rel), "rb") if not f then return nil end - local bytes = f:read("*a"); f:close(); return bytes + local bytes = f:read("*a"); f:close(); return CacheBlob.decode(rel, bytes) end - return love.filesystem.read(path(rel)) + return CacheBlob.readFs(path(rel)) end function cache:write(rel, bytes) checkCancel() + bytes = CacheBlob.encode(rel, bytes) -- No directory creation or mounting in a worker; derived caches are optional. if spec.directory then local f = io.open(spec.directory .. "/" .. path(rel), "wb") diff --git a/src/core/game3/dataset.lua b/src/core/game3/dataset.lua index 024b6c52..1afd4edb 100644 --- a/src/core/game3/dataset.lua +++ b/src/core/game3/dataset.lua @@ -5,10 +5,11 @@ local Versions = require("src.import.gba.versions") local Extract = require("src.import.gba.extract_island1") local MapIds = require("src.core.game3.map_ids") local Profile = require("src.core.game3.profile") +local CacheBlob = require("src.import.CacheBlob") local Dataset = {} -local function diskFallback(rel) +local function diskFallbackRaw(rel) local override = Dataset.cacheRootOverride if override then local f = io.open(override .. "/" .. rel:gsub("^data/generated/gba/", ""), "rb") @@ -63,6 +64,10 @@ local function diskFallback(rel) return nil end +local function diskFallback(rel) + return CacheBlob.decode(rel, diskFallbackRaw(rel)) +end + local function loveCache() return { assetWorkerSpec = function(_, root, kind, key) @@ -82,7 +87,7 @@ local function loveCache() if type(bytes) == "string" then return bytes end end if love and love.filesystem then - local bytes = love.filesystem.read(rel) + local bytes = CacheBlob.readFs(rel) if type(bytes) == "string" then return bytes end end return diskFallback(rel) @@ -93,7 +98,7 @@ local function loveCache() return CacheFs.write(rel, bytes) end if not love or not love.filesystem then return false end - return love.filesystem.write(rel, bytes) + return love.filesystem.write(rel, CacheBlob.encode(rel, bytes)) end, exists = function(_, rel) local ok, CacheFs = pcall(require, "src.import.CacheFs") @@ -108,7 +113,7 @@ local function loveCache() and love.filesystem.getInfo(rel, "file") then return true end - return diskFallback(rel) ~= nil + return diskFallbackRaw(rel) ~= nil end, } end diff --git a/src/core/game3/doors.lua b/src/core/game3/doors.lua index c93ede68..fabafef3 100644 --- a/src/core/game3/doors.lua +++ b/src/core/game3/doors.lua @@ -8,6 +8,7 @@ local SE = require("src.core.game3.se_ids") local MB = require("src.core.game3.mb") +local CacheBlob = require("src.import.CacheBlob") local Doors = {} @@ -619,13 +620,13 @@ local function loadSheet(tileName, sheetFile) end if not bytes and love and love.filesystem and love.filesystem.read then - bytes = love.filesystem.read(relPath) or love.filesystem.read("doors/" .. file) + bytes = CacheBlob.readFs(relPath) or CacheBlob.readFs("doors/" .. file) end if not bytes then local f = io.open(relPath, "rb") if f then - bytes = f:read("*a") + bytes = CacheBlob.decode(relPath, f:read("*a")) f:close() end end diff --git a/src/core/game3/pokedex_data.lua b/src/core/game3/pokedex_data.lua index dbcb33bc..338112a4 100644 --- a/src/core/game3/pokedex_data.lua +++ b/src/core/game3/pokedex_data.lua @@ -5,6 +5,7 @@ local Extract = require("src.import.gba.extract_island1") local Dex = require("src.core.game3.dex") local Pokemon = require("src.core.game3.pokemon") local RomText = require("src.core.game3.rom_text") +local CacheBlob = require("src.import.CacheBlob") local PokedexData = {} @@ -40,7 +41,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/core/game3/pokemon.lua b/src/core/game3/pokemon.lua index 88dba36c..b265086f 100644 --- a/src/core/game3/pokemon.lua +++ b/src/core/game3/pokemon.lua @@ -3,6 +3,7 @@ local CachePaths = require("src.core.game3.cache_paths") local PokemonExtract = require("src.import.gba.pokemon_extract") local Versions = require("src.import.gba.versions") local ModRuntime = require("src.mods.Runtime") +local CacheBlob = require("src.import.CacheBlob") local Pokemon = {} @@ -56,7 +57,7 @@ local function resolve_cache(cache) end local f = io.open(rel, "rb") or io.open("data/generated/gba/" .. rel, "rb") if f then - local data = f:read("*a") + local data = CacheBlob.decode(rel, f:read("*a")) f:close() return data end diff --git a/src/core/game3/rse/berry_blender.lua b/src/core/game3/rse/berry_blender.lua index de727ef1..3dd45809 100644 --- a/src/core/game3/rse/berry_blender.lua +++ b/src/core/game3/rse/berry_blender.lua @@ -4,6 +4,7 @@ local band, rshift = bit.band, bit.rshift local Tasks = require("src.core.game3.gba_tasks") local RsPolicy = require("src.core.game3.rs.berry_blender_policy") +local CacheBlob = require("src.import.CacheBlob") local Blender = {} Blender.__index = Blender @@ -71,7 +72,7 @@ local function readCache(path) if okR and s then return s end end if love and love.filesystem and love.filesystem.getInfo and love.filesystem.getInfo(path) then - return love.filesystem.read(path) + return CacheBlob.readFs(path) end return nil end diff --git a/src/core/game3/trainer_tower.lua b/src/core/game3/trainer_tower.lua index 012cd23a..a523d7c9 100644 --- a/src/core/game3/trainer_tower.lua +++ b/src/core/game3/trainer_tower.lua @@ -1,3 +1,4 @@ +local CacheBlob = require("src.import.CacheBlob") local Tower = {} -- pokefirered/include/constants/trainer_tower.h:30 @@ -152,12 +153,12 @@ local function read_bytes(rel) if okR and type(d) == "string" and #d > 0 then return d end end if type(love) == "table" and love.filesystem and love.filesystem.read then - local okR, d = pcall(love.filesystem.read, rel) + local okR, d = pcall(CacheBlob.readFs, rel) if okR and type(d) == "string" and #d > 0 then return d end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if type(d) == "string" and #d > 0 then return d end end diff --git a/src/import/CacheBlob.lua b/src/import/CacheBlob.lua new file mode 100644 index 00000000..27cd92fb --- /dev/null +++ b/src/import/CacheBlob.lua @@ -0,0 +1,96 @@ +local CacheBlob = {} + +CacheBlob.LEVEL = 6 +CacheBlob.DERIVED_LEVEL = 1 + +local PACKED = { rgba = true, idx = true } + +local function extension(rel) + return type(rel) == "string" and rel:match("%.([^./\\]+)$") or nil +end + +function CacheBlob.packs(rel) + local ext = extension(rel) + return ext ~= nil and PACKED[ext] == true +end + +local loveData +local function loveBackend() + if loveData ~= nil then return loveData end + loveData = false + local L = rawget(_G, "love") + if L and not (L.data and L.data.compress) then pcall(require, "love.data") end + if L and L.data and L.data.compress and L.data.decompress then loveData = L.data end + return loveData +end + +local zlib +local function ffiBackend() + if zlib ~= nil then return zlib end + zlib = false + local okF, ffi = pcall(require, "ffi") + if not okF then return zlib end + pcall(ffi.cdef, [[ + unsigned long compressBound(unsigned long sourceLen); + int compress2(uint8_t *dest, unsigned long *destLen, const uint8_t *source, unsigned long sourceLen, int level); + int uncompress(uint8_t *dest, unsigned long *destLen, const uint8_t *source, unsigned long sourceLen); + ]]) + for _, name in ipairs(ffi.os == "Windows" and { "zlib1", "z" } or { "z", "libz.so.1" }) do + local okL, lib = pcall(ffi.load, name) + if okL and lib and pcall(function() return lib.uncompress end) then + zlib = { ffi = ffi, lib = lib } + break + end + end + return zlib +end + +function CacheBlob.deflate(raw, level) + level = level or CacheBlob.LEVEL + local L = loveBackend() + if L then return L.compress("string", "zlib", raw, level) end + local Z = assert(ffiBackend(), "CacheBlob: no zlib backend (love.data or libz)") + local ffi = Z.ffi + local cap = tonumber(Z.lib.compressBound(#raw)) + local out = ffi.new("uint8_t[?]", cap) + local len = ffi.new("unsigned long[1]", cap) + local rc = Z.lib.compress2(out, len, raw, #raw, level) + assert(rc == 0, "CacheBlob: compress2 failed (" .. tostring(rc) .. ")") + return ffi.string(out, tonumber(len[0])) +end + +function CacheBlob.inflate(z) + local L = loveBackend() + if L then return L.decompress("string", "zlib", z) end + local Z = assert(ffiBackend(), "CacheBlob: no zlib backend (love.data or libz)") + local ffi = Z.ffi + local cap = math.max(4096, #z * 16) + while true do + local out = ffi.new("uint8_t[?]", cap) + local len = ffi.new("unsigned long[1]", cap) + local rc = Z.lib.uncompress(out, len, z, #z) + if rc == 0 then return ffi.string(out, tonumber(len[0])) end + assert(rc == -5, "CacheBlob: uncompress failed (" .. tostring(rc) .. ")") + cap = cap * 4 + end +end + +function CacheBlob.encode(rel, bytes) + if type(bytes) ~= "string" or not CacheBlob.packs(rel) then return bytes end + return CacheBlob.deflate(bytes, rel:find("/atlas_", 1, true) and CacheBlob.DERIVED_LEVEL or CacheBlob.LEVEL) +end + +function CacheBlob.decode(rel, bytes) + if type(bytes) ~= "string" or not CacheBlob.packs(rel) then return bytes end + local ok, raw = pcall(CacheBlob.inflate, bytes) + if not ok then error("cache blob " .. tostring(rel) .. " is not deflated (stale cache, reimport): " .. tostring(raw), 2) end + return raw +end + +function CacheBlob.readFs(rel) + if not (love and love.filesystem and love.filesystem.read) then return nil end + local bytes = love.filesystem.read(rel) + return CacheBlob.decode(rel, bytes) +end + +return CacheBlob diff --git a/src/import/CacheContract.lua b/src/import/CacheContract.lua index 5d415b7e..929c1f4a 100644 --- a/src/import/CacheContract.lua +++ b/src/import/CacheContract.lua @@ -22,12 +22,12 @@ CacheContract.VERSION_FORMAT = { -- data/pikachu/pikachu_pic_animation.asm:340 yellow = "rom-cache-v12-yellow2:", -- v8: M4A tracks retain reachable patterns and explicit entry offsets. - firered = "rom-cache-v24-firered:", - leafgreen = "rom-cache-v9-leafgreen:", - emerald = "rom-cache-v4-emerald:", + firered = "rom-cache-v25-firered:", + leafgreen = "rom-cache-v10-leafgreen:", + emerald = "rom-cache-v5-emerald:", -- pokeruby/src/string_util.c:408 - ruby = "rom-cache-v6-ruby:", - sapphire = "rom-cache-v6-sapphire:", + ruby = "rom-cache-v7-ruby:", + sapphire = "rom-cache-v7-sapphire:", } CacheContract.MARKER_PATH = "rom-cache.complete" @@ -1009,7 +1009,7 @@ function CacheContract.sourceTreeHasData(version) local exact = { read = function(path) local full = prefix .. path - if love.filesystem.getRealDirectory(full) == source then return love.filesystem.read(full) end + if love.filesystem.getRealDirectory(full) == source then return require("src.import.CacheBlob").readFs(full) end end, exists = function(path) local full = prefix .. path diff --git a/src/import/CacheFs.lua b/src/import/CacheFs.lua index ed341e8f..5fe08fe8 100644 --- a/src/import/CacheFs.lua +++ b/src/import/CacheFs.lua @@ -29,6 +29,7 @@ local CacheFs = {} local Platform = require("src.core.Platform") +local CacheBlob = require("src.import.CacheBlob") local SaveData = setmetatable({}, { __index = function(_, k) return require("src.core.SaveData")[k] end, }) @@ -324,6 +325,7 @@ end function CacheFs.write(rel, data) rel = withPrefix(rel) if unsafe_rel(rel) then return false, "unsafe cache path" end + data = CacheBlob.encode(rel, data) local root, rootErr = resolveWriteRoot() if not root and rootErr then return false, rootErr end if root then @@ -389,12 +391,12 @@ function CacheFs.readAt(rel) if not f then return nil end local data = f:read("*a") f:close() - return data + return CacheBlob.decode(rel, data) end -- headless (plain luajit, e.g. the modkit validate/pack driver): there is -- no save directory to read from, so a cache miss is nil, not a crash if not (love and love.filesystem and love.filesystem.read) then return nil end - return love.filesystem.read(rel) + return (CacheBlob.readFs(rel)) end -- read cache-relative `rel`; returns the bytes or nil diff --git a/src/import/gba/battle_anim_extract.lua b/src/import/gba/battle_anim_extract.lua index 910189a4..760982af 100644 --- a/src/import/gba/battle_anim_extract.lua +++ b/src/import/gba/battle_anim_extract.lua @@ -6,6 +6,7 @@ local Versions = require("src.import.gba.versions") local Lz77 = require("src.import.gba.lz77") +local CacheBlob = require("src.import.CacheBlob") local BattleAnimExtract = {} @@ -504,16 +505,6 @@ local function crc32(str) return bxor(c, 0xFFFFFFFF) end -local function adler32(str) - local s1 = 1 - local s2 = 0 - for i = 1, #str do - s1 = (s1 + str:byte(i)) % 65521 - s2 = (s2 + s1) % 65521 - end - return s2 * 65536 + s1 -end - local function u32be(n) n = band(n, 0xFFFFFFFF) return string.char( @@ -524,10 +515,6 @@ local function u32be(n) ) end -local function u16le(n) - return string.char(band(n, 0xFF), band(rshift(n, 8), 0xFF)) -end - local function make_chunk(type_str, data) local crc = crc32(type_str .. data) return u32be(#data) .. type_str .. data .. u32be(crc) @@ -607,31 +594,7 @@ local function encode_png(pixels, w, h) raw_data = table.concat(raw_lines) end - local idat_data - if love and love.data and love.data.compress then - local ok, comp = pcall(love.data.compress, "string", "zlib", raw_data) - if ok and comp then - idat_data = comp - end - end - - if not idat_data then - -- Deflate uncompressed blocks (max 65535 per block) - local zlib_blocks = { string.char(0x78, 0x01) } -- ZLIB header - local pos = 1 - local total_len = #raw_data - while pos <= total_len do - local chunk_len = math.min(total_len - pos + 1, 65535) - local is_final = (pos + chunk_len > total_len) and 1 or 0 - zlib_blocks[#zlib_blocks + 1] = string.char(is_final) - zlib_blocks[#zlib_blocks + 1] = u16le(chunk_len) - zlib_blocks[#zlib_blocks + 1] = u16le(bxor(chunk_len, 0xFFFF)) - zlib_blocks[#zlib_blocks + 1] = raw_data:sub(pos, pos + chunk_len - 1) - pos = pos + chunk_len - end - zlib_blocks[#zlib_blocks + 1] = u32be(adler32(raw_data)) - idat_data = table.concat(zlib_blocks) - end + local idat_data = CacheBlob.deflate(raw_data, 9) -- PNG Signature + IHDR + IDAT + IEND local sig = "\137PNG\r\n\026\n" diff --git a/src/import/gba/battle_chrome_extract.lua b/src/import/gba/battle_chrome_extract.lua index b14ad304..0874f65f 100644 --- a/src/import/gba/battle_chrome_extract.lua +++ b/src/import/gba/battle_chrome_extract.lua @@ -4,6 +4,7 @@ local Versions = require("src.import.gba.versions") local Lz77 = require("src.import.gba.lz77") +local CacheBlob = require("src.import.CacheBlob") local BattleChromeExtract = {} @@ -725,11 +726,11 @@ function BattleChromeExtract.ready(cache, cacheRoot) local CacheFs = require("src.import.CacheFs") local bytes = CacheFs.readActive and CacheFs.readActive(rel) if bytes then return bytes end - if love and love.filesystem then bytes = love.filesystem.read(rel) end + if love and love.filesystem then bytes = CacheBlob.readFs(rel) end if bytes then return bytes end local file = io.open(rel, "rb") if not file then return nil end - bytes = file:read("*a"); file:close(); return bytes + bytes = CacheBlob.decode(rel, file:read("*a")); file:close(); return bytes end local body = read_file(root .. "/manifest.lua") local chunk = type(body) == "string" and load(body, "@battle/manifest.lua", "t", {}) @@ -767,7 +768,7 @@ function BattleChromeExtract.ready(cache, cacheRoot) if data and #data >= minSize then return true end end if love and love.filesystem and love.filesystem.read then - local ok, data = pcall(love.filesystem.read, rel) + local ok, data = pcall(CacheBlob.readFs, rel) if ok and data and #data >= minSize then return true end end local f = io.open(rel, "rb") diff --git a/src/import/gba/file_io.lua b/src/import/gba/file_io.lua index 50202e64..7c04a5d7 100644 --- a/src/import/gba/file_io.lua +++ b/src/import/gba/file_io.lua @@ -1,6 +1,7 @@ -- File-backed mod.imports / mod.cache shim for offline extract (dev CLI). local FileIO = {} +local CacheBlob = require("src.import.CacheBlob") function FileIO.makeImports(path, md5, id) id = id or "firered" @@ -45,7 +46,7 @@ function FileIO.makeCache(root) local parent = path:match("^(.*)/[^/]+$") if parent then mkdir_p(parent) end local f = assert(io.open(path, "wb")) - f:write(bytes) + f:write(CacheBlob.encode(rel, bytes)) f:close() return true end @@ -54,7 +55,7 @@ function FileIO.makeCache(root) if not f then return nil end local d = f:read("*a") f:close() - return d + return CacheBlob.decode(rel, d) end function cache:exists(rel) local f = io.open(root .. "/" .. rel, "rb") diff --git a/src/import/gba/games/emerald.lua b/src/import/gba/games/emerald.lua index ba272fc9..95e91d7d 100644 --- a/src/import/gba/games/emerald.lua +++ b/src/import/gba/games/emerald.lua @@ -3,7 +3,7 @@ local VersionsRse = require("src.import.gba.versions_rse") local V = VersionsRse.new("emerald") local sym, count = V.sym, V.count -V.CACHE_VERSION = 14 +V.CACHE_VERSION = 15 V.NATIVE_VERSION = 2 V.OW_VERSION = 1 V.ANIM_VERSION = 1 diff --git a/src/import/gba/games/rs.lua b/src/import/gba/games/rs.lua index 7bbee619..d59d7258 100644 --- a/src/import/gba/games/rs.lua +++ b/src/import/gba/games/rs.lua @@ -6,7 +6,7 @@ local Rs = {} local function tables(game, revision) local V = VersionsRse.new(game, revision.build) local sym, count = V.sym, V.count - V.CACHE_VERSION = 2 + V.CACHE_VERSION = 3 V.NATIVE_VERSION = 2 V.OW_VERSION = 1 V.ANIM_VERSION = 1 diff --git a/src/import/gba/party_chrome_extract.lua b/src/import/gba/party_chrome_extract.lua index d73561be..b14932c2 100644 --- a/src/import/gba/party_chrome_extract.lua +++ b/src/import/gba/party_chrome_extract.lua @@ -3,6 +3,7 @@ local Versions = require("src.import.gba.versions") local Lz77 = require("src.import.gba.lz77") +local CacheBlob = require("src.import.CacheBlob") local PartyChromeExtract = {} @@ -488,12 +489,12 @@ function PartyChromeExtract.ready(cache, cacheRoot) if d and #d >= 80 * 56 * 4 then return true end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(need) + local d = CacheBlob.readFs(need) if d and #d >= 80 * 56 * 4 then return true end end local f = io.open(need, "rb") or io.open("data/generated/gba/" .. PartyChromeExtract.CACHE_SUB .. "/slot_main.rgba", "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(need, f:read("*a")) f:close() if d and #d >= 80 * 56 * 4 then return true end end diff --git a/src/import/gba/pokedex_chrome_extract.lua b/src/import/gba/pokedex_chrome_extract.lua index 2fd82737..4d6b55f9 100644 --- a/src/import/gba/pokedex_chrome_extract.lua +++ b/src/import/gba/pokedex_chrome_extract.lua @@ -8,6 +8,7 @@ local Versions = require("src.import.gba.versions") local TextIR = require("src.core.game3.scripting.text_ir") local Lz77 = require("src.import.gba.lz77") +local CacheBlob = require("src.import.CacheBlob") local PokedexChromeExtract = {} @@ -873,7 +874,7 @@ function PokedexChromeExtract.ready(cache, cacheRoot) if data and #data >= minSize then return true end end if love and love.filesystem and love.filesystem.read then - local ok, data = pcall(love.filesystem.read, rel) + local ok, data = pcall(CacheBlob.readFs, rel) if ok and data and #data >= minSize then return true end end local f = io.open(rel, "rb") diff --git a/src/import/gba/region_map_extract.lua b/src/import/gba/region_map_extract.lua index a529d88f..179dca8e 100644 --- a/src/import/gba/region_map_extract.lua +++ b/src/import/gba/region_map_extract.lua @@ -1,3 +1,5 @@ +local CacheBlob = require("src.import.CacheBlob") + -- src/region_map.c:393-427 local RegionMapExtract = {} @@ -553,12 +555,12 @@ local function baked(cache, rel) if d and #d > 8 then return true end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if d and #d > 8 then return true end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if d and #d > 8 then return true end end diff --git a/src/import/gba/rse/boot_gfx.lua b/src/import/gba/rse/boot_gfx.lua index d6f3ecdf..0922cf9e 100644 --- a/src/import/gba/rse/boot_gfx.lua +++ b/src/import/gba/rse/boot_gfx.lua @@ -1,5 +1,6 @@ local Lz77 = require("src.import.gba.lz77") local LuaWriter = require("src.import.LuaWriter") +local CacheBlob = require("src.import.CacheBlob") local bit = rawget(_G, "bit") or require("bit") local band, bxor, rshift = bit.band, bit.bxor, bit.rshift @@ -51,40 +52,9 @@ local function chunk(kind, data) return be32(#data) .. kind .. data .. be32(crc32(kind .. data)) end -local function adler32(s) - local a, b = 1, 0 - for i = 1, #s do - a = (a + s:byte(i)) % 65521 - b = (b + a) % 65521 - end - return b * 65536 + a -end - -local function zlibStored(raw) - local parts = { "\120\1" } - local n = #raw - local pos = 1 - repeat - local len = math.min(65535, n - pos + 1) - local final = (pos + len > n) and 1 or 0 - parts[#parts + 1] = string.char(final, len % 256, math.floor(len / 256), - (65535 - len) % 256, math.floor((65535 - len) / 256)) - parts[#parts + 1] = raw:sub(pos, pos + len - 1) - pos = pos + len - until pos > n - parts[#parts + 1] = be32(adler32(raw)) - return table.concat(parts) -end - local function zlib(raw) - local love = rawget(_G, "love") - if love and love.data and love.data.compress then - local ok, out = pcall(love.data.compress, "string", "zlib", raw) - if ok and type(out) == "string" then return out end - end - return zlibStored(raw) + return CacheBlob.deflate(raw, 9) end -K.zlibStored = zlibStored local function scanlines(w, h, idx) local rows = {} diff --git a/src/import/gba/summary_chrome_extract.lua b/src/import/gba/summary_chrome_extract.lua index 2efbfbf1..6070e164 100644 --- a/src/import/gba/summary_chrome_extract.lua +++ b/src/import/gba/summary_chrome_extract.lua @@ -3,6 +3,7 @@ local Versions = require("src.import.gba.versions") local Lz77 = require("src.import.gba.lz77") +local CacheBlob = require("src.import.CacheBlob") local SummaryChromeExtract = {} @@ -82,12 +83,12 @@ local function read_bin(candidates) if d and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local ok, d = pcall(love.filesystem.read, p) + local ok, d = pcall(CacheBlob.readFs, p) if ok and d and #d > 0 then return d end end local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end @@ -709,12 +710,12 @@ function SummaryChromeExtract.ready(cache, cacheRoot) if d and #d >= 240 * 160 * 4 then return true end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(need) + local d = CacheBlob.readFs(need) if d and #d >= 240 * 160 * 4 then return true end end local f = io.open(need, "rb") or io.open("data/generated/gba/" .. SummaryChromeExtract.CACHE_SUB .. "/page_info.rgba", "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(need, f:read("*a")) f:close() if d and #d >= 240 * 160 * 4 then return true end end diff --git a/src/import/gba/trainer_card_extract.lua b/src/import/gba/trainer_card_extract.lua index 1263546d..b76499ce 100644 --- a/src/import/gba/trainer_card_extract.lua +++ b/src/import/gba/trainer_card_extract.lua @@ -3,6 +3,7 @@ local Versions = require("src.import.gba.versions") local Lz77 = require("src.import.gba.lz77") +local CacheBlob = require("src.import.CacheBlob") local TrainerCardExtract = {} @@ -406,12 +407,12 @@ function TrainerCardExtract.ready(cache, cacheRoot) if d and #d >= 240 * 160 * 4 then return true end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(need) + local d = CacheBlob.readFs(need) if d and #d >= 240 * 160 * 4 then return true end end local f = io.open(need, "rb") or io.open("data/generated/gba/" .. TrainerCardExtract.CACHE_SUB .. "/bg.rgba", "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(need, f:read("*a")) f:close() if d and #d >= 240 * 160 * 4 then return true end end diff --git a/src/import/gba/versions_frlg.lua b/src/import/gba/versions_frlg.lua index 4ba5ec23..16bd28e9 100644 --- a/src/import/gba/versions_frlg.lua +++ b/src/import/gba/versions_frlg.lua @@ -43,7 +43,7 @@ Versions.ROM_SIZE = 16777216 -- v115: LeafGreen profiles, edition-specific title assets and Deoxys stats. -- v121: chrome/fonts/japanese_{normal,small}_* and japanese_widths.lua, the -- cart's Japanese fonts, for text a Japanese translation mod prints. -Versions.CACHE_VERSION = 129 +Versions.CACHE_VERSION = 130 Versions.NATIVE_VERSION = 6 Versions.OW_VERSION = 3 Versions.ANIM_VERSION = 1 diff --git a/src/ui/game3/bag_chrome.lua b/src/ui/game3/bag_chrome.lua index cc931108..e269a538 100644 --- a/src/ui/game3/bag_chrome.lua +++ b/src/ui/game3/bag_chrome.lua @@ -2,6 +2,7 @@ local Extract = require("src.import.gba.extract_island1") local BagChromeExtract = require("src.import.gba.bag_chrome_extract") +local CacheBlob = require("src.import.CacheBlob") local BagChrome = {} @@ -48,10 +49,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -61,7 +62,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/battle_chrome.lua b/src/ui/game3/battle_chrome.lua index 7a27aa99..9f2f42c6 100644 --- a/src/ui/game3/battle_chrome.lua +++ b/src/ui/game3/battle_chrome.lua @@ -2,6 +2,7 @@ local Extract = require("src.import.gba.extract_island1") local BattleChromeExtract = require("src.import.gba.battle_chrome_extract") +local CacheBlob = require("src.import.CacheBlob") local BattleChrome = {} @@ -68,10 +69,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -81,7 +82,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/berry_pouch_chrome.lua b/src/ui/game3/berry_pouch_chrome.lua index d89fd142..720b62d4 100644 --- a/src/ui/game3/berry_pouch_chrome.lua +++ b/src/ui/game3/berry_pouch_chrome.lua @@ -2,6 +2,7 @@ local Extract = require("src.import.gba.extract_island1") local BerryPouchExtract = require("src.import.gba.berry_pouch_extract") +local CacheBlob = require("src.import.CacheBlob") local BerryPouchChrome = {} @@ -37,10 +38,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -50,7 +51,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/braille.lua b/src/ui/game3/braille.lua index 0e243747..3a81bb6b 100644 --- a/src/ui/game3/braille.lua +++ b/src/ui/game3/braille.lua @@ -2,6 +2,7 @@ local FrlgFont = require("src.ui.game3.frlg_font") local TextIR = require("src.core.game3.scripting.text_ir") +local CacheBlob = require("src.import.CacheBlob") local Braille = {} @@ -109,17 +110,17 @@ local function read_bytes(rel) if okR and type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local okR, d = pcall(love.filesystem.read, rel) + local okR, d = pcall(CacheBlob.readFs, rel) if okR and type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - okR, d = pcall(love.filesystem.read, alt) + okR, d = pcall(CacheBlob.readFs, alt) if okR and type(d) == "string" and #d > 0 then return d end end local candidates = { rel, "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) } for _, path in ipairs(candidates) do local f = io.open(path, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(path, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/egg_hatch.lua b/src/ui/game3/egg_hatch.lua index e42972be..5a569550 100644 --- a/src/ui/game3/egg_hatch.lua +++ b/src/ui/game3/egg_hatch.lua @@ -9,6 +9,7 @@ local Oam = require("src.core.game3.oam") local SE = require("src.core.game3.se_ids") local RomText = require("src.core.game3.rom_text") local BattleChrome = require("src.ui.game3.battle_chrome") +local CacheBlob = require("src.import.CacheBlob") local EggHatch = {} @@ -70,13 +71,13 @@ local function read_bytes(path) if love and love.filesystem and love.filesystem.getInfo then local info = love.filesystem.getInfo(path) if info then - local data = love.filesystem.read(path) + local data = CacheBlob.readFs(path) if data and #data > 0 then return data end end end local f = io.open(path, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(path, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/fame_checker.lua b/src/ui/game3/fame_checker.lua index dc31f23e..dbd69c7f 100644 --- a/src/ui/game3/fame_checker.lua +++ b/src/ui/game3/fame_checker.lua @@ -6,6 +6,7 @@ local FrlgFont = require("src.ui.game3.frlg_font") local FameChecker = require("src.core.game3.fame_checker") local TextIR = require("src.core.game3.scripting.text_ir") local RomText = require("src.core.game3.rom_text") +local CacheBlob = require("src.import.CacheBlob") local FameCheckerUi = { isMenu = true } @@ -105,12 +106,12 @@ local function read_bytes(rel) if ok and type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local ok, d = pcall(love.filesystem.read, rel) + local ok, d = pcall(CacheBlob.readFs, rel) if ok and type(d) == "string" and #d > 0 then return d end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/frlg_font.lua b/src/ui/game3/frlg_font.lua index e47611dc..b827eb92 100644 --- a/src/ui/game3/frlg_font.lua +++ b/src/ui/game3/frlg_font.lua @@ -2,6 +2,7 @@ -- Field dialogue must use this — Gen2 Font.lua is fixed 8px and overflows the 208px box. local TextIR = require("src.core.game3.scripting.text_ir") +local CacheBlob = require("src.import.CacheBlob") local FrlgFont = {} @@ -246,15 +247,15 @@ local function loadImage(candidates) end end if not data and love and love.filesystem and love.filesystem.read then - data = love.filesystem.read(path) + data = CacheBlob.readFs(path) if not data then - data = love.filesystem.read("data/generated/gba/" .. (path:gsub("^data/generated/gba/", ""))) + data = CacheBlob.readFs("data/generated/gba/" .. (path:gsub("^data/generated/gba/", ""))) end end if not data then local f = io.open(path, "rb") or io.open("data/generated/gba/" .. (path:gsub("^data/generated/gba/", "")), "rb") if f then - data = f:read("*a") + data = CacheBlob.decode(path, f:read("*a")) f:close() end end diff --git a/src/ui/game3/link_menu.lua b/src/ui/game3/link_menu.lua index 49121925..be557ef4 100644 --- a/src/ui/game3/link_menu.lua +++ b/src/ui/game3/link_menu.lua @@ -2,6 +2,7 @@ local Stack = require("src.ui.game3.stack") local Window = require("src.ui.game3.window") local FrlgFont = require("src.ui.game3.frlg_font") local Status = require("src.core.game3.link.status") +local CacheBlob = require("src.import.CacheBlob") local LinkMenu = {} @@ -53,12 +54,12 @@ local function read_bytes(rel) if okR and type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local okR, d = pcall(love.filesystem.read, "data/generated/gba/" .. rel) + local okR, d = pcall(CacheBlob.readFs, "data/generated/gba/" .. rel) if okR and type(d) == "string" and #d > 0 then return d end end local f = io.open("data/generated/gba/" .. rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode("data/generated/gba/" .. rel, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/map_preview_screen.lua b/src/ui/game3/map_preview_screen.lua index 2624bea5..64b3e3e9 100644 --- a/src/ui/game3/map_preview_screen.lua +++ b/src/ui/game3/map_preview_screen.lua @@ -5,6 +5,7 @@ local CaveTransition = require("src.ui.game3.cave_transition") local Extract = require("src.import.gba.extract_island1") local MapPreviewExtract = require("src.import.gba.map_preview_extract") local Strings = require("src.core.Strings") +local CacheBlob = require("src.import.CacheBlob") local MapPreviewScreen = {} @@ -87,10 +88,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -100,7 +101,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/move_relearner.lua b/src/ui/game3/move_relearner.lua index 99cbafd4..5466b037 100644 --- a/src/ui/game3/move_relearner.lua +++ b/src/ui/game3/move_relearner.lua @@ -37,6 +37,7 @@ local WIN_PROMPT = Window.template(2, 15, 26, 4) -- pokefirered/src/learn_move.c:329 sMoveRelearnerYesNoMenuTemplate local WIN_YESNO = Window.template(21, 8, 6, 4) local SE = require("src.core.game3.se_ids") +local CacheBlob = require("src.import.CacheBlob") local function se(id) pcall(function() @@ -57,12 +58,12 @@ local function read_bytes(rel) if ok and type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local ok, d = pcall(love.filesystem.read, rel) + local ok, d = pcall(CacheBlob.readFs, rel) if ok and type(d) == "string" and #d > 0 then return d end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/party_chrome.lua b/src/ui/game3/party_chrome.lua index ae9977ae..5f6241a3 100644 --- a/src/ui/game3/party_chrome.lua +++ b/src/ui/game3/party_chrome.lua @@ -5,6 +5,7 @@ local Extract = require("src.import.gba.extract_island1") local PartyChromeExtract = require("src.import.gba.party_chrome_extract") local FrlgFont = require("src.ui.game3.frlg_font") local RomText = require("src.core.game3.rom_text") +local CacheBlob = require("src.import.CacheBlob") local PartyChrome = {} @@ -54,10 +55,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -67,7 +68,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/pc_chrome.lua b/src/ui/game3/pc_chrome.lua index 996b8d0a..ae1b5c38 100644 --- a/src/ui/game3/pc_chrome.lua +++ b/src/ui/game3/pc_chrome.lua @@ -7,6 +7,7 @@ local Pokemon = require("src.core.game3.pokemon") local ItemsData = require("src.core.game3.items_data") local Strings = require("src.core.Strings") local Presentation = require("src.ui.game3.storage_presentation") +local CacheBlob = require("src.import.CacheBlob") local PcChrome = {} @@ -62,12 +63,12 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local ok, d = pcall(love.filesystem.read, rel) + local ok, d = pcall(CacheBlob.readFs, rel) if ok and type(d) == "string" and #d > 0 then return d end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if type(d) == "string" and #d > 0 then return d end end diff --git a/src/ui/game3/pokedex_chrome.lua b/src/ui/game3/pokedex_chrome.lua index 3f8dabf6..3db93df6 100644 --- a/src/ui/game3/pokedex_chrome.lua +++ b/src/ui/game3/pokedex_chrome.lua @@ -5,6 +5,7 @@ local Display = require("src.core.game3.display") local Extract = require("src.import.gba.extract_island1") local PokedexData = require("src.core.game3.pokedex_data") +local CacheBlob = require("src.import.CacheBlob") local PokedexChrome = {} @@ -38,10 +39,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -51,7 +52,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/rs/summary_menu.lua b/src/ui/game3/rs/summary_menu.lua index 7b9522d4..960a9fd9 100644 --- a/src/ui/game3/rs/summary_menu.lua +++ b/src/ui/game3/rs/summary_menu.lua @@ -7,6 +7,7 @@ local SummaryData = require("src.core.game3.summary_data") local Policy = require("src.ui.game3.rs.summary_policy") local Pal = require("src.core.game3.pal_fade") local Audio = require("src.core.game3.audio") +local CacheBlob = require("src.import.CacheBlob") local S = {isMenu = true, open = false, PAGE = Policy.PAGE, MODE = Policy.MODE, policy = Policy} local layers, tiles, quads = {}, {}, {} local function rawMon() return S._party and S._party[S._cursor] end @@ -275,7 +276,7 @@ local function frame(entry, index, x, y) if not quads[key] then quads[key] = love.graphics.newQuad(0, index * entry.h, entry.w, entry.h, image:getDimensions()) end love.graphics.setColor(1, 1, 1, 1); love.graphics.draw(image, quads[key], x, y) end -local function read(path) return assert(love.filesystem.read(path), path) end +local function read(path) return assert(CacheBlob.readFs(path), path) end local function shiny() return not Pokemon.isEgg(mon()) and Pokemon.isShiny(mon()) end local function nativeImage(key, tile, bank, sourceOverride) local palette = S._man.palettes.bg diff --git a/src/ui/game3/rse/berry_blender.lua b/src/ui/game3/rse/berry_blender.lua index 8dc3ba19..5e557c89 100644 --- a/src/ui/game3/rse/berry_blender.lua +++ b/src/ui/game3/rse/berry_blender.lua @@ -7,6 +7,7 @@ local Sprites = require("src.core.game3.gba_sprites") local Machine = require("src.ui.game3.rse.gba_machine") local Affine = require("src.core.game3.bg_affine") local B = require("src.core.game3.rse.berry_blender") +local CacheBlob = require("src.import.CacheBlob") local UI = {} UI.__index = UI @@ -102,7 +103,7 @@ function UI:readCache(path) if ok and Dataset and Dataset.cache then data = Dataset.cache():read(path) end end if not data and love and love.filesystem and love.filesystem.getInfo and love.filesystem.getInfo(path) then - data = love.filesystem.read(path) + data = CacheBlob.readFs(path) end return assert(data, "berry_blender: missing " .. tostring(path)) end diff --git a/src/ui/game3/rse/cable_car.lua b/src/ui/game3/rse/cable_car.lua index 85796321..00d32872 100644 --- a/src/ui/game3/rse/cable_car.lua +++ b/src/ui/game3/rse/cable_car.lua @@ -5,6 +5,7 @@ local Palette = require("src.core.game3.gba_palette") local Sprites = require("src.core.game3.gba_sprites") local TileLayer = require("src.ui.game3.rse.tile_layer") local OwSheet = require("src.ui.game3.rse.ow_sheet") +local CacheBlob = require("src.import.CacheBlob") local band = bit.band @@ -406,7 +407,7 @@ function CableCar:loadCb() ppu.sprites:freeAllPalettes() ppu.palette:resetFade() self:startWeather() - local tiles = assert(love.filesystem.read(self.man.bgTiles), "cable_car: bg tiles missing from cache") + local tiles = assert(CacheBlob.readFs(self.man.bgTiles), "cable_car: bg tiles missing from cache") self.bg = {} for i = 0, 3 do self.bg[i] = TileLayer.new(tiles) end -- pokeemerald/src/cable_car.c:95 diff --git a/src/ui/game3/rse/pokeblock_gfx.lua b/src/ui/game3/rse/pokeblock_gfx.lua index 3d8bdd0d..2f352d21 100644 --- a/src/ui/game3/rse/pokeblock_gfx.lua +++ b/src/ui/game3/rse/pokeblock_gfx.lua @@ -1,4 +1,5 @@ local Kit = require("src.ui.game3.rse.scene_kit") +local CacheBlob = require("src.import.CacheBlob") local Gfx = {} Gfx.__index = Gfx @@ -16,7 +17,7 @@ local function readCache(path) end end if not data and love and love.filesystem and love.filesystem.getInfo(path) then - data = love.filesystem.read(path) + data = CacheBlob.readFs(path) end return data end diff --git a/src/ui/game3/rse/pokedex_gfx.lua b/src/ui/game3/rse/pokedex_gfx.lua index ee840cd5..d8b8c4cb 100644 --- a/src/ui/game3/rse/pokedex_gfx.lua +++ b/src/ui/game3/rse/pokedex_gfx.lua @@ -1,4 +1,5 @@ local Kit = require("src.ui.game3.rse.scene_kit") +local CacheBlob = require("src.import.CacheBlob") local Gfx = {} @@ -11,7 +12,7 @@ local function readCache(path) local okC, CacheFs = pcall(require, "src.import.CacheFs") local data = okC and CacheFs and CacheFs.read and CacheFs.read(path) or nil if not data and love and love.filesystem and love.filesystem.getInfo(path) then - data = love.filesystem.read(path) + data = CacheBlob.readFs(path) end return data end diff --git a/src/ui/game3/rse/scene_kit.lua b/src/ui/game3/rse/scene_kit.lua index c1bf7c6f..3aaafa22 100644 --- a/src/ui/game3/rse/scene_kit.lua +++ b/src/ui/game3/rse/scene_kit.lua @@ -4,6 +4,7 @@ local RomText = require("src.core.game3.rom_text") local FrlgFont = require("src.ui.game3.frlg_font") local Chrome = require("src.ui.game3.chrome") local Pal = require("src.core.game3.pal_fade") +local CacheBlob = require("src.import.CacheBlob") local Kit = {} @@ -60,7 +61,7 @@ function Kit.rgbaImage(path, w, h) local okC, CacheFs = pcall(require, "src.import.CacheFs") if okC and CacheFs and CacheFs.read then data = CacheFs.read(path) end if (not data) and love and love.filesystem and love.filesystem.getInfo(path) then - data = love.filesystem.read(path) + data = CacheBlob.readFs(path) end if type(data) == "string" and #data == w * h * 4 and love and love.image then local ok, id = pcall(love.image.newImageData, w, h, "rgba8", data) diff --git a/src/ui/game3/seagallop.lua b/src/ui/game3/seagallop.lua index be788489..9f6bab13 100644 --- a/src/ui/game3/seagallop.lua +++ b/src/ui/game3/seagallop.lua @@ -7,6 +7,7 @@ local Seagallop = {} local W, H = 240, 160 local SE = require("src.core.game3.se_ids") -- pokefirered/include/constants/songs.h:23 +local CacheBlob = require("src.import.CacheBlob") local CROSSING_FRAMES = 140 local MUSIC_FADE_FRAMES = 64 @@ -54,10 +55,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local home = os.getenv("HOME") or "" @@ -71,7 +72,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/shop_chrome.lua b/src/ui/game3/shop_chrome.lua index b94445b9..b77339bb 100644 --- a/src/ui/game3/shop_chrome.lua +++ b/src/ui/game3/shop_chrome.lua @@ -2,6 +2,7 @@ local Extract = require("src.import.gba.extract_island1") local ShopChromeExtract = require("src.import.gba.shop_chrome_extract") +local CacheBlob = require("src.import.CacheBlob") local ShopChrome = {} @@ -59,10 +60,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -72,7 +73,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/slot_machine.lua b/src/ui/game3/slot_machine.lua index 2362a76d..3455afac 100644 --- a/src/ui/game3/slot_machine.lua +++ b/src/ui/game3/slot_machine.lua @@ -6,6 +6,7 @@ local FrlgFont = require("src.ui.game3.frlg_font") local Strings = require("src.core.Strings") local RomText = require("src.core.game3.rom_text") local Model = require("src.core.game3.slot_machine") +local CacheBlob = require("src.import.CacheBlob") local SlotMachineUi = {} @@ -119,12 +120,12 @@ local function read_bytes(rel) if okR and type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local okR, d = pcall(love.filesystem.read, rel) + local okR, d = pcall(CacheBlob.readFs, rel) if okR and type(d) == "string" and #d > 0 then return d end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/summary_chrome.lua b/src/ui/game3/summary_chrome.lua index b90642ec..0fd5844f 100644 --- a/src/ui/game3/summary_chrome.lua +++ b/src/ui/game3/summary_chrome.lua @@ -4,6 +4,7 @@ local Display = require("src.core.game3.display") local Extract = require("src.import.gba.extract_island1") local SummaryChromeExtract = require("src.import.gba.summary_chrome_extract") +local CacheBlob = require("src.import.CacheBlob") local SummaryChrome = {} @@ -56,10 +57,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -69,7 +70,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/teachy_tv.lua b/src/ui/game3/teachy_tv.lua index 2d910015..9ec0f61c 100644 --- a/src/ui/game3/teachy_tv.lua +++ b/src/ui/game3/teachy_tv.lua @@ -6,6 +6,7 @@ local Chrome = require("src.ui.game3.chrome") local FrlgFont = require("src.ui.game3.frlg_font") local TeachyTv = require("src.core.game3.teachy_tv") local SeIds = require("src.core.game3.se_ids") +local CacheBlob = require("src.import.CacheBlob") local Ui = {} @@ -129,12 +130,12 @@ local function read_bytes(rel) if ok and type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local ok, d = pcall(love.filesystem.read, rel) + local ok, d = pcall(CacheBlob.readFs, rel) if ok and type(d) == "string" and #d > 0 then return d end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/tm_case_chrome.lua b/src/ui/game3/tm_case_chrome.lua index 7d316088..08454543 100644 --- a/src/ui/game3/tm_case_chrome.lua +++ b/src/ui/game3/tm_case_chrome.lua @@ -2,6 +2,7 @@ local Extract = require("src.import.gba.extract_island1") local TmCaseExtract = require("src.import.gba.tm_case_extract") +local CacheBlob = require("src.import.CacheBlob") local TmCaseChrome = {} @@ -41,10 +42,10 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end local candidates = { @@ -54,7 +55,7 @@ local function read_bytes(rel) for _, p in ipairs(candidates) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/trade_scene.lua b/src/ui/game3/trade_scene.lua index 40aa2aaa..8334da3c 100644 --- a/src/ui/game3/trade_scene.lua +++ b/src/ui/game3/trade_scene.lua @@ -6,6 +6,7 @@ local Pokemon = require("src.core.game3.pokemon") local Extract = require("src.import.gba.extract_island1") local Profile = require("src.core.game3.profile") local RsTrade = require("src.ui.game3.rs.trade_policy") +local CacheBlob = require("src.import.CacheBlob") local TradeSceneUi = {} @@ -45,16 +46,16 @@ local function read_bytes(rel) if type(d) == "string" and #d > 0 then return d end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(rel) + local d = CacheBlob.readFs(rel) if type(d) == "string" and #d > 0 then return d end local alt = "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if type(d) == "string" and #d > 0 then return d end end for _, p in ipairs({ rel, "data/generated/gba/" .. (rel:gsub("^data/generated/gba/", "")) }) do local f = io.open(p, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/trainer_card.lua b/src/ui/game3/trainer_card.lua index 48a34ab6..529b8280 100644 --- a/src/ui/game3/trainer_card.lua +++ b/src/ui/game3/trainer_card.lua @@ -3,6 +3,7 @@ local Stack = require("src.ui.game3.stack") local FrlgFont = require("src.ui.game3.frlg_font") local RomText = require("src.core.game3.rom_text") +local CacheBlob = require("src.import.CacheBlob") local TrainerCard = { isMenu = true } @@ -47,15 +48,15 @@ local function read_cache_file(path) end end if love and love.filesystem and love.filesystem.read then - local d = love.filesystem.read(path) + local d = CacheBlob.readFs(path) if d and #d > 0 then return d end local alt = "data/generated/gba/" .. (path:gsub("^data/generated/gba/", "")) - d = love.filesystem.read(alt) + d = CacheBlob.readFs(alt) if d and #d > 0 then return d end end local f = io.open(path, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(path, f:read("*a")) f:close() if d and #d > 0 then return d end end diff --git a/src/ui/game3/trainer_tower_records.lua b/src/ui/game3/trainer_tower_records.lua index 3a4f84a5..03a58b8f 100644 --- a/src/ui/game3/trainer_tower_records.lua +++ b/src/ui/game3/trainer_tower_records.lua @@ -22,6 +22,7 @@ Records.BOARD_WINDOW_ID = 1 Records.LINK_ROWS = 5 -- pokefirered/include/constants/songs.h:9 local SE = require("src.core.game3.se_ids") +local CacheBlob = require("src.import.CacheBlob") Records.CACHE_BG = "data/generated/gba/trainer_tower/records_bg.rgba" Records.CACHE_MANIFEST = "data/generated/gba/trainer_tower/manifest.lua" @@ -78,12 +79,12 @@ local function read_bytes(rel) if okR and type(d) == "string" and #d > 0 then return d end end if type(love) == "table" and love.filesystem and love.filesystem.read then - local okR, d = pcall(love.filesystem.read, rel) + local okR, d = pcall(CacheBlob.readFs, rel) if okR and type(d) == "string" and #d > 0 then return d end end local f = io.open(rel, "rb") if f then - local d = f:read("*a") + local d = CacheBlob.decode(rel, f:read("*a")) f:close() if type(d) == "string" and #d > 0 then return d end end diff --git a/tests/emerald_contest_ui_test.lua b/tests/emerald_contest_ui_test.lua index ad9fdc32..806da0d4 100644 --- a/tests/emerald_contest_ui_test.lua +++ b/tests/emerald_contest_ui_test.lua @@ -1,4 +1,5 @@ package.path = "./?.lua;./?/init.lua;" .. package.path +local CacheBlob = require("src.import.CacheBlob") local T = require("tests.harness") local check, eq = T.check, T.eq @@ -62,7 +63,7 @@ local function readFile(path) if not IDROOT then return nil end local h = io.open(IDROOT .. path, "rb") if not h then return nil end - local s = h:read("*a") + local s = CacheBlob.decode(IDROOT .. path, h:read("*a")) h:close() return s end diff --git a/tests/emerald_text_chrome_test.lua b/tests/emerald_text_chrome_test.lua index b744f8e7..a09f6108 100644 --- a/tests/emerald_text_chrome_test.lua +++ b/tests/emerald_text_chrome_test.lua @@ -1,4 +1,5 @@ package.path = "./?.lua;./?/init.lua;" .. package.path +local CacheBlob = require("src.import.CacheBlob") local T = require("tests.harness") local check, eq = T.check, T.eq @@ -29,7 +30,7 @@ end local function read(rel) local f = io.open(ROOT .. "/" .. rel, "rb") if not f then return nil end - local s = f:read("*a") + local s = CacheBlob.decode(ROOT .. "/" .. rel, f:read("*a")) f:close() return s end diff --git a/tests/engine/cache_contract_emerald_test.lua b/tests/engine/cache_contract_emerald_test.lua index 83f6850f..25bc9cb2 100644 --- a/tests/engine/cache_contract_emerald_test.lua +++ b/tests/engine/cache_contract_emerald_test.lua @@ -16,8 +16,8 @@ local function digest(list) return h end -eq(CacheContract.markerFor("emerald", SHA), "rom-cache-v4-emerald:" .. SHA, "emerald marker") -check(CacheContract.markerMatches("emerald", "rom-cache-v4-emerald:" .. SHA), "emerald marker matches") +eq(CacheContract.markerFor("emerald", SHA), "rom-cache-v5-emerald:" .. SHA, "emerald marker") +check(CacheContract.markerMatches("emerald", "rom-cache-v5-emerald:" .. SHA), "emerald marker matches") check(not CacheContract.markerMatches("emerald", "rom-cache-v17-firered:" .. SHA), "a FireRed marker does not") eq(#CacheContract.requiredFiles("firered"), 456, "FireRed required list size") @@ -83,7 +83,7 @@ check(not CacheContract.cacheVersionCurrent("emerald", stale), "an emerald meta local complete = {} for _, p in ipairs(em) do complete["emerald/" .. p] = "x" end -complete["emerald/" .. CacheContract.MARKER_PATH] = "rom-cache-v4-emerald:" .. SHA +complete["emerald/" .. CacheContract.MARKER_PATH] = "rom-cache-v5-emerald:" .. SHA complete["emerald/data/generated/gba/meta.json"] = emMeta check(CacheContract.isReady("emerald", memfs(complete)), "a complete emerald cache is ready") diff --git a/tests/engine/game3_emerald_boot_assets_test.lua b/tests/engine/game3_emerald_boot_assets_test.lua index 1f3cb844..916dc3e3 100644 --- a/tests/engine/game3_emerald_boot_assets_test.lua +++ b/tests/engine/game3_emerald_boot_assets_test.lua @@ -59,9 +59,11 @@ check(png:find("tRNS", 1, true) ~= nil, "transparent png has tRNS") check(K.encodeIndexed(1, 1, { 0 }, { [0] = 0 }, false):find("tRNS", 1, true) == nil, "opaque png has no tRNS") eq(select(1, K.pngSize(K.encodeGray(4, 5, K.blank(4, 5)))), 4, "gray png width") -local stored = K.zlibStored(string.rep("a", 70000)) -eq(stored:byte(1), 0x78, "zlib header") -eq(#stored, 2 + 70000 + 5 * 2 + 4, "two stored blocks plus adler") +local CacheBlob = require("src.import.CacheBlob") +local deflated = CacheBlob.deflate(string.rep("a", 70000), 9) +eq(deflated:byte(1), 0x78, "zlib header") +check(#deflated < 1000, "png idat is deflated") +eq(CacheBlob.inflate(deflated), string.rep("a", 70000), "deflate round trip") local mods = { "extract_intro_emerald", "intro_credits_gfx_extract", "extract_title_rse", diff --git a/tests/engine/game3_post_dex_background_2637.lua b/tests/engine/game3_post_dex_background_2637.lua index cad15ea5..8c40c60d 100644 --- a/tests/engine/game3_post_dex_background_2637.lua +++ b/tests/engine/game3_post_dex_background_2637.lua @@ -167,7 +167,7 @@ local GameVersion = require("src.core.GameVersion") for _, profile in ipairs(profiles) do local version = GameVersion.forSha1(profile[2]) Versions.select(profile[2]) - T.eq(Versions.CACHE_VERSION, 129, profile[1] .. " active edition retains shared129 cache stamp") + T.eq(Versions.CACHE_VERSION, 130, profile[1] .. " active edition retains shared130 cache stamp") local files, set = {}, {} for _, path in ipairs(Contract.requiredFiles(version)) do files[version .. "/" .. path] = "fixture" @@ -178,10 +178,10 @@ for _, profile in ipairs(profiles) do local profileFs = { prefix = "" } profileFs.exists = function(path) return files[profileFs.prefix .. path] ~= nil end profileFs.read = function(path) return files[profileFs.prefix .. path] end - files[meta] = '{"cache_version":128}' - T.eq(Contract.isReady(version, profileFs), false, profile[1] .. " old128 stamp requires reimport") files[meta] = '{"cache_version":129}' - T.eq(Contract.isReady(version, profileFs), true, profile[1] .. " complete129 cache is ready") + T.eq(Contract.isReady(version, profileFs), false, profile[1] .. " old129 stamp requires reimport") + files[meta] = '{"cache_version":130}' + T.eq(Contract.isReady(version, profileFs), true, profile[1] .. " complete130 cache is ready") local count = 0 for key, info in pairs(frlgManifests[profile[1]].terrains) do count = count + 1 @@ -202,6 +202,6 @@ for _, profile in ipairs(profiles) do end end Versions.select("firered") -T.eq(V.CACHE_VERSION, 14, "Emerald cache version advanced once to14") -T.eq(require("src.import.gba.versions_frlg").CACHE_VERSION, 129, "FRLG cache version advanced once to129") +T.eq(V.CACHE_VERSION, 15, "Emerald cache version advanced once to15") +T.eq(require("src.import.gba.versions_frlg").CACHE_VERSION, 130, "FRLG cache version advanced once to130") T.finish("game3_post_dex_background_2637") diff --git a/tests/game3_ball_sheets_test.lua b/tests/game3_ball_sheets_test.lua index 0d5bc87c..78aa2e65 100644 --- a/tests/game3_ball_sheets_test.lua +++ b/tests/game3_ball_sheets_test.lua @@ -1,6 +1,7 @@ #!/usr/bin/env luajit package.path = "./?.lua;./?/init.lua;" .. package.path local GameCache = require("tests.game3_cache") +local CacheBlob = require("src.import.CacheBlob") local root = GameCache.mountOrSkip("game3_ball_sheets_test") require("tests.fixture_data.game3_items").install() @@ -17,7 +18,7 @@ end local function slurp(path) local f = io.open(path, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(path, f:read("*a")) f:close() return d end diff --git a/tests/game3_cache.lua b/tests/game3_cache.lua index a4e62f7b..c4f19031 100644 --- a/tests/game3_cache.lua +++ b/tests/game3_cache.lua @@ -1,3 +1,4 @@ +local CacheBlob = require("src.import.CacheBlob") local M = {} local function readable(path) @@ -40,7 +41,7 @@ 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 "" + local src = CacheBlob.decode(root .. "/meta.json", 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 @@ -104,7 +105,7 @@ function M.cache() read = function(_, rel) local f = io.open(rel, "rb") if not f then return nil end - local data = f:read("*a") + local data = CacheBlob.decode(rel, f:read("*a")) f:close() if type(data) == "string" and #data > 0 then return data end return nil diff --git a/tests/game3_fame_screen_test.lua b/tests/game3_fame_screen_test.lua index d661f1b4..f4d464ac 100644 --- a/tests/game3_fame_screen_test.lua +++ b/tests/game3_fame_screen_test.lua @@ -28,6 +28,7 @@ print("[info] FireRed cache at " .. cacheRoot) local FameChecker = require("src.core.game3.fame_checker") local Ui = require("src.ui.game3.fame_checker") local Stack = require("src.ui.game3.stack") +local CacheBlob = require("src.import.CacheBlob") local PERSON = FameChecker.PERSON local PICK = FameChecker.PICKSTATE @@ -131,7 +132,7 @@ do local f = io.open(path, "rb") check(f ~= nil, "the trainer pic is in the cache today") if f then - local bytes = f:read("*a") + local bytes = CacheBlob.decode(path, f:read("*a")) f:close() eq(#bytes, 64 * 64 * 4, "it is a 64x64 RGBA sprite") end diff --git a/tests/game3_import2_corner_assets_test.lua b/tests/game3_import2_corner_assets_test.lua index eb4eedd6..66f4eb70 100644 --- a/tests/game3_import2_corner_assets_test.lua +++ b/tests/game3_import2_corner_assets_test.lua @@ -31,6 +31,7 @@ local Versions = require("src.import.gba.versions") local Slot = require("src.import.gba.slot_machine_extract") local Trade = require("src.import.gba.trade_extract") local LinkArt = require("src.import.gba.link_art_extract") +local CacheBlob = require("src.import.CacheBlob") local SHEETS = { { "slot_machine/reel_icons.rgba", 32, 224 }, @@ -139,7 +140,7 @@ print("[info] FireRed cache at " .. root) local function readFile(rel) local f = io.open(root .. "/" .. rel, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(root .. "/" .. rel, f:read("*a")) f:close() return d end diff --git a/tests/game3_import2_misc_assets_test.lua b/tests/game3_import2_misc_assets_test.lua index b26719a5..0e2e657a 100644 --- a/tests/game3_import2_misc_assets_test.lua +++ b/tests/game3_import2_misc_assets_test.lua @@ -35,6 +35,7 @@ local TrainerTowerExtract = require("src.import.gba.trainer_tower_extract") local TrainerCardExtract = require("src.import.gba.trainer_card_extract") local RegionMapExtract = require("src.import.gba.region_map_extract") local EggExtract = require("src.import.gba.egg_extract") +local CacheBlob = require("src.import.CacheBlob") print("[test] 1. the ROM offsets follow pret's declaration order") -- src/script_menu.c:647 aerodactyl tiles, palette, then kabutops tiles, palette @@ -188,7 +189,7 @@ print("[info] FireRed cache at " .. root) local function readFile(rel) local f = io.open(root .. "/" .. rel, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(root .. "/" .. rel, f:read("*a")) f:close() return d end diff --git a/tests/game3_import2_system_assets_test.lua b/tests/game3_import2_system_assets_test.lua index f5d86680..0d362ad0 100644 --- a/tests/game3_import2_system_assets_test.lua +++ b/tests/game3_import2_system_assets_test.lua @@ -35,6 +35,7 @@ local MysteryGiftExtract = require("src.import.gba.mystery_gift_extract") local TrainerTowerExtract = require("src.import.gba.trainer_tower_extract") local TutorExtract = require("src.import.gba.tutor_extract") local AltLayouts = require("src.import.gba.alt_layouts") +local CacheBlob = require("src.import.CacheBlob") local SHEETS = { { "fame_checker/bg.rgba", 240, 160 }, @@ -160,7 +161,7 @@ print("[info] FireRed cache at " .. root) local function readFile(rel) local f = io.open(root .. "/" .. rel, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(root .. "/" .. rel, f:read("*a")) f:close() return d end diff --git a/tests/game3_import_assets_test.lua b/tests/game3_import_assets_test.lua index 9344e484..576cdde7 100644 --- a/tests/game3_import_assets_test.lua +++ b/tests/game3_import_assets_test.lua @@ -27,6 +27,7 @@ local Seagallop = require("src.import.gba.seagallop_extract") local BattleChrome = require("src.import.gba.battle_chrome_extract") local CacheContract = require("src.import.CacheContract") local Versions = require("src.import.gba.versions") +local CacheBlob = require("src.import.CacheBlob") local function fakeRom(str) return { @@ -256,7 +257,7 @@ print("[info] FireRed cache at " .. root) local function readFile(rel) local f = io.open(root .. "/" .. rel, "rb") if not f then return nil end - local data = f:read("*a") + local data = CacheBlob.decode(root .. "/" .. rel, f:read("*a")) f:close() return data end diff --git a/tests/game3_import_battle_terrain_test.lua b/tests/game3_import_battle_terrain_test.lua index b0e085ab..2e775b1d 100644 --- a/tests/game3_import_battle_terrain_test.lua +++ b/tests/game3_import_battle_terrain_test.lua @@ -14,6 +14,7 @@ end local BattleChromeExtract = require("src.import.gba.battle_chrome_extract") local Versions = require("src.import.gba.versions") +local CacheBlob = require("src.import.CacheBlob") -- include/constants/battle.h:287 local PRET_KEYS = { @@ -108,7 +109,7 @@ print("[info] FireRed cache at " .. root) local function readFile(rel) local f = io.open(root .. "/pokemon/battle/" .. rel, "rb") if not f then return nil end - local data = f:read("*a") + local data = CacheBlob.decode(root .. "/pokemon/battle/" .. rel, f:read("*a")) f:close() return data end diff --git a/tests/game3_import_party_tilemaps_test.lua b/tests/game3_import_party_tilemaps_test.lua index 411068a8..25cb99ff 100644 --- a/tests/game3_import_party_tilemaps_test.lua +++ b/tests/game3_import_party_tilemaps_test.lua @@ -2,6 +2,7 @@ -- src/data/party_menu.h:111 package.path = "./?.lua;./?/init.lua;" .. package.path +local CacheBlob = require("src.import.CacheBlob") local failed = 0 local function check(cond, msg) @@ -25,7 +26,7 @@ end local function slurp(path) local f = io.open(path, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(path, f:read("*a")) f:close() return d end diff --git a/tests/game3_import_pokedex_assets_test.lua b/tests/game3_import_pokedex_assets_test.lua index e4a6f110..ec4abbba 100644 --- a/tests/game3_import_pokedex_assets_test.lua +++ b/tests/game3_import_pokedex_assets_test.lua @@ -24,6 +24,7 @@ end local Extract = require("src.import.gba.pokedex_chrome_extract") local Versions = require("src.import.gba.versions") local CacheContract = require("src.import.CacheContract") +local CacheBlob = require("src.import.CacheBlob") local PAPER_BYTES = 240 * 160 * 4 local FOOT_BYTES = 16 * 16 * 4 @@ -179,7 +180,7 @@ print("[info] FireRed cache at " .. root) local function readFile(rel) local f = io.open(root .. "/pokemon/pokedex/" .. rel, "rb") if not f then return nil end - local data = f:read("*a") + local data = CacheBlob.decode(root .. "/pokemon/pokedex/" .. rel, f:read("*a")) f:close() return data end diff --git a/tests/game3_map_onload_test.lua b/tests/game3_map_onload_test.lua index e5439e3a..9c7a56cb 100644 --- a/tests/game3_map_onload_test.lua +++ b/tests/game3_map_onload_test.lua @@ -33,6 +33,7 @@ print("[info] FireRed cache at " .. cacheRoot) local ExtractScripts = require("src.import.gba.extract_scripts") local Objects = require("src.core.game3.objects") local Field = require("src.core.game3.field") +local CacheBlob = require("src.import.CacheBlob") Space.bundle = ExtractScripts.loadBundle(Cache.cache(), cacheRoot, { allowIncomplete = true }) check(Space.bundle ~= nil, "script bundle loads") @@ -163,7 +164,7 @@ if gym then local f = io.open(cacheRoot .. "/native/" .. pairName .. "/mids.idx", "rb") local packed = {} if f then - local idx = NativePack.decodeIdx(f:read("*a")) + local idx = NativePack.decodeIdx(CacheBlob.decode(cacheRoot .. "/native/" .. pairName .. "/mids.idx", f:read("*a"))) f:close() for _, mid in ipairs(idx and idx.midIds or {}) do packed[mid] = true end end @@ -192,7 +193,7 @@ if gym then local f = io.open(cacheRoot .. "/native/" .. pairName .. "/mids.idx", "rb") local packed = {} if f then - local idx = NativePack.decodeIdx(f:read("*a")) + local idx = NativePack.decodeIdx(CacheBlob.decode(cacheRoot .. "/native/" .. pairName .. "/mids.idx", f:read("*a"))) f:close() for _, mid in ipairs(idx and idx.midIds or {}) do packed[mid] = true end end diff --git a/tests/game3_party_hold_icons_test.lua b/tests/game3_party_hold_icons_test.lua index 69a8e4f4..d6c673ef 100644 --- a/tests/game3_party_hold_icons_test.lua +++ b/tests/game3_party_hold_icons_test.lua @@ -2,6 +2,7 @@ -- src/data/party_menu.h:664, src/party_menu.c:2743, :2785 package.path = "./?.lua;./?/init.lua;" .. package.path +local CacheBlob = require("src.import.CacheBlob") local failed = 0 local function check(cond, msg) @@ -29,7 +30,7 @@ end local function slurp(path) local f = io.open(path, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(path, f:read("*a")) f:close() return d end diff --git a/tests/game3_pokedex_area_chrome_test.lua b/tests/game3_pokedex_area_chrome_test.lua index f9f8c1b1..fa26d9ff 100644 --- a/tests/game3_pokedex_area_chrome_test.lua +++ b/tests/game3_pokedex_area_chrome_test.lua @@ -30,6 +30,7 @@ local Versions = require("src.import.gba.versions") local Extract = require("src.import.gba.pokedex_chrome_extract") local PokedexChrome = require("src.ui.game3.pokedex_chrome") local Pokedex = require("src.ui.game3.pokedex") +local CacheBlob = require("src.import.CacheBlob") print("[test] 1. versions.lua carries the area-page / size-page ROM offsets") check(Versions.CACHE_VERSION >= 103, "CACHE_VERSION at or past the dex chrome import (" @@ -233,7 +234,7 @@ else local function slurp(rel) local f = io.open(dexRoot .. "/" .. rel, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(dexRoot .. "/" .. rel, f:read("*a")) f:close() return d end diff --git a/tests/game3_region_map_assets_test.lua b/tests/game3_region_map_assets_test.lua index d729cea6..c180719d 100644 --- a/tests/game3_region_map_assets_test.lua +++ b/tests/game3_region_map_assets_test.lua @@ -50,6 +50,7 @@ check(MultichoiceExtract.ready({ print("[test] 2. baked assets in an imported cache") local Cache = require("tests.game3_cache") +local CacheBlob = require("src.import.CacheBlob") local root = Cache.root("region_map/extract_status.json") if not root then print("[skip] region map assets: " .. tostring(Cache.reason)) @@ -65,7 +66,7 @@ print("[info] FireRed cache at " .. root) local function readFile(rel) local f = io.open(root .. "/" .. rel, "rb") if not f then return nil end - local data = f:read("*a") + local data = CacheBlob.decode(root .. "/" .. rel, f:read("*a")) f:close() return data end diff --git a/tests/game3_render_caches_test.lua b/tests/game3_render_caches_test.lua index 394143f7..befa3dc5 100644 --- a/tests/game3_render_caches_test.lua +++ b/tests/game3_render_caches_test.lua @@ -11,6 +11,7 @@ -- * bag: listPocket rows are reused until the pocket changes. package.path = package.path .. ";./?.lua" +local CacheBlob = require("src.import.CacheBlob") local passed, failed = 0, 0 local function test(name, fn) @@ -89,7 +90,7 @@ love = { filesystem = { read = function(path) counts.fsRead = counts.fsRead + 1 - if path:find("trainers/front/", 1, true) then return string.rep("\0", 64 * 64 * 4) end + if path:find("trainers/front/", 1, true) then return CacheBlob.deflate(string.rep("\0", 64 * 64 * 4)) end return nil end, }, diff --git a/tests/game3_stitchimp_alt_layouts_test.lua b/tests/game3_stitchimp_alt_layouts_test.lua index 5c038b88..9c810ef1 100644 --- a/tests/game3_stitchimp_alt_layouts_test.lua +++ b/tests/game3_stitchimp_alt_layouts_test.lua @@ -28,6 +28,7 @@ end local Versions = require("src.import.gba.versions") local MapCatalog = require("src.import.gba.map_catalog") local NativePack = require("src.import.gba.native_pack") +local CacheBlob = require("src.import.CacheBlob") MapCatalog.rebuildIndex() -- pokefirered/include/constants/layouts.h:253,267,268,308 @@ -169,7 +170,7 @@ else local function readFile(rel) local f = io.open(root .. "/" .. rel, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(root .. "/" .. rel, f:read("*a")) f:close() return d end diff --git a/tests/game3_stitchimp_chrome_keys_test.lua b/tests/game3_stitchimp_chrome_keys_test.lua index 15c260c5..6a3841e2 100644 --- a/tests/game3_stitchimp_chrome_keys_test.lua +++ b/tests/game3_stitchimp_chrome_keys_test.lua @@ -3,6 +3,7 @@ -- pokefirered/src/region_map.c:425 package.path = "./?.lua;./?/init.lua;" .. package.path +local CacheBlob = require("src.import.CacheBlob") local failed = 0 local function check(cond, msg) @@ -21,7 +22,7 @@ end local function slurp(path) local f = io.open(path, "rb") if not f then return nil end - local s = f:read("*a") + local s = CacheBlob.decode(path, f:read("*a")) f:close() return s end diff --git a/tests/game3_stitchuid_footprint_test.lua b/tests/game3_stitchuid_footprint_test.lua index 91994fa2..13e7c09d 100644 --- a/tests/game3_stitchuid_footprint_test.lua +++ b/tests/game3_stitchuid_footprint_test.lua @@ -39,11 +39,12 @@ Pokemon.install(nil) local DIR = root .. "/pokemon/pokedex/footprints" local NUM_SPECIES = require("src.import.gba.versions").NUM_SPECIES or 412 +local CacheBlob = require("src.import.CacheBlob") local function file_bytes(rel) local f = io.open(DIR .. "/" .. rel, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(DIR .. "/" .. rel, f:read("*a")) f:close() if type(d) == "string" and #d > 0 then return d end return nil diff --git a/tests/game3_summary_chrome_bake_s3_test.lua b/tests/game3_summary_chrome_bake_s3_test.lua index 021de281..d46bbd37 100644 --- a/tests/game3_summary_chrome_bake_s3_test.lua +++ b/tests/game3_summary_chrome_bake_s3_test.lua @@ -4,6 +4,7 @@ package.path = "./?.lua;./?/init.lua;" .. package.path local T = require("tests.harness") +local CacheBlob = require("src.import.CacheBlob") local check, eq = T.check, T.eq local PRET = "../pokefirered" @@ -13,7 +14,7 @@ local ROM_SHA1 = "41cb23d8dccc8ebd7c649cd8fbb58eeace6e2fdc" local function slurp(p) local f = io.open(p, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(p, f:read("*a")) f:close() return d end diff --git a/tests/game3_trade_extract_test.lua b/tests/game3_trade_extract_test.lua index 52bce06c..fac3654b 100644 --- a/tests/game3_trade_extract_test.lua +++ b/tests/game3_trade_extract_test.lua @@ -28,6 +28,7 @@ end local Versions = require("src.import.gba.versions") local Trade = require("src.import.gba.trade_extract") +local CacheBlob = require("src.import.CacheBlob") local MENU_SHEETS = { { "menu_bg1", 240, 160 }, @@ -136,7 +137,7 @@ print("[test] 3. the offsets hit pret's graphics/trade bins in a matching build" local function slurp(path) local f = io.open(path, "rb") if not f then return nil end - local d = f:read("*a") + local d = CacheBlob.decode(path, f:read("*a")) f:close() return d end diff --git a/tools/driver_preflight.lua b/tools/driver_preflight.lua index cc1e8d74..cd07e70b 100644 --- a/tools/driver_preflight.lua +++ b/tools/driver_preflight.lua @@ -92,7 +92,9 @@ end local fs = { prefix = "" } function fs.exists(rel) return isFile(saveDir .. "/" .. fs.prefix .. rel) end -function fs.read(rel) return readFile(saveDir .. "/" .. fs.prefix .. rel) end +function fs.read(rel) + return require("src.import.CacheBlob").decode(rel, readFile(saveDir .. "/" .. fs.prefix .. rel)) +end if not identityOnly and sourceTreeHasData() then print("READY source tree") diff --git a/tools/generate_example_mod_sprite.py b/tools/generate_example_mod_sprite.py index 5ef11922..45170194 100644 --- a/tools/generate_example_mod_sprite.py +++ b/tools/generate_example_mod_sprite.py @@ -3,6 +3,7 @@ from pathlib import Path import sys +import zlib from PIL import Image, ImageOps @@ -29,7 +30,7 @@ def invert(source: Path, destination: Path) -> None: def invert_rgba(source: Path, destination: Path) -> None: - raw = source.read_bytes() + raw = zlib.decompress(source.read_bytes()) size = GBA_PIC * GBA_PIC * 4 if len(raw) < size: raise SystemExit(f"{source}: expected {size} bytes of 64x64 RGBA, got {len(raw)}")