mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-01 23:42:25 -04:00
+11
-15
@@ -1086,23 +1086,19 @@ function BattleState:drawPic(mon, back)
|
||||
local bandY = (back and BattleState.PLAYER_PIC_TILE_Y
|
||||
or BattleState.ENEMY_PIC_TILE_Y) * 8 + lifted[1] * 8
|
||||
local bandH = lifted[2] * 8
|
||||
local psx, psy, psw, psh
|
||||
if G.getScissor then psx, psy, psw, psh = G.getScissor() end
|
||||
if self.liftedPass then
|
||||
G.setScissor(0, bandY, 160, bandH)
|
||||
local function band(y, h)
|
||||
G.push("all")
|
||||
Chrome.clipTo(0, y, 160, h)
|
||||
paint()
|
||||
else
|
||||
if bandY > 0 then
|
||||
G.setScissor(0, 0, 160, bandY)
|
||||
paint()
|
||||
end
|
||||
local below = 144 - bandY - bandH
|
||||
if below > 0 then
|
||||
G.setScissor(0, bandY + bandH, 160, below)
|
||||
paint()
|
||||
end
|
||||
G.pop()
|
||||
end
|
||||
if self.liftedPass then
|
||||
band(bandY, bandH)
|
||||
else
|
||||
if bandY > 0 then band(0, bandY) end
|
||||
local below = 144 - bandY - bandH
|
||||
if below > 0 then band(bandY + bandH, below) end
|
||||
end
|
||||
if psx then G.setScissor(psx, psy, psw, psh) else G.setScissor() end
|
||||
end
|
||||
|
||||
-- MonsterSpriteGFX (gfx/sprites.asm:82): the facing-DOWN 16x16 frame for the
|
||||
|
||||
@@ -118,6 +118,12 @@ end
|
||||
-- pokegold engine/battle/core.asm:8646, engine/events/halloffame.asm:270
|
||||
local function clipTo(x, y, w, h)
|
||||
local G = love.graphics
|
||||
if G.transformPoint then
|
||||
local x1, y1 = G.transformPoint(x, y)
|
||||
local x2, y2 = G.transformPoint(x + w, y + h)
|
||||
x, y = math.floor(math.min(x1, x2)), math.floor(math.min(y1, y2))
|
||||
w, h = math.ceil(math.abs(x2 - x1)), math.ceil(math.abs(y2 - y1))
|
||||
end
|
||||
if G.intersectScissor then G.intersectScissor(x, y, w, h)
|
||||
else G.setScissor(x, y, w, h) end
|
||||
end
|
||||
|
||||
@@ -427,11 +427,7 @@ function MagnetTrainRide:drawPanel()
|
||||
end
|
||||
|
||||
function MagnetTrainRide:draw()
|
||||
local G = love.graphics
|
||||
G.push("all")
|
||||
G.setScissor(0, 0, SCREEN_W, SCREEN_H)
|
||||
self:drawPanel()
|
||||
G.pop()
|
||||
Chrome.withClip(function() self:drawPanel() end)
|
||||
end
|
||||
|
||||
-- MagnetTrain_LoadGFX_PlayMusic opens on ClearBGPalettes / ClearSprites
|
||||
@@ -449,7 +445,7 @@ function MagnetTrainRide:drawWidescreen(winW, winH)
|
||||
local scale = Chrome.fitScale(winW, winH)
|
||||
local ox, oy = Chrome.fitOrigin(winW, winH, scale)
|
||||
G.push("all")
|
||||
G.setScissor(ox, oy, SCREEN_W * scale, SCREEN_H * scale)
|
||||
Chrome.clipTo(ox, oy, SCREEN_W * scale, SCREEN_H * scale)
|
||||
G.translate(ox, oy)
|
||||
G.scale(scale, scale)
|
||||
self:drawPanel()
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
-- Mom's SetDayOfWeek wheel drawn over the living room (#2232).
|
||||
-- ../pokecrystal/engine/rtc/timeset.asm:385
|
||||
-- ../pokecrystal/maps/PlayersHouse1F.asm:49
|
||||
--
|
||||
-- POKEPORT_VERSION=crystal POKEPORT_IDENTITY=<sandbox> POKEPORT_TOUCH=0 \
|
||||
-- POKEPORT_SHOT_DIR=<dir> POKEPORT_DRIVER=tests/drivers/crystal_day_wheel_bug2232.lua love .
|
||||
local U = require("tests.drivers.util")
|
||||
local Chrome = require("src.ui.gen2.Chrome")
|
||||
|
||||
local SHOT_DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/pokeport-shots"
|
||||
|
||||
return function(game)
|
||||
local fails = 0
|
||||
local function say(line) print("[2232] " .. line) end
|
||||
local function ok(cond, line)
|
||||
if not cond then fails = fails + 1 end
|
||||
say((cond and "PASS " or "FAIL ") .. line)
|
||||
end
|
||||
|
||||
local function tap(button, frames)
|
||||
game.input.pressQueue[#game.input.pressQueue + 1] = button
|
||||
game.input.state[button] = true
|
||||
U.wait(2)
|
||||
game.input.state[button] = false
|
||||
U.wait(frames or 4)
|
||||
end
|
||||
|
||||
local function dayWheel()
|
||||
local top = game.stack and game.stack:top()
|
||||
if top and top.mode == "day" and top.pickerBox then return top end
|
||||
return nil
|
||||
end
|
||||
|
||||
U.wait(45)
|
||||
local world = game.world
|
||||
if not (world and world.map) then
|
||||
say("FAIL the crystal world did not boot")
|
||||
return
|
||||
end
|
||||
|
||||
-- ../pokecrystal/maps/PlayersHouse1F.asm:395
|
||||
world:setMap("PLAYERS_HOUSE_1F", 7, 3, "down")
|
||||
U.wait(20)
|
||||
for _ = 1, 3 do tap("down", 8) end
|
||||
U.wait(40)
|
||||
ok(world.map and world.map.id == "PLAYERS_HOUSE_1F", "in the living room")
|
||||
|
||||
local wheel
|
||||
for _ = 1, 300 do
|
||||
wheel = dayWheel()
|
||||
if wheel then break end
|
||||
tap("a", 4)
|
||||
end
|
||||
ok(wheel ~= nil, "Mom's scene reached the day-of-week wheel")
|
||||
if not wheel then return end
|
||||
|
||||
local seen
|
||||
local drawPanel = wheel.drawPanel
|
||||
wheel.drawPanel = function(self)
|
||||
seen = { love.graphics.getScissor() }
|
||||
return drawPanel(self)
|
||||
end
|
||||
U.wait(3)
|
||||
wheel.drawPanel = drawPanel
|
||||
local w, h = love.graphics.getDimensions()
|
||||
local scale = Chrome.fitScale(w, h)
|
||||
local ox, oy = Chrome.fitOrigin(w, h, scale)
|
||||
ok(seen ~= nil, "the wheel drew its panel")
|
||||
if seen then
|
||||
ok(seen[1] == ox and seen[2] == oy
|
||||
and seen[3] == 160 * scale and seen[4] == 144 * scale,
|
||||
("the wheel clips to the panel %d,%d %dx%d, got %s,%s %sx%s"):format(
|
||||
ox, oy, 160 * scale, 144 * scale,
|
||||
tostring(seen[1]), tostring(seen[2]), tostring(seen[3]), tostring(seen[4])))
|
||||
end
|
||||
U.shot(game, SHOT_DIR .. "/2232_day_wheel.png")
|
||||
|
||||
say(fails == 0 and "all claims passed" or (fails .. " claims failed"))
|
||||
say("the SUNDAY picker at the top right and \"What day is it?\" should both")
|
||||
say("be on screen over the living room. a bare room with Mom next to you")
|
||||
say("and nothing to answer is the bug. up/down changes the day, A confirms.")
|
||||
while true do U.wait(60) end
|
||||
end
|
||||
@@ -0,0 +1,121 @@
|
||||
-- NEW GAME with a touch skin active, from the intro menu to the bedroom (#2230).
|
||||
-- ../pokecrystal/engine/menus/init_gender.asm:23
|
||||
-- ../pokecrystal/engine/menus/intro_menu.asm:80
|
||||
--
|
||||
-- POKEPORT_VERSION=crystal POKEPORT_IDENTITY=<sandbox> POKEPORT_TOUCH=1 \
|
||||
-- POKEPORT_BOOT_CINEMA=1 POKEPORT_SKIN=<skin id> POKEPORT_SHOT_DIR=<dir> \
|
||||
-- POKEPORT_DRIVER=tests/drivers/crystal_skin_newgame_bug2230.lua love .
|
||||
local U = require("tests.drivers.util")
|
||||
local TouchSkin = require("src.core.TouchSkin")
|
||||
local TouchControls = require("src.core.TouchControls")
|
||||
local Playfield = require("src.render.Playfield")
|
||||
local MainMenu = require("src.ui.gen2.MainMenu")
|
||||
local GenderSelect = require("src.ui.gen2.GenderSelect")
|
||||
local InitClock = require("src.ui.gen2.InitClock")
|
||||
local OakSpeech = require("src.ui.gen2.OakSpeech")
|
||||
local NamePick = require("src.ui.gen2.NamePick")
|
||||
|
||||
local SHOT_DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/pokeport-shots"
|
||||
|
||||
return function(game)
|
||||
local fails = 0
|
||||
local function say(line) print("[2230] " .. line) end
|
||||
local function ok(cond, line)
|
||||
if not cond then fails = fails + 1 end
|
||||
say((cond and "PASS " or "FAIL ") .. line)
|
||||
end
|
||||
local function top() return game.stack:top() end
|
||||
local function isA(class) return top() ~= nil and getmetatable(top()) == class end
|
||||
|
||||
local function tap(button, frames)
|
||||
game.input.pressQueue[#game.input.pressQueue + 1] = button
|
||||
game.input.state[button] = true
|
||||
U.wait(2)
|
||||
game.input.state[button] = false
|
||||
U.wait(frames or 4)
|
||||
end
|
||||
|
||||
local function waitFor(label, predicate, frames, spam)
|
||||
for _ = 1, frames or 900 do
|
||||
if predicate() then return true end
|
||||
if spam then tap(spam, 2) else U.wait(1) end
|
||||
end
|
||||
ok(false, "stalled waiting for " .. label .. " (top is " .. tostring(top()) .. ")")
|
||||
U.shot(game, SHOT_DIR .. "/2230_stall.png")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Counts the non-white, non-black pixels inside the skin's screen cutout:
|
||||
-- a GB page that actually painted there has plenty, a page clipped away
|
||||
-- leaves only the letterbox fill.
|
||||
local function paintedInCutout(path)
|
||||
local f = io.open(path, "rb")
|
||||
if not f then return nil end
|
||||
local bytes = f:read("*a")
|
||||
f:close()
|
||||
local image = love.image.newImageData(love.filesystem.newFileData(bytes, "shot.png"))
|
||||
local w, h = love.graphics.getDimensions()
|
||||
local cx, cy, cw, ch = Playfield.cutout(w, h)
|
||||
if not cx then cx, cy, cw, ch = 0, 0, w, h end
|
||||
local sx = image:getWidth() / w
|
||||
local painted = 0
|
||||
for y = cy, cy + ch - 1, 4 do
|
||||
for x = cx, cx + cw - 1, 4 do
|
||||
local r, g, b = image:getPixel(math.floor(x * sx), math.floor(y * sx))
|
||||
local lit = r > 0.05 or g > 0.05 or b > 0.05
|
||||
local white = r > 0.95 and g > 0.95 and b > 0.95
|
||||
if lit and not white then painted = painted + 1 end
|
||||
end
|
||||
end
|
||||
return painted
|
||||
end
|
||||
|
||||
local skins = TouchSkin.list()
|
||||
local want = os.getenv("POKEPORT_SKIN")
|
||||
if not want or want == "" then want = skins[1] and skins[1].id end
|
||||
ok(want ~= nil, "a skin is installed to select")
|
||||
if not want then return end
|
||||
local controls = game.touchControls or TouchControls
|
||||
local skin, err = controls:selectSkin(want)
|
||||
ok(skin ~= nil, "selected skin " .. tostring(want) .. " " .. tostring(err or ""))
|
||||
ok(TouchSkin.drawable(), "the skin is live, so Playfield cuts the screen out")
|
||||
|
||||
if not waitFor("the intro menu", function() return isA(MainMenu) end, 2400, "start") then return end
|
||||
local menu = top()
|
||||
for i, item in ipairs(menu.list.items) do
|
||||
if item.value == "new" then menu.list.index = i end
|
||||
end
|
||||
tap("a")
|
||||
|
||||
if not waitFor("the gender menu",
|
||||
function() return isA(GenderSelect) and top():menuOpen() end, 900) then return end
|
||||
U.wait(5)
|
||||
local genderShot = SHOT_DIR .. "/2230_01_gender_in_cutout.png"
|
||||
U.shot(game, genderShot)
|
||||
local painted = paintedInCutout(genderShot)
|
||||
ok(painted and painted > 200,
|
||||
("the gender page painted inside the cutout (%s coloured samples)"):format(tostring(painted)))
|
||||
tap("a")
|
||||
|
||||
if not waitFor("the clock", function() return isA(InitClock) end, 900) then return end
|
||||
U.shot(game, SHOT_DIR .. "/2230_02_clock.png")
|
||||
if not waitFor("Oak", function() return isA(OakSpeech) end, 1200, "a") then return end
|
||||
U.wait(30)
|
||||
U.shot(game, SHOT_DIR .. "/2230_03_oak.png")
|
||||
if not waitFor("the name picker", function() return isA(NamePick) end, 1500, "a") then return end
|
||||
U.wait(60)
|
||||
top().cursor = 2
|
||||
tap("a")
|
||||
if not waitFor("the bedroom", function()
|
||||
return game.phase == "play" and game.world and game.world.map ~= nil
|
||||
end, 2400, "a") then return end
|
||||
ok(game.world.map.id == "PLAYERS_HOUSE_2F", "new game landed in the bedroom under the skin")
|
||||
U.wait(30)
|
||||
U.shot(game, SHOT_DIR .. "/2230_04_bedroom.png")
|
||||
|
||||
say(fails == 0 and "all claims passed" or (fails .. " claims failed"))
|
||||
say("2230_01_gender_in_cutout.png should show the boy/girl prompt inside the")
|
||||
say("skin's screen window. an empty white window there, or a lua error after")
|
||||
say("the name picker, is the bug.")
|
||||
love.event.quit(fails == 0 and 0 or 1)
|
||||
end
|
||||
Reference in New Issue
Block a user