Decipher and label the $1c duel-gfx block (Gfx2)

The bank switch in CopyFontsOrDuelGraphicsTiles is done by BankpushROM
(src/home/switch_rom.asm): it sets bank = BANK(Fonts) + the top 2 bits of
hl and masks the address into $4000-$7fff. So an operand hl<$4000 reads
Gfx1 (bank $1b) at hl+$4000, while $4000<=hl<$8000 reads Gfx2 (bank $1c)
at hl. A SameBoy trace confirmed this (header/symbol loaders read $1b;
the draw-cards/box-message loaders read $1c).

With that, the formerly anonymous $1c:4000-4a30 blob (gfx_070000.bin) is
fully identified -- 163 tiles partition exactly into 7 duel-screen
graphics, each carved out as a labeled region and INCBIN'd:

  $4000 (36t) DuelCheckPokemonScreenGfx     face-down cards + ACT/BPx
  $4240 (45t) DuelPlayAreaScreenGfx         play-area screen (CGB)
  $4510 (45t) DuelPlayAreaScreenGfxDMG      play-area screen (DMG/SGB)
  $47e0 (13t) DuelDeckAndDiscardPileIcons
  $48b0  (8t) DuelCoinTossResultTiles       [O]/[X]
  $4930  (8t) DuelMenuAndCardPicBorderTiles
  $49b0  (8t) DuelDrawCardsScreenIcons      Deck/Hand

The raw $4xxx operands in tiles.asm/bills_pc.asm now reference these
labels (byte-faithful: each label resolves to the old constant), and
Func_1dff -> LoadDuelPlayAreaScreenTiles since it loads that region.

make compare: poketcg2.gbc OK (byte-identical).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Test User
2026-06-06 16:23:21 -04:00
parent 3484b3a0de
commit 14efcb6e9e
14 changed files with 58 additions and 21 deletions

View File

@@ -543,7 +543,7 @@ _DrawYourOrOppPlayAreaScreen::
DrawYourOrOppPlayAreaScreen_EmptiedScreen:
call LoadSymbolsFont
call Func_1dff
call LoadDuelPlayAreaScreenTiles
bank1call SetDefaultPalettes
lb de, 6, 0
call InitTextPrinting
@@ -637,7 +637,7 @@ DrawInPlayAreaScreen::
push af
ld a, CONSOLE_DMG
ld [wConsole], a
call Func_1dff
call LoadDuelPlayAreaScreenTiles
pop af
ld [wConsole], a
bank1call SetDefaultPalettes
@@ -694,7 +694,7 @@ _DrawPlayersPrizeAndBenchCards::
call DoFrame
call EmptyScreen
call LoadSymbolsFont
call Func_1dff
call LoadDuelPlayAreaScreenTiles
; player cards
ld a, PLAYER_TURN
ld [wCheckMenuPlayAreaWhichDuelist], a

View File

@@ -76,7 +76,7 @@ _BillsPC:
call SetupText
call EmptyScreen
ld hl, $4930 ; DuelOtherGraphics + $30 tiles
ld hl, DuelMenuAndCardPicBorderTiles
ld de, v0Tiles2 + $30 tiles
ld b, 8
call CopyFontsOrDuelGraphicsTiles

View File

