This commit is contained in:
bryanthaboi
2026-08-18 10:36:44 -04:00
parent 25ec896545
commit c2c7fdafcf
2 changed files with 92 additions and 16 deletions
+33 -16
View File
@@ -24,14 +24,18 @@
-- MoneyTopRightMenuHeader menu_coords 11, 0, 19, 2 -- a 9x3 box, and
-- PlaceMoneyTextbox writes the amount at
-- MenuBoxCoord2Tile + SCREEN_WIDTH + 1 = (12,1)
-- MenuHeader_Buy menu_coords 1, 3, 19, 11 -- a 19x9 box holding 4
-- entries of two rows. ScrollingMenu_UpdateDisplay
-- starts at (2,4); PlaceMenuItemName prints the name
-- there and .PrintBCDPrices is handed that origin
-- plus the menu's own width (8) plus SCREEN_WIDTH, so
-- the price lands at (10,5). The ▲ sits on the box's
-- top right corner (19,3) and the ▼ on its bottom
-- right (19,11).
-- MenuHeader_Buy menu_coords 1, 3, 19, 11 -- a 19x9 rect holding 4
-- entries of two rows. BuyMenuLoop copies that
-- header and calls ScrollingMenu; it never calls
-- InitScrollingMenu or MenuBox, so the rect is NOT
-- a framed window. ScrollingMenu_UpdateDisplay
-- calls ClearWholeMenuBox on it (spaces, no border)
-- and starts printing at (2,4); PlaceMenuItemName
-- prints the name there and .PrintBCDPrices is
-- handed that origin plus the menu's own width (8)
-- plus SCREEN_WIDTH, so the price lands at (10,5).
-- The ▲ sits on the rect's top right (19,3) and
-- the ▼ on its bottom right (19,11).
-- UpdateItemDescription Textbox (0,12) interior 18x4 -- a 20x6 box -- with
-- the description at (1,14)
-- BuyItem_MenuHeader menu_coords 7, 15, 19, 17 -- a 13x3 box, and
@@ -75,7 +79,9 @@ local SFX_TRANSACTION = "Sfx_Transaction"
local MartMenu = {}
MartMenu.__index = MartMenu
-- engine/items/mart.asm:54
-- The top menu overlays the mart (StandardMart .HowMayIHelpYou /
-- .AnythingElse: LoadStandardMenuHeader + PrintText). BuyMenu is
-- FadeToMenu + BlankScreen, so enterBuy shadows this for the list.
MartMenu.isOpaque = false
-- constants/mart_constants.asm. The `pokemart` macro emits this as one byte
@@ -563,6 +569,10 @@ function MartMenu:enterBuy()
self.phase = "buy"
self.index = 1
self.scroll = 0
-- BuyMenu (engine/items/mart.asm): `call FadeToMenu / farcall BlankScreen`.
-- BlankScreen fills the tilemap with spaces and the palettes with white, so
-- the mart must not keep drawing in the letterbox under the list.
self.isOpaque = (self.phase == "buy")
end
function MartMenu:total()
@@ -618,6 +628,8 @@ end
-- BuyMenu returns into StandardMart .Buy, which falls through to
-- .AnythingElse; the other three dialog kinds end on their come-again line.
function MartMenu:leaveBuy()
-- CloseSubmenu restores the map before .AnythingElse / the come-again line.
self.isOpaque = nil
if self.martType == "STANDARD" then
self:enterTop(self.text.askMore)
else
@@ -885,11 +897,10 @@ function MartMenu:description()
return def and def.description or nil
end
-- The bottom visible entry's price row IS the box's bottom border row
-- (entry row 10 + SCREEN_WIDTH = 11, MenuHeader_Buy's own last line), and a
-- GB glyph REPLACES the tile it prints over, border and all. White under
-- the seven money tiles first is that replacement; on the three rows clear
-- of the border it repaints white over white.
-- The bottom visible entry's price row is MenuHeader_Buy's last line
-- (entry row 10 + SCREEN_WIDTH = 11). A GB glyph REPLACES the tile it
-- prints over, so white under the seven money tiles first is that
-- replacement. On a BlankScreen field it is white over white.
local function printPriceOpaque(amount, ty)
local G = love.graphics
G.setColor(1, 1, 1, 1)
@@ -899,8 +910,10 @@ local function printPriceOpaque(amount, ty)
end
function MartMenu:drawBuyList()
-- engine/items/mart.asm:542
Chrome.box(LIST_BOX_X, LIST_BOX_Y, LIST_BOX_W, LIST_BOX_H)
-- ScrollingMenu_UpdateDisplay (engine/menus/scrolling_menu.asm) calls
-- ClearWholeMenuBox, not MenuBox: the MenuHeader_Buy rect is a cleared
-- field, not a framed window. BlankScreen already filled the tilemap
-- with spaces, so the names just land on white.
for row = 1, VISIBLE_ROWS do
local i = row + self.scroll
local ty = LIST_Y + (row - 1) * LIST_SPACING
@@ -960,6 +973,10 @@ function MartMenu:drawUnder()
self:drawTopMenu()
self:drawTextBox(self.topLines)
elseif phase == "buy" or phase == "buyQuantity" then
-- BlankScreen (engine/overworld/player_object.asm): the whole tilemap
-- is spaces before PlaceMoneyTopRight / the scrolling list / the
-- description textbox go down. Only those last two are framed.
Chrome.clear()
self:drawMoneyBox()
self:drawBuyList()
self:drawDescription()
+59
View File
@@ -179,6 +179,65 @@ check("the cursor is the column-1 arrow on the label row",
check("the cursor starts on the first row", cursorAt and cursorAt.y, 2)
check("FRAME still prints its literal TYPE", findPrint(":TYPE") ~= nil, true)
-- ------------------------------------------------------- mart buy list
--
-- BuyMenu (engine/items/mart.asm) is FadeToMenu + BlankScreen, then
-- PlaceMoneyTopRight and ScrollingMenu_UpdateDisplay's ClearWholeMenuBox.
-- The list is not MenuBox'd; only the money box and UpdateItemDescription's
-- textbox are. The top menu still overlays the mart, so it must not blank.
local MartMenu = require("src.ui.gen2.MartMenu")
local Save = require("src.core.gen2.Save")
local martBoxes, martClears = {}, 0
local martClear, martBox = Chrome.clear, Chrome.box
local martPrint, martCursor = Chrome.print, Chrome.cursor
Chrome.clear = function() martClears = martClears + 1 end
Chrome.box = function(x, y, w, h)
martBoxes[#martBoxes + 1] = { x = x, y = y, w = w, h = h }
end
Chrome.print = function() end
Chrome.cursor = function() end
local function martHasBox(x, y, w, h)
for _, b in ipairs(martBoxes) do
if b.x == x and b.y == y and b.w == w and b.h == h then return true end
end
return false
end
local martSave = Save.newGame()
local martItems = {
POTION = { id = "POTION", name = "POTION", pocket = "ITEM", price = 300,
description = "Restores HP\nby 20." },
}
local mart = MartMenu.new({ save = martSave, data = { items = martItems } }, {
save = martSave,
items = martItems,
marts = { lists = { { "POTION" } } },
})
mart:draw()
check("the top menu does not blank the tilemap", martClears, 0)
check("and frames BUY/SELL/QUIT", martHasBox(0, 0, 12, 9), true)
check("and the welcome speech box", martHasBox(0, 12, 20, 6), true)
check("the top menu is not opaque", mart.isOpaque, false)
martClears, martBoxes = 0, {}
mart:enterBuy()
mart:draw()
check("BUY blanks the screen (BlankScreen)", martClears > 0, true)
check("the money box is framed", martHasBox(11, 0, 9, 3), true)
check("the description box is framed", martHasBox(0, 12, 20, 6), true)
check("the item list is not (ClearWholeMenuBox, not MenuBox)",
martHasBox(1, 3, 19, 9), false)
check("BlankScreen shadows isOpaque so the letterbox is not the mart",
mart.isOpaque, true)
mart:leaveBuy()
check("leaving BUY unshadows isOpaque", mart.isOpaque, false)
Chrome.clear, Chrome.box = martClear, martBox
Chrome.print, Chrome.cursor = martPrint, martCursor
-- ------------------------------------------------------- one blit scale
--
-- Every Gold screen paints its 160x144 panel through the same helper. A