Files
gen1recomp/tests/lz77_test.lua
T
1jamie 6be2de2844 feat(game3): finished Gen 3 save editor, scripting specials, field elevation, and parallel ROM extraction
- Save Editor: Implement full Gen 3 FireRed save editing including PID/personality, IVs/EVs, natures, ability slots, gender, shiny toggles, held items, Pokédex flags, and event/trainer toggles.
- Scripting & Specials: Add Pokédex rating evaluations, Magikarp/Heracross size records, Trainer Fan Club tracking, and FireRed event flag mappings.
- Overworld & Rendering: Interleave metatile and actor draw calls by row bucket with OAM elevation priority sorting for bridges and overhead layers.
- ROM Extractor: Parallelize Gen 3 extraction across 4 concurrent love.thread workers with love.filesystem searchers for cross-platform support (Switch/Xbox/Mobile/Desktop).
- LZ77 Decompressor: Accelerate GBA LZ77 with preallocated FFI buffers and 0-based displacement indexing ensuring 100% byte-for-byte asset parity.
- Testing: Add unit test suites for LZ77, size records, Pokédex rating, Fan Club, elevation priority, Seafoam puzzles, and Gen 3 save editor operations.
2026-09-21 17:07:50 -05:00

58 lines
2.0 KiB
Lua

-- Unit test for GBA LZ77 decompression
local Lz77 = require("src.import.gba.lz77")
local function test_lz77_basic()
local payload = "HELLO WORLD, THIS IS A TEST OF GBA LZ77 COMPRESSION AND DECOMPRESSION!"
local compressed = Lz77.compressStore(payload)
assert(compressed[1] == 0x10, "header type 0x10")
local decomp, consumed = Lz77.decompressFromBytes(compressed, 0)
assert(#decomp == #payload, ("decomp length %d != payload %d"):format(#decomp, #payload))
local decompStr = Lz77.toString(decomp)
assert(decompStr == payload, "decompressed string must match original payload")
print("✓ test_lz77_basic passed")
end
local function test_lz77_matches()
-- Create a payload with repeated patterns to test LZ77 sliding window references
local raw = "ABCDEFGHABCDEFGH" -- 16 bytes: 8 literals, then 1 match of length 8 at disp 8
local bytes = {
0x10, 16, 0, 0,
0x00, -- flags: 8 literals
string.byte("A"), string.byte("B"), string.byte("C"), string.byte("D"),
string.byte("E"), string.byte("F"), string.byte("G"), string.byte("H"),
0x80, -- flags: bit 7 is match
0x50, 0x07, -- length=8 (0x5+3), disp=7 (goes back 7+1=8 bytes)
}
local decomp, consumed = Lz77.decompressFromBytes(bytes, 0)
local decompStr = Lz77.toString(decomp)
assert(decompStr == raw, ("expected '%s', got '%s'"):format(raw, decompStr))
print("✓ test_lz77_matches passed")
end
local function test_lz77_bounds_safety()
-- Corrupted match with negative / out-of-bounds displacement
local bytes = {
0x10, 4, 0, 0,
0x80, -- match on first byte! read_pos = 0 - 100 < 0
0x10, 0x64, -- length=4, disp=100
}
-- Should NOT crash or segfault; safely writes 0s
local decomp, consumed = Lz77.decompressFromBytes(bytes, 0)
assert(#decomp == 4, "should decompress 4 bytes")
for i = 1, 4 do
assert(decomp[i] == 0, "OOB read should produce 0")
end
print("✓ test_lz77_bounds_safety passed")
end
local function run_all()
test_lz77_basic()
test_lz77_matches()
test_lz77_bounds_safety()
print("All LZ77 unit tests passed!")
end
run_all()