@@ -19,7 +19,20 @@ DuelOtherGraphics::
INCBIN "gfx/duel/duel_other_gfx.bin"
SECTION "Gfx 1c", ROMX[$4000], BANK[$1c]
INCBIN "gfx/cards/misc/gfx_070000.bin"
DuelCheckPokemonScreenGfx::
INCBIN "gfx/duel/check_pokemon_screen.bin"
DuelPlayAreaScreenGfx::
INCBIN "gfx/duel/play_area_screen.bin"
DuelPlayAreaScreenGfxDMG::
INCBIN "gfx/duel/play_area_screen_dmg.bin"
DuelDeckAndDiscardPileIcons::
INCBIN "gfx/duel/deck_discard_icons.bin"
DuelCoinTossResultTiles::
INCBIN "gfx/duel/coin_toss_result_symbols.bin"
DuelMenuAndCardPicBorderTiles::
INCBIN "gfx/duel/menu_card_pic_border.bin"
DuelDrawCardsScreenIcons::
INCBIN "gfx/duel/draw_cards_icons.bin"
DuelBoxMessages::
INCBIN "gfx/duel/box_messages.2bpp"
ds $2450, $ff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -64,7 +64,7 @@ LoadCardSet2Tiles::
add hl, hl
add hl, hl
add hl, hl
ld de, $3dd0 ; DuelOtherGraphics + $1d tiles
ld de, DuelOtherGraphics + $1d tiles - $4000 ; card set 2 icons
add hl, de
ld de, v0Tiles1 + $7c tiles
ld b, $04
@@ -86,7 +86,7 @@ LoadCardSet2Tiles::
; loads the Deck and Hand icons for the "Draw X card(s) from the deck." screen
LoadDuelDrawCardsScreenTiles::
ld hl, $49b0 ; DuelOtherGraphics + $29 tiles
ld hl, DuelDrawCardsScreenIcons
ld de, v0Tiles1 + $74 tiles
ld b, $08
jp CopyFontsOrDuelGraphicsTiles
@@ -102,7 +102,7 @@ LoadDuelCheckPokemonScreenTiles::
; fallthrough
.got_num_tiles
ld hl, $4000
ld hl, DuelCheckPokemonScreenGfx
ld de, v0Tiles1 + $50 tiles
call CopyFontsOrDuelGraphicsTiles
bank1call Func_6c12
@@ -111,7 +111,7 @@ LoadDuelCheckPokemonScreenTiles::
; loads the 8 tiles that make up the border of the main duel menu as well as the border
; of a large card picture (displayed after drawing the card or placing it in the arena).
LoadCardOrDuelMenuBorderTiles::
ld hl, $4930 ; DuelOtherGraphics + $15 tiles
ld hl, DuelMenuAndCardPicBorderTiles
ld de, v0Tiles1 + $50 tiles
ld b, $08
jr CopyFontsOrDuelGraphicsTiles
@@ -150,16 +150,18 @@ LoadDeckAndDiscardPileIcons::
ld de, $cb16
ld c, $08
call CopyFontsOrDuelGraphicsBytes
ld hl, $47e0
ld hl, DuelDeckAndDiscardPileIcons
ld de, $8a00
ld b, $0d
call CopyFontsOrDuelGraphicsTiles
Func_1dff::
ld hl, $4240
; load the tiles for the player's / opponent's Play Area screen
; (uses a separate set of tiles on CGB vs DMG/SGB)
LoadDuelPlayAreaScreenTiles::
ld hl, DuelPlayAreaScreenGfx
ld a, [wConsole]
cp CONSOLE_CGB
jr z, .copy
ld hl, $4510
ld hl, DuelPlayAreaScreenGfxDMG
.copy
ld de, v0Tiles1 + $50 tiles
ld b, $30
@@ -171,7 +173,7 @@ LoadDuelCoinTossResultTiles::
ld de, $cafe
ld c, $08
call CopyFontsOrDuelGraphicsBytes
ld hl, $48b0 ; DuelOtherGraphics + $d tiles
ld hl, DuelCoinTossResultTiles
ld de, v0Tiles2 + $30 tiles
ld b, $08
jr CopyFontsOrDuelGraphicsTiles
@@ -203,7 +205,7 @@ Func_212f::
ld b, $30
call CopyFontsOrDuelGraphicsTiles
; text box frame tiles
ld hl, $4930 ; DuelOtherGraphics + $15 tiles
ld hl, DuelMenuAndCardPicBorderTiles
ld de, sGfxBuffer1 + $30 tiles
ld b, $8
call CopyFontsOrDuelGraphicsTiles

View File

