mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-22 21:46:51 +02:00
feat: enhance Goldenrod Game Corner graphics extraction
Added functions to write raw graphics assets for the Slot Machine and Card Flip games, ensuring that the necessary files are generated when the corresponding symbols are present in the ROM. Updated the manifest to include required symbols for these assets, preventing fallback to labelled cells when graphics are missing.
This commit is contained in:
@@ -5258,9 +5258,26 @@ function RomExtractorGen2:extractMenuGfx()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Goldenrod Game Corner: Slot Machine graphics assets
|
-- Goldenrod Game Corner: Slot Machine graphics assets
|
||||||
|
local CacheFs = require("src.import.CacheFs")
|
||||||
|
local function packBytes(bytes)
|
||||||
|
local chars = {}
|
||||||
|
for i = 1, #bytes do chars[i] = string.char(bytes[i]) end
|
||||||
|
return table.concat(chars)
|
||||||
|
end
|
||||||
|
local function writeRaw(relative, bytes)
|
||||||
|
local ok, writeError = CacheFs.write(
|
||||||
|
"assets/generated/" .. relative, packBytes(bytes))
|
||||||
|
if not ok then
|
||||||
|
error("could not write " .. relative .. ": " .. tostring(writeError))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local slots = nil
|
||||||
if self.symbols["Slots1LZ"] then
|
if self.symbols["Slots1LZ"] then
|
||||||
local raw1 = self:decompressLz3Symbol("Slots1LZ")
|
local raw1 = self:decompressLz3Symbol("Slots1LZ")
|
||||||
self:write2bpp(raw1, 16, #raw1 / 4, "slots/gold_slots_1.png")
|
self:write2bpp(raw1, 16, #raw1 / 4, "slots/gold_slots_1.png")
|
||||||
|
slots = slots or {}
|
||||||
|
slots.sheet1 = "assets/generated/slots/gold_slots_1.png"
|
||||||
end
|
end
|
||||||
if self.symbols["Slots2LZ"] then
|
if self.symbols["Slots2LZ"] then
|
||||||
local raw2 = self:decompressLz3Symbol("Slots2LZ")
|
local raw2 = self:decompressLz3Symbol("Slots2LZ")
|
||||||
@@ -5269,6 +5286,8 @@ function RomExtractorGen2:extractMenuGfx()
|
|||||||
raw2[i] = bit.band(bit.bnot(raw2[i]), 0xFF)
|
raw2[i] = bit.band(bit.bnot(raw2[i]), 0xFF)
|
||||||
end
|
end
|
||||||
self:write2bpp(raw2, 16, #raw2 / 4, "slots/gold_slots_2.png")
|
self:write2bpp(raw2, 16, #raw2 / 4, "slots/gold_slots_2.png")
|
||||||
|
slots = slots or {}
|
||||||
|
slots.sheet2 = "assets/generated/slots/gold_slots_2.png"
|
||||||
end
|
end
|
||||||
if self.symbols["Slots3LZ"] then
|
if self.symbols["Slots3LZ"] then
|
||||||
local raw3 = self:decompressLz3Symbol("Slots3LZ")
|
local raw3 = self:decompressLz3Symbol("Slots3LZ")
|
||||||
@@ -5283,55 +5302,58 @@ function RomExtractorGen2:extractMenuGfx()
|
|||||||
-- Y=192: Chansey 5 (Egg Drop pose, 24x32)
|
-- Y=192: Chansey 5 (Egg Drop pose, 24x32)
|
||||||
-- Y=224: Egg (8x16 at X=0)
|
-- Y=224: Egg (8x16 at X=0)
|
||||||
self:write2bpp(raw3, 24, #raw3 / 6, "slots/gold_slots_actors.png", true)
|
self:write2bpp(raw3, 24, #raw3 / 6, "slots/gold_slots_actors.png", true)
|
||||||
|
slots = slots or {}
|
||||||
|
slots.sheet3 = "assets/generated/slots/gold_slots_3.png"
|
||||||
end
|
end
|
||||||
if self.symbols["SlotsTilemap"] then
|
if self.symbols["SlotsTilemap"] then
|
||||||
local symbol = self:symbol("SlotsTilemap")
|
local symbol = self:symbol("SlotsTilemap")
|
||||||
local tm = self.rom:bytes(symbol.bank, symbol.address, 20 * 12)
|
local tm = self.rom:bytes(symbol.bank, symbol.address, 20 * 12)
|
||||||
self:save(tm, "slots/gold_slots.tilemap")
|
writeRaw("slots/gold_slots.tilemap", tm)
|
||||||
|
slots = slots or {}
|
||||||
|
slots.tilemap = "assets/generated/slots/gold_slots.tilemap"
|
||||||
end
|
end
|
||||||
|
if slots then out.slots = slots end
|
||||||
|
|
||||||
-- Goldenrod Game Corner: Card Flip graphics assets
|
-- Goldenrod Game Corner: Card Flip graphics assets
|
||||||
|
local cardFlip = nil
|
||||||
if self.symbols["CardFlipLZ01"] then
|
if self.symbols["CardFlipLZ01"] then
|
||||||
local raw1 = self:decompressLz3Symbol("CardFlipLZ01")
|
local raw1 = self:decompressLz3Symbol("CardFlipLZ01")
|
||||||
self:write2bpp(raw1, 128, #raw1 / 32, "card_flip/card_flip_1.png")
|
self:write2bpp(raw1, 128, #raw1 / 32, "card_flip/card_flip_1.png")
|
||||||
|
cardFlip = cardFlip or {}
|
||||||
|
cardFlip.sheet1 = "assets/generated/card_flip/card_flip_1.png"
|
||||||
end
|
end
|
||||||
if self.symbols["CardFlipLZ02"] then
|
if self.symbols["CardFlipLZ02"] then
|
||||||
local raw2 = self:decompressLz3Symbol("CardFlipLZ02")
|
local raw2 = self:decompressLz3Symbol("CardFlipLZ02")
|
||||||
self:write2bpp(raw2, 24, #raw2 / 6, "card_flip/card_flip_2.png")
|
self:write2bpp(raw2, 24, #raw2 / 6, "card_flip/card_flip_2.png")
|
||||||
|
cardFlip = cardFlip or {}
|
||||||
|
cardFlip.sheet2 = "assets/generated/card_flip/card_flip_2.png"
|
||||||
end
|
end
|
||||||
if self.symbols["CardFlipLZ03"] then
|
if self.symbols["CardFlipLZ03"] then
|
||||||
local raw3 = self:decompressLz3Symbol("CardFlipLZ03")
|
local raw3 = self:decompressLz3Symbol("CardFlipLZ03")
|
||||||
self:write2bpp(raw3, 8, #raw3 / 2, "card_flip/card_flip_3.png")
|
self:write2bpp(raw3, 8, #raw3 / 2, "card_flip/card_flip_3.png")
|
||||||
|
cardFlip = cardFlip or {}
|
||||||
|
cardFlip.sheet3 = "assets/generated/card_flip/card_flip_3.png"
|
||||||
end
|
end
|
||||||
if self.symbols["CardFlipOnButtonGFX"] then
|
if self.symbols["CardFlipOnButtonGFX"] then
|
||||||
local symbol = self:symbol("CardFlipOnButtonGFX")
|
local symbol = self:symbol("CardFlipOnButtonGFX")
|
||||||
self:write2bpp(self.rom:bytes(symbol.bank, symbol.address, 16), 8, 8, "card_flip/on.png")
|
self:write2bpp(self.rom:bytes(symbol.bank, symbol.address, 16), 8, 8, "card_flip/on.png")
|
||||||
|
cardFlip = cardFlip or {}
|
||||||
|
cardFlip.on = "assets/generated/card_flip/on.png"
|
||||||
end
|
end
|
||||||
if self.symbols["CardFlipOffButtonGFX"] then
|
if self.symbols["CardFlipOffButtonGFX"] then
|
||||||
local symbol = self:symbol("CardFlipOffButtonGFX")
|
local symbol = self:symbol("CardFlipOffButtonGFX")
|
||||||
self:write2bpp(self.rom:bytes(symbol.bank, symbol.address, 16), 8, 8, "card_flip/off.png")
|
self:write2bpp(self.rom:bytes(symbol.bank, symbol.address, 16), 8, 8, "card_flip/off.png")
|
||||||
|
cardFlip = cardFlip or {}
|
||||||
|
cardFlip.off = "assets/generated/card_flip/off.png"
|
||||||
end
|
end
|
||||||
if self.symbols["CardFlipTilemap"] then
|
if self.symbols["CardFlipTilemap"] then
|
||||||
local symbol = self:symbol("CardFlipTilemap")
|
local symbol = self:symbol("CardFlipTilemap")
|
||||||
local tm = self.rom:bytes(symbol.bank, symbol.address, 11 * 12)
|
local tm = self.rom:bytes(symbol.bank, symbol.address, 11 * 12)
|
||||||
self:save(tm, "card_flip/card_flip.tilemap")
|
writeRaw("card_flip/card_flip.tilemap", tm)
|
||||||
|
cardFlip = cardFlip or {}
|
||||||
|
cardFlip.tilemap = "assets/generated/card_flip/card_flip.tilemap"
|
||||||
end
|
end
|
||||||
|
if cardFlip then out.cardFlip = cardFlip end
|
||||||
out.slots = {
|
|
||||||
sheet1 = "assets/generated/slots/gold_slots_1.png",
|
|
||||||
sheet2 = "assets/generated/slots/gold_slots_2.png",
|
|
||||||
sheet3 = "assets/generated/slots/gold_slots_3.png",
|
|
||||||
tilemap = "assets/generated/slots/gold_slots.tilemap",
|
|
||||||
}
|
|
||||||
|
|
||||||
out.cardFlip = {
|
|
||||||
sheet1 = "assets/generated/card_flip/card_flip_1.png",
|
|
||||||
sheet2 = "assets/generated/card_flip/card_flip_2.png",
|
|
||||||
sheet3 = "assets/generated/card_flip/card_flip_3.png",
|
|
||||||
on = "assets/generated/card_flip/on.png",
|
|
||||||
off = "assets/generated/card_flip/off.png",
|
|
||||||
tilemap = "assets/generated/card_flip/card_flip.tilemap",
|
|
||||||
}
|
|
||||||
|
|
||||||
self:write("menu_gfx", out)
|
self:write("menu_gfx", out)
|
||||||
self:tick("Menu graphics", 1, 1)
|
self:tick("Menu graphics", 1, 1)
|
||||||
|
|||||||
@@ -140,6 +140,12 @@ local VERSION_REQUIRED_FILES_OVERRIDE = {
|
|||||||
-- before the four ball tiles were extracted (#1502).
|
-- before the four ball tiles were extracted (#1502).
|
||||||
"assets/generated/battle/hud/balls.png",
|
"assets/generated/battle/hud/balls.png",
|
||||||
"assets/generated/audio/programs.bin",
|
"assets/generated/audio/programs.bin",
|
||||||
|
-- Goldenrod Game Corner reel + board art (#1581). menu_gfx.lua used to
|
||||||
|
-- advertise these paths even when Slots*LZ / CardFlip* were absent from
|
||||||
|
-- the manifest, so a cache that never wrote the PNGs still looked
|
||||||
|
-- complete and SlotMachine crashed on its labelled-cell fallback.
|
||||||
|
"assets/generated/slots/gold_slots_1.png",
|
||||||
|
"assets/generated/card_flip/card_flip_1.png",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
-- Same Gen 2 extract, so a Silver cache is complete when the same files exist.
|
-- Same Gen 2 extract, so a Silver cache is complete when the same files exist.
|
||||||
|
|||||||
@@ -49,9 +49,9 @@
|
|||||||
-- Textbox at (0,12) with an 18x4 interior
|
-- Textbox at (0,12) with an 18x4 interior
|
||||||
--
|
--
|
||||||
-- The cart's own art (gfx/card_flip/card_flip_1..3.2bpp.lz and
|
-- The cart's own art (gfx/card_flip/card_flip_1..3.2bpp.lz and
|
||||||
-- gfx/card_flip/card_flip.tilemap) is NOT in the cache: no `cardFlip` entry is
|
-- gfx/card_flip/card_flip.tilemap) is extracted into assets/generated/card_flip/
|
||||||
-- written into menu_gfx.lua yet, so the board draws as labelled cells until one
|
-- when the Gold/Silver manifest carries CardFlip*. Until those files exist,
|
||||||
-- appears.
|
-- the board draws as labelled cells.
|
||||||
|
|
||||||
local Chrome = require("src.ui.gen2.Chrome")
|
local Chrome = require("src.ui.gen2.Chrome")
|
||||||
local CoinCase = require("src.core.gen2.CoinCase")
|
local CoinCase = require("src.core.gen2.CoinCase")
|
||||||
@@ -616,10 +616,8 @@ local TILEMAP = nil
|
|||||||
local function getCardFlipTilemap()
|
local function getCardFlipTilemap()
|
||||||
if TILEMAP == nil then
|
if TILEMAP == nil then
|
||||||
local path = "assets/generated/card_flip/card_flip.tilemap"
|
local path = "assets/generated/card_flip/card_flip.tilemap"
|
||||||
local f = io.open(path, "rb")
|
local data = love and love.filesystem and love.filesystem.read(path)
|
||||||
if f then
|
if data and #data > 0 then
|
||||||
local data = f:read("*a")
|
|
||||||
f:close()
|
|
||||||
TILEMAP = {}
|
TILEMAP = {}
|
||||||
for i = 1, #data do
|
for i = 1, #data do
|
||||||
TILEMAP[i] = string.byte(data, i)
|
TILEMAP[i] = string.byte(data, i)
|
||||||
|
|||||||
+22
-10
@@ -39,11 +39,9 @@
|
|||||||
-- tiles at (2,13),(3,13),(2,14),(3,14) and the ▼ at
|
-- tiles at (2,13),(3,13),(2,14),(3,14) and the ▼ at
|
||||||
-- (18,17)
|
-- (18,17)
|
||||||
--
|
--
|
||||||
-- The cart's own reel art (gfx/slots/slots_1..3.2bpp.lz plus
|
-- Reel art (gfx/slots/slots_1..3.2bpp.lz + slots.tilemap) is extracted into
|
||||||
-- gfx/slots/slots.tilemap) is NOT in the cache: src/import/RomExtractorGen2.lua
|
-- assets/generated/slots/ when the Gold/Silver manifest carries Slots*LZ.
|
||||||
-- writes no `slots` entry into menu_gfx.lua yet. SlotMachine:sheet() reads one
|
-- Until those files exist, drawReels falls back to labelled cells.
|
||||||
-- the moment it appears and falls back to labelled cells until then, the same
|
|
||||||
-- way src/ui/gen2/PackGfx.lua degrades.
|
|
||||||
|
|
||||||
local Chrome = require("src.ui.gen2.Chrome")
|
local Chrome = require("src.ui.gen2.Chrome")
|
||||||
local CoinCase = require("src.core.gen2.CoinCase")
|
local CoinCase = require("src.core.gen2.CoinCase")
|
||||||
@@ -1160,10 +1158,8 @@ local TILEMAP = nil
|
|||||||
local function getTilemap()
|
local function getTilemap()
|
||||||
if TILEMAP == nil then
|
if TILEMAP == nil then
|
||||||
local path = "assets/generated/slots/gold_slots.tilemap"
|
local path = "assets/generated/slots/gold_slots.tilemap"
|
||||||
local f = io.open(path, "rb")
|
local data = love and love.filesystem and love.filesystem.read(path)
|
||||||
if f then
|
if data and #data > 0 then
|
||||||
local data = f:read("*a")
|
|
||||||
f:close()
|
|
||||||
TILEMAP = {}
|
TILEMAP = {}
|
||||||
for i = 1, #data do
|
for i = 1, #data do
|
||||||
TILEMAP[i] = string.byte(data, i)
|
TILEMAP[i] = string.byte(data, i)
|
||||||
@@ -1175,6 +1171,14 @@ local function getTilemap()
|
|||||||
return TILEMAP or nil
|
return TILEMAP or nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Placeholder 2x2 symbol cell used when reel sheets are not in the cache yet.
|
||||||
|
local function cell(tx, ty, label)
|
||||||
|
local G = love.graphics
|
||||||
|
G.setColor(0, 0, 0, 1)
|
||||||
|
G.rectangle("line", tx * 8, ty * 8, 16, 16)
|
||||||
|
Chrome.print(label, tx, ty + 1)
|
||||||
|
end
|
||||||
|
|
||||||
function SlotMachine:sheets()
|
function SlotMachine:sheets()
|
||||||
if self.sheet1 == nil then
|
if self.sheet1 == nil then
|
||||||
self.sheet1 = TileSheet.new({ path = "assets/generated/slots/gold_slots_1.png", wide = 2, firstTile = 0 })
|
self.sheet1 = TileSheet.new({ path = "assets/generated/slots/gold_slots_1.png", wide = 2, firstTile = 0 })
|
||||||
@@ -1253,6 +1257,9 @@ function SlotMachine:drawReels()
|
|||||||
-- Draw 4 consecutive 2x2 symbols from bottom to top, exactly matching SlotMachine.window
|
-- Draw 4 consecutive 2x2 symbols from bottom to top, exactly matching SlotMachine.window
|
||||||
for row = 0, 3 do
|
for row = 0, 3 do
|
||||||
local sym = strip[a + row + 1]
|
local sym = strip[a + row + 1]
|
||||||
|
if type(sym) ~= "number" then
|
||||||
|
cell(REEL_X[i], REEL_ROW[row + 1], "?")
|
||||||
|
else
|
||||||
local py = 64 - (row * 16) + dy
|
local py = 64 - (row * 16) + dy
|
||||||
local pal = GBC_PALS.obj[math.floor(sym / 4)] or GBC_PALS.obj[0]
|
local pal = GBC_PALS.obj[math.floor(sym / 4)] or GBC_PALS.obj[0]
|
||||||
s2.palette = pal
|
s2.palette = pal
|
||||||
@@ -1286,6 +1293,7 @@ function SlotMachine:drawReels()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function SlotMachine:actorsImage()
|
function SlotMachine:actorsImage()
|
||||||
@@ -1439,6 +1447,9 @@ function SlotMachine:drawMessage()
|
|||||||
and self.phase == "payoutText" then
|
and self.phase == "payoutText" then
|
||||||
local _, s2 = self:sheets()
|
local _, s2 = self:sheets()
|
||||||
local sym = self.matched
|
local sym = self.matched
|
||||||
|
if type(sym) ~= "number" then
|
||||||
|
cell(PAYOUT_SYMBOL_X, PAYOUT_SYMBOL_Y, "?")
|
||||||
|
else
|
||||||
local pal = GBC_PALS.obj[math.floor(sym / 4)] or GBC_PALS.obj[0]
|
local pal = GBC_PALS.obj[math.floor(sym / 4)] or GBC_PALS.obj[0]
|
||||||
s2.palette = pal
|
s2.palette = pal
|
||||||
local t0 = s2:quad(sym + 0)
|
local t0 = s2:quad(sym + 0)
|
||||||
@@ -1463,7 +1474,8 @@ function SlotMachine:drawMessage()
|
|||||||
drawWin()
|
drawWin()
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
cell(PAYOUT_SYMBOL_X, PAYOUT_SYMBOL_Y, SlotMachine.LABELS[self.matched] or "?")
|
cell(PAYOUT_SYMBOL_X, PAYOUT_SYMBOL_Y, SlotMachine.LABELS[sym] or "?")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -785,6 +785,14 @@ REQUIRED_SYMBOLS = {
|
|||||||
"KabutoPuzzleLZ", "OmanytePuzzleLZ", "AerodactylPuzzleLZ", "HoOhPuzzleLZ",
|
"KabutoPuzzleLZ", "OmanytePuzzleLZ", "AerodactylPuzzleLZ", "HoOhPuzzleLZ",
|
||||||
"UnownPuzzleStartCancelLZ", "UnownPuzzleCursorGFX",
|
"UnownPuzzleStartCancelLZ", "UnownPuzzleCursorGFX",
|
||||||
"PuzzlePieceBorderData.TileBordersGFX",
|
"PuzzlePieceBorderData.TileBordersGFX",
|
||||||
|
# Goldenrod Game Corner (engine/games/slot_machine.asm + card_flip.asm).
|
||||||
|
# Slots1LZ/2LZ/3LZ are the reel + actor sheets; SlotsTilemap is the 20x12
|
||||||
|
# BG map. CardFlipLZ01..03 + On/Off button tiles and CardFlipTilemap are
|
||||||
|
# the odds-board art. Without these in the manifest the extractor skips
|
||||||
|
# the files and SlotMachine/CardFlip fall back to labelled cells.
|
||||||
|
"Slots1LZ", "Slots2LZ", "Slots3LZ", "SlotsTilemap",
|
||||||
|
"CardFlipLZ01", "CardFlipLZ02", "CardFlipLZ03",
|
||||||
|
"CardFlipOnButtonGFX", "CardFlipOffButtonGFX", "CardFlipTilemap",
|
||||||
# Emote bubbles (data/sprites/emotes.asm): showemote's ! over a trainer
|
# Emote bubbles (data/sprites/emotes.asm): showemote's ! over a trainer
|
||||||
# who just spotted the player, and the other faces scripts use.
|
# who just spotted the player, and the other faces scripts use.
|
||||||
"ShockEmote", "QuestionEmote", "HappyEmote", "SadEmote",
|
"ShockEmote", "QuestionEmote", "HappyEmote", "SadEmote",
|
||||||
|
|||||||
Reference in New Issue
Block a user