From 14efcb6e9ebfd21e935c727645debee2e2953702 Mon Sep 17 00:00:00 2001 From: Test User Date: Sat, 6 Jun 2026 16:23:21 -0400 Subject: [PATCH] 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) --- src/engine/bank02.asm | 6 +++--- src/engine/bills_pc.asm | 2 +- src/gfx/card_graphics.asm | 15 ++++++++++++++- src/gfx/cards/misc/gfx_070000.bin | Bin 2608 -> 0 bytes src/gfx/duel/check_pokemon_screen.bin | Bin 0 -> 576 bytes src/gfx/duel/coin_toss_result_symbols.bin | Bin 0 -> 128 bytes src/gfx/duel/deck_discard_icons.bin | Bin 0 -> 208 bytes src/gfx/duel/draw_cards_icons.bin | Bin 0 -> 128 bytes src/gfx/duel/menu_card_pic_border.bin | Bin 0 -> 128 bytes src/gfx/duel/play_area_screen.bin | Bin 0 -> 720 bytes src/gfx/duel/play_area_screen_dmg.bin | Bin 0 -> 720 bytes src/home/tiles.asm | 22 ++++++++++++---------- tools/extract_card_gfx.py | 18 ++++++++++++++++-- tools/trace_gfx_reads.py | 16 ++++++++++++---- 14 files changed, 58 insertions(+), 21 deletions(-) delete mode 100644 src/gfx/cards/misc/gfx_070000.bin create mode 100644 src/gfx/duel/check_pokemon_screen.bin create mode 100644 src/gfx/duel/coin_toss_result_symbols.bin create mode 100644 src/gfx/duel/deck_discard_icons.bin create mode 100644 src/gfx/duel/draw_cards_icons.bin create mode 100644 src/gfx/duel/menu_card_pic_border.bin create mode 100644 src/gfx/duel/play_area_screen.bin create mode 100644 src/gfx/duel/play_area_screen_dmg.bin diff --git a/src/engine/bank02.asm b/src/engine/bank02.asm index 1b7d98b..2626ac5 100644 --- a/src/engine/bank02.asm +++ b/src/engine/bank02.asm @@ -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 diff --git a/src/engine/bills_pc.asm b/src/engine/bills_pc.asm index add1e01..6e38d54 100644 --- a/src/engine/bills_pc.asm +++ b/src/engine/bills_pc.asm @@ -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 diff --git a/src/gfx/card_graphics.asm b/src/gfx/card_graphics.asm index d78780a..d16d29f 100644 --- a/src/gfx/card_graphics.asm +++ b/src/gfx/card_graphics.asm @@ -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 diff --git a/src/gfx/cards/misc/gfx_070000.bin b/src/gfx/cards/misc/gfx_070000.bin deleted file mode 100644 index dab394c99fad47831d09a4b598bf78bf76c6bc87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2608 zcmd^AU1%It6uz^w?p|cvnUFk8VRUXuAlp#MU|&YF*%>4*D5Y6MkVv6|F%$*7xL&$)NEA*rB}f)9S* z&fGcQx#!&ZIeQNwgxIzL=rX#2V3IVYfH}GXM6C=oG)w5?`5eOUL z3pr=Z^DthjtE)Xdckg06AqO)Mf*E{22u1|L`A!D8zEnp>Zrtdse~;heKk^^=SAv{x z12_1uV&tGBzvu7s2f%>u_#)p0N+65rv|aBPFR0iz_QL;IHSEW!1@eG7DH z;}RIZ)3%r3hL$1kGT4Ma4rIK@M+6BsfF|z|BLN*bz%Rf|pq%dT(>w#_GjPtrG(YCes;MGf#SFUhgF01O(Cx)Lre%$l!|9tK$UG&J3tQ7dX-Or}!Um2?I*t=n@K)pa*>HkdK0m_&@*u@cAtwwjDUj5#JyJ z-(yEJU{*(yqkMO!VVQd^zPH!1OjCq=p2OH6D@x+`G%4MrMM*X|2u?`{_ms^|a7vnD zPkYq$97pbdRL{Mo{sZ+qH?iXOAFAh-hwAz01%32-u2jwdDuBcN1hvt>=_d;d&E_It zc6R=ue$r?(|3N?5&v3Y(%+Gf+{B=JOMS6sSe$@30-7&cqeH~qonu5?!cHSfo?3<>| zJim?&W{+rOEk2fJTbXY;SG-Ae_W`d%WQW(HF!bvoWW2aNcI=A}E?*uS%iL5p6t2|6 ztM5+#Ha#;lsqS-FeM}9*neZaCa9kbQI3FEltYI$a6LN=;JDg`S*{o^)6zigQalWSP zD#Pj%>a@D1D7WG6rpT0ezVy8DGC7aeu;Z(?UbY;!=CE3A9O@%Vlfc!if|e~5a^vH* zanK#dEnBvpS97^S4s=bk0yjftZC%gjDYdL}ISA4;N#Zz)@_AjiZK>31 zj73o#Cy9)(EGjl8T{jHaVET)F#XkJrNkVBWtF3E&8Ysa2BC`!$M;~h1x|L07lAw)% jrxH&qEfnyFDj_0XW)Wu*k2%`JIS2dYzuRAq+OPiv(DIfq diff --git a/src/gfx/duel/check_pokemon_screen.bin b/src/gfx/duel/check_pokemon_screen.bin new file mode 100644 index 0000000000000000000000000000000000000000..47696e2da62043b90f14e73a9b92dc25dcbf4793 GIT binary patch literal 576 zcmY*Tze_?<82u23M+82}!9jR$aEPX8e&8J*PEihx{s|5K0n)oI;o#QN)IZ_akf2~o zv=|KzIS397E{YFQPUpK%i_YQR@1FDhx*{S$;1fmvh@_M>^@xu5LaJBPv>ybTQ?H|G zFHKd8B#AMmZZ62Wsf$dfp+gi^3H8jSF-f95g@SsD*(^_NHh{JE(LUQAd1t%*zA>#< zqtR?$IoJp0ED(mZn)YYzcw8zim)bA#e}afkFs9v(9c*_$A={t1aXcLE_ph+RCqD4x z2rS4szFY)-Lv7^8z%P6@h^pz*LW+j=GpW+-j$}`@17UvMb!wrv5x6GJPhpDc* aOvJb93iTmRWv6w4_Io=W@jDUcYW)uyYC)3# literal 0 HcmV?d00001 diff --git a/src/gfx/duel/coin_toss_result_symbols.bin b/src/gfx/duel/coin_toss_result_symbols.bin new file mode 100644 index 0000000000000000000000000000000000000000..848cb21c4c48653668167d8770a3d1a5b42df71f GIT binary patch literal 128 zcmXBLu?g&DJ-5GB4jhXj~Fe3uAMkI1?W`w&L03!1zs&ksTM|=lS FYkwbyD}4X} literal 0 HcmV?d00001 diff --git a/src/gfx/duel/deck_discard_icons.bin b/src/gfx/duel/deck_discard_icons.bin new file mode 100644 index 0000000000000000000000000000000000000000..78736ac273d53942a70da03273da6f9f36425874 GIT binary patch literal 208 zcmezWzv07<1A7kaJFp)N|Nm$BUd&*?z|JlquVC*`59I&<$H2qz@PXtHmOo7A{{LsR zuVwxVhx>p!VQ|NRh6acF2B3-k?;|C*O`9|+GLq>S<8#LUjP(s0+8cj1HaFKYBcLra zD|16bb3=c_{sxfk4gdfD_xD#&m?3eT{R6{i28Pf7|1&YMut-Qee!$Q0pMe1=|B&%7 eqb)Npb0hOZM#hgo*VQr9Nu=302?Q~uf!F|TK4WA6 literal 0 HcmV?d00001 diff --git a/src/gfx/duel/draw_cards_icons.bin b/src/gfx/duel/draw_cards_icons.bin new file mode 100644 index 0000000000000000000000000000000000000000..a092b4427a34183b2447684935cbf7ba99535a9b GIT binary patch literal 128 zcmZQzU|?WmWMXDv=in2RRj^}VcyPet1J56(e{3~;R&pf{^#%4d{`JQ7KK91)JnYPN zuWGLRSn(m?!GZ%04Gloe4E+2Y9M%%q8M8Zfc1C(KFnstRAn>7J#*Afcm5jBFQC?bF fIyy2k!ooZ}Al1K^s+dGrSXekXPMk0>U|;|MKd&T% literal 0 HcmV?d00001 diff --git a/src/gfx/duel/menu_card_pic_border.bin b/src/gfx/duel/menu_card_pic_border.bin new file mode 100644 index 0000000000000000000000000000000000000000..d3eb353ae38db5a8b4a270b76be5a2ac4d52e441 GIT binary patch literal 128 zcmZQzU|`_q7ZA`_&`{S<(NF<$89sdA;P}JB^Mpr*2PguB>KY320{r|SIgl976B(8t j93MV__#p8AKM;cvgb(3>L>U;s`XQ!(Nw9v98BhoS?N=9B literal 0 HcmV?d00001 diff --git a/src/gfx/duel/play_area_screen.bin b/src/gfx/duel/play_area_screen.bin new file mode 100644 index 0000000000000000000000000000000000000000..ffa43d5d9fa0d1d8f37008291f3d1bef9bbb0330 GIT binary patch literal 720 zcmZ9JziZn-6vv-!QQsh98GF#6Ru|GC2`Lg}QDfJ-!8Np$Mnj>r1hN*oc<7K81>F=} z$dE0DLer_VL!r>AQ#FL*Kfr&0hfqxMpdqB92&?bu(2#yVpyR&Z`=R#^pwVEgW4?Ux zZuI@_vj+f4Vi?JAJpOp}x^h@~{%~`1Ys<1)EnNrH-|CxcThlbgCKJ~s2cS}^*0efX zY2M^LfH-y&J*zHngeyC@UWsVvhr7{s^vK_~^?I%MJDjGUl3?~B7E%J#>tT4mzrP;@ zPlG?n=}DS0w$K*~$N9YR1^IfSI6KSpUawZWvvKe4>Zaei^1b{a zzadBRIF5xF4ufEC?@1v!#!Tip=U6-LSMGG$ZeL!i{#`$T-VgsrgkissJT6aA_ba#G zKR;LZQw0_jW#d7B!^dCfJ!gv4x literal 0 HcmV?d00001 diff --git a/src/gfx/duel/play_area_screen_dmg.bin b/src/gfx/duel/play_area_screen_dmg.bin new file mode 100644 index 0000000000000000000000000000000000000000..537dc5bbe3e604022b68434e4f268d766b9db14f GIT binary patch literal 720 zcmZ9JziZn-6vv-!QQsh98GF#6Ru@vp4^m{vqSmfYgKKChwT41z31lsF@z5a+D$-AlRbo@Kfr&0hfqxMpdqB92&?buq9Of!L5IHIyLWm|0F?@3P5sr& z55phto<9VLB2A0>$T(eh1c`<{KsO?RLiCIZ*LZVj@c4QLaPl7C1KYx{$IxM9WhM}scJP8y;Bd2 z4OxgHuS&6Inv{_@q?l!QqvQLI)9pS%x(Lp1&NEuA+X#8Rp5ypFovBpFBhJt9Ct&|+ z8U!aNlgW2vFc^)dQ^)D|U3Y)~X~uXwnFK+aaxMg&m+ovmbFWpY(>`dNIJ%IsP-}sa(O^~2D=AMSTa!;<=>~zi0S4p~BC5EnNr-f*6Zt*QC Znx@X!f^A80%fe8qK|L)N7)t3l(|`W4$4>wN literal 0 HcmV?d00001 diff --git a/src/home/tiles.asm b/src/home/tiles.asm index 22c7161..0e51bff 100644 --- a/src/home/tiles.asm +++ b/src/home/tiles.asm @@ -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 diff --git a/tools/extract_card_gfx.py b/tools/extract_card_gfx.py index 3d0252e..321bb09 100644 --- a/tools/extract_card_gfx.py +++ b/tools/extract_card_gfx.py @@ -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 `