@@ -37,12 +37,26 @@ REGION_END = 0xd9818 # end of last card; rest of region is 0xff pad
# tiles = 48+48+19+64). The loaders keep their raw operands; these labels just
# document and source the data.
# (file offset, size, label, gfx path stem, png width in tiles | None for raw .bin)
# Bank-layout note: these duel graphics are reached through CopyFontsOrDuelGraphicsTiles,
# whose BankpushROM (src/home/switch_rom.asm) sets bank = BANK(Fonts) + hl's top 2 bits and
# masks the address into $4000-$7fff. So an operand hl<$4000 reads Gfx1 (bank $1b) at hl+$4000,
# while $4000<=hl<$8000 reads Gfx2 (bank $1c) at hl. That's why the $1b tail (file 0x6f4d0..0x70000)
# and the $1c block (file 0x70000..) are one logical duel-gfx region split across two banks.
KNOWN_PRE = [
# --- Gfx1 tail (bank $1b), referenced as `<label> - $4000` -------------------------------
(0x6f4d0, 48*16, 'DuelCardHeaderGraphics', 'gfx/duel/card_type_headers', None), # TRAINER/ENERGY/POKEMON
(0x6f7d0, 48*16, 'DuelCgbSymbolGraphics', 'gfx/duel/cgb_card_symbols', None), # CGB rarity/type symbols
(0x6fad0, 19*16, 'DuelDmgSgbSymbolGraphics', 'gfx/duel/dmg_sgb_card_symbols', None), # DMG/SGB symbols
(0x6fc00, 64*16, 'DuelOtherGraphics', 'gfx/duel/duel_other_gfx', None),
(0x70a30, 7*40*16, 'DuelBoxMessages', 'gfx/duel/box_messages', 10), # 7 box msgs, 10x4
(0x6fc00, 64*16, 'DuelOtherGraphics', 'gfx/duel/duel_other_gfx', None), # incl. card set 2 icons (LoadCardSet2Tiles)
# --- Gfx2 ($1c:4000..4a30), referenced by the raw $4xxx operands directly ----------------
(0x70000, 36*16, 'DuelCheckPokemonScreenGfx', 'gfx/duel/check_pokemon_screen', None), # face-down cards + ACT/BPx (LoadDuelCheckPokemonScreenTiles)
(0x70240, 45*16, 'DuelPlayAreaScreenGfx', 'gfx/duel/play_area_screen', None), # CGB play-area screen (Func_1dff)
(0x70510, 45*16, 'DuelPlayAreaScreenGfxDMG', 'gfx/duel/play_area_screen_dmg', None), # DMG/SGB variant
(0x707e0, 13*16, 'DuelDeckAndDiscardPileIcons', 'gfx/duel/deck_discard_icons', None), # LoadDeckAndDiscardPileIcons
(0x708b0, 8*16, 'DuelCoinTossResultTiles', 'gfx/duel/coin_toss_result_symbols', None), # [O]/[X] (LoadDuelCoinTossResultTiles); distinct from CoinTossResultGfx
(0x70930, 8*16, 'DuelMenuAndCardPicBorderTiles', 'gfx/duel/menu_card_pic_border', None), # LoadCardOrDuelMenuBorderTiles
(0x709b0, 8*16, 'DuelDrawCardsScreenIcons', 'gfx/duel/draw_cards_icons', None), # Deck/Hand (LoadDuelDrawCardsScreenTiles)
(0x70a30, 7*40*16, 'DuelBoxMessages', 'gfx/duel/box_messages', 10), # 7 box msgs, 10x4
]
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
GFXDIR = os.path.join(ROOT, "src/gfx/cards")

View File

@@ -56,10 +56,18 @@ def classify(bank, addr):
if lo <= addr < hi:
return off, f"{name} + ${addr-lo:x} ($1b:{addr:04x})"
if bank == 0x1c:
if 0x4000 <= addr < 0x4a30:
return off, f"$1c:4000-4a30 UNLABELED blob (gfx_070000) + ${addr-0x4000:x}"
if 0x4a30 <= addr < 0x5bb0:
return off, f"DuelBoxMessages + ${addr-0x4a30:x} ($1c:{addr:04x})"
for lo, hi, name in [
(0x4000, 0x4240, "DuelCheckPokemonScreenGfx"),
(0x4240, 0x4510, "DuelPlayAreaScreenGfx"),
(0x4510, 0x47e0, "DuelPlayAreaScreenGfxDMG"),
(0x47e0, 0x48b0, "DuelDeckAndDiscardPileIcons"),
(0x48b0, 0x4930, "DuelCoinTossResultTiles"),
(0x4930, 0x49b0, "DuelMenuAndCardPicBorderTiles"),
(0x49b0, 0x4a30, "DuelDrawCardsScreenIcons"),
(0x4a30, 0x5bb0, "DuelBoxMessages"),
]:
if lo <= addr < hi:
return off, f"{name} + ${addr-lo:x} ($1c:{addr:04x})"
return off, f"$1c:{addr:04x} (padding region)"
if 0x1d <= bank <= 0x36:
idx = (off - CG) // 8