mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
166 lines
5.8 KiB
Lua
166 lines
5.8 KiB
Lua
-- POKEPORT_IDENTITY=red-sep04 POKEPORT_TOUCH=0 POKEPORT_SHOT_DIR=/tmp/2235 POKEPORT_DRIVER=tests/drivers/shaderfx_grid_2235.lua love .
|
|
local U = require("tests.drivers.util")
|
|
local ShaderFX = require("src.render.ShaderFX")
|
|
local Zoom = require("src.render.Zoom")
|
|
local GameVersion = require("src.core.GameVersion")
|
|
|
|
local SHOT_DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/2235"
|
|
|
|
local WANT = {
|
|
{ file = "retro-v3.slangp", tag = "retro" },
|
|
{ file = "sameboy-lcd.slangp", tag = "sameboy" },
|
|
}
|
|
|
|
local ZOOMS = {
|
|
{ offset = 0, tag = "fit" },
|
|
{ offset = -1, tag = "out1" },
|
|
{ offset = -2, tag = "out2" },
|
|
}
|
|
|
|
return function(game)
|
|
local fails = 0
|
|
local function ok(cond, label)
|
|
if not cond then fails = fails + 1 end
|
|
print((cond and "PASS " or "FAIL ") .. label)
|
|
end
|
|
|
|
love.window.setMode(1024, 768, { resizable = true })
|
|
U.wait(30)
|
|
|
|
local gen2 = GameVersion.generation() == 2
|
|
if gen2 then
|
|
game.world:warpToMapId("NEW_BARK_TOWN", 6, 6, "down")
|
|
else
|
|
U.teleport(game, "PALLET_TOWN", 10, 8, "down")
|
|
end
|
|
U.wait(60)
|
|
|
|
local byName = {}
|
|
for _, e in ipairs(ShaderFX.list()) do byName[e.name] = e end
|
|
local ready = {}
|
|
for _, want in ipairs(WANT) do
|
|
local entry = byName[want.file]
|
|
if entry and not entry.converted then
|
|
local converted = ShaderFX.convert(entry)
|
|
if not converted then entry = nil end
|
|
end
|
|
if entry then
|
|
ready[#ready + 1] = { entry = entry, tag = want.tag }
|
|
else
|
|
print("SKIP " .. want.file .. " is not in this identity's shaders/")
|
|
end
|
|
end
|
|
ok(#ready > 0, "2235 a grid preset is installed")
|
|
if #ready == 0 then love.event.quit(1) return end
|
|
|
|
local captured = {}
|
|
local realRunChain = ShaderFX.runChain
|
|
ShaderFX.runChain = function(state, img, luts, viewport, original, layer)
|
|
captured[layer or "main"] = { vw = viewport.w, vh = viewport.h, ow = original.w, oh = original.h }
|
|
return realRunChain(state, img, luts, viewport, original, layer)
|
|
end
|
|
|
|
local function fitScale()
|
|
if gen2 then return game.world:fitScale() end
|
|
return game.renderer:fitScale()
|
|
end
|
|
|
|
local function scanlineBands(path, s)
|
|
local f = io.open(path, "rb")
|
|
if not f then return nil, "no shot" end
|
|
local bytes = f:read("*a")
|
|
f:close()
|
|
local okImg, id = pcall(love.image.newImageData, love.filesystem.newFileData(bytes, "shot.png"))
|
|
if not okImg then return nil, tostring(id) end
|
|
local w, h = id:getWidth(), id:getHeight()
|
|
local rows = {}
|
|
for y = 0, h - 1 do
|
|
local sum, n = 0, 0
|
|
for x = 0, w - 1, 2 do
|
|
local r, g, b = id:getPixel(x, y)
|
|
sum, n = sum + (r + g + b) / 3, n + 1
|
|
end
|
|
rows[y] = sum / n * 255
|
|
end
|
|
local best
|
|
for off = 0, s - 1 do
|
|
local groups, total = {}, 0
|
|
for y0 = off, h - s, s do
|
|
local lo, hi = rows[y0], rows[y0]
|
|
for y = y0 + 1, y0 + s - 1 do
|
|
if rows[y] < lo then lo = rows[y] end
|
|
if rows[y] > hi then hi = rows[y] end
|
|
end
|
|
local c = hi >= 40 and (hi - lo) / hi or nil
|
|
groups[#groups + 1] = c
|
|
total = total + (c or 0)
|
|
end
|
|
if not best or total < best.total then best = { off = off, groups = groups, total = total } end
|
|
end
|
|
local blocks = {}
|
|
for b = 1, #best.groups, 16 do
|
|
local sum, n = 0, 0
|
|
for g = b, math.min(b + 15, #best.groups) do
|
|
local c = best.groups[g]
|
|
if c then sum, n = sum + c, n + 1 end
|
|
end
|
|
if n >= 4 then blocks[#blocks + 1] = sum / n end
|
|
end
|
|
local lo, hi = math.huge, 0
|
|
for _, v in ipairs(blocks) do
|
|
if v < lo then lo = v end
|
|
if v > hi then hi = v end
|
|
end
|
|
return { off = best.off, blocks = blocks, lo = lo, hi = hi }
|
|
end
|
|
|
|
local gtag = tostring(GameVersion.get())
|
|
for _, r in ipairs(ready) do
|
|
ShaderFX.deactivate("secondary")
|
|
local on, err = ShaderFX.activate("main", r.entry)
|
|
ok(on, ("2235 %s activates %s"):format(r.tag, tostring(err or "")))
|
|
if on then
|
|
for _, z in ipairs(ZOOMS) do
|
|
Zoom.offset = Zoom.clampOffset(z.offset, fitScale())
|
|
captured = {}
|
|
U.wait(6)
|
|
local rect = ShaderFX._lastRect
|
|
local m = captured.main
|
|
ok(rect ~= nil and m ~= nil
|
|
and m.vw == m.ow * rect.scale and m.vh == m.oh * rect.scale,
|
|
("2235 %s %s world viewport is an exact multiple of its source"):format(r.tag, z.tag))
|
|
local shot = ("%s/2235_%s_%s_%s_map.png"):format(SHOT_DIR, gtag, r.tag, z.tag)
|
|
U.shot(game, shot)
|
|
if r.tag == "sameboy" and z.tag == "out2" and rect then
|
|
local bands, err = scanlineBands(shot, rect.scale)
|
|
local parts = {}
|
|
for i, v in ipairs(bands and bands.blocks or {}) do parts[i] = ("%.3f"):format(v) end
|
|
print(("info sameboy out2 scanline depth per 48px row band (phase %s): %s"):format(
|
|
tostring(bands and bands.off), #parts > 0 and table.concat(parts, " ") or tostring(err)))
|
|
ok(bands ~= nil and #bands.blocks >= 8 and bands.lo >= 0.015 and bands.lo >= 0.5 * bands.hi,
|
|
"2235 sameboy out2 every 48px row band carries scanlines of similar depth")
|
|
end
|
|
end
|
|
|
|
Zoom.offset = Zoom.clampOffset(-2, fitScale())
|
|
U.tap(game, "start")
|
|
U.wait(20)
|
|
captured = {}
|
|
U.wait(4)
|
|
local ui = captured.ui or captured.main
|
|
ok(ui ~= nil and ui.vw % ui.ow == 0 and ui.vh % ui.oh == 0
|
|
and ui.vw / ui.ow == ui.vh / ui.oh,
|
|
("2235 %s out2 menu layer viewport is an exact multiple of its source"):format(r.tag))
|
|
U.shot(game, ("%s/2235_%s_%s_out2_start_menu.png"):format(SHOT_DIR, gtag, r.tag))
|
|
U.tap(game, "b")
|
|
U.wait(20)
|
|
end
|
|
end
|
|
|
|
ShaderFX.runChain = realRunChain
|
|
ShaderFX.deactivate("main")
|
|
Zoom.offset = 0
|
|
print(fails == 0 and "PASS 2235 shaderfx grid alignment" or "FAIL 2235 shaderfx grid alignment")
|
|
love.event.quit(fails == 0 and 0 or 1)
|
|
end
|