summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rwxr-xr-xengine/events/diploma.asm93
-rwxr-xr-xengine/events/print_unown_2.asm111
-rwxr-xr-xengine/games/card_flip.asm1614
-rwxr-xr-xengine/games/dummy_game.asm590
-rwxr-xr-xengine/games/unown_puzzle.asm846
-rwxr-xr-xengine/pokemon/bills_pc.asm2509
-rwxr-xr-xgfx/card_flip/card_flip.pal44
-rwxr-xr-xgfx/card_flip/card_flip.tilemapbin0 -> 132 bytes
-rwxr-xr-xgfx/card_flip/card_flip_1.2bpp.lzbin0 -> 402 bytes
-rwxr-xr-xgfx/card_flip/card_flip_1.pngbin0 -> 476 bytes
-rwxr-xr-xgfx/card_flip/card_flip_2.2bpp.lzbin0 -> 612 bytes
-rwxr-xr-xgfx/card_flip/card_flip_2.pngbin0 -> 466 bytes
-rwxr-xr-xgfx/card_flip/card_flip_3.2bpp.lzbin0 -> 27 bytes
-rwxr-xr-xgfx/card_flip/card_flip_3.pngbin0 -> 99 bytes
-rwxr-xr-xgfx/card_flip/off.2bpp1
-rwxr-xr-xgfx/card_flip/off.pngbin0 -> 79 bytes
-rwxr-xr-xgfx/card_flip/on.2bpp1
-rwxr-xr-xgfx/card_flip/on.pngbin0 -> 79 bytes
-rwxr-xr-xgfx/diploma/diploma.2bpp.lzbin0 -> 1094 bytes
-rwxr-xr-xgfx/diploma/diploma.pngbin0 -> 938 bytes
-rwxr-xr-xgfx/diploma/page1.tilemapbin0 -> 360 bytes
-rwxr-xr-xgfx/diploma/page2.tilemapbin0 -> 360 bytes
-rwxr-xr-xgfx/dummy_game/dummy_game.2bpp.lzbin0 -> 368 bytes
-rwxr-xr-xgfx/dummy_game/dummy_game.pngbin0 -> 445 bytes
-rwxr-xr-xgfx/pc/pc.2bpp.lzbin0 -> 32 bytes
-rw-r--r--gfx/pc/pc.pngbin0 -> 113 bytes
-rwxr-xr-xgfx/pc/pc_mail.2bppbin0 -> 64 bytes
-rwxr-xr-xgfx/pc/pc_mail.pngbin0 -> 114 bytes
-rwxr-xr-xgfx/unown_puzzle/aerodactyl.2bpp.lzbin0 -> 432 bytes
-rwxr-xr-xgfx/unown_puzzle/aerodactyl.pngbin0 -> 324 bytes
-rwxr-xr-xgfx/unown_puzzle/cursor.2bppbin0 -> 64 bytes
-rwxr-xr-xgfx/unown_puzzle/cursor.pngbin0 -> 75 bytes
-rwxr-xr-xgfx/unown_puzzle/hooh.2bpp.lzbin0 -> 336 bytes
-rwxr-xr-xgfx/unown_puzzle/hooh.pngbin0 -> 349 bytes
-rwxr-xr-xgfx/unown_puzzle/kabuto.2bpp.lzbin0 -> 240 bytes
-rwxr-xr-xgfx/unown_puzzle/kabuto.pngbin0 -> 276 bytes
-rwxr-xr-xgfx/unown_puzzle/omanyte.2bpp.lzbin0 -> 448 bytes
-rwxr-xr-xgfx/unown_puzzle/omanyte.pngbin0 -> 335 bytes
-rwxr-xr-xgfx/unown_puzzle/start_cancel.2bpp.lzbin0 -> 166 bytes
-rwxr-xr-xgfx/unown_puzzle/start_cancel.pngbin0 -> 216 bytes
-rwxr-xr-xgfx/unown_puzzle/tile_borders.2bppbin0 -> 128 bytes
-rwxr-xr-xgfx/unown_puzzle/tile_borders.pngbin0 -> 113 bytes
-rw-r--r--main.asm41
-rw-r--r--tools/gfx.py24
-rw-r--r--wram.asm67
46 files changed, 5915 insertions, 35 deletions
diff --git a/.gitignore b/.gitignore
index 6095246c..7f4400fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,12 @@ gfx/pokedex/question_mark.2bpp
gfx/tilesets/*.2bpp
gfx/battle_anims/*.2bpp
gfx/title/*.2bpp
+gfx/card_flip/card_flip_*.2bpp
+gfx/diploma/diploma.2bpp
+gfx/dummy_game/dummy_game.2bpp
+gfx/pc/pc.2bpp
+gfx/unown_puzzle/aerodactyl.2bpp
+gfx/unown_puzzle/hooh.2bpp
+gfx/unown_puzzle/kabuto.2bpp
+gfx/unown_puzzle/omanyte.2bpp
+gfx/unown_puzzle/start_cancel.2bpp
diff --git a/engine/events/diploma.asm b/engine/events/diploma.asm
new file mode 100755
index 00000000..22cbcdd7
--- /dev/null
+++ b/engine/events/diploma.asm
@@ -0,0 +1,93 @@
+ret_e0000:
+ ret
+
+ ret ; unused
+
+_Diploma:
+ call PlaceDiplomaOnScreen
+ call WaitPressAorB_BlinkCursor
+ ret
+
+PlaceDiplomaOnScreen:
+ call ClearBGPalettes
+ call ClearTilemap
+ call ClearSprites
+ call DisableLCD
+ ld hl, DiplomaGFX
+ ld de, vTiles2
+ call Decompress
+ ld hl, DiplomaPage1Tilemap
+ decoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ call CopyBytes
+ ld de, .Player
+ hlcoord 2, 5
+ call PlaceString
+ ld de, .EmptyString
+ hlcoord 15, 5
+ call PlaceString
+ ld de, wPlayerName
+ hlcoord 9, 5
+ call PlaceString
+ ld de, .Certification
+ hlcoord 2, 8
+ call PlaceString
+ call EnableLCD
+ call WaitBGMap
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call SetPalettes
+ call DelayFrame
+ ret
+
+.Player:
+ db "PLAYER@"
+
+.EmptyString:
+ db "@"
+
+.Certification:
+ db "This certifies"
+ next "that you have"
+ next "completed the"
+ next "new #DEX."
+ next "Congratulations!"
+ db "@"
+
+PrintDiplomaPage2:
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ ld hl, DiplomaPage2Tilemap
+ decoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ call CopyBytes
+ ld de, .GameFreak
+ hlcoord 8, 0
+ call PlaceString
+ ld de, .PlayTime
+ hlcoord 3, 15
+ call PlaceString
+ hlcoord 12, 15
+ ld de, wGameTimeHours
+ lb bc, 2, 4
+ call PrintNum
+ ld [hl], $67 ; colon
+ inc hl
+ ld de, wGameTimeMinutes
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ ret
+
+.PlayTime: db "PLAY TIME@"
+.GameFreak: db "GAME FREAK@"
+
+DiplomaGFX:
+INCBIN "gfx/diploma/diploma.2bpp.lz"
+
+DiplomaPage1Tilemap:
+INCBIN "gfx/diploma/page1.tilemap"
+
+DiplomaPage2Tilemap:
+INCBIN "gfx/diploma/page2.tilemap"
diff --git a/engine/events/print_unown_2.asm b/engine/events/print_unown_2.asm
new file mode 100755
index 00000000..aaeeec76
--- /dev/null
+++ b/engine/events/print_unown_2.asm
@@ -0,0 +1,111 @@
+RotateUnownFrontpic:
+; something to do with Unown printer
+ push de
+ xor a ; BANK(sScratch)
+ call OpenSRAM
+ ld hl, sScratch
+ ld bc, 0
+.loop
+ push bc
+ push hl
+ push bc
+ ld de, wceed
+ call .Copy
+ call .Rotate
+ ld hl, UnownPrinter_GBPrinterRectangle
+ pop bc
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld e, a
+ ld d, [hl]
+ ld hl, wcefd
+ call .Copy
+ pop hl
+ ld bc, $10
+ add hl, bc
+ pop bc
+ inc c
+ ld a, c
+ cp 7 * 7
+ jr c, .loop
+
+ ld hl, wGameboyPrinterRAM
+ ld de, sScratch
+ ld bc, 7 * 7 tiles
+ call CopyBytes
+ pop hl
+ ld de, sScratch
+ ld c, 7 * 7
+ ldh a, [hROMBank]
+ ld b, a
+ call Get2bpp
+ call CloseSRAM
+ ret
+
+.Copy:
+ ld c, $10
+.loop_copy
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .loop_copy
+ ret
+
+.Rotate:
+ ld hl, wcefd
+ ld e, %10000000
+ ld d, 8
+.loop_decompress
+ push hl
+ ld hl, wceed
+ call .CountSetBit
+ pop hl
+ ld a, b
+ ld [hli], a
+ push hl
+ ld hl, wceee
+ call .CountSetBit
+ pop hl
+ ld a, b
+ ld [hli], a
+ srl e
+ dec d
+ jr nz, .loop_decompress
+ ret
+
+.CountSetBit:
+ ld b, 0
+ ld c, 8
+.loop_count
+ ld a, [hli]
+ and e
+ jr z, .clear
+ scf
+ jr .apply
+
+.clear
+ and a
+
+.apply
+ rr b
+ inc hl
+ dec c
+ jr nz, .loop_count
+ ret
+
+gbprinterrect: MACRO
+y = 0
+rept \1
+x = \1 * (\2 - 1) + y
+rept \2
+ dw wGameboyPrinterRAM tile x
+x = x - \2
+endr
+y = y + 1
+endr
+ENDM
+
+UnownPrinter_GBPrinterRectangle:
+ gbprinterrect 7, 7
diff --git a/engine/games/card_flip.asm b/engine/games/card_flip.asm
new file mode 100755
index 00000000..82faf692
--- /dev/null
+++ b/engine/games/card_flip.asm
@@ -0,0 +1,1614 @@
+CARDFLIP_LIGHT_OFF EQU "♂" ; $ef
+CARDFLIP_LIGHT_ON EQU "♀" ; $f5
+
+CARDFLIP_DECK_SIZE EQU 4 * 6
+
+; two labels below called from inside ./dummy_game.asm
+Unknown_e0908:
+; Graphics for an unused Game Corner
+; game were meant to be here.
+ret_e0908:
+ ret
+
+_CardFlip:
+ ld hl, wOptions
+ set NO_TEXT_SCROLL, [hl]
+ call ClearBGPalettes
+ call ClearTilemap
+ call ClearSprites
+ ld de, MUSIC_NONE
+ call PlayMusic
+ call DelayFrame
+ call DisableLCD
+ call LoadStandardFont
+ call LoadFontsExtra
+
+ ld hl, CardFlipLZ01
+ ld de, vTiles2 tile $00
+ call Decompress
+ ld hl, CardFlipLZ02
+ ld de, vTiles2 tile $3e
+ call Decompress
+ ld hl, CardFlipLZ03
+ ld de, vTiles0 tile $00
+ call Decompress
+ ld hl, CardFlipOffButtonGFX
+ ld de, vTiles0 tile CARDFLIP_LIGHT_OFF
+ ld bc, 1 tiles
+ call CopyBytes
+ ld hl, CardFlipOnButtonGFX
+ ld de, vTiles0 tile CARDFLIP_LIGHT_ON
+ ld bc, 1 tiles
+ call CopyBytes
+
+ call CardFlip_InitTilemap
+ call CardFlip_InitAttrPals
+ call EnableLCD
+ call WaitBGMap2
+ ld a, %11100100
+ call DmgToCgbBGPals
+ lb de, %11100100, %11100100
+ call DmgToCgbObjPals
+ call DelayFrame
+ xor a
+ ld [wJumptableIndex], a
+ ld a, $2
+ ld [wCardFlipCursorY], a
+ ld [wCardFlipCursorX], a
+ ld de, MUSIC_GAME_CORNER
+ call PlayMusic
+.MasterLoop:
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .leavethegame
+ call .CardFlip
+ jr .MasterLoop
+.leavethegame
+ call WaitSFX
+ ld de, SFX_QUIT_SLOTS
+ call PlaySFX
+ call WaitSFX
+ call ClearBGPalettes
+ ld hl, wOptions
+ res 4, [hl]
+ ret
+
+.CardFlip:
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Jumptable:
+ dw .AskPlayWithThree
+ dw .DeductCoins
+ dw .ChooseACard
+ dw .PlaceYourBet
+ dw .CheckTheCard
+ dw .TabulateTheResult
+ dw .PlayAgain
+ dw .Quit
+
+.Increment:
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.AskPlayWithThree:
+ ld hl, .CardFlipPlayWithThreeCoinsText
+ call CardFlip_UpdateCoinBalanceDisplay
+ call YesNoBox
+ jr c, .SaidNo
+ call CardFlip_ShuffleDeck
+ call .Increment
+ ret
+
+.SaidNo:
+ ld a, 7
+ ld [wJumptableIndex], a
+ ret
+
+.CardFlipPlayWithThreeCoinsText:
+ text_far _CardFlipPlayWithThreeCoinsText
+ text_end
+
+.DeductCoins:
+ ld a, [wCoins]
+ ld h, a
+ ld a, [wCoins + 1]
+ ld l, a
+ ld a, h
+ and a
+ jr nz, .deduct ; You have at least 256 coins.
+ ld a, l
+ cp 3
+ jr nc, .deduct ; You have at least 3 coins.
+ ld hl, .CardFlipNotEnoughCoinsText
+ call CardFlip_UpdateCoinBalanceDisplay
+ ld a, 7
+ ld [wJumptableIndex], a
+ ret
+
+.deduct
+ ld de, -3
+ add hl, de
+ ld a, h
+ ld [wCoins], a
+ ld a, l
+ ld [wCoins + 1], a
+ ld de, SFX_TRANSACTION
+ call PlaySFX
+ xor a
+ ldh [hBGMapMode], a
+ call CardFlip_PrintCoinBalance
+ ld a, $1
+ ldh [hBGMapMode], a
+ call WaitSFX
+ call .Increment
+ ret
+
+.CardFlipNotEnoughCoinsText:
+ text_far _CardFlipNotEnoughCoinsText
+ text_end
+
+.ChooseACard:
+ xor a
+ ldh [hBGMapMode], a
+ hlcoord 0, 0
+ lb bc, 12, 9
+ call CardFlip_FillGreenBox
+ hlcoord 9, 0
+ ld bc, SCREEN_WIDTH
+ ld a, [wCardFlipNumCardsPlayed]
+ call AddNTimes
+ ld [hl], CARDFLIP_LIGHT_ON
+ ld a, $1
+ ldh [hBGMapMode], a
+ ld c, 20
+ call DelayFrames
+ hlcoord 2, 0
+ call PlaceCardFaceDown
+ ld a, $1
+ ldh [hBGMapMode], a
+ ld c, 20
+ call DelayFrames
+ hlcoord 2, 6
+ call PlaceCardFaceDown
+ call WaitBGMap
+ ld hl, .CardFlipChooseACardText
+ call CardFlip_UpdateCoinBalanceDisplay
+ xor a
+ ld [wCardFlipWhichCard], a
+.loop
+ call JoyTextDelay
+ ldh a, [hJoyLast]
+ and A_BUTTON
+ jr nz, .next
+ ld de, SFX_KINESIS
+ call PlaySFX
+ call PlaceOAMCardBorder
+ ld c, 4
+ call DelayFrames
+ ld hl, wCardFlipWhichCard
+ ld a, [hl]
+ xor $1
+ ld [hl], a
+ jr .loop
+
+.next
+ ld de, SFX_SLOT_MACHINE_START
+ call PlaySFX
+ ld a, $3
+.loop2
+ push af
+ call PlaceOAMCardBorder
+ ld c, 4
+ call DelayFrames
+ call ClearSprites
+ ld c, 4
+ call DelayFrames
+ pop af
+ dec a
+ jr nz, .loop2
+ ld hl, wCardFlipWhichCard
+ ld a, [hl]
+ push af
+ xor $1
+ ld [hl], a
+ call GetCoordsOfChosenCard
+ lb bc, 6, 5
+ call CardFlip_FillGreenBox
+ pop af
+ ld [wCardFlipWhichCard], a
+ call .Increment
+ ret
+
+.CardFlipChooseACardText:
+ text_far _CardFlipChooseACardText
+ text_end
+
+.PlaceYourBet:
+ ld hl, .CardFlipPlaceYourBetText
+ call CardFlip_UpdateCoinBalanceDisplay
+.betloop
+ call JoyTextDelay
+ ldh a, [hJoyLast]
+ and A_BUTTON
+ jr nz, .betdone
+ call ChooseCard_HandleJoypad
+ call CardFlip_UpdateCursorOAM
+ call DelayFrame
+ jr .betloop
+
+.betdone
+ call .Increment
+ ret
+
+.CardFlipPlaceYourBetText:
+ text_far _CardFlipPlaceYourBetText
+ text_end
+
+.CheckTheCard:
+ xor a
+ ldh [hVBlankCounter], a
+ call CardFlip_UpdateCursorOAM
+ call WaitSFX
+ ld de, SFX_CHOOSE_A_CARD
+ call PlaySFX
+ call WaitSFX
+ ld a, [wCardFlipNumCardsPlayed]
+ ld e, a
+ ld d, 0
+ ld hl, wDeck
+ add hl, de
+ add hl, de
+ ld a, [wCardFlipWhichCard]
+ ld e, a
+ add hl, de
+ ld a, [hl]
+ ld [wCardFlipFaceUpCard], a
+ ld e, a
+ ld hl, wDiscardPile
+ add hl, de
+ ld [hl], TRUE
+ call GetCoordsOfChosenCard
+ call CardFlip_DisplayCardFaceUp
+ call WaitBGMap2
+ call .Increment
+ ret
+
+.TabulateTheResult:
+ call CardFlip_CheckWinCondition
+ call WaitPressAorB_BlinkCursor
+ call .Increment
+ ret
+
+.PlayAgain:
+ call ClearSprites
+ ld hl, .CardFlipPlayAgainText
+ call CardFlip_UpdateCoinBalanceDisplay
+ call YesNoBox
+ jr nc, .Continue
+ call .Increment
+ ret
+
+.Continue:
+ ld a, [wCardFlipNumCardsPlayed]
+ inc a
+ ld [wCardFlipNumCardsPlayed], a
+ cp 12
+ jr c, .KeepTheCurrentDeck
+ call CardFlip_InitTilemap
+ ld a, $1
+ ldh [hBGMapMode], a
+ call CardFlip_ShuffleDeck
+ ld hl, .CardFlipShuffledText
+ call PrintText
+ jr .LoopAround
+
+.KeepTheCurrentDeck:
+ call CardFlip_BlankDiscardedCardSlot
+
+.LoopAround:
+ ld a, 1
+ ld [wJumptableIndex], a
+ ret
+
+.CardFlipPlayAgainText:
+ text_far _CardFlipPlayAgainText
+ text_end
+
+.CardFlipShuffledText:
+ text_far _CardFlipShuffledText
+ text_end
+
+.Quit:
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+CardFlip_ShuffleDeck:
+ ld hl, wDeck
+ ld bc, CARDFLIP_DECK_SIZE
+ xor a
+ call ByteFill
+ ld de, wDeck
+ ld c, CARDFLIP_DECK_SIZE - 1
+.loop
+ call Random
+ and $1f
+ cp CARDFLIP_DECK_SIZE
+ jr nc, .loop
+ ld l, a
+ ld h, $0
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .loop
+ ld [hl], c
+ dec c
+ jr nz, .loop
+ xor a
+ ld [wCardFlipNumCardsPlayed], a
+ ld hl, wDiscardPile
+ ld bc, CARDFLIP_DECK_SIZE
+ call ByteFill
+ ret
+
+CollapseCursorPosition:
+ ld hl, 0
+ ld bc, 6
+ ld a, [wCardFlipCursorY]
+ call AddNTimes
+ ld b, $0
+ ld a, [wCardFlipCursorX]
+ ld c, a
+ add hl, bc
+ ret
+
+GetCoordsOfChosenCard:
+ ld a, [wCardFlipWhichCard]
+ and a
+ jr nz, .BottomCard
+ hlcoord 2, 0
+ bcpixel 2, 3
+ jr .done
+
+.BottomCard:
+ hlcoord 2, 6
+ bcpixel 8, 3
+
+.done
+ ret
+
+PlaceCardFaceDown:
+ xor a
+ ldh [hBGMapMode], a
+ ld de, .FaceDownCardTilemap
+ lb bc, 6, 5
+ call CardFlip_CopyToBox
+ ret
+
+.FaceDownCardTilemap:
+ db $08, $09, $09, $09, $0a
+ db $0b, $28, $2b, $28, $0c
+ db $0b, $2c, $2d, $2e, $0c
+ db $0b, $2f, $30, $31, $0c
+ db $0b, $32, $33, $34, $0c
+ db $0d, $0e, $0e, $0e, $0f
+
+CardFlip_DisplayCardFaceUp:
+ xor a
+ ldh [hBGMapMode], a
+ push hl
+ push hl
+ ; Flip the card face up.
+ ld de, .FaceUpCardTilemap
+ lb bc, 6, 5
+ call CardFlip_CopyToBox
+
+ ; Get the level and species of the upturned card.
+ ld a, [wCardFlipFaceUpCard]
+ ld e, a
+ ld d, 0
+ ld hl, .Deck
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld e, a
+ ld d, [hl]
+
+ ; Place the level.
+ pop hl
+ ld bc, 3 + SCREEN_WIDTH
+ add hl, bc
+ ld [hl], e
+
+ ; Place the Pokepic.
+ ld bc, SCREEN_HEIGHT
+ add hl, bc
+ ld a, d
+ ld de, SCREEN_WIDTH
+ ld b, 3
+.row
+ push hl
+ ld c, 3
+.col
+ ld [hli], a
+ inc a
+ dec c
+ jr nz, .col
+ pop hl
+ add hl, de
+ dec b
+ jr nz, .row
+ pop hl
+
+ ; Pointless CGB check
+ ldh a, [hCGB]
+ and a
+ ret z
+
+ ; Set the attributes
+ ld de, wAttrmap - wTilemap
+ add hl, de
+ ld a, [wCardFlipFaceUpCard]
+ and 3
+ inc a
+ lb bc, 6, 5
+ call CardFlip_FillBox
+ ret
+
+.FaceUpCardTilemap:
+ db $18, $19, $19, $19, $1a
+ db $1b, $35, $7f, $7f, $1c
+ db $0b, $28, $28, $28, $0c
+ db $0b, $28, $28, $28, $0c
+ db $0b, $28, $28, $28, $0c
+ db $1d, $1e, $1e, $1e, $1f
+
+.Deck:
+ ; level, pic anchor (3x3)
+ db "1", $4e, "1", $57, "1", $69, "1", $60
+ db "2", $4e, "2", $57, "2", $69, "2", $60
+ db "3", $4e, "3", $57, "3", $69, "3", $60
+ db "4", $4e, "4", $57, "4", $69, "4", $60
+ db "5", $4e, "5", $57, "5", $69, "5", $60
+ db "6", $4e, "6", $57, "6", $69, "6", $60
+
+CardFlip_UpdateCoinBalanceDisplay:
+ push hl
+ hlcoord 0, 12
+ ld b, 4
+ ld c, SCREEN_WIDTH - 2
+ call Textbox
+ pop hl
+ call PrintTextboxText
+ call CardFlip_PrintCoinBalance
+ ret
+
+CardFlip_PrintCoinBalance:
+ hlcoord 9, 15
+ lb bc, 1, 9
+ call Textbox
+ hlcoord 10, 16
+ ld de, .CoinStr
+ call PlaceString
+ hlcoord 15, 16
+ ld de, wCoins
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 4
+ call PrintNum
+ ret
+
+.CoinStr:
+ db "COIN@"
+
+CardFlip_InitTilemap:
+ xor a
+ ldh [hBGMapMode], a
+ hlcoord 0, 0
+ ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+ ld a, $29
+ call ByteFill
+ hlcoord 9, 0
+ ld de, CardFlipTilemap
+ lb bc, 12, 11
+ call CardFlip_CopyToBox
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call Textbox
+ ret
+
+CardFlip_FillGreenBox:
+ ld a, $29
+
+CardFlip_FillBox:
+.row
+ push bc
+ push hl
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+
+CardFlip_CopyToBox:
+.row
+ push bc
+ push hl
+.col
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+
+CardFlip_CopyOAM:
+ ld de, wVirtualOAMSprite00
+ ld a, [hli]
+.loop
+ push af
+ ld a, [hli]
+ add b
+ ld [de], a ; y
+ inc de
+ ld a, [hli]
+ add c
+ ld [de], a ; x
+ inc de
+ ld a, [hli]
+ ld [de], a ; tile id
+ inc de
+ ld a, [hli]
+ ld [de], a ; attributes
+ inc de
+ pop af
+ dec a
+ jr nz, .loop
+ ret
+
+CardFlip_ShiftDigitsUpOnePixel:
+; The top rows of digits 1-9 become the bottom rows of 0-8,
+; so this routine relies on the top rows being blank.
+ ld de, vTiles0 tile "0"
+ ld hl, vTiles0 tile "0" + 2
+ ld bc, 10 tiles - 2
+ call CopyBytes
+ ld hl, vTiles0 tile "9" + 1 tiles - 2
+ xor a
+ ld [hli], a
+ ld [hl], a
+ ret
+
+CardFlip_BlankDiscardedCardSlot:
+ xor a
+ ldh [hBGMapMode], a
+ ld a, [wCardFlipFaceUpCard]
+ ld e, a
+ ld d, 0
+
+ and 3 ; get mon
+ ld c, a
+ ld b, 0
+
+ ld a, e
+ and $1c ; get level
+ srl a
+ add LOW(.Jumptable)
+ ld l, a
+ ld a, 0
+ adc HIGH(.Jumptable)
+ ld h, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Jumptable:
+ dw .Level1
+ dw .Level2
+ dw .Level3
+ dw .Level4
+ dw .Level5
+ dw .Level6
+
+.Level1:
+ ld hl, wDiscardPile + 4
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .discarded2
+ hlcoord 13, 3
+ add hl, bc
+ add hl, bc
+ ld [hl], $36
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $37
+ ret
+
+.discarded2
+ hlcoord 13, 3
+ add hl, bc
+ add hl, bc
+ ld [hl], $36
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3d
+ ret
+
+.Level2:
+ ld hl, wDiscardPile - 4
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .discarded1
+ hlcoord 13, 4
+ add hl, bc
+ add hl, bc
+ ld [hl], $3b
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3a
+ ret
+
+.discarded1
+ hlcoord 13, 4
+ add hl, bc
+ add hl, bc
+ ld [hl], $3d
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3a
+ ret
+
+.Level3:
+ ld hl, wDiscardPile + 4
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .discarded4
+ hlcoord 13, 6
+ add hl, bc
+ add hl, bc
+ ld [hl], $36
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $38
+ ret
+
+.discarded4
+ hlcoord 13, 6
+ add hl, bc
+ add hl, bc
+ ld [hl], $36
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3d
+ ret
+
+.Level4:
+ ld hl, wDiscardPile - 4
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .discarded3
+ hlcoord 13, 7
+ add hl, bc
+ add hl, bc
+ ld [hl], $3c
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3a
+ ret
+
+.discarded3
+ hlcoord 13, 7
+ add hl, bc
+ add hl, bc
+ ld [hl], $3d
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3a
+ ret
+
+.Level5:
+ ld hl, wDiscardPile + 4
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .discarded6
+ hlcoord 13, 9
+ add hl, bc
+ add hl, bc
+ ld [hl], $36
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $39
+ ret
+
+.discarded6
+ hlcoord 13, 9
+ add hl, bc
+ add hl, bc
+ ld [hl], $36
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3d
+ ret
+
+.Level6:
+ ld hl, wDiscardPile - 4
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .discarded5
+ hlcoord 13, 10
+ add hl, bc
+ add hl, bc
+ ld [hl], $3c
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3a
+ ret
+
+.discarded5
+ hlcoord 13, 10
+ add hl, bc
+ add hl, bc
+ ld [hl], $3d
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hl], $3a
+ ret
+
+CardFlip_CheckWinCondition:
+ call CollapseCursorPosition
+ add hl, hl
+ ld de, .Jumptable
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Jumptable:
+ dw .Impossible
+ dw .Impossible
+ dw .PikaJiggly
+ dw .PikaJiggly
+ dw .PoliOddish
+ dw .PoliOddish
+
+ dw .Impossible
+ dw .Impossible
+ dw .Pikachu
+ dw .Jigglypuff
+ dw .Poliwag
+ dw .Oddish
+
+ dw .OneTwo
+ dw .One
+ dw .PikaOne
+ dw .JigglyOne
+ dw .PoliOne
+ dw .OddOne
+
+ dw .OneTwo
+ dw .Two
+ dw .PikaTwo
+ dw .JigglyTwo
+ dw .PoliTwo
+ dw .OddTwo
+
+ dw .ThreeFour
+ dw .Three
+ dw .PikaThree
+ dw .JigglyThree
+ dw .PoliThree
+ dw .OddThree
+
+ dw .ThreeFour
+ dw .Four
+ dw .PikaFour
+ dw .JigglyFour
+ dw .PoliFour
+ dw .OddFour
+
+ dw .FiveSix
+ dw .Five
+ dw .PikaFive
+ dw .JigglyFive
+ dw .PoliFive
+ dw .OddFive
+
+ dw .FiveSix
+ dw .Six
+ dw .PikaSix
+ dw .JigglySix
+ dw .PoliSix
+ dw .OddSix
+
+.Impossible:
+ jp .Lose
+
+.PikaJiggly:
+ ld a, [wCardFlipFaceUpCard]
+ and $2
+ jp nz, .Lose
+ jr .WinSix
+
+.PoliOddish:
+ ld a, [wCardFlipFaceUpCard]
+ and $2
+ jr nz, .WinSix
+ jp .Lose
+
+.WinSix:
+ ld c, $6
+ ld de, SFX_2ND_PLACE
+ jp .Payout
+
+.OneTwo:
+ ld a, [wCardFlipFaceUpCard]
+ and $18
+ jr z, .WinNine
+ jp .Lose
+
+.ThreeFour:
+ ld a, [wCardFlipFaceUpCard]
+ and $18
+ cp $8
+ jr z, .WinNine
+ jp .Lose
+
+.FiveSix:
+ ld a, [wCardFlipFaceUpCard]
+ and $18
+ cp $10
+ jr z, .WinNine
+ jp .Lose
+
+.WinNine:
+ ld c, $9
+ ld de, SFX_2ND_PLACE
+ jp .Payout
+
+.Pikachu:
+ ld a, [wCardFlipFaceUpCard]
+ and $3
+ jr z, .WinTwelve
+ jp .Lose
+
+.Jigglypuff:
+ ld a, [wCardFlipFaceUpCard]
+ and $3
+ cp $1
+ jr z, .WinTwelve
+ jp .Lose
+
+.Poliwag:
+ ld a, [wCardFlipFaceUpCard]
+ and $3
+ cp $2
+ jr z, .WinTwelve
+ jp .Lose
+
+.Oddish:
+ ld a, [wCardFlipFaceUpCard]
+ and $3
+ cp $3
+ jr z, .WinTwelve
+ jp .Lose
+
+.WinTwelve:
+ ld c, $c
+ ld de, SFX_2ND_PLACE
+ jp .Payout
+
+.One:
+ ld a, [wCardFlipFaceUpCard]
+ and $1c
+ jr z, .WinEighteen
+ jp .Lose
+
+.Two:
+ ld a, [wCardFlipFaceUpCard]
+ and $1c
+ cp $4
+ jr z, .WinEighteen
+ jp .Lose
+
+.Three:
+ ld a, [wCardFlipFaceUpCard]
+ and $1c
+ cp $8
+ jr z, .WinEighteen
+ jp .Lose
+
+.Four:
+ ld a, [wCardFlipFaceUpCard]
+ and $1c
+ cp $c
+ jr z, .WinEighteen
+ jp .Lose
+
+.Five:
+ ld a, [wCardFlipFaceUpCard]
+ and $1c
+ cp $10
+ jr z, .WinEighteen
+ jp .Lose
+
+.Six:
+ ld a, [wCardFlipFaceUpCard]
+ and $1c
+ cp $14
+ jr z, .WinEighteen
+ jp .Lose
+
+.WinEighteen:
+ ld c, $12
+ ld de, SFX_2ND_PLACE
+ jp .Payout
+
+.PikaOne:
+ ld e, $0
+ jr .CheckWin72
+
+.JigglyOne:
+ ld e, $1
+ jr .CheckWin72
+
+.PoliOne:
+ ld e, $2
+ jr .CheckWin72
+
+.OddOne:
+ ld e, $3
+ jr .CheckWin72
+
+.PikaTwo:
+ ld e, $4
+ jr .CheckWin72
+
+.JigglyTwo:
+ ld e, $5
+ jr .CheckWin72
+
+.PoliTwo:
+ ld e, $6
+ jr .CheckWin72
+
+.OddTwo:
+ ld e, $7
+ jr .CheckWin72
+
+.PikaThree:
+ ld e, $8
+ jr .CheckWin72
+
+.JigglyThree:
+ ld e, $9
+ jr .CheckWin72
+
+.PoliThree:
+ ld e, $a
+ jr .CheckWin72
+
+.OddThree:
+ ld e, $b
+ jr .CheckWin72
+
+.PikaFour:
+ ld e, $c
+ jr .CheckWin72
+
+.JigglyFour:
+ ld e, $d
+ jr .CheckWin72
+
+.PoliFour:
+ ld e, $e
+ jr .CheckWin72
+
+.OddFour:
+ ld e, $f
+ jr .CheckWin72
+
+.PikaFive:
+ ld e, $10
+ jr .CheckWin72
+
+.JigglyFive:
+ ld e, $11
+ jr .CheckWin72
+
+.PoliFive:
+ ld e, $12
+ jr .CheckWin72
+
+.OddFive:
+ ld e, $13
+ jr .CheckWin72
+
+.PikaSix:
+ ld e, $14
+ jr .CheckWin72
+
+.JigglySix:
+ ld e, $15
+ jr .CheckWin72
+
+.PoliSix:
+ ld e, $16
+ jr .CheckWin72
+
+.OddSix:
+ ld e, $17
+
+.CheckWin72:
+ ld a, [wCardFlipFaceUpCard]
+ cp e
+ jr nz, .Lose
+ ld c, 72
+ ld de, SFX_2ND_PLACE
+ jr .Payout
+
+.Lose:
+ ld de, SFX_WRONG
+ call PlaySFX
+ ld hl, .CardFlipDarnText
+ call CardFlip_UpdateCoinBalanceDisplay
+ call WaitSFX
+ ret
+
+.Payout:
+ push bc
+ push de
+ ld hl, .CardFlipYeahText
+ call CardFlip_UpdateCoinBalanceDisplay
+ pop de
+ call PlaySFX
+ call WaitSFX
+ pop bc
+.loop
+ push bc
+ call .IsCoinCaseFull
+ jr c, .full
+ call .AddCoinPlaySFX
+
+.full
+ call CardFlip_PrintCoinBalance
+ ld c, 2
+ call DelayFrames
+ pop bc
+ dec c
+ jr nz, .loop
+ ret
+
+.CardFlipYeahText:
+ text_far _CardFlipYeahText
+ text_end
+
+.CardFlipDarnText:
+ text_far _CardFlipDarnText
+ text_end
+
+.AddCoinPlaySFX:
+ ld a, [wCoins]
+ ld h, a
+ ld a, [wCoins + 1]
+ ld l, a
+ inc hl
+ ld a, h
+ ld [wCoins], a
+ ld a, l
+ ld [wCoins + 1], a
+ ld de, SFX_PAY_DAY
+ call PlaySFX
+ ret
+
+.IsCoinCaseFull:
+ ld a, [wCoins]
+ cp HIGH(MAX_COINS)
+ jr c, .less
+ jr z, .check_low
+ jr .more
+
+.check_low
+ ld a, [wCoins + 1]
+ cp LOW(MAX_COINS)
+ jr c, .less
+
+.more
+ scf
+ ret
+
+.less
+ and a
+ ret
+
+PlaceOAMCardBorder:
+ call GetCoordsOfChosenCard
+ ld hl, .SpriteData
+ call CardFlip_CopyOAM
+ ret
+
+.SpriteData:
+ db 18
+ dbsprite 0, 0, 0, 0, $04, 0
+ dbsprite 1, 0, 0, 0, $06, 0
+ dbsprite 2, 0, 0, 0, $06, 0
+ dbsprite 3, 0, 0, 0, $06, 0
+ dbsprite 4, 0, 0, 0, $04, 0 | X_FLIP
+
+ dbsprite 0, 1, 0, 0, $05, 0
+ dbsprite 4, 1, 0, 0, $05, 0 | X_FLIP
+
+ dbsprite 0, 2, 0, 0, $05, 0
+ dbsprite 4, 2, 0, 0, $05, 0 | X_FLIP
+
+ dbsprite 0, 3, 0, 0, $05, 0
+ dbsprite 4, 3, 0, 0, $05, 0 | X_FLIP
+
+ dbsprite 0, 4, 0, 0, $05, $00
+ dbsprite 4, 4, 0, 0, $05, 0 | X_FLIP
+
+ dbsprite 0, 5, 0, 0, $04, 0 | Y_FLIP
+ dbsprite 1, 5, 0, 0, $06, 0 | Y_FLIP
+ dbsprite 2, 5, 0, 0, $06, 0 | Y_FLIP
+ dbsprite 3, 5, 0, 0, $06, 0 | Y_FLIP
+ dbsprite 4, 5, 0, 0, $04, 0 | X_FLIP | Y_FLIP
+
+ChooseCard_HandleJoypad:
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_LEFT
+ jp nz, .d_left
+ ld a, [hl]
+ and D_RIGHT
+ jp nz, .d_right
+ ld a, [hl]
+ and D_UP
+ jp nz, .d_up
+ ld a, [hl]
+ and D_DOWN
+ jp nz, .d_down
+ ret
+
+.d_left
+ ld hl, wCardFlipCursorX
+ ld a, [wCardFlipCursorY]
+ and a
+ jr z, .mon_pair_left
+ cp $1
+ jr z, .mon_group_left
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ jp .play_sound
+
+.mon_group_left
+ ld a, [hl]
+ cp $3
+ jr c, .left_to_number_gp
+ dec [hl]
+ jp .play_sound
+
+.mon_pair_left
+ ld a, [hl]
+ and $e
+ ld [hl], a
+ cp $3
+ jr c, .left_to_number_gp
+ dec [hl]
+ dec [hl]
+ jp .play_sound
+
+.left_to_number_gp
+ ld a, $2
+ ld [wCardFlipCursorY], a
+ ld a, $1
+ ld [wCardFlipCursorX], a
+ jp .play_sound
+
+.d_right
+ ld hl, wCardFlipCursorX
+ ld a, [wCardFlipCursorY]
+ and a
+ jr z, .mon_pair_right
+ ld a, [hl]
+ cp $5
+ ret nc
+ inc [hl]
+ jr .play_sound
+
+.mon_pair_right
+ ld a, [hl]
+ and $e
+ ld [hl], a
+ cp $4
+ ret nc
+ inc [hl]
+ inc [hl]
+ jr .play_sound
+
+.d_up
+ ld hl, wCardFlipCursorY
+ ld a, [wCardFlipCursorX]
+ and a
+ jr z, .num_pair_up
+ cp $1
+ jr z, .num_gp_up
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ jr .play_sound
+
+.num_gp_up
+ ld a, [hl]
+ cp $3
+ jr c, .up_to_mon_group
+ dec [hl]
+ jr .play_sound
+
+.num_pair_up
+ ld a, [hl]
+ and $e
+ ld [hl], a
+ cp $3
+ jr c, .up_to_mon_group
+ dec [hl]
+ dec [hl]
+ jr .play_sound
+
+.up_to_mon_group
+ ld a, $1
+ ld [wCardFlipCursorY], a
+ ld a, $2
+ ld [wCardFlipCursorX], a
+ jr .play_sound
+
+.d_down
+ ld hl, wCardFlipCursorY
+ ld a, [wCardFlipCursorX]
+ and a
+ jr z, .num_pair_down
+ ld hl, wCardFlipCursorY
+ ld a, [hl]
+ cp $7
+ ret nc
+ inc [hl]
+ jr .play_sound
+
+.num_pair_down
+ ld a, [hl]
+ and $e
+ ld [hl], a
+ cp $6
+ ret nc
+ inc [hl]
+ inc [hl]
+
+.play_sound
+ ld de, SFX_POKEBALLS_PLACED_ON_TABLE
+ call PlaySFX
+ ret
+
+CardFlip_UpdateCursorOAM:
+ call ClearSprites
+ ldh a, [hCGB]
+ and a
+ jr nz, .skip
+ ldh a, [hVBlankCounter]
+ and $4
+ ret nz
+
+.skip
+ call CollapseCursorPosition
+ add hl, hl
+ add hl, hl
+ ld de, .OAMData
+ add hl, de
+ ld a, [hli]
+ ld c, a
+ ld a, [hli]
+ ld b, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call CardFlip_CopyOAM
+ ret
+
+.OAMData:
+cardflip_cursor: MACRO
+if _NARG >= 5
+ dbpixel \1, \2, \3, \4
+ dw \5
+else
+ dbpixel \1, \2
+ dw \3
+endc
+ENDM
+
+ cardflip_cursor 11, 2, .Impossible
+ cardflip_cursor 12, 2, .Impossible
+ cardflip_cursor 13, 2, .PokeGroupPair
+ cardflip_cursor 13, 2, .PokeGroupPair
+ cardflip_cursor 17, 2, .PokeGroupPair
+ cardflip_cursor 17, 2, .PokeGroupPair
+
+ cardflip_cursor 11, 3, .Impossible
+ cardflip_cursor 12, 3, .Impossible
+ cardflip_cursor 13, 3, .PokeGroup
+ cardflip_cursor 15, 3, .PokeGroup
+ cardflip_cursor 17, 3, .PokeGroup
+ cardflip_cursor 19, 3, .PokeGroup
+
+ cardflip_cursor 11, 5, .NumGroupPair
+ cardflip_cursor 12, 5, .NumGroup
+ cardflip_cursor 13, 5, .SingleTile
+ cardflip_cursor 15, 5, .SingleTile
+ cardflip_cursor 17, 5, .SingleTile
+ cardflip_cursor 19, 5, .SingleTile
+
+ cardflip_cursor 11, 5, .NumGroupPair
+ cardflip_cursor 12, 6, 0, 4, .NumGroup
+ cardflip_cursor 13, 6, 0, 4, .SingleTile
+ cardflip_cursor 15, 6, 0, 4, .SingleTile
+ cardflip_cursor 17, 6, 0, 4, .SingleTile
+ cardflip_cursor 19, 6, 0, 4, .SingleTile
+
+ cardflip_cursor 11, 8, .NumGroupPair
+ cardflip_cursor 12, 8, .NumGroup
+ cardflip_cursor 13, 8, .SingleTile
+ cardflip_cursor 15, 8, .SingleTile
+ cardflip_cursor 17, 8, .SingleTile
+ cardflip_cursor 19, 8, .SingleTile
+
+ cardflip_cursor 11, 8, .NumGroupPair
+ cardflip_cursor 12, 9, 0, 4, .NumGroup
+ cardflip_cursor 13, 9, 0, 4, .SingleTile
+ cardflip_cursor 15, 9, 0, 4, .SingleTile
+ cardflip_cursor 17, 9, 0, 4, .SingleTile
+ cardflip_cursor 19, 9, 0, 4, .SingleTile
+
+ cardflip_cursor 11, 11, .NumGroupPair
+ cardflip_cursor 12, 11, .NumGroup
+ cardflip_cursor 13, 11, .SingleTile
+ cardflip_cursor 15, 11, .SingleTile
+ cardflip_cursor 17, 11, .SingleTile
+ cardflip_cursor 19, 11, .SingleTile
+
+ cardflip_cursor 11, 11, .NumGroupPair
+ cardflip_cursor 12, 12, 0, 4, .NumGroup
+ cardflip_cursor 13, 12, 0, 4, .SingleTile
+ cardflip_cursor 15, 12, 0, 4, .SingleTile
+ cardflip_cursor 17, 12, 0, 4, .SingleTile
+ cardflip_cursor 19, 12, 0, 4, .SingleTile
+
+.SingleTile:
+ db 6
+ dbsprite -1, 0, 7, 0, $00, 0 | PRIORITY
+ dbsprite 0, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 1, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 0, 7, 5, $00, 0 | Y_FLIP | PRIORITY
+ dbsprite 0, 0, 0, 5, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 1, 0, 0, 5, $03, 0 | PRIORITY
+
+.PokeGroup:
+ db 26
+ dbsprite -1, 0, 7, 0, $00, 0 | PRIORITY
+ dbsprite 0, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 1, 0, 0, 0, $00, 0 | X_FLIP | PRIORITY
+ dbsprite -1, 1, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 1, 0, 0, $01, 0 | X_FLIP | PRIORITY
+ dbsprite -1, 2, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 2, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 3, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 3, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 4, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 4, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 5, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 5, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 6, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 6, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 7, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 7, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 8, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 8, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 9, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 9, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 10, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 10, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 10, 7, 1, $00, 0 | Y_FLIP | PRIORITY
+ dbsprite 0, 10, 0, 1, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 1, 10, 0, 1, $03, 0 | PRIORITY
+
+.NumGroup:
+ db 20
+ dbsprite -1, 0, 7, 0, $00, 0 | PRIORITY
+ dbsprite 0, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 1, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 2, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 4, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite 5, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 6, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite 7, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 8, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 0, 7, 5, $00, 0 | Y_FLIP | PRIORITY
+ dbsprite 0, 0, 0, 5, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 1, 0, 0, 5, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 2, 0, 0, 5, $03, 0 | PRIORITY
+ dbsprite 3, 0, 0, 5, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 4, 0, 0, 5, $03, 0 | PRIORITY
+ dbsprite 5, 0, 0, 5, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 6, 0, 0, 5, $03, 0 | PRIORITY
+ dbsprite 7, 0, 0, 5, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 8, 0, 0, 5, $03, 0 | PRIORITY
+
+.NumGroupPair:
+ db 30
+ dbsprite 0, 0, 0, 0, $00, 0 | PRIORITY
+ dbsprite 1, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 2, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 3, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite 4, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 5, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite 6, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 7, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite 8, 0, 0, 0, $02, 0 | PRIORITY
+ dbsprite 9, 0, 0, 0, $03, 0 | PRIORITY
+ dbsprite 0, 1, 0, 0, $01, 0 | PRIORITY
+ dbsprite 3, 1, 0, 0, $03, 0 | PRIORITY
+ dbsprite 5, 1, 0, 0, $03, 0 | PRIORITY
+ dbsprite 7, 1, 0, 0, $03, 0 | PRIORITY
+ dbsprite 9, 1, 0, 0, $03, 0 | PRIORITY
+ dbsprite 0, 2, 0, 0, $01, 0 | PRIORITY
+ dbsprite 3, 2, 0, 0, $03, 0 | PRIORITY
+ dbsprite 5, 2, 0, 0, $03, 0 | PRIORITY
+ dbsprite 7, 2, 0, 0, $03, 0 | PRIORITY
+ dbsprite 9, 2, 0, 0, $03, 0 | PRIORITY
+ dbsprite 0, 2, 0, 1, $00, 0 | Y_FLIP | PRIORITY
+ dbsprite 1, 2, 0, 1, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 2, 2, 0, 1, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 3, 2, 0, 1, $03, 0 | PRIORITY
+ dbsprite 4, 2, 0, 1, $03, 0 | PRIORITY
+ dbsprite 5, 2, 0, 1, $03, 0 | PRIORITY
+ dbsprite 6, 2, 0, 1, $03, 0 | PRIORITY
+ dbsprite 7, 2, 0, 1, $03, 0 | PRIORITY
+ dbsprite 8, 2, 0, 1, $03, 0 | PRIORITY
+ dbsprite 9, 2, 0, 1, $03, 0 | PRIORITY
+
+.PokeGroupPair:
+ db 38
+ dbsprite -1, 0, 7, 0, $00, 0 | PRIORITY
+ dbsprite 3, 0, 0, 0, $00, 0 | X_FLIP | PRIORITY
+ dbsprite -1, 1, 7, 0, $01, 0 | PRIORITY
+ dbsprite 3, 1, 0, 0, $01, 0 | X_FLIP | PRIORITY
+ dbsprite -1, 2, 7, 0, $01, 0 | PRIORITY
+ dbsprite 3, 2, 0, 0, $01, 0 | X_FLIP | PRIORITY
+ dbsprite -1, 3, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 3, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 3, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 4, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 4, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 4, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 5, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 5, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 5, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 6, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 6, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 6, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 7, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 7, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 7, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 8, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 8, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 8, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 9, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 9, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 9, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 10, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 10, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 10, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 11, 7, 0, $01, 0 | PRIORITY
+ dbsprite 1, 11, 0, 0, $03, 0 | PRIORITY
+ dbsprite 3, 11, 0, 0, $03, 0 | PRIORITY
+ dbsprite -1, 11, 7, 1, $00, 0 | Y_FLIP | PRIORITY
+ dbsprite 0, 11, 0, 1, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 1, 11, 0, 1, $03, 0 | Y_FLIP | PRIORITY
+ dbsprite 2, 11, 0, 1, $02, 0 | Y_FLIP | PRIORITY
+ dbsprite 3, 11, 0, 1, $03, 0 | X_FLIP | Y_FLIP | PRIORITY
+
+.Impossible:
+ db 4
+ dbsprite 0, 0, 0, 0, $00, 0 | PRIORITY
+ dbsprite 1, 0, 0, 0, $00, 0 | X_FLIP | PRIORITY
+ dbsprite 0, 1, 0, 0, $00, 0 | Y_FLIP | PRIORITY
+ dbsprite 1, 1, 0, 0, $00, 0 | X_FLIP | Y_FLIP | PRIORITY
+
+CardFlip_InitAttrPals:
+ ldh a, [hCGB]
+ and a
+ ret z
+
+ hlcoord 0, 0, wAttrmap
+ ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+ xor a
+ call ByteFill
+
+ hlcoord 12, 1, wAttrmap
+ lb bc, 2, 2
+ ld a, $1
+ call CardFlip_FillBox
+
+ hlcoord 14, 1, wAttrmap
+ lb bc, 2, 2
+ ld a, $2
+ call CardFlip_FillBox
+
+ hlcoord 16, 1, wAttrmap
+ lb bc, 2, 2
+ ld a, $3
+ call CardFlip_FillBox
+
+ hlcoord 18, 1, wAttrmap
+ lb bc, 2, 2
+ ld a, $4
+ call CardFlip_FillBox
+
+ hlcoord 9, 0, wAttrmap
+ lb bc, 12, 1
+ ld a, $1
+ call CardFlip_FillBox
+
+ ld hl, .palettes
+ ld de, wBGPals1
+ ld bc, 9 palettes
+ call CopyBytes
+ ret
+
+.palettes
+INCLUDE "gfx/card_flip/card_flip.pal"
+
+CardFlipLZ03:
+INCBIN "gfx/card_flip/card_flip_3.2bpp.lz"
+
+CardFlipOffButtonGFX:
+INCBIN "gfx/card_flip/off.2bpp"
+
+CardFlipOnButtonGFX:
+INCBIN "gfx/card_flip/on.2bpp"
+
+CardFlipLZ01:
+INCBIN "gfx/card_flip/card_flip_1.2bpp.lz"
+
+CardFlipLZ02:
+INCBIN "gfx/card_flip/card_flip_2.2bpp.lz"
+
+CardFlipTilemap:
+INCBIN "gfx/card_flip/card_flip.tilemap"
diff --git a/engine/games/dummy_game.asm b/engine/games/dummy_game.asm
new file mode 100755
index 00000000..e12c791b
--- /dev/null
+++ b/engine/games/dummy_game.asm
@@ -0,0 +1,590 @@
+_DummyGame:
+ call .LoadGFXAndPals
+ call DelayFrame
+.loop
+ call .JumptableLoop
+ jr nc, .loop
+ ret
+
+.LoadGFXAndPals:
+ call DisableLCD
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ callfar ClearSpriteAnims
+ ld hl, DummyGameLZ
+ ld de, vTiles2 tile $00
+ call Decompress
+ ld hl, Unknown_e0908
+ ld de, vTiles0 tile $00
+ ld bc, 4 tiles
+ ld a, BANK(Unknown_e0908)
+ call FarCopyBytes
+ ld a, 8
+ ld hl, wc508
+ ld [hli], a
+ ld [hl], 0
+ hlcoord 0, 0
+ ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+ xor a
+ call ByteFill
+ xor a
+ ldh [hSCY], a
+ ldh [hSCX], a
+ ldh [rWY], a
+ ld [wJumptableIndex], a
+ ld a, $1
+ ldh [hBGMapMode], a
+ ld a, LCDC_DEFAULT
+ ldh [rLCDC], a
+ ld a, $e4
+ call DmgToCgbBGPals
+ ld a, $e0
+ call DmgToCgbObjPal0
+ ret
+
+.JumptableLoop:
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .quit
+ call .ExecuteJumptable
+ callfar PlaySpriteAnimations
+ call DelayFrame
+ and a
+ ret
+
+.quit
+ scf
+ ret
+
+.ExecuteJumptable:
+ jumptable .Jumptable, wJumptableIndex
+
+.Jumptable:
+ dw .RestartGame
+ dw .ResetBoard
+ dw .InitBoardTilemapAndCursorObject
+ dw .CheckTriesRemaining
+ dw .PickCard1
+ dw .PickCard2
+ dw .DelayPickAgain
+ dw .RevealAll
+ dw .AskPlayAgain
+
+.RestartGame:
+ call DummyGame_InitStrings
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.ResetBoard:
+ call ret_e0908
+ jr nc, .proceed
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.proceed
+ call DummyGame_InitBoard
+ ld hl, wJumptableIndex
+ inc [hl]
+ xor a
+ ld [wDummyGameCounter], a
+ ld hl, wDummyGameLastMatches
+rept 4
+ ld [hli], a
+endr
+ ld [hl], a
+ ld [wDummyGameNumCardsMatched], a
+.InitBoardTilemapAndCursorObject:
+ ld hl, wDummyGameCounter
+ ld a, [hl]
+ cp 45
+ jr nc, .spawn_object
+ inc [hl]
+ call DummyGame_Card2Coord
+ xor a
+ ld [wDummyGameLastCardPicked], a
+ call DummyGame_PlaceCard
+ ret
+
+.spawn_object
+ depixel 6, 3, 4, 4
+ ld a, SPRITE_ANIM_INDEX_DUMMY_GAME
+ call InitSpriteAnimStruct
+ ld a, 5
+ ld [wDummyGameNumberTriesRemaining], a
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.CheckTriesRemaining:
+ ld a, [wDummyGameNumberTriesRemaining]
+ hlcoord 17, 0
+ add "0"
+ ld [hl], a
+ ld hl, wDummyGameNumberTriesRemaining
+ ld a, [hl]
+ and a
+ jr nz, .next_try
+ ld a, $7
+ ld [wJumptableIndex], a
+ ret
+
+.next_try
+ dec [hl]
+ xor a
+ ld [wce64], a
+ ld hl, wJumptableIndex
+ inc [hl]
+.PickCard1:
+ ld a, [wce64]
+ and a
+ ret z
+ dec a
+ ld e, a
+ ld d, 0
+ ld hl, wDummyGameCards
+ add hl, de
+ ld a, [hl]
+ cp -1
+ ret z
+ ld [wDummyGameLastCardPicked], a
+ ld [wDummyGameCard1], a
+ ld a, e
+ ld [wDummyGameCard1Location], a
+ call DummyGame_Card2Coord
+ call DummyGame_PlaceCard
+ xor a
+ ld [wce64], a
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.PickCard2:
+ ld a, [wce64]
+ and a
+ ret z
+ dec a
+ ld hl, wDummyGameCard1Location
+ cp [hl]
+ ret z
+ ld e, a
+ ld d, 0
+ ld hl, wDummyGameCards
+ add hl, de
+ ld a, [hl]
+ cp -1
+ ret z
+ ld [wDummyGameLastCardPicked], a
+ ld [wDummyGameCard2], a
+ ld a, e
+ ld [wDummyGameCard2Location], a
+ call DummyGame_Card2Coord
+ call DummyGame_PlaceCard
+ ld a, 64
+ ld [wDummyGameCounter], a
+ ld hl, wJumptableIndex
+ inc [hl]
+.DelayPickAgain:
+ ld hl, wDummyGameCounter
+ ld a, [hl]
+ and a
+ jr z, .PickAgain
+ dec [hl]
+ ret
+
+.PickAgain:
+ call DummyGame_CheckMatch
+ ld a, $3
+ ld [wJumptableIndex], a
+ ret
+
+.RevealAll:
+ ldh a, [hJoypadPressed]
+ and A_BUTTON
+ ret z
+ xor a
+ ld [wDummyGameCounter], a
+.RevelationLoop:
+ ld hl, wDummyGameCounter
+ ld a, [hl]
+ cp 45
+ jr nc, .finish_round
+ inc [hl]
+ push af
+ call DummyGame_Card2Coord
+ pop af
+ push hl
+ ld e, a
+ ld d, $0
+ ld hl, wDummyGameCards
+ add hl, de
+ ld a, [hl]
+ pop hl
+ cp -1
+ jr z, .RevelationLoop
+ ld [wDummyGameLastCardPicked], a
+ call DummyGame_PlaceCard
+ jr .RevelationLoop
+
+.finish_round
+ call WaitPressAorB_BlinkCursor
+ ld hl, wJumptableIndex
+ inc [hl]
+.AskPlayAgain:
+ call ret_e0908
+ jr nc, .restart
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.restart
+ xor a
+ ld [wJumptableIndex], a
+ ret
+
+DummyGame_CheckMatch:
+ ld hl, wDummyGameCard1
+ ld a, [hli]
+ cp [hl]
+ jr nz, .no_match
+
+ ld a, [wDummyGameCard1Location]
+ call DummyGame_Card2Coord
+ call DummyGame_DeleteCard
+
+ ld a, [wDummyGameCard2Location]
+ call DummyGame_Card2Coord
+ call DummyGame_DeleteCard
+
+ ld a, [wDummyGameCard1Location]
+ ld e, a
+ ld d, $0
+ ld hl, wDummyGameCards
+ add hl, de
+ ld [hl], -1
+
+ ld a, [wDummyGameCard2Location]
+ ld e, a
+ ld d, 0
+ ld hl, wDummyGameCards
+ add hl, de
+ ld [hl], -1
+
+ ld hl, wDummyGameLastMatches
+.find_empty_slot
+ ld a, [hli]
+ and a
+ jr nz, .find_empty_slot
+ dec hl
+ ld a, [wDummyGameCard1]
+ ld [hl], a
+ ld [wDummyGameLastCardPicked], a
+ ld hl, wDummyGameNumCardsMatched
+ ld e, [hl]
+ inc [hl]
+ inc [hl]
+ ld d, 0
+ hlcoord 5, 0
+ add hl, de
+ call DummyGame_PlaceCard
+ ld hl, .VictoryText
+ call PrintText
+ ret
+
+.no_match
+ xor a
+ ld [wDummyGameLastCardPicked], a
+
+ ld a, [wDummyGameCard1Location]
+ call DummyGame_Card2Coord
+ call DummyGame_PlaceCard
+
+ ld a, [wDummyGameCard2Location]
+ call DummyGame_Card2Coord
+ call DummyGame_PlaceCard
+
+ ld hl, DummyGameDarnText
+ call PrintText
+ ret
+
+.VictoryText:
+ text_asm
+ push bc
+ hlcoord 2, 13
+ call DummyGame_PlaceCard
+ ld hl, DummyGameYeahText
+ pop bc
+ inc bc
+ inc bc
+ inc bc
+ ret
+
+DummyGameYeahText:
+ text_far _DummyGameYeahText
+ text_end
+
+DummyGameDarnText:
+ text_far _DummyGameDarnText
+ text_end
+
+DummyGame_InitBoard:
+ ld hl, wDummyGameCards
+ ld bc, wDummyGameCardsEnd - wDummyGameCards
+ xor a
+ call ByteFill
+ call DummyGame_GetDistributionOfTiles
+
+ ld c, 2
+ ld b, [hl]
+ call DummyGame_SampleTilePlacement
+
+ ld c, 8
+ ld b, [hl]
+ call DummyGame_SampleTilePlacement
+
+ ld c, 4
+ ld b, [hl]
+ call DummyGame_SampleTilePlacement
+
+ ld c, 7
+ ld b, [hl]
+ call DummyGame_SampleTilePlacement
+
+ ld c, 3
+ ld b, [hl]
+ call DummyGame_SampleTilePlacement
+
+ ld c, 6
+ ld b, [hl]
+ call DummyGame_SampleTilePlacement
+
+ ld c, 1
+ ld b, [hl]
+ call DummyGame_SampleTilePlacement
+
+ ld c, 5
+ ld hl, wDummyGameCards
+ ld b, wDummyGameCardsEnd - wDummyGameCards
+.loop
+ ld a, [hl]
+ and a
+ jr nz, .no_load
+ ld [hl], c
+.no_load
+ inc hl
+ dec b
+ jr nz, .loop
+ ret
+
+DummyGame_SampleTilePlacement:
+ push hl
+ ld de, wDummyGameCards
+.loop
+ call Random
+ and %00111111
+ cp 45
+ jr nc, .loop
+ ld l, a
+ ld h, 0
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .loop
+ ld [hl], c
+ dec b
+ jr nz, .loop
+ pop hl
+ inc hl
+ ret
+
+DummyGame_GetDistributionOfTiles:
+ ld a, [wMenuCursorY]
+ dec a
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ add hl, hl
+ ld de, .distributions
+ add hl, de
+ ret
+
+.distributions
+ db $02, $03, $06, $06, $06, $08, $08, $06
+ db $02, $02, $04, $06, $06, $08, $08, $09
+ db $02, $02, $02, $04, $07, $08, $08, $0c
+
+DummyGame_PlaceCard:
+ ld a, [wDummyGameLastCardPicked]
+ sla a
+ sla a
+ add 4
+ ld [hli], a
+ inc a
+ ld [hld], a
+ inc a
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hli], a
+ inc a
+ ld [hl], a
+ ld c, 3
+ call DelayFrames
+ ret
+
+DummyGame_DeleteCard:
+ ld a, $1
+ ld [hli], a
+ ld [hld], a
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld [hli], a
+ ld [hl], a
+ ld c, 3
+ call DelayFrames
+ ret
+
+DummyGame_InitStrings:
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, $1
+ call ByteFill
+ hlcoord 0, 0
+ ld de, .japstr1
+ call PlaceString
+ hlcoord 15, 0
+ ld de, .japstr2
+ call PlaceString
+ ld hl, .dummy_text
+ call PrintText
+ ret
+
+.dummy_text
+ db "@"
+.japstr1
+ db "とったもの@"
+.japstr2
+ db "あと かい@"
+
+DummyGame_Card2Coord:
+ ld d, 0
+.find_row
+ sub 9
+ jr c, .found_row
+ inc d
+ jr .find_row
+
+.found_row
+ add 9
+ ld e, a
+ hlcoord 1, 2
+ ld bc, 2 * SCREEN_WIDTH
+.loop2
+ ld a, d
+ and a
+ jr z, .done
+ add hl, bc
+ dec d
+ jr .loop2
+
+.done
+ sla e
+ add hl, de
+ ret
+
+DummyGame_InterpretJoypad_AnimateCursor:
+ ld a, [wJumptableIndex]
+ cp $7
+ jr nc, .quit
+ call JoyTextDelay
+ ld hl, hJoypadPressed
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .pressed_a
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .pressed_left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .pressed_right
+ ld a, [hl]
+ and D_UP
+ jr nz, .pressed_up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .pressed_down
+ ret
+
+.quit
+ ld hl, SPRITEANIMSTRUCT_INDEX
+ add hl, bc
+ ld [hl], $0
+ ret
+
+.pressed_a
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ inc a
+ ld [wce64], a
+ ret
+
+.pressed_left
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld a, [hl]
+ and a
+ ret z
+ sub 1 tiles
+ ld [hl], a
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ dec [hl]
+ ret
+
+.pressed_right
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld a, [hl]
+ cp (9 - 1) tiles
+ ret z
+ add 1 tiles
+ ld [hl], a
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ inc [hl]
+ ret
+
+.pressed_up
+ ld hl, SPRITEANIMSTRUCT_YOFFSET
+ add hl, bc
+ ld a, [hl]
+ and a
+ ret z
+ sub 1 tiles
+ ld [hl], a
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ sub 9
+ ld [hl], a
+ ret
+
+.pressed_down
+ ld hl, SPRITEANIMSTRUCT_YOFFSET
+ add hl, bc
+ ld a, [hl]
+ cp (5 - 1) tiles
+ ret z
+ add 1 tiles
+ ld [hl], a
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ add 9
+ ld [hl], a
+ ret
+
+DummyGameLZ:
+INCBIN "gfx/dummy_game/dummy_game.2bpp.lz"
diff --git a/engine/games/unown_puzzle.asm b/engine/games/unown_puzzle.asm
new file mode 100755
index 00000000..6151107d
--- /dev/null
+++ b/engine/games/unown_puzzle.asm
@@ -0,0 +1,846 @@
+PUZZLE_BORDER EQU $ee
+PUZZLE_VOID EQU $ef
+
+puzcoord EQUS "* 6 +"
+
+_UnownPuzzle:
+ ldh a, [hInMenu]
+ push af
+ ld a, $1
+ ldh [hInMenu], a
+ call ClearBGPalettes
+ call ClearTilemap
+ call ClearSprites
+ xor a
+ ldh [hBGMapMode], a
+ call DisableLCD
+ ld hl, wUnownPuzzle ; includes wPuzzlePieces
+ ld bc, wUnownPuzzleEnd - wUnownPuzzle
+ xor a
+ call ByteFill
+ ld hl, UnownPuzzleCursorGFX
+ ld de, vTiles0 tile $e0
+ ld bc, 4 tiles
+ call CopyBytes
+ ld hl, UnownPuzzleStartCancelLZ
+ ld de, vTiles0 tile $ed
+ call Decompress
+ call LoadUnownPuzzlePiecesGFX
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, PUZZLE_BORDER
+ call ByteFill
+ hlcoord 4, 3
+ lb bc, 12, 12
+ ld a, PUZZLE_VOID
+ call UnownPuzzle_FillBox
+ call InitUnownPuzzlePiecePositions
+ call UnownPuzzle_UpdateTilemap
+ call PlaceStartCancelBox
+ xor a
+ ldh [hSCY], a
+ ldh [hSCX], a
+ ldh [rWY], a
+ ld [wJumptableIndex], a
+ ld [wHoldingUnownPuzzlePiece], a
+ ld [wUnownPuzzleCursorPosition], a
+ ld [wUnownPuzzleHeldPiece], a
+ ld a, %10010011
+ ldh [rLCDC], a
+ call WaitBGMap
+ ld b, SCGB_UNOWN_PUZZLE
+ call GetSGBLayout
+ ld a, $e4
+ call DmgToCgbBGPals
+ ld a, $24
+ call DmgToCgbObjPal0
+ xor a
+ ld [wSolvedUnownPuzzle], a
+ call DelayFrame
+.loop
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .quit
+ call UnownPuzzleJumptable
+ ld a, [wHoldingUnownPuzzlePiece]
+ and a
+ jr nz, .holding_piece
+ ldh a, [hVBlankCounter]
+ and $10
+ jr z, .clear
+.holding_piece
+ call RedrawUnownPuzzlePieces
+ jr .next
+
+.clear
+ call ClearSprites
+.next
+ call DelayFrame
+ jr .loop
+
+.quit
+ pop af
+ ldh [hInMenu], a
+ call ClearBGPalettes
+ call ClearTilemap
+ call ClearSprites
+ ld a, LCDC_DEFAULT
+ ldh [rLCDC], a
+ ret
+
+InitUnownPuzzlePiecePositions:
+ ld c, 1
+ ld b, 16
+.load_loop
+ call Random
+ and $f
+ ld hl, .PuzzlePieceInitialPositions
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld e, [hl]
+ ld hl, wPuzzlePieces
+ add hl, de
+ ld a, [hl]
+ and a
+ jr nz, .load_loop
+ ld [hl], c
+ inc c
+ dec b
+ jr nz, .load_loop
+ ret
+
+.PuzzlePieceInitialPositions:
+initpuzcoord: MACRO
+rept _NARG / 2
+ db \1 puzcoord \2
+ shift 2
+endr
+ENDM
+ initpuzcoord 0,0, 0,1, 0,2, 0,3, 0,4, 0,5
+ initpuzcoord 1,0, 1,5
+ initpuzcoord 2,0, 2,5
+ initpuzcoord 3,0, 3,5
+ initpuzcoord 4,0, 4,5
+ initpuzcoord 5,0, 5,5
+ ; START > CANCEL
+
+PlaceStartCancelBox:
+ call PlaceStartCancelBoxBorder
+ hlcoord 5, 16
+ ld a, $f6
+ ld c, 10
+.loop
+ ld [hli], a
+ inc a
+ dec c
+ jr nz, .loop
+ ret
+
+PlaceStartCancelBoxBorder:
+ hlcoord 4, 15
+ ld a, $f0
+ ld [hli], a
+ ld bc, 10
+ ld a, $f1
+ call ByteFill
+ hlcoord 15, 15
+ ld a, $f2
+ ld [hli], a
+ hlcoord 4, 16
+ ld a, $f3
+ ld [hli], a
+ ld bc, 10
+ ld a, PUZZLE_VOID
+ call ByteFill
+ hlcoord 15, 16
+ ld a, $f3
+ ld [hli], a
+ hlcoord 4, 17
+ ld a, $f4
+ ld [hli], a
+ ld bc, 10
+ ld a, $f1
+ call ByteFill
+ hlcoord 15, 17
+ ld a, $f5
+ ld [hl], a
+ ret
+
+UnownPuzzleJumptable:
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Jumptable:
+ dw .Function
+
+.Function:
+ ldh a, [hJoyPressed]
+ and START
+ jp nz, UnownPuzzle_Quit
+ ldh a, [hJoyPressed]
+ and A_BUTTON
+ jp nz, UnownPuzzle_A
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .d_up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .d_down
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .d_left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .d_right
+ ret
+
+.d_up
+ ld hl, wUnownPuzzleCursorPosition
+ ld a, [hl]
+ cp 1 puzcoord 0
+ ret c
+ sub 6
+ ld [hl], a
+ jr .done_joypad
+
+.d_down
+ ld hl, wUnownPuzzleCursorPosition
+ ld a, [hl]
+ cp 4 puzcoord 1
+ ret z
+ cp 4 puzcoord 2
+ ret z
+ cp 4 puzcoord 3
+ ret z
+ cp 4 puzcoord 4
+ ret z
+ cp 5 puzcoord 0
+ ret nc
+ add 6
+ ld [hl], a
+ jr .done_joypad
+
+.d_left
+ ld hl, wUnownPuzzleCursorPosition
+ ld a, [hl]
+ and a
+ ret z
+ cp 1 puzcoord 0
+ ret z
+ cp 2 puzcoord 0
+ ret z
+ cp 3 puzcoord 0
+ ret z
+ cp 4 puzcoord 0
+ ret z
+ cp 5 puzcoord 0
+ ret z
+ cp 5 puzcoord 5
+ jr z, .left_overflow
+ dec [hl]
+ jr .done_joypad
+
+.left_overflow
+ ld [hl], 5 puzcoord 0
+ jr .done_joypad
+
+.d_right
+ ld hl, wUnownPuzzleCursorPosition
+ ld a, [hl]
+ cp 0 puzcoord 5
+ ret z
+ cp 1 puzcoord 5
+ ret z
+ cp 2 puzcoord 5
+ ret z
+ cp 3 puzcoord 5
+ ret z
+ cp 4 puzcoord 5
+ ret z
+ cp 5 puzcoord 5
+ ret z
+ cp 5 puzcoord 0
+ jr z, .right_overflow
+ inc [hl]
+ jr .done_joypad
+
+.right_overflow
+ ld [hl], 5 puzcoord 5
+
+.done_joypad
+ ld a, [wHoldingUnownPuzzlePiece]
+ and a
+ jr nz, .holding_piece
+ ld de, SFX_POUND
+ jr .play_sfx
+
+.holding_piece
+ ld de, SFX_MOVE_PUZZLE_PIECE
+
+.play_sfx
+ call PlaySFX
+ ret
+
+UnownPuzzle_A:
+ ld a, [wHoldingUnownPuzzlePiece]
+ and a
+ jr nz, .TryPlacePiece
+ call UnownPuzzle_CheckCurrentTileOccupancy
+ and a
+ jr z, UnownPuzzle_InvalidAction
+ ld de, SFX_MEGA_KICK
+ call PlaySFX
+ ld [hl], 0
+ ld [wUnownPuzzleHeldPiece], a
+ call RedrawUnownPuzzlePieces
+ call FillUnoccupiedPuzzleSpace
+ call WaitBGMap
+ call WaitSFX
+ ld a, TRUE
+ ld [wHoldingUnownPuzzlePiece], a
+ ret
+
+.TryPlacePiece:
+ call UnownPuzzle_CheckCurrentTileOccupancy
+ and a
+ jr nz, UnownPuzzle_InvalidAction
+ ld de, SFX_PLACE_PUZZLE_PIECE_DOWN
+ call PlaySFX
+ ld a, [wUnownPuzzleHeldPiece]
+ ld [hl], a
+ call PlaceUnownPuzzlePieceGFX
+ call WaitBGMap
+ xor a
+ ld [wUnownPuzzleHeldPiece], a
+ call RedrawUnownPuzzlePieces
+ xor a
+ ld [wHoldingUnownPuzzlePiece], a
+ call WaitSFX
+ call CheckSolvedUnownPuzzle
+ ret nc
+
+; You solved the puzzle!
+ call PlaceStartCancelBoxBorder
+ call ClearSprites
+ ld de, SFX_1ST_PLACE
+ call PlaySFX
+ call WaitSFX
+ call SimpleWaitPressAorB
+ ld a, TRUE
+ ld [wSolvedUnownPuzzle], a
+UnownPuzzle_Quit:
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+UnownPuzzle_InvalidAction:
+ ld de, SFX_WRONG
+ call PlaySFX
+ call WaitSFX
+ ret
+
+UnownPuzzle_FillBox:
+ ld de, SCREEN_WIDTH
+.row
+ push bc
+ push hl
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ add hl, de
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+
+UnownPuzzle_UpdateTilemap:
+ xor a
+ ld [wUnownPuzzleCursorPosition], a
+ ld c, 6 * 6
+.loop
+ push bc
+ call UnownPuzzle_CheckCurrentTileOccupancy
+ ld [wUnownPuzzleHeldPiece], a
+ and a
+ jr z, .not_holding_piece
+ call PlaceUnownPuzzlePieceGFX
+ jr .next
+
+.not_holding_piece
+ call FillUnoccupiedPuzzleSpace
+
+.next
+ ld hl, wUnownPuzzleCursorPosition
+ inc [hl]
+ pop bc
+ dec c
+ jr nz, .loop
+ ret
+
+PlaceUnownPuzzlePieceGFX:
+ ld a, $2 ; tilemap coords
+ call GetUnownPuzzleCoordData
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ push hl
+ call GetCurrentPuzzlePieceVTileCorner
+ pop hl
+ ld de, SCREEN_WIDTH
+ ld b, 3
+.row
+ ld c, 3
+ push hl
+.col
+ ld [hli], a
+ inc a
+ dec c
+ jr nz, .col
+ add 9
+ pop hl
+ add hl, de
+ dec b
+ jr nz, .row
+ ret
+
+FillUnoccupiedPuzzleSpace:
+ ld a, 2 ; tilemap coords
+ call GetUnownPuzzleCoordData
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ push hl
+ ld a, 4 ; tile
+ call GetUnownPuzzleCoordData
+ ld a, [hl]
+ pop hl
+ ld de, SCREEN_WIDTH
+ ld b, 3
+.row
+ ld c, 3
+ push hl
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ add hl, de
+ dec b
+ jr nz, .row
+ ret
+
+GetUnownPuzzleCoordData:
+ ld e, a
+ ld d, 0
+ ld hl, UnownPuzzleCoordData
+ add hl, de
+ ld a, [wUnownPuzzleCursorPosition]
+ ld e, a
+rept 6
+ add hl, de
+endr
+ ret
+
+UnownPuzzle_CheckCurrentTileOccupancy:
+ ld hl, wPuzzlePieces
+ ld a, [wUnownPuzzleCursorPosition]
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld a, [hl]
+ ret
+
+GetCurrentPuzzlePieceVTileCorner:
+ ld a, [wUnownPuzzleHeldPiece]
+ ld hl, .Corners
+ add l
+ ld l, a
+ ld a, $0
+ adc h
+ ld h, a
+ ld a, [hl]
+ ret
+
+.Corners:
+; 00, 01, 02
+; 0c, 0d, 0e
+; 18, 19, 1a
+ db $e0 ; no piece selected
+ db $00, $03, $06, $09
+ db $24, $27, $2a, $2d
+ db $48, $4b, $4e, $51
+ db $6c, $6f, $72, $75
+
+CheckSolvedUnownPuzzle:
+ ld hl, .SolvedPuzzleConfiguration
+ ld de, wPuzzlePieces
+ ld c, 6 * 6
+.loop
+ ld a, [de]
+ cp [hl]
+ jr nz, .not_solved
+ inc de
+ inc hl
+ dec c
+ jr nz, .loop
+ scf
+ ret
+
+.not_solved
+ and a
+ ret
+
+.SolvedPuzzleConfiguration:
+ db $00, $00, $00, $00, $00, $00
+ db $00, $01, $02, $03, $04, $00
+ db $00, $05, $06, $07, $08, $00
+ db $00, $09, $0a, $0b, $0c, $00
+ db $00, $0d, $0e, $0f, $10, $00
+ db $00, $00, $00, $00, $00, $00
+
+RedrawUnownPuzzlePieces:
+ call GetCurrentPuzzlePieceVTileCorner
+ ld [wceed], a
+ xor a
+ call GetUnownPuzzleCoordData ; get pixel positions
+ ld a, [hli]
+ ld b, [hl]
+ ld c, a
+ ld a, [wceed]
+ cp $e0
+ jr z, .NoPiece
+ ld hl, .OAM_HoldingPiece
+ jr .load
+
+.NoPiece:
+ ld hl, .OAM_NotHoldingPiece
+
+.load
+ ld de, wVirtualOAMSprite00
+.loop
+ ld a, [hli]
+ cp -1
+ ret z
+ add b
+ ld [de], a ; y
+ inc de
+ ld a, [hli]
+ add c
+ ld [de], a ; x
+ inc de
+ ld a, [wceed]
+ add [hl]
+ ld [de], a ; tile id
+ inc hl
+ inc de
+ ld a, [hli]
+ ld [de], a ; attributes
+ inc de
+ jr .loop
+
+.OAM_HoldingPiece:
+ dbsprite -1, -1, -4, -4, $00, 0
+ dbsprite 0, -1, -4, -4, $01, 0
+ dbsprite 0, -1, 4, -4, $02, 0
+ dbsprite -1, 0, -4, -4, $0c, 0
+ dbsprite 0, 0, -4, -4, $0d, 0
+ dbsprite 0, 0, 4, -4, $0e, 0
+ dbsprite -1, 0, -4, 4, $18, 0
+ dbsprite 0, 0, -4, 4, $19, 0
+ dbsprite 0, 0, 4, 4, $1a, 0
+ db -1
+
+.OAM_NotHoldingPiece:
+ dbsprite -1, -1, -4, -4, $00, 0
+ dbsprite 0, -1, -4, -4, $01, 0
+ dbsprite 0, -1, 4, -4, $00, 0 | X_FLIP
+ dbsprite -1, 0, -4, -4, $02, 0
+ dbsprite 0, 0, -4, -4, $03, 0
+ dbsprite 0, 0, 4, -4, $02, 0 | X_FLIP
+ dbsprite -1, 0, -4, 4, $00, 0 | Y_FLIP
+ dbsprite 0, 0, -4, 4, $01, 0 | Y_FLIP
+ dbsprite 0, 0, 4, 4, $00, 0 | X_FLIP | Y_FLIP
+ db -1
+
+UnownPuzzleCoordData:
+
+puzzle_coords: MACRO
+ dbpixel \1, \2, \3, \4
+ dwcoord \5, \6
+ db \7, \8
+ENDM
+; OAM coords, tilemap coords, vacant tile, filler
+ puzzle_coords 3, 3, 4, 4, 1, 0, PUZZLE_BORDER, 0
+ puzzle_coords 6, 3, 4, 4, 4, 0, PUZZLE_BORDER, 0
+ puzzle_coords 9, 3, 4, 4, 7, 0, PUZZLE_BORDER, 0
+ puzzle_coords 12, 3, 4, 4, 10, 0, PUZZLE_BORDER, 0
+ puzzle_coords 15, 3, 4, 4, 13, 0, PUZZLE_BORDER, 0
+ puzzle_coords 18, 3, 4, 4, 16, 0, PUZZLE_BORDER, 0
+
+ puzzle_coords 3, 6, 4, 4, 1, 3, PUZZLE_BORDER, 0
+ puzzle_coords 6, 6, 4, 4, 4, 3, PUZZLE_VOID, 0
+ puzzle_coords 9, 6, 4, 4, 7, 3, PUZZLE_VOID, 0
+ puzzle_coords 12, 6, 4, 4, 10, 3, PUZZLE_VOID, 0
+ puzzle_coords 15, 6, 4, 4, 13, 3, PUZZLE_VOID, 0
+ puzzle_coords 18, 6, 4, 4, 16, 3, PUZZLE_BORDER, 0
+
+ puzzle_coords 3, 9, 4, 4, 1, 6, PUZZLE_BORDER, 0
+ puzzle_coords 6, 9, 4, 4, 4, 6, PUZZLE_VOID, 0
+ puzzle_coords 9, 9, 4, 4, 7, 6, PUZZLE_VOID, 0
+ puzzle_coords 12, 9, 4, 4, 10, 6, PUZZLE_VOID, 0
+ puzzle_coords 15, 9, 4, 4, 13, 6, PUZZLE_VOID, 0
+ puzzle_coords 18, 9, 4, 4, 16, 6, PUZZLE_BORDER, 0
+
+ puzzle_coords 3, 12, 4, 4, 1, 9, PUZZLE_BORDER, 0
+ puzzle_coords 6, 12, 4, 4, 4, 9, PUZZLE_VOID, 0
+ puzzle_coords 9, 12, 4, 4, 7, 9, PUZZLE_VOID, 0
+ puzzle_coords 12, 12, 4, 4, 10, 9, PUZZLE_VOID, 0
+ puzzle_coords 15, 12, 4, 4, 13, 9, PUZZLE_VOID, 0
+ puzzle_coords 18, 12, 4, 4, 16, 9, PUZZLE_BORDER, 0
+
+ puzzle_coords 3, 15, 4, 4, 1, 12, PUZZLE_BORDER, 0
+ puzzle_coords 6, 15, 4, 4, 4, 12, PUZZLE_VOID, 0
+ puzzle_coords 9, 15, 4, 4, 7, 12, PUZZLE_VOID, 0
+ puzzle_coords 12, 15, 4, 4, 10, 12, PUZZLE_VOID, 0
+ puzzle_coords 15, 15, 4, 4, 13, 12, PUZZLE_VOID, 0
+ puzzle_coords 18, 15, 4, 4, 16, 12, PUZZLE_BORDER, 0
+
+ puzzle_coords 3, 18, 4, 4, 1, 15, PUZZLE_BORDER, 0
+ puzzle_coords 6, 18, 4, 4, 4, 15, PUZZLE_BORDER, 0
+ puzzle_coords 9, 18, 4, 4, 7, 15, PUZZLE_BORDER, 0
+ puzzle_coords 12, 18, 4, 4, 10, 15, PUZZLE_BORDER, 0
+ puzzle_coords 15, 18, 4, 4, 13, 15, PUZZLE_BORDER, 0
+ puzzle_coords 18, 18, 4, 4, 16, 15, PUZZLE_BORDER, 0
+
+ConvertLoadedPuzzlePieces:
+ ld hl, vTiles2
+ ld de, vTiles0
+ ld b, 6
+.loop
+ push bc
+ push hl
+ push hl
+ call .EnlargePuzzlePieceTiles
+ pop hl
+ ld bc, 1 tiles / 2
+ add hl, bc
+ call .EnlargePuzzlePieceTiles
+ pop hl
+ ld bc, 6 tiles
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .loop
+ call UnownPuzzle_AddPuzzlePieceBorders
+ ret
+
+.EnlargePuzzlePieceTiles:
+; double size
+ ld c, 6
+.loop1
+ push bc
+ push hl
+ push hl
+ ld c, 4
+.loop2
+ push bc
+ ld a, [hli]
+ and $f0
+ swap a
+ call .GetEnlargedTile
+ ld c, a
+ ld a, [hli]
+ and $f0
+ swap a
+ call .GetEnlargedTile
+ ld b, a
+ ld a, c
+ ld [de], a
+ inc de
+ ld a, b
+ ld [de], a
+ inc de
+ ld a, c
+ ld [de], a
+ inc de
+ ld a, b
+ ld [de], a
+ inc de
+ pop bc
+ dec c
+ jr nz, .loop2
+ pop hl
+ ld c, 4
+.loop3
+ push bc
+ ld a, [hli]
+ and $f
+ call .GetEnlargedTile
+ ld c, a
+ ld a, [hli]
+ and $f
+ call .GetEnlargedTile
+ ld b, a
+ ld a, c
+ ld [de], a
+ inc de
+ ld a, b
+ ld [de], a
+ inc de
+ ld a, c
+ ld [de], a
+ inc de
+ ld a, b
+ ld [de], a
+ inc de
+ pop bc
+ dec c
+ jr nz, .loop3
+ pop hl
+ ld bc, 1 tiles
+ add hl, bc
+ pop bc
+ dec c
+ jr nz, .loop1
+ ret
+
+.GetEnlargedTile:
+ push hl
+ ld hl, .EnlargedTiles
+ add l
+ ld l, a
+ ld a, 0
+ adc h
+ ld h, a
+ ld a, [hl]
+ pop hl
+ ret
+
+.EnlargedTiles:
+x = 0
+rept 16
+ db ((x & %1000) * %11000) + ((x & %0100) * %1100) + ((x & %0010) * %110) + ((x & %0001) * %11)
+x = x + 1
+endr
+
+UnownPuzzle_AddPuzzlePieceBorders:
+ ld hl, PuzzlePieceBorderData
+ ld a, 8
+.loop
+ push af
+ push hl
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call .LoadGFX
+ pop hl
+rept 4
+ inc hl
+endr
+ pop af
+ dec a
+ jr nz, .loop
+ ret
+
+.LoadGFX:
+ lb bc, 4, 4
+.loop1
+ push bc
+
+.loop2
+ push de
+ push hl
+
+ ld b, 1 tiles
+.loop3
+ ld a, [de]
+ or [hl]
+ ld [hli], a
+ inc de
+ dec b
+ jr nz, .loop3
+
+ pop hl
+ ld de, 3 tiles
+ add hl, de
+ pop de
+ dec c
+ jr nz, .loop2
+
+ ld bc, 24 tiles
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .loop1
+ ret
+
+PuzzlePieceBorderData:
+ dw .TileBordersGFX + 0 tiles, vTiles0 tile $00
+ dw .TileBordersGFX + 1 tiles, vTiles0 tile $01
+ dw .TileBordersGFX + 2 tiles, vTiles0 tile $02
+ dw .TileBordersGFX + 3 tiles, vTiles0 tile $0c
+ dw .TileBordersGFX + 4 tiles, vTiles0 tile $0e
+ dw .TileBordersGFX + 5 tiles, vTiles0 tile $18
+ dw .TileBordersGFX + 6 tiles, vTiles0 tile $19
+ dw .TileBordersGFX + 7 tiles, vTiles0 tile $1a
+
+.TileBordersGFX:
+INCBIN "gfx/unown_puzzle/tile_borders.2bpp"
+
+LoadUnownPuzzlePiecesGFX:
+ ld a, [wScriptVar]
+ maskbits NUM_UNOWN_PUZZLES
+ ld e, a
+ ld d, 0
+ ld hl, .LZPointers
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, vTiles2
+ call Decompress
+ call ConvertLoadedPuzzlePieces
+ ret
+
+.LZPointers:
+; entries correspond to UNOWNPUZZLE_* constants
+ dw KabutoPuzzleLZ
+ dw OmanytePuzzleLZ
+ dw AerodactylPuzzleLZ
+ dw HoOhPuzzleLZ
+
+UnownPuzzleCursorGFX:
+INCBIN "gfx/unown_puzzle/cursor.2bpp"
+
+UnownPuzzleStartCancelLZ:
+INCBIN "gfx/unown_puzzle/start_cancel.2bpp.lz"
+
+HoOhPuzzleLZ:
+INCBIN "gfx/unown_puzzle/hooh.2bpp.lz"
+
+AerodactylPuzzleLZ:
+INCBIN "gfx/unown_puzzle/aerodactyl.2bpp.lz"
+
+KabutoPuzzleLZ:
+INCBIN "gfx/unown_puzzle/kabuto.2bpp.lz"
+
+OmanytePuzzleLZ:
+INCBIN "gfx/unown_puzzle/omanyte.2bpp.lz"
diff --git a/engine/pokemon/bills_pc.asm b/engine/pokemon/bills_pc.asm
new file mode 100755
index 00000000..fa610df1
--- /dev/null
+++ b/engine/pokemon/bills_pc.asm
@@ -0,0 +1,2509 @@
+_DepositPKMN:
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ ld a, [wVramState]
+ push af
+ xor a
+ ld [wVramState], a
+ ldh a, [hInMenu]
+ push af
+ ld a, $1
+ ldh [hInMenu], a
+ xor a
+ ldh [hMapAnims], a
+ call BillsPC_InitRAM
+ xor a
+ ld [wBillsPC_LoadedBox], a
+ call DelayFrame
+.loop
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .done
+ call .RunJumptable
+ call DelayFrame
+ jr .loop
+.done
+ call ClearSprites
+ pop af
+ ldh [hInMenu], a
+ pop af
+ ld [wVramState], a
+ pop af
+ ld [wOptions], a
+ ret
+
+.RunJumptable:
+ ld a, [wJumptableIndex]
+ ld hl, .Jumptable
+ call BillsPC_Jumptable
+ jp hl
+
+.Jumptable:
+ dw .Init
+ dw .HandleJoypad
+ dw .WhatsUp
+ dw .Submenu
+ dw BillsPC_EndJumptableLoop
+
+.Init:
+ xor a
+ ldh [hBGMapMode], a
+ call ClearSprites
+ call CopyBoxmonSpecies
+ call BillsPC_BoxName
+ ld de, PCString_ChooseaPKMN
+ call BillsPC_PlaceString
+ ld a, $5
+ ld [wBillsPC_NumMonsOnScreen], a
+ call BillsPC_RefreshTextboxes
+ call PCMonInfo
+ ld a, $ff
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ call WaitBGMap
+ call BillsPC_UpdateSelectionCursor
+ call BillsPC_IncrementJumptableIndex
+ ret
+
+.HandleJoypad:
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b_button
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a_button
+ call Withdraw_UpDown
+ and a
+ ret z
+ call BillsPC_UpdateSelectionCursor
+ xor a
+ ldh [hBGMapMode], a
+ call BillsPC_RefreshTextboxes
+ call PCMonInfo
+ ld a, $1
+ ldh [hBGMapMode], a
+ call DelayFrame
+ call DelayFrame
+ ret
+
+.a_button
+ call BillsPC_GetSelectedPokemonSpecies
+ and a
+ ret z
+ cp -1
+ jr z, .b_button
+ ld a, $2
+ ld [wJumptableIndex], a
+ ret
+
+.go_back
+ ld hl, wJumptableIndex
+ dec [hl]
+ ret
+
+.b_button
+ ld a, $4
+ ld [wJumptableIndex], a
+ ret
+
+.WhatsUp:
+ xor a
+ ldh [hBGMapMode], a
+ call ClearSprites
+ call BillsPC_GetSelectedPokemonSpecies
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ ld de, PCString_WhatsUp
+ call BillsPC_PlaceString
+ ld a, $1
+ ld [wMenuCursorY], a
+ call BillsPC_IncrementJumptableIndex
+ ret
+
+.Submenu:
+ ld hl, BillsPCDepositMenuHeader
+ call CopyMenuHeader
+ ld a, [wMenuCursorY]
+ call StoreTo_wMenuCursorBuffer
+ call VerticalMenu
+ jp c, BillsPCDepositFuncCancel
+ ld a, [wMenuCursorY]
+ dec a
+ and %11
+ ld e, a
+ ld d, 0
+ ld hl, BillsPCDepositJumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+BillsPCDepositJumptable:
+ dw BillsPCDepositFuncDeposit ; Deposit Pokemon
+ dw BillsPCDepositFuncStats ; Pokemon Stats
+ dw BillsPCDepositFuncRelease ; Release Pokemon
+ dw BillsPCDepositFuncCancel ; Cancel
+
+BillsPCDepositFuncDeposit:
+ call BillsPC_CheckMail_PreventBlackout
+ jp c, BillsPCDepositFuncCancel
+ call DepositPokemon
+ jr c, .box_full
+ ld a, $0
+ ld [wJumptableIndex], a
+ xor a
+ ld [wBillsPC_CursorPosition], a
+ ld [wBillsPC_ScrollPosition], a
+ ret
+
+.box_full
+ ld de, PCString_WhatsUp
+ call BillsPC_PlaceString
+ ret
+
+BillsPCDepositFuncStats:
+ call LoadStandardMenuHeader
+ call BillsPC_StatsScreen
+ call ExitMenu
+ call PCMonInfo
+ call BillsPC_GetSelectedPokemonSpecies
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ ret
+
+BillsPCDepositFuncRelease:
+ call BillsPC_CheckMail_PreventBlackout
+ jr c, BillsPCDepositFuncCancel
+ call BillsPC_IsMonAnEgg
+ jr c, BillsPCDepositFuncCancel
+ ld a, [wMenuCursorY]
+ push af
+ ld de, PCString_ReleasePKMN
+ call BillsPC_PlaceString
+ call LoadStandardMenuHeader
+ lb bc, 14, 11
+ call PlaceYesNoBox
+ ld a, [wMenuCursorY]
+ dec a
+ call ExitMenu
+ and a
+ jr nz, .failed_release
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ xor a ; REMOVE_PARTY
+ ld [wPokemonWithdrawDepositParameter], a
+ farcall RemoveMonFromPartyOrBox
+ call ReleasePKMN_ByePKMN
+ ld a, $0
+ ld [wJumptableIndex], a
+ xor a
+ ld [wBillsPC_CursorPosition], a
+ ld [wBillsPC_ScrollPosition], a
+ pop af
+ ret
+
+.failed_release
+ ld de, PCString_WhatsUp
+ call BillsPC_PlaceString
+ pop af
+ ld [wMenuCursorY], a
+ ret
+
+BillsPCDepositFuncCancel:
+ ld a, $0
+ ld [wJumptableIndex], a
+ ret
+
+BillsPCDepositMenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 9, 4, SCREEN_WIDTH - 1, 13
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData:
+ db STATICMENU_CURSOR ; flags
+ db 4 ; items
+ db "DEPOSIT@"
+ db "STATS@"
+ db "RELEASE@"
+ db "CANCEL@"
+
+_WithdrawPKMN:
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ ld a, [wVramState]
+ push af
+ xor a
+ ld [wVramState], a
+ ldh a, [hInMenu]
+ push af
+ ld a, $1
+ ldh [hInMenu], a
+ xor a
+ ldh [hMapAnims], a
+ call BillsPC_InitRAM
+ ld a, NUM_BOXES + 1
+ ld [wBillsPC_LoadedBox], a
+ call DelayFrame
+.loop
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .done
+ call .RunJumptable
+ call DelayFrame
+ jr .loop
+.done
+ call ClearSprites
+ pop af
+ ldh [hInMenu], a
+ pop af
+ ld [wVramState], a
+ pop af
+ ld [wOptions], a
+ ret
+
+.RunJumptable:
+ ld a, [wJumptableIndex]
+ ld hl, .Jumptable
+ call BillsPC_Jumptable
+ jp hl
+
+.Jumptable:
+ dw .Init
+ dw .Joypad
+ dw .PrepSubmenu
+ dw BillsPC_Withdraw
+ dw BillsPC_EndJumptableLoop
+
+.Init:
+ ld a, NUM_BOXES + 1
+ ld [wBillsPC_LoadedBox], a
+ xor a
+ ldh [hBGMapMode], a
+ call ClearSprites
+ call CopyBoxmonSpecies
+ call BillsPC_BoxName
+ ld de, PCString_ChooseaPKMN
+ call BillsPC_PlaceString
+ ld a, $5
+ ld [wBillsPC_NumMonsOnScreen], a
+ call BillsPC_RefreshTextboxes
+ call PCMonInfo
+ ld a, $ff
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ call WaitBGMap
+ call BillsPC_UpdateSelectionCursor
+ call BillsPC_IncrementJumptableIndex
+ ret
+
+.Joypad:
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b_button
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a_button
+ call Withdraw_UpDown
+ and a
+ ret z
+ call BillsPC_UpdateSelectionCursor
+ xor a
+ ldh [hBGMapMode], a
+ call BillsPC_RefreshTextboxes
+ call PCMonInfo
+ ld a, $1
+ ldh [hBGMapMode], a
+ call DelayFrame
+ call DelayFrame
+ ret
+.a_button
+ call BillsPC_GetSelectedPokemonSpecies
+ and a
+ ret z
+ cp -1
+ jr z, .b_button
+ ld a, $2
+ ld [wJumptableIndex], a
+ ret
+
+.unused
+ ld hl, wJumptableIndex
+ dec [hl]
+ ret
+
+.b_button
+ ld a, $4
+ ld [wJumptableIndex], a
+ ret
+
+.PrepSubmenu:
+ xor a
+ ldh [hBGMapMode], a
+ call ClearSprites
+ call BillsPC_GetSelectedPokemonSpecies
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ ld de, PCString_WhatsUp
+ call BillsPC_PlaceString
+ ld a, $1
+ ld [wMenuCursorY], a
+ call BillsPC_IncrementJumptableIndex
+ ret
+
+BillsPC_Withdraw:
+ ld hl, .MenuHeader
+ call CopyMenuHeader
+ ld a, [wMenuCursorY]
+ call StoreTo_wMenuCursorBuffer
+ call VerticalMenu
+ jp c, .cancel
+ ld a, [wMenuCursorY]
+ dec a
+ and %11
+ ld e, a
+ ld d, 0
+ ld hl, .dw
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.dw
+ dw .withdraw ; Withdraw
+ dw .stats ; Stats
+ dw .release ; Release
+ dw .cancel ; Cancel
+
+.withdraw
+ call BillsPC_CheckMail_PreventBlackout
+ jp c, .cancel
+ call TryWithdrawPokemon
+ jr c, .FailedWithdraw
+ ld a, $0
+ ld [wJumptableIndex], a
+ xor a
+ ld [wBillsPC_CursorPosition], a
+ ld [wBillsPC_ScrollPosition], a
+ ret
+.FailedWithdraw:
+ ld de, PCString_WhatsUp
+ call BillsPC_PlaceString
+ ret
+
+.stats
+ call LoadStandardMenuHeader
+ call BillsPC_StatsScreen
+ call ExitMenu
+ call PCMonInfo
+ call BillsPC_GetSelectedPokemonSpecies
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ ret
+
+.release
+ ld a, [wMenuCursorY]
+ push af
+ call BillsPC_IsMonAnEgg
+ jr c, .FailedRelease
+ ld de, PCString_ReleasePKMN
+ call BillsPC_PlaceString
+ call LoadStandardMenuHeader
+ lb bc, 14, 11
+ call PlaceYesNoBox
+ ld a, [wMenuCursorY]
+ dec a
+ call ExitMenu
+ and a
+ jr nz, .FailedRelease
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ ld a, REMOVE_BOX
+ ld [wPokemonWithdrawDepositParameter], a
+ farcall RemoveMonFromPartyOrBox
+ call ReleasePKMN_ByePKMN
+ ld a, $0
+ ld [wJumptableIndex], a
+ xor a
+ ld [wBillsPC_CursorPosition], a
+ ld [wBillsPC_ScrollPosition], a
+ pop af
+ ret
+.FailedRelease:
+ ld de, PCString_WhatsUp
+ call BillsPC_PlaceString
+ pop af
+ ld [wMenuCursorY], a
+ ret
+
+.cancel
+ ld a, $0
+ ld [wJumptableIndex], a
+ ret
+
+.MenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 9, 4, SCREEN_WIDTH - 1, 13
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData:
+ db STATICMENU_CURSOR ; flags
+ db 4 ; items
+ db "WITHDRAW@"
+ db "STATS@"
+ db "RELEASE@"
+ db "CANCEL@"
+
+_MovePKMNWithoutMail:
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ ld a, [wVramState]
+ push af
+ xor a
+ ld [wVramState], a
+ ldh a, [hInMenu]
+ push af
+ ld a, $1
+ ldh [hInMenu], a
+ xor a
+ ldh [hMapAnims], a
+ call BillsPC_InitRAM
+ ld a, [wCurBox]
+ and $f
+ inc a
+ ld [wBillsPC_LoadedBox], a
+ call DelayFrame
+.asm_e2781
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .asm_e2793
+ call .RunJumptable
+ call DelayFrame
+ jr .asm_e2781
+
+.asm_e2793
+ call ClearSprites
+ pop af
+ ldh [hInMenu], a
+ pop af
+ ld [wVramState], a
+ pop af
+ ld [wOptions], a
+ ret
+
+.RunJumptable:
+ ld a, [wJumptableIndex]
+ ld hl, .Jumptable
+ call BillsPC_Jumptable
+ jp hl
+
+.Jumptable:
+ dw .Init
+ dw .Joypad
+ dw .PrepSubmenu
+ dw .MoveMonWOMailSubmenu
+ dw .PrepInsertCursor
+ dw .Joypad2
+ dw BillsPC_EndJumptableLoop
+
+.Init:
+ xor a
+ ldh [hBGMapMode], a
+ call ClearSprites
+ call CopyBoxmonSpecies
+ ld de, PCString_ChooseaPKMN
+ call BillsPC_PlaceString
+ ld a, 5
+ ld [wBillsPC_NumMonsOnScreen], a
+ call BillsPC_RefreshTextboxes
+ call BillsPC_MoveMonWOMail_BoxNameAndArrows
+ call PCMonInfo
+ ld a, $ff
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ call WaitBGMap
+ call BillsPC_UpdateSelectionCursor
+ call BillsPC_IncrementJumptableIndex
+ ret
+
+.Joypad:
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b_button
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a_button
+ call MoveMonWithoutMail_DPad
+ jr c, .d_pad
+ and a
+ ret z
+ call BillsPC_UpdateSelectionCursor
+ xor a
+ ldh [hBGMapMode], a
+ call BillsPC_RefreshTextboxes
+ call PCMonInfo
+ ld a, $1
+ ldh [hBGMapMode], a
+ call DelayFrame
+ call DelayFrame
+ ret
+
+.d_pad
+ xor a
+ ld [wBillsPC_CursorPosition], a
+ ld [wBillsPC_ScrollPosition], a
+ ld a, $0
+ ld [wJumptableIndex], a
+ ret
+
+.a_button
+ call BillsPC_GetSelectedPokemonSpecies
+ and a
+ ret z
+ cp -1
+ jr z, .b_button
+ ld a, $2
+ ld [wJumptableIndex], a
+ ret
+
+.unused
+ ld hl, wJumptableIndex
+ dec [hl]
+ ret
+
+.b_button
+ ld a, $6
+ ld [wJumptableIndex], a
+ ret
+
+.PrepSubmenu:
+ xor a
+ ldh [hBGMapMode], a
+ call ClearSprites
+ call BillsPC_GetSelectedPokemonSpecies
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ ld de, PCString_WhatsUp
+ call BillsPC_PlaceString
+ ld a, $1
+ ld [wMenuCursorY], a
+ call BillsPC_IncrementJumptableIndex
+ ret
+
+.MoveMonWOMailSubmenu:
+ ld hl, .MenuHeader
+ call CopyMenuHeader
+ ld a, [wMenuCursorY]
+ call StoreTo_wMenuCursorBuffer
+ call VerticalMenu
+ jp c, .Cancel
+ ld a, [wMenuCursorY]
+ dec a
+ and %11
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable2
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Jumptable2:
+ dw .Move
+ dw .Stats
+ dw .Cancel
+
+.Move:
+ call BillsPC_CheckMail_PreventBlackout
+ jp c, .Cancel
+ ld a, [wBillsPC_ScrollPosition]
+ ld [wBillsPC_BackupScrollPosition], a
+ ld a, [wBillsPC_CursorPosition]
+ ld [wBillsPC_BackupCursorPosition], a
+ ld a, [wBillsPC_LoadedBox]
+ ld [wBillsPC_BackupLoadedBox], a
+ ld a, $4
+ ld [wJumptableIndex], a
+ ret
+
+.Stats:
+ call LoadStandardMenuHeader
+ call BillsPC_StatsScreen
+ call ExitMenu
+ call PCMonInfo
+ call BillsPC_GetSelectedPokemonSpecies
+ ld [wCurPartySpecies], a
+ ld a, SCGB_BILLS_PC
+ call BillsPC_ApplyPalettes
+ ret
+
+.Cancel:
+ ld a, $0
+ ld [wJumptableIndex], a
+ ret
+
+.MenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 9, 4, SCREEN_WIDTH - 1, 13
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData:
+ db STATICMENU_CURSOR ; flags
+ db 3 ; items
+ db "MOVE@"
+ db "STATS@"
+ db "CANCEL@"
+
+.PrepInsertCursor:
+ xor a
+ ldh [hBGMapMode], a
+ call CopyBoxmonSpecies
+ ld de, PCString_MoveToWhere
+ call BillsPC_PlaceString
+ ld a, $5
+ ld [wBillsPC_NumMonsOnScreen], a
+ call BillsPC_RefreshTextboxes
+ call BillsPC_MoveMonWOMail_BoxNameAndArrows
+ call ClearSprites
+ call BillsPC_UpdateInsertCursor
+ call WaitBGMap
+ call BillsPC_IncrementJumptableIndex
+ ret
+
+.Joypad2:
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b_button_2
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a_button_2
+ call MoveMonWithoutMail_DPad_2
+ jr c, .dpad_2
+ and a
+ ret z
+ call BillsPC_UpdateInsertCursor
+ xor a
+ ldh [hBGMapMode], a
+ call BillsPC_RefreshTextboxes
+ ld a, $1
+ ldh [hBGMapMode], a
+ call DelayFrame
+ call DelayFrame
+ ret
+
+.dpad_2
+ xor a
+ ld [wBillsPC_CursorPosition], a
+ ld [wBillsPC_ScrollPosition], a
+ ld a, $4
+ ld [wJumptableIndex], a
+ ret
+
+.a_button_2
+ call BillsPC_CheckSpaceInDestination
+ jr c, .no_space
+ call MovePKMNWitoutMail_InsertMon
+ ld a, $0
+ ld [wJumptableIndex], a
+ ret
+
+.no_space
+ ld hl, wJumptableIndex
+ dec [hl]
+ ret
+
+.b_button_2
+ ld a, [wBillsPC_BackupScrollPosition]
+ ld [wBillsPC_ScrollPosition], a
+ ld a, [wBillsPC_BackupCursorPosition]
+ ld [wBillsPC_CursorPosition], a
+ ld a, [wBillsPC_BackupLoadedBox]
+ ld [wBillsPC_LoadedBox], a
+ ld a, $0
+ ld [wJumptableIndex], a
+ ret
+
+BillsPC_InitRAM:
+ call ClearBGPalettes
+ call ClearSprites
+ call ClearTilemap
+ call BillsPC_InitGFX
+ ld hl, wBillsPCData
+ ld bc, wBillsPCDataEnd - wBillsPCData
+ xor a
+ call ByteFill
+ xor a
+ ld [wJumptableIndex], a
+ ld [wce64], a
+ ld [wce65], a
+ ld [wce66], a
+ ld [wBillsPC_CursorPosition], a
+ ld [wBillsPC_ScrollPosition], a
+ ret
+
+BillsPC_IncrementJumptableIndex:
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+BillsPC_EndJumptableLoop:
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+_StatsScreenDPad:
+ ld a, [wBillsPC_NumMonsOnScreen]
+ ld d, a
+ ld a, [wBillsPC_NumMonsInBox]
+ and a
+ jr z, .empty
+ dec a
+ cp $1
+ jr z, .empty
+ ld e, a
+ ld a, [hl]
+ and D_UP
+ jr nz, BillsPC_PressUp
+ ld a, [hl]
+ and D_DOWN
+ jr nz, BillsPC_PressDown
+.empty
+ jp BillsPC_JoypadDidNothing
+
+Withdraw_UpDown:
+ ld hl, hJoyLast
+ ld a, [wBillsPC_NumMonsOnScreen]
+ ld d, a
+ ld a, [wBillsPC_NumMonsInBox]
+ ld e, a
+ and a
+ jr z, .empty
+ ld a, [hl]
+ and D_UP
+ jr nz, BillsPC_PressUp
+ ld a, [hl]
+ and D_DOWN
+ jr nz, BillsPC_PressDown
+.empty
+ jp BillsPC_JoypadDidNothing
+
+MoveMonWithoutMail_DPad:
+ ld hl, hJoyLast
+ ld a, [wBillsPC_NumMonsOnScreen]
+ ld d, a
+ ld a, [wBillsPC_NumMonsInBox]
+ ld e, a
+ and a
+ jr z, .check_left_right
+ ld a, [hl]
+ and D_UP
+ jr nz, BillsPC_PressUp
+ ld a, [hl]
+ and D_DOWN
+ jr nz, BillsPC_PressDown
+
+.check_left_right
+ ld a, [hl]
+ and D_LEFT
+ jr nz, BillsPC_PressLeft
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, BillsPC_PressRight
+ jr BillsPC_JoypadDidNothing
+
+MoveMonWithoutMail_DPad_2:
+ ld hl, hJoyLast
+ ld a, [wBillsPC_NumMonsOnScreen]
+ ld d, a
+ ld a, [wBillsPC_NumMonsInBox]
+ ld e, a
+ and a
+ jr z, .check_left_right
+
+ ld a, [hl]
+ and D_UP
+ jr nz, BillsPC_PressUp
+ ld a, [hl]
+ and D_DOWN
+ jr nz, BillsPC_PressDown
+
+.check_left_right
+ ld a, [hl]
+ and D_LEFT
+ jr nz, BillsPC_PressLeft
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, BillsPC_PressRight
+ jr BillsPC_JoypadDidNothing
+
+BillsPC_PressUp:
+ ld hl, wBillsPC_CursorPosition
+ ld a, [hl]
+ and a
+ jr z, .top
+ dec [hl]
+ jr BillsPC_UpDownDidSomething
+
+.top
+ ld hl, wBillsPC_ScrollPosition
+ ld a, [hl]
+ and a
+ jr z, BillsPC_JoypadDidNothing
+ dec [hl]
+ jr BillsPC_UpDownDidSomething
+
+BillsPC_PressDown:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ inc a
+ cp e
+ jr nc, BillsPC_JoypadDidNothing
+
+ ld hl, wBillsPC_CursorPosition
+ ld a, [hl]
+ inc a
+ cp d
+ jr nc, .not_bottom
+ inc [hl]
+ jr BillsPC_UpDownDidSomething
+
+.not_bottom
+ ld hl, wBillsPC_ScrollPosition
+ inc [hl]
+ jr BillsPC_UpDownDidSomething
+
+BillsPC_PressLeft:
+ ld hl, wBillsPC_LoadedBox
+ ld a, [hl]
+ and a
+ jr z, .wrap_around
+ dec [hl]
+ jr BillsPC_LeftRightDidSomething
+
+.wrap_around
+ ld [hl], NUM_BOXES
+ jr BillsPC_LeftRightDidSomething
+
+BillsPC_PressRight:
+ ld hl, wBillsPC_LoadedBox
+ ld a, [hl]
+ cp NUM_BOXES
+ jr z, .wrap_around
+ inc [hl]
+ jr BillsPC_LeftRightDidSomething
+
+.wrap_around
+ ld [hl], 0
+ jr BillsPC_LeftRightDidSomething
+
+BillsPC_JoypadDidNothing:
+ xor a
+ and a
+ ret
+
+BillsPC_UpDownDidSomething:
+ ld a, TRUE
+ and a
+ ret
+
+BillsPC_LeftRightDidSomething:
+ scf
+ ret
+
+BillsPC_PlaceString:
+ push de
+ hlcoord 0, 15
+ lb bc, 1, 18
+ call Textbox
+ pop de
+ hlcoord 1, 16
+ call PlaceString
+ ret
+
+BillsPC_MoveMonWOMail_BoxNameAndArrows:
+ call BillsPC_BoxName
+ hlcoord 8, 1
+ ld [hl], $5f
+ hlcoord 19, 1
+ ld [hl], $5e
+ ret
+
+BillsPC_BoxName:
+ hlcoord 8, 0
+ lb bc, 1, 10
+ call Textbox
+
+ ld a, [wBillsPC_LoadedBox]
+ and a
+ jr z, .party
+
+ cp NUM_BOXES + 1
+ jr nz, .gotbox
+
+ ld a, [wCurBox]
+ inc a
+.gotbox
+ dec a
+ ld hl, wBoxNames
+ ld bc, BOX_NAME_LENGTH
+ call AddNTimes
+ ld e, l
+ ld d, h
+ jr .print
+
+.party
+ ld de, .PartyPKMN
+.print
+ hlcoord 10, 1
+ call PlaceString
+ ret
+
+.PartyPKMN:
+ db "PARTY <PK><MN>@"
+
+PCMonInfo:
+; Display a monster's pic and
+; attributes when highlighting
+; it in a PC menu.
+
+; Includes the neat cascading
+; effect when showing the pic.
+
+; Example: Species, level, gender,
+; whether it's holding an item.
+
+ hlcoord 0, 0
+ lb bc, 15, 8
+ call ClearBox
+
+ hlcoord 8, 14
+ lb bc, 1, 3
+ call ClearBox
+
+ call BillsPC_GetSelectedPokemonSpecies
+ and a
+ ret z
+ cp -1
+ ret z
+
+ ld [wTempSpecies], a
+ hlcoord 1, 4
+ xor a
+ ld b, 7
+.row
+ ld c, 7
+ push af
+ push hl
+.col
+ ld [hli], a
+ add 7
+ dec c
+ jr nz, .col
+ pop hl
+ ld de, SCREEN_WIDTH
+ add hl, de
+ pop af
+ inc a
+ dec b
+ jr nz, .row
+
+ call BillsPC_LoadMonStats
+ ld a, [wTempSpecies]
+ ld [wCurPartySpecies], a
+ ld [wCurSpecies], a
+ ld hl, wTempMonDVs
+ predef GetUnownLetter
+ call GetBaseData
+ ld de, vTiles2 tile $00
+ predef GetMonFrontpic
+ xor a
+ ld [wBillsPC_MonHasMail], a
+ ld a, [wCurPartySpecies]
+ ld [wTempSpecies], a
+ cp EGG
+ ret z
+
+ call GetBasePokemonName
+ hlcoord 1, 14
+ call PlaceString
+
+ hlcoord 1, 12
+ call PrintLevel
+
+ ld a, $3
+ ld [wMonType], a
+ farcall GetGender
+ jr c, .skip_gender
+ ld a, "♂"
+ jr nz, .printgender
+ ld a, "♀"
+.printgender
+ hlcoord 5, 12
+ ld [hl], a
+.skip_gender
+
+ ld a, [wTempMonItem]
+ and a
+ ret z
+
+ ld d, a
+ callfar ItemIsMail
+ jr c, .mail
+ ld a, $5d ; item icon
+ jr .printitem
+.mail
+ ld a, $1
+ ld [wBillsPC_MonHasMail], a
+ ld a, $5c ; mail icon
+.printitem
+ hlcoord 7, 12
+ ld [hl], a
+ ret
+
+BillsPC_LoadMonStats:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld e, a
+ ld d, $0
+ ld hl, wBillsPCPokemonList + 1 ; box number
+ add hl, de
+ add hl, de
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .party
+ cp NUM_BOXES + 1
+ jr z, .sBox
+ ld b, a
+ call GetBoxPointer
+ ld a, b
+ call OpenSRAM
+ push hl
+ ld bc, sBoxMon1Level - sBox
+ add hl, bc
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld a, [hl]
+ ld [wTempMonLevel], a
+ pop hl
+ push hl
+ ld bc, sBoxMon1Item - sBox
+ add hl, bc
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld a, [hl]
+ ld [wTempMonItem], a
+ pop hl
+ ld bc, sBoxMon1DVs - sBox
+ add hl, bc
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld de, wTempMonDVs
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ call CloseSRAM
+ ret
+
+.party
+ ld hl, wPartyMon1Level
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld a, [hl]
+ ld [wTempMonLevel], a
+ ld hl, wPartyMon1Item
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld a, [hl]
+ ld [wTempMonItem], a
+ ld hl, wPartyMon1DVs
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld de, wTempMonDVs
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ ret
+
+.sBox
+ ld a, BANK(sBox)
+ call OpenSRAM
+ ld hl, sBoxMon1Level
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld a, [hl]
+ ld [wTempMonLevel], a
+
+ ld hl, sBoxMon1Item
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld a, [hl]
+ ld [wTempMonItem], a
+
+ ld hl, sBoxMon1DVs
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld de, wTempMonDVs
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+
+ call CloseSRAM
+ ret
+
+BillsPC_RefreshTextboxes:
+ hlcoord 8, 2
+ lb bc, 10, 10
+ call Textbox
+
+ hlcoord 8, 2
+ ld [hl], "└"
+ hlcoord 19, 2
+ ld [hl], "┘"
+
+ ld a, [wBillsPC_ScrollPosition]
+ ld e, a
+ ld d, 0
+ ld hl, wBillsPCPokemonList
+ add hl, de
+ add hl, de
+ add hl, de
+ ld e, l
+ ld d, h
+ hlcoord 9, 4
+ ld a, [wBillsPC_NumMonsOnScreen]
+.loop
+ push af
+ push de
+ push hl
+ call .PlaceNickname
+ pop hl
+ ld de, 2 * SCREEN_WIDTH
+ add hl, de
+ pop de
+ inc de
+ inc de
+ inc de
+ pop af
+ dec a
+ jr nz, .loop
+ ret
+
+.CancelString:
+ db "CANCEL@"
+
+.PlaceNickname:
+ ld a, [de]
+ and a
+ ret z
+ cp -1
+ jr nz, .get_nickname
+ ld de, .CancelString
+ call PlaceString
+ ret
+
+.get_nickname
+ inc de
+ ld a, [de]
+ ld b, a
+ inc de
+ ld a, [de]
+ ld e, a
+ ld a, b
+ and a
+ jr z, .party
+ cp NUM_BOXES + 1
+ jr z, .sBox
+ push hl
+ call GetBoxPointer
+ ld a, b
+ call OpenSRAM
+ push hl
+ ld bc, sBoxMons - sBox
+ add hl, bc
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, e
+ call AddNTimes
+ ld a, [hl]
+ pop hl
+ and a
+ jr z, .boxfail
+ ld bc, sBoxMonNicknames - sBox
+ add hl, bc
+ ld bc, MON_NAME_LENGTH
+ ld a, e
+ call AddNTimes
+ ld de, wStringBuffer1
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+ call CloseSRAM
+ pop hl
+ ld de, wStringBuffer1
+ call PlaceString
+ ret
+
+.boxfail
+ call CloseSRAM
+ pop hl
+ jr .placeholder_string
+
+.party
+ push hl
+ ld hl, wPartySpecies
+ ld d, $0
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .partyfail
+ ld hl, wPartyMonNicknames
+ ld bc, MON_NAME_LENGTH
+ ld a, e
+ call AddNTimes
+ ld de, wStringBuffer1
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+ pop hl
+ ld de, wStringBuffer1
+ call PlaceString
+ ret
+
+.partyfail
+ pop hl
+ jr .placeholder_string
+
+.sBox
+ push hl
+ ld a, BANK(sBox)
+ call OpenSRAM
+ ld hl, sBoxSpecies
+ ld d, $0
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .sBoxFail
+ ld hl, sBoxMonNicknames
+ ld bc, MON_NAME_LENGTH
+ ld a, e
+ call AddNTimes
+ ld de, wStringBuffer1
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+ call CloseSRAM
+ pop hl
+ ld de, wStringBuffer1
+ call PlaceString
+ ret
+
+.sBoxFail
+ call CloseSRAM
+ pop hl
+.placeholder_string
+ ld de, .Placeholder
+ call PlaceString
+ ret
+
+.Placeholder:
+ db "-----@"
+
+copy_box_data: MACRO
+.loop\@
+ ld a, [hl]
+ cp -1
+ jr z, .done\@
+ and a
+ jr z, .done\@
+ ld [de], a
+ inc de
+ ld a, [wBillsPC_LoadedBox]
+ ld [de], a
+ inc de
+ ld a, [wceee]
+ ld [de], a
+ inc a
+ ld [wceee], a
+ inc de
+ inc hl
+ ld a, [wceef]
+ inc a
+ ld [wceef], a
+ jr .loop\@
+
+.done\@
+if \1
+ call CloseSRAM
+endc
+ ld a, -1
+ ld [de], a
+ ld a, [wceef]
+ inc a
+ ld [wBillsPC_NumMonsInBox], a
+ENDM
+
+CopyBoxmonSpecies:
+ xor a
+ ld hl, wBillsPCPokemonList
+ ld bc, 3 * 30
+ call ByteFill
+ ld de, wBillsPCPokemonList
+ xor a
+ ld [wceee], a
+ ld [wceef], a
+ ld a, [wBillsPC_LoadedBox]
+ and a
+ jr z, .party
+ cp NUM_BOXES + 1
+ jr z, .sBox
+ ld b, a
+ call GetBoxPointer
+ ld a, b
+ call OpenSRAM
+ inc hl
+ copy_box_data 1
+ ret
+
+.party
+ ld hl, wPartySpecies
+ copy_box_data 0
+ ret
+
+.sBox
+ ld a, BANK(sBox)
+ call OpenSRAM
+ ld hl, sBoxSpecies
+ copy_box_data 1
+ ret
+
+BillsPC_GetSelectedPokemonSpecies:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld e, a
+ ld d, $0
+ ld hl, wBillsPCPokemonList
+ add hl, de
+ add hl, de
+ add hl, de
+ ld a, [hl]
+ ret
+
+BillsPC_UpdateSelectionCursor:
+ ld a, [wBillsPC_NumMonsInBox]
+ and a
+ jr nz, .place_cursor
+ call ClearSprites
+ ret
+
+.place_cursor
+ ld hl, .OAM
+ ld de, wVirtualOAMSprite00
+.loop
+ ld a, [hl]
+ cp -1
+ ret z
+ ld a, [wBillsPC_CursorPosition]
+ and $7
+ swap a
+ add [hl]
+ inc hl
+ ld [de], a ; y
+ inc de
+rept SPRITEOAMSTRUCT_LENGTH - 1
+ ld a, [hli]
+ ld [de], a
+ inc de
+endr
+ jr .loop
+
+.OAM:
+ dbsprite 9, 5, 7, 1, $00, 0
+ dbsprite 10, 5, 7, 1, $01, 0
+ dbsprite 11, 5, 7, 1, $01, 0
+ dbsprite 12, 5, 7, 1, $01, 0
+ dbsprite 13, 5, 7, 1, $01, 0
+ dbsprite 14, 5, 7, 1, $01, 0
+ dbsprite 15, 5, 7, 1, $01, 0
+ dbsprite 16, 5, 7, 1, $01, 0
+ dbsprite 17, 5, 7, 1, $01, 0
+ dbsprite 18, 5, 7, 1, $02, 0
+ dbsprite 9, 6, 7, 1, $03, 0
+ dbsprite 10, 6, 7, 1, $04, 0
+ dbsprite 11, 6, 7, 1, $04, 0
+ dbsprite 12, 6, 7, 1, $04, 0
+ dbsprite 13, 6, 7, 1, $04, 0
+ dbsprite 14, 6, 7, 1, $04, 0
+ dbsprite 15, 6, 7, 1, $04, 0
+ dbsprite 16, 6, 7, 1, $04, 0
+ dbsprite 17, 6, 7, 1, $04, 0
+ dbsprite 18, 6, 7, 1, $05, 0
+ db -1
+
+BillsPC_UpdateInsertCursor:
+ ld hl, .OAM
+ ld de, wVirtualOAMSprite00
+.loop
+ ld a, [hl]
+ cp -1
+ ret z
+ ld a, [wBillsPC_CursorPosition]
+ and $7
+ swap a
+ add [hl]
+ inc hl
+ ld [de], a ; y
+ inc de
+rept SPRITEOAMSTRUCT_LENGTH - 1
+ ld a, [hli]
+ ld [de], a
+ inc de
+endr
+ jr .loop
+
+.OAM:
+ dbsprite 10, 4, 0, 7, $06, 0
+ dbsprite 11, 5, 0, 3, $01, 0
+ dbsprite 12, 5, 0, 3, $01, 0
+ dbsprite 13, 5, 0, 3, $01, 0
+ dbsprite 14, 5, 0, 3, $01, 0
+ dbsprite 15, 5, 0, 3, $01, 0
+ dbsprite 16, 5, 0, 3, $01, 0
+ dbsprite 17, 5, 0, 3, $01, 0
+ dbsprite 18, 5, 0, 3, $01, 0
+ dbsprite 19, 4, 0, 7, $07, 0
+ db -1
+
+Unreferenced_BillsPC_FillBox:
+.row
+ push bc
+ push hl
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+
+BillsPC_CheckSpaceInDestination:
+; If moving within a box, no need to be here.
+ ld hl, wBillsPC_LoadedBox
+ ld a, [wBillsPC_BackupLoadedBox]
+ cp [hl]
+ jr z, .same_box
+
+; Exceeding box or party capacity is a big no-no.
+ ld a, [wBillsPC_LoadedBox]
+ and a
+ jr z, .party
+ ld e, MONS_PER_BOX + 1
+ jr .compare
+
+.party
+ ld e, PARTY_LENGTH + 1
+.compare
+ ld a, [wBillsPC_NumMonsInBox]
+ cp e
+ jr nc, .no_room
+.same_box
+ and a
+ ret
+
+.no_room
+ ld de, PCString_TheresNoRoom
+ call BillsPC_PlaceString
+ ld de, SFX_WRONG
+ call WaitPlaySFX
+ call WaitSFX
+ ld c, 50
+ call DelayFrames
+ scf
+ ret
+
+BillsPC_CheckMail_PreventBlackout:
+ ld a, [wBillsPC_LoadedBox]
+ and a
+ jr nz, .Okay
+ ld a, [wBillsPC_NumMonsInBox]
+ cp $3
+ jr c, .ItsYourLastPokemon
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ farcall CheckCurPartyMonFainted
+ jr c, .AllOthersFainted
+ ld a, [wBillsPC_MonHasMail]
+ and a
+ jr nz, .HasMail
+.Okay:
+ and a
+ ret
+
+.HasMail:
+ ld de, PCString_RemoveMail
+ jr .NotOkay
+
+.AllOthersFainted:
+ ld de, PCString_NoMoreUsablePKMN
+ jr .NotOkay
+
+.ItsYourLastPokemon:
+ ld de, PCString_ItsYourLastPKMN
+.NotOkay:
+ call BillsPC_PlaceString
+ ld de, SFX_WRONG
+ call WaitPlaySFX
+ call WaitSFX
+ ld c, 50
+ call DelayFrames
+ scf
+ ret
+
+BillsPC_IsMonAnEgg:
+ ld a, [wCurPartySpecies]
+ cp EGG
+ jr z, .egg
+ and a
+ ret
+
+.egg
+ ld de, PCString_NoReleasingEGGS
+ call BillsPC_PlaceString
+ ld de, SFX_WRONG
+ call WaitPlaySFX
+ call WaitSFX
+ ld c, 50
+ call DelayFrames
+ scf
+ ret
+
+BillsPC_StatsScreen:
+ call LowVolume
+ call BillsPC_CopyMon
+ ld a, 3
+ ld [wMonType], a
+ predef StatsScreenInit
+ call BillsPC_InitGFX
+ call MaxVolume
+ ret
+
+StatsScreenDPad:
+ call JoyTextDelay
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and A_BUTTON | B_BUTTON | D_RIGHT | D_LEFT
+ ld [wMenuJoypad], a
+ jr nz, .pressed_a_b_right_left
+ ld a, [hl]
+ and D_DOWN | D_UP
+ ld [wMenuJoypad], a
+ jr nz, .pressed_down_up
+ call DelayFrame
+ jr StatsScreenDPad
+
+.pressed_down_up
+ call _StatsScreenDPad
+ and a
+ jr z, StatsScreenDPad
+ call BillsPC_GetSelectedPokemonSpecies
+ ld [wTempSpecies], a
+ call BillsPC_LoadMonStats
+ ld a, [wTempSpecies]
+ ld [wCurPartySpecies], a
+ ld [wCurSpecies], a
+ ld hl, wTempMonDVs
+ predef GetUnownLetter
+ call GetBaseData
+ call BillsPC_CopyMon
+.pressed_a_b_right_left
+ ret
+
+BillsPC_CopyMon:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ ld a, [wBillsPC_LoadedBox]
+ and a
+ jr z, .party
+ cp NUM_BOXES + 1
+ jr nz, .box
+ ld a, BANK(sBox)
+ call OpenSRAM
+ ld hl, sBoxSpecies
+ call CopySpeciesToTemp
+ ld hl, sBoxMonNicknames
+ call CopyNicknameToTemp
+ ld hl, sBoxMonOT
+ call CopyOTNameToTemp
+ ld hl, sBoxMons
+ ld bc, BOXMON_STRUCT_LENGTH
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ ld de, wBufferMon
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call CopyBytes
+ call CloseSRAM
+ farcall CalcBufferMonStats
+ ret
+
+.party
+ ld hl, wPartySpecies
+ call CopySpeciesToTemp
+ ld hl, wPartyMonNicknames
+ call CopyNicknameToTemp
+ ld hl, wPartyMonOT
+ call CopyOTNameToTemp
+ ld hl, wPartyMon1
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ ld de, wBufferMon
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call CopyBytes
+ ret
+
+.box
+ ld b, a
+ call GetBoxPointer
+ ld a, b
+ call OpenSRAM
+ push hl
+ inc hl
+ call CopySpeciesToTemp
+ pop hl
+ push hl
+ ld bc, sBoxMonNicknames - sBox
+ add hl, bc
+ call CopyNicknameToTemp
+ pop hl
+ push hl
+ ld bc, sBoxMonOT - sBox
+ add hl, bc
+ call CopyOTNameToTemp
+ pop hl
+ ld bc, sBoxMons - sBox
+ add hl, bc
+ ld bc, BOXMON_STRUCT_LENGTH
+ call CopyMonToTemp
+ call CloseSRAM
+ farcall CalcBufferMonStats
+ ret
+
+DepositPokemon:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ ld hl, wPartyMonNicknames
+ ld a, [wCurPartyMon]
+ call GetNick
+ ld a, PC_DEPOSIT
+ ld [wPokemonWithdrawDepositParameter], a
+ predef SendGetMonIntoFromBox
+ jr c, .asm_boxisfull
+ xor a ; REMOVE_PARTY
+ ld [wPokemonWithdrawDepositParameter], a
+ farcall RemoveMonFromPartyOrBox
+ ld a, [wCurPartySpecies]
+ call PlayMonCry
+ hlcoord 0, 0
+ lb bc, 15, 8
+ call ClearBox
+ hlcoord 8, 14
+ lb bc, 1, 3
+ call ClearBox
+ hlcoord 0, 15
+ lb bc, 1, 18
+ call Textbox
+ call WaitBGMap
+ hlcoord 1, 16
+ ld de, PCString_Stored
+ call PlaceString
+ ld l, c
+ ld h, b
+ ld de, wStringBuffer1
+ call PlaceString
+ ld a, "!"
+ ld [bc], a
+ ld c, 50
+ call DelayFrames
+ and a
+ ret
+
+.asm_boxisfull
+ ld de, PCString_BoxFull
+ call BillsPC_PlaceString
+ ld de, SFX_WRONG
+ call WaitPlaySFX
+ call WaitSFX
+ ld c, 50
+ call DelayFrames
+ scf
+ ret
+
+TryWithdrawPokemon:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ ld a, BANK(sBoxMonNicknames)
+ call OpenSRAM
+ ld a, [wCurPartyMon]
+ ld hl, sBoxMonNicknames
+ call GetNick
+ call CloseSRAM
+ xor a
+ ld [wPokemonWithdrawDepositParameter], a
+ predef SendGetMonIntoFromBox
+ jr c, .PartyFull
+ ld a, REMOVE_BOX
+ ld [wPokemonWithdrawDepositParameter], a
+ farcall RemoveMonFromPartyOrBox
+ ld a, [wCurPartySpecies]
+ call PlayMonCry
+ hlcoord 0, 0
+ lb bc, 15, 8
+ call ClearBox
+ hlcoord 8, 14
+ lb bc, 1, 3
+ call ClearBox
+ hlcoord 0, 15
+ lb bc, 1, 18
+ call Textbox
+ call WaitBGMap
+ hlcoord 1, 16
+ ld de, PCString_Got
+ call PlaceString
+ ld l, c
+ ld h, b
+ ld de, wStringBuffer1
+ call PlaceString
+ ld a, "!"
+ ld [bc], a
+ ld c, 50
+ call DelayFrames
+ and a
+ ret
+
+.PartyFull:
+ ld de, PCString_PartyFull
+ call BillsPC_PlaceString
+ ld de, SFX_WRONG
+ call WaitPlaySFX
+ call WaitSFX
+ ld c, 50
+ call DelayFrames
+ scf
+ ret
+
+ReleasePKMN_ByePKMN:
+ hlcoord 0, 0
+ lb bc, 15, 8
+ call ClearBox
+ hlcoord 8, 14
+ lb bc, 1, 3
+ call ClearBox
+ hlcoord 0, 15
+ lb bc, 1, 18
+ call Textbox
+
+ call WaitBGMap
+ ld a, [wCurPartySpecies]
+ call GetCryIndex
+ jr c, .skip_cry
+ ld e, c
+ ld d, b
+ call PlayCry
+.skip_cry
+
+ ld a, [wCurPartySpecies]
+ ld [wTempSpecies], a
+ call GetPokemonName
+ hlcoord 1, 16
+ ld de, PCString_ReleasedPKMN
+ call PlaceString
+ ld c, 80
+ call DelayFrames
+ hlcoord 0, 15
+ lb bc, 1, 18
+ call Textbox
+ hlcoord 1, 16
+ ld de, PCString_Bye
+ call PlaceString
+ ld l, c
+ ld h, b
+ inc hl
+ ld de, wStringBuffer1
+ call PlaceString
+ ld l, c
+ ld h, b
+ ld [hl], "!"
+ ld c, 50
+ call DelayFrames
+ ret
+
+MovePKMNWitoutMail_InsertMon:
+ push hl
+ push de
+ push bc
+ push af
+ hlcoord 0, 15
+ lb bc, 1, 18
+ call Textbox
+ hlcoord 1, 16
+ ld de, .Saving_LeaveOn
+ call PlaceString
+ ld c, 20
+ call DelayFrames
+ pop af
+ pop bc
+ pop de
+ pop hl
+ ld a, [wCurBox]
+ push af
+ ld bc, 0
+ ld a, [wBillsPC_BackupLoadedBox]
+ and a
+ jr nz, .moving_from_box
+ set 0, c
+
+.moving_from_box
+ ld a, [wBillsPC_LoadedBox]
+ and a
+ jr nz, .moving_to_box
+ set 1, c
+
+.moving_to_box
+ ld hl, .Jumptable
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, .dw_return
+ push de
+ jp hl
+
+.dw_return
+ pop af
+ ld e, a
+ farcall MoveMonWOMail_InsertMon_SaveGame
+ ret
+
+.Saving_LeaveOn:
+ db "Saving… Leave ON!@"
+
+.Jumptable:
+ dw .BoxToBox
+ dw .PartyToBox
+ dw .BoxToParty
+ dw .PartyToParty
+
+.BoxToBox:
+ ld hl, wBillsPC_BackupLoadedBox
+ ld a, [wBillsPC_LoadedBox]
+ cp [hl]
+ jr z, .same_box
+ call .CopyFromBox
+ call .CopyToBox
+ ret
+
+.same_box
+ call .CopyFromBox
+ call .CheckTrivialMove
+ call .CopyToBox
+ ret
+
+.PartyToBox:
+ call .CopyFromParty
+ ld a, $1
+ ld [wGameLogicPaused], a
+ farcall SaveGameData
+ xor a
+ ld [wGameLogicPaused], a
+ call .CopyToBox
+ ret
+
+.BoxToParty:
+ call .CopyFromBox
+ call .CopyToParty
+ ret
+
+.PartyToParty:
+ call .CopyFromParty
+ call .CheckTrivialMove
+ call .CopyToParty
+ ret
+
+.CheckTrivialMove:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld e, a
+ ld a, [wBillsPC_BackupCursorPosition]
+ ld hl, wBillsPC_BackupScrollPosition
+ add [hl]
+ cp e
+ ret nc
+ ld hl, wBillsPC_CursorPosition
+ ld a, [hl]
+ and a
+ jr z, .top_of_screen
+ dec [hl]
+ ret
+
+.top_of_screen
+ ld hl, wBillsPC_ScrollPosition
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ ret
+
+.CopyFromBox:
+ ld a, [wBillsPC_BackupLoadedBox]
+ dec a
+ ld e, a
+ farcall MoveMonWOMail_SaveGame
+ ld a, [wBillsPC_BackupCursorPosition]
+ ld hl, wBillsPC_BackupScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ ld a, BANK(sBox)
+ call OpenSRAM
+ ld hl, sBoxSpecies
+ call CopySpeciesToTemp
+ ld hl, sBoxMonNicknames
+ call CopyNicknameToTemp
+ ld hl, sBoxMonOT
+ call CopyOTNameToTemp
+ ld hl, sBoxMons
+ ld bc, BOXMON_STRUCT_LENGTH
+ call CopyMonToTemp
+ call CloseSRAM
+ farcall CalcBufferMonStats
+ ld a, REMOVE_BOX
+ ld [wPokemonWithdrawDepositParameter], a
+ farcall RemoveMonFromPartyOrBox
+ ret
+
+.CopyToBox:
+ ld a, [wBillsPC_LoadedBox]
+ dec a
+ ld e, a
+ farcall MoveMonWOMail_SaveGame
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ farcall InsertPokemonIntoBox
+ ret
+
+.CopyFromParty:
+ ld a, [wBillsPC_BackupCursorPosition]
+ ld hl, wBillsPC_BackupScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ ld hl, wPartySpecies
+ call CopySpeciesToTemp
+ ld hl, wPartyMonNicknames
+ call CopyNicknameToTemp
+ ld hl, wPartyMonOT
+ call CopyOTNameToTemp
+ ld hl, wPartyMon1Species
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call CopyMonToTemp
+ xor a ; REMOVE_PARTY
+ ld [wPokemonWithdrawDepositParameter], a
+ farcall RemoveMonFromPartyOrBox
+ ret
+
+.CopyToParty:
+ ld a, [wBillsPC_CursorPosition]
+ ld hl, wBillsPC_ScrollPosition
+ add [hl]
+ ld [wCurPartyMon], a
+ farcall InsertPokemonIntoParty
+ ret
+
+CopySpeciesToTemp:
+ ld a, [wCurPartyMon]
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [hl]
+ ld [wCurPartySpecies], a
+ ret
+
+CopyNicknameToTemp:
+ ld bc, MON_NAME_LENGTH
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ ld de, wBufferMonNick
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+ ret
+
+CopyOTNameToTemp:
+ ld bc, NAME_LENGTH
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ ld de, wBufferMonOT
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ret
+
+CopyMonToTemp:
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ ld de, wBufferMon
+ call CopyBytes
+ ret
+
+GetBoxPointer:
+ dec b
+ ld c, b
+ ld b, 0
+ ld hl, .boxes
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld b, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ret
+
+.boxes
+ ; bank, address
+ dba sBox1
+ dba sBox2
+ dba sBox3
+ dba sBox4
+ dba sBox5
+ dba sBox6
+ dba sBox7
+ dba sBox8
+ dba sBox9
+ dba sBox10
+ dba sBox11
+ dba sBox12
+ dba sBox13
+ dba sBox14
+
+BillsPC_ApplyPalettes:
+ ld b, a
+ call GetSGBLayout
+ ld a, %11100100
+ call DmgToCgbBGPals
+ ld a, %11111100
+ call DmgToCgbObjPal0
+ ret
+
+BillsPC_Jumptable:
+ ld e, a
+ ld d, $0
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ret
+
+BillsPC_InitGFX:
+ call DisableLCD
+ ld hl, vTiles2 tile $00
+ ld bc, $31 tiles
+ xor a
+ call ByteFill
+ call LoadStandardFont
+ call LoadFontsBattleExtra
+ ld hl, PCMailGFX
+ ld de, vTiles2 tile $5c
+ ld bc, 4 tiles
+ call CopyBytes
+ ld hl, PCSelectLZ
+ ld de, vTiles0 tile $00
+ call Decompress
+ ld a, 6
+ call SkipMusic
+ call EnableLCD
+ ret
+
+PCSelectLZ: INCBIN "gfx/pc/pc.2bpp.lz"
+PCMailGFX: INCBIN "gfx/pc/pc_mail.2bpp"
+
+PCString_ChooseaPKMN: db "Choose a <PK><MN>.@"
+PCString_WhatsUp: db "What's up?@"
+PCString_ReleasePKMN: db "Release <PK><MN>?@"
+PCString_MoveToWhere: db "Move to where?@"
+PCString_ItsYourLastPKMN: db "It's your last <PK><MN>!@"
+PCString_TheresNoRoom: db "There's no room!@"
+PCString_NoMoreUsablePKMN: db "No more usable <PK><MN>!@"
+PCString_RemoveMail: db "Remove MAIL.@"
+PCString_ReleasedPKMN: db "Released <PK><MN>.@"
+PCString_Bye: db "Bye,@"
+PCString_Stored: db "Stored @"
+PCString_Got: db "Got @"
+PCString_Non: db "Non.@"
+PCString_BoxFull: db "The BOX is full.@"
+PCString_PartyFull: db "The party's full!@"
+PCString_NoReleasingEGGS: db "No releasing EGGS!@"
+
+_ChangeBox:
+ call LoadStandardMenuHeader
+ call BillsPC_ClearTilemap
+.loop
+ xor a
+ ldh [hBGMapMode], a
+ call BillsPC_PrintBoxName
+ call BillsPC_PlaceChooseABoxString
+ ld hl, _ChangeBox_MenuHeader
+ call CopyMenuHeader
+ xor a
+ ld [wMenuScrollPosition], a
+ hlcoord 0, 4
+ lb bc, 8, 9
+ call Textbox
+ call ScrollingMenu
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .done
+ call BillsPC_PlaceWhatsUpString
+ call BillsPC_ChangeBoxSubmenu
+ jr .loop
+.done
+ call CloseWindow
+ ret
+
+BillsPC_ClearTilemap:
+ xor a
+ ldh [hBGMapMode], a
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ ret
+
+_ChangeBox_MenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 1, 5, 9, 12
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData
+ db SCROLLINGMENU_CALL_FUNCTION3_NO_SWITCH | SCROLLINGMENU_ENABLE_FUNCTION3 ; flags
+ db 4, 0 ; rows, columns
+ db SCROLLINGMENU_ITEMS_NORMAL ; item format
+ dba .boxes
+ dba .boxnames
+ dba NULL
+ dba BillsPC_PrintBoxCountAndCapacity
+
+.boxes
+ db NUM_BOXES
+x = 1
+rept NUM_BOXES
+ db x
+x = x + 1
+endr
+ db -1
+
+.boxnames
+ push de
+ ld a, [wMenuSelection]
+ dec a
+ call GetBoxName
+ pop hl
+ call PlaceString
+ ret
+
+GetBoxName:
+ ld bc, BOX_NAME_LENGTH
+ ld hl, wBoxNames
+ call AddNTimes
+ ld d, h
+ ld e, l
+ ret
+
+BillsPC_PrintBoxCountAndCapacity:
+ hlcoord 11, 7
+ lb bc, 5, 7
+ call Textbox
+ ld a, [wMenuSelection]
+ cp -1
+ ret z
+ hlcoord 12, 9
+ ld de, .Pokemon
+ call PlaceString
+ call GetBoxCount
+ ld [wDeciramBuffer], a
+ hlcoord 13, 11
+ ld de, wDeciramBuffer
+ lb bc, 1, 2
+ call PrintNum
+ ld de, .out_of_20
+ call PlaceString
+ ret
+
+.Pokemon:
+ db "#MON@"
+
+.out_of_20
+ ; db "/20@"
+ db "/"
+ db "0" + MONS_PER_BOX / 10 ; "2"
+ db "0" + MONS_PER_BOX % 10 ; "0"
+ db "@"
+
+GetBoxCount:
+ ld a, [wCurBox]
+ ld c, a
+ ld a, [wMenuSelection]
+ dec a
+ cp c
+ jr z, .activebox
+ ld c, a
+ ld b, 0
+ ld hl, .boxbanks
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld b, a
+ call OpenSRAM
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [hl]
+ call CloseSRAM
+ ld c, a
+ ld a, [wSavedAtLeastOnce]
+ and a
+ jr z, .newfile
+ ld a, c
+ ret
+
+.newfile
+ xor a
+ ret
+
+.activebox
+ ld a, BANK(sBoxCount)
+ ld b, a
+ call OpenSRAM
+ ld hl, sBoxCount
+ ld a, [hl]
+ call CloseSRAM
+ ret
+
+.boxbanks
+ dba sBox1
+ dba sBox2
+ dba sBox3
+ dba sBox4
+ dba sBox5
+ dba sBox6
+ dba sBox7
+ dba sBox8
+ dba sBox9
+ dba sBox10
+ dba sBox11
+ dba sBox12
+ dba sBox13
+ dba sBox14
+
+BillsPC_PrintBoxName:
+ hlcoord 0, 0
+ ld b, 2
+ ld c, 18
+ call Textbox
+ hlcoord 1, 2
+ ld de, .Current
+ call PlaceString
+ ld a, [wCurBox]
+ and $f
+ call GetBoxName
+ hlcoord 11, 2
+ call PlaceString
+ ret
+
+.Current:
+ db "CURRENT@"
+
+BillsPC_ChangeBoxSubmenu:
+ ld hl, .MenuHeader
+ call LoadMenuHeader
+ call VerticalMenu
+ call ExitMenu
+ ret c
+ ld a, [wMenuCursorY]
+ cp $1
+ jr z, .Switch
+ cp $2
+ jr z, .Name
+ cp $3
+ jr z, .Print
+ and a
+ ret
+
+.Print:
+ call GetBoxCount
+ and a
+ jr z, .EmptyBox
+ ld e, l
+ ld d, h
+ ld a, [wMenuSelection]
+ dec a
+ ld c, a
+ farcall PrintPCBox
+ call BillsPC_ClearTilemap
+ and a
+ ret
+
+.EmptyBox:
+ call BillsPC_PlaceEmptyBoxString_SFX
+ and a
+ ret
+
+.Switch:
+ ld a, [wMenuSelection]
+ dec a
+ ld e, a
+ ld a, [wCurBox]
+ cp e
+ ret z
+ farcall ChangeBoxSaveGame
+ ret
+
+.Name:
+ ld b, NAME_BOX
+ ld de, wceed
+ farcall NamingScreen
+ call ClearTilemap
+ call LoadStandardFont
+ call LoadFontsBattleExtra
+ ld a, [wMenuSelection]
+ dec a
+ call GetBoxName
+ ld e, l
+ ld d, h
+ ld hl, wceed
+ ld c, BOX_NAME_LENGTH - 1
+ call InitString
+ ld a, [wMenuSelection]
+ dec a
+ call GetBoxName
+ ld de, wceed
+ call CopyName2
+ ret
+
+ hlcoord 11, 7 ; unused
+
+.MenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 11, 4, SCREEN_WIDTH - 1, 13
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData:
+ db STATICMENU_CURSOR ; flags
+ db 4 ; items
+ db "SWITCH@"
+ db "NAME@"
+ db "PRINT@"
+ db "QUIT@"
+
+BillsPC_PlaceChooseABoxString:
+ ld de, .ChooseABox
+ jr BillsPC_PlaceChangeBoxString
+
+.ChooseABox:
+ db "Choose a BOX.@"
+
+BillsPC_PlaceWhatsUpString:
+ ld de, .WhatsUp
+ jr BillsPC_PlaceChangeBoxString
+
+.WhatsUp:
+ db "What's up?@"
+
+BillsPC_PlaceEmptyBoxString_SFX:
+ ld de, .NoMonString
+ call BillsPC_PlaceChangeBoxString
+ ld de, SFX_WRONG
+ call WaitPlaySFX
+ call WaitSFX
+ ld c, 50
+ call DelayFrames
+ ret
+
+.NoMonString:
+ db "There's no #MON.@"
+
+BillsPC_PlaceChangeBoxString:
+ push de
+ hlcoord 0, 14
+ lb bc, 2, 18
+ call Textbox
+ pop de
+ hlcoord 1, 16
+ call PlaceString
+ ld a, $1
+ ldh [hBGMapMode], a
+ ret
diff --git a/gfx/card_flip/card_flip.pal b/gfx/card_flip/card_flip.pal
new file mode 100755
index 00000000..24c5566f
--- /dev/null
+++ b/gfx/card_flip/card_flip.pal
@@ -0,0 +1,44 @@
+ RGB 31, 31, 31
+ RGB 17, 07, 31
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 29, 25, 00
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 31, 13, 30
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 08, 17, 30
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 08, 31, 08
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 17, 07, 31
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 17, 07, 31
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 17, 07, 31
+ RGB 06, 19, 08
+ RGB 00, 00, 00
+
+ RGB 31, 31, 31
+ RGB 31, 31, 31
+ RGB 31, 00, 00
+ RGB 31, 00, 00
diff --git a/gfx/card_flip/card_flip.tilemap b/gfx/card_flip/card_flip.tilemap
new file mode 100755
index 00000000..f6cdbefb
--- /dev/null
+++ b/gfx/card_flip/card_flip.tilemap
Binary files differ
diff --git a/gfx/card_flip/card_flip_1.2bpp.lz b/gfx/card_flip/card_flip_1.2bpp.lz
new file mode 100755
index 00000000..8a60b966
--- /dev/null
+++ b/gfx/card_flip/card_flip_1.2bpp.lz
Binary files differ
diff --git a/gfx/card_flip/card_flip_1.png b/gfx/card_flip/card_flip_1.png
new file mode 100755
index 00000000..d3bfef22
--- /dev/null
+++ b/gfx/card_flip/card_flip_1.png
Binary files differ
diff --git a/gfx/card_flip/card_flip_2.2bpp.lz b/gfx/card_flip/card_flip_2.2bpp.lz
new file mode 100755
index 00000000..f238c797
--- /dev/null
+++ b/gfx/card_flip/card_flip_2.2bpp.lz
Binary files differ
diff --git a/gfx/card_flip/card_flip_2.png b/gfx/card_flip/card_flip_2.png
new file mode 100755
index 00000000..1ac1e29d
--- /dev/null
+++ b/gfx/card_flip/card_flip_2.png
Binary files differ
diff --git a/gfx/card_flip/card_flip_3.2bpp.lz b/gfx/card_flip/card_flip_3.2bpp.lz
new file mode 100755
index 00000000..12baf9a8
--- /dev/null
+++ b/gfx/card_flip/card_flip_3.2bpp.lz
Binary files differ
diff --git a/gfx/card_flip/card_flip_3.png b/gfx/card_flip/card_flip_3.png
new file mode 100755
index 00000000..22745096
--- /dev/null
+++ b/gfx/card_flip/card_flip_3.png
Binary files differ
diff --git a/gfx/card_flip/off.2bpp b/gfx/card_flip/off.2bpp
new file mode 100755
index 00000000..0e7c66a3
--- /dev/null
+++ b/gfx/card_flip/off.2bpp
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/gfx/card_flip/off.png b/gfx/card_flip/off.png
new file mode 100755
index 00000000..ac588564
--- /dev/null
+++ b/gfx/card_flip/off.png
Binary files differ
diff --git a/gfx/card_flip/on.2bpp b/gfx/card_flip/on.2bpp
new file mode 100755
index 00000000..18497c4f
--- /dev/null
+++ b/gfx/card_flip/on.2bpp
@@ -0,0 +1 @@
+ÁÁÁÁ \ No newline at end of file
diff --git a/gfx/card_flip/on.png b/gfx/card_flip/on.png
new file mode 100755
index 00000000..cea1577e
--- /dev/null
+++ b/gfx/card_flip/on.png
Binary files differ
diff --git a/gfx/diploma/diploma.2bpp.lz b/gfx/diploma/diploma.2bpp.lz
new file mode 100755
index 00000000..5c35bb6e
--- /dev/null
+++ b/gfx/diploma/diploma.2bpp.lz
Binary files differ
diff --git a/gfx/diploma/diploma.png b/gfx/diploma/diploma.png
new file mode 100755
index 00000000..768bbf91
--- /dev/null
+++ b/gfx/diploma/diploma.png
Binary files differ
diff --git a/gfx/diploma/page1.tilemap b/gfx/diploma/page1.tilemap
new file mode 100755
index 00000000..fb5d7989
--- /dev/null
+++ b/gfx/diploma/page1.tilemap
Binary files differ
diff --git a/gfx/diploma/page2.tilemap b/gfx/diploma/page2.tilemap
new file mode 100755
index 00000000..26e0d07b
--- /dev/null
+++ b/gfx/diploma/page2.tilemap
Binary files differ
diff --git a/gfx/dummy_game/dummy_game.2bpp.lz b/gfx/dummy_game/dummy_game.2bpp.lz
new file mode 100755
index 00000000..b01fe34d
--- /dev/null
+++ b/gfx/dummy_game/dummy_game.2bpp.lz
Binary files differ
diff --git a/gfx/dummy_game/dummy_game.png b/gfx/dummy_game/dummy_game.png
new file mode 100755
index 00000000..e0f1d325
--- /dev/null
+++ b/gfx/dummy_game/dummy_game.png
Binary files differ
diff --git a/gfx/pc/pc.2bpp.lz b/gfx/pc/pc.2bpp.lz
new file mode 100755
index 00000000..c2cf8491
--- /dev/null
+++ b/gfx/pc/pc.2bpp.lz
Binary files differ
diff --git a/gfx/pc/pc.png b/gfx/pc/pc.png
new file mode 100644
index 00000000..ec41e462
--- /dev/null
+++ b/gfx/pc/pc.png
Binary files differ
diff --git a/gfx/pc/pc_mail.2bpp b/gfx/pc/pc_mail.2bpp
new file mode 100755
index 00000000..9a6d66ab
--- /dev/null
+++ b/gfx/pc/pc_mail.2bpp
Binary files differ
diff --git a/gfx/pc/pc_mail.png b/gfx/pc/pc_mail.png
new file mode 100755
index 00000000..fd4b2892
--- /dev/null
+++ b/gfx/pc/pc_mail.png
Binary files differ
diff --git a/gfx/unown_puzzle/aerodactyl.2bpp.lz b/gfx/unown_puzzle/aerodactyl.2bpp.lz
new file mode 100755
index 00000000..cc73411f
--- /dev/null
+++ b/gfx/unown_puzzle/aerodactyl.2bpp.lz
Binary files differ
diff --git a/gfx/unown_puzzle/aerodactyl.png b/gfx/unown_puzzle/aerodactyl.png
new file mode 100755
index 00000000..c7b37bbb
--- /dev/null
+++ b/gfx/unown_puzzle/aerodactyl.png
Binary files differ
diff --git a/gfx/unown_puzzle/cursor.2bpp b/gfx/unown_puzzle/cursor.2bpp
new file mode 100755
index 00000000..dc42cfc7
--- /dev/null
+++ b/gfx/unown_puzzle/cursor.2bpp
Binary files differ
diff --git a/gfx/unown_puzzle/cursor.png b/gfx/unown_puzzle/cursor.png
new file mode 100755
index 00000000..c10b810f
--- /dev/null
+++ b/gfx/unown_puzzle/cursor.png
Binary files differ
diff --git a/gfx/unown_puzzle/hooh.2bpp.lz b/gfx/unown_puzzle/hooh.2bpp.lz
new file mode 100755
index 00000000..d8c899e8
--- /dev/null
+++ b/gfx/unown_puzzle/hooh.2bpp.lz
Binary files differ
diff --git a/gfx/unown_puzzle/hooh.png b/gfx/unown_puzzle/hooh.png
new file mode 100755
index 00000000..bb8be6cf
--- /dev/null
+++ b/gfx/unown_puzzle/hooh.png
Binary files differ
diff --git a/gfx/unown_puzzle/kabuto.2bpp.lz b/gfx/unown_puzzle/kabuto.2bpp.lz
new file mode 100755
index 00000000..a9405031
--- /dev/null
+++ b/gfx/unown_puzzle/kabuto.2bpp.lz
Binary files differ
diff --git a/gfx/unown_puzzle/kabuto.png b/gfx/unown_puzzle/kabuto.png
new file mode 100755
index 00000000..823401cc
--- /dev/null
+++ b/gfx/unown_puzzle/kabuto.png
Binary files differ
diff --git a/gfx/unown_puzzle/omanyte.2bpp.lz b/gfx/unown_puzzle/omanyte.2bpp.lz
new file mode 100755
index 00000000..5bdd993d
--- /dev/null
+++ b/gfx/unown_puzzle/omanyte.2bpp.lz
Binary files differ
diff --git a/gfx/unown_puzzle/omanyte.png b/gfx/unown_puzzle/omanyte.png
new file mode 100755
index 00000000..83ba6774
--- /dev/null
+++ b/gfx/unown_puzzle/omanyte.png
Binary files differ
diff --git a/gfx/unown_puzzle/start_cancel.2bpp.lz b/gfx/unown_puzzle/start_cancel.2bpp.lz
new file mode 100755
index 00000000..96fbb1fb
--- /dev/null
+++ b/gfx/unown_puzzle/start_cancel.2bpp.lz
Binary files differ
diff --git a/gfx/unown_puzzle/start_cancel.png b/gfx/unown_puzzle/start_cancel.png
new file mode 100755
index 00000000..66455dcc
--- /dev/null
+++ b/gfx/unown_puzzle/start_cancel.png
Binary files differ
diff --git a/gfx/unown_puzzle/tile_borders.2bpp b/gfx/unown_puzzle/tile_borders.2bpp
new file mode 100755
index 00000000..570244c8
--- /dev/null
+++ b/gfx/unown_puzzle/tile_borders.2bpp
Binary files differ
diff --git a/gfx/unown_puzzle/tile_borders.png b/gfx/unown_puzzle/tile_borders.png
new file mode 100755
index 00000000..c075d568
--- /dev/null
+++ b/gfx/unown_puzzle/tile_borders.png
Binary files differ
diff --git a/main.asm b/main.asm
index addb6945..6bb13b94 100644
--- a/main.asm
+++ b/main.asm
@@ -316,41 +316,12 @@ INCBIN "gfx/font/font_inversed.1bpp"
SECTION "bank38", ROMX
-ret_e0000:
- ret
-; unused
- ret
-_Diploma::
- dr $e0002, $e0009
-PlaceDiplomaOnScreen::
- dr $e0009, $e00ae
-PrintDiplomaPage2::
- dr $e00ae, $e081b
-RotateUnownFrontpic::
- dr $e081b, $e0908
-ret_e0908::
- ret
-_CardFlip::
- dr $e0909, $e199d
-
-_UnownPuzzle::
- dr $e199d, $e2668
-
-_DummyGame::
- dr $e2668, $e29ae
-DummyGame_InterpretJoypad_AnimateCursor::
- dr $e29ae, $e2b9e
-_DepositPKMN::
- dr $e2b9e, $e2d71
-_WithdrawPKMN::
- dr $e2d71, $e2f47
-_MovePKMNWithoutMail::
- dr $e2f47, $e3773
-
-StatsScreenDPad::
- dr $e3773, $e3d25
-_ChangeBox::
- dr $e3d25, $e3f74
+INCLUDE "engine/events/diploma.asm"
+INCLUDE "engine/events/print_unown_2.asm"
+INCLUDE "engine/games/card_flip.asm"
+INCLUDE "engine/games/unown_puzzle.asm"
+INCLUDE "engine/games/dummy_game.asm"
+INCLUDE "engine/pokemon/bills_pc.asm"
SECTION "bank39", ROMX
diff --git a/tools/gfx.py b/tools/gfx.py
index e0cc0399..2ad3784d 100644
--- a/tools/gfx.py
+++ b/tools/gfx.py
@@ -107,6 +107,16 @@ def filepath_rules(filepath):
elif name == 'balls':
args['width'] = 32
+ elif 'gfx/card_flip' in filedir:
+ if name == 'card_flip_1':
+ args['width'] = 128
+ elif name == 'card_flip_2':
+ args['width'] = 24
+ args['rows'] = [
+ (0, 2), (0, 2), (0, 2), (0, 2), (0, 2), (0, 2), (0, 2), (0, 2),
+ (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3)
+ ]
+
elif 'gfx/credits' in filedir:
if name in ['bellossom', 'togepi', 'elekid', 'sentret']:
args['width'] = 32
@@ -119,6 +129,14 @@ def filepath_rules(filepath):
if name == 'color_test':
args['width'] = 176
+ elif 'gfx/diploma' in filedir:
+ if name == 'diploma':
+ args['width'] = 128
+
+ elif 'gfx/dummy_game' in filedir:
+ if name == 'dummy_game':
+ args['width'] = 16
+
elif 'gfx/font' in filedir:
if name == 'font_inversed':
args['width'] = 128
@@ -260,6 +278,12 @@ def filepath_rules(filepath):
elif name == 'game_boy':
args['width'] = 56
+ elif 'gfx/unown_puzzle' in filedir:
+ if name == 'start_cancel':
+ args['width'] = 152
+ elif name == 'tile_borders':
+ args['width'] = 64
+
elif os.path.join(filedir, name) in pics:
args['pic'] = True
diff --git a/wram.asm b/wram.asm
index 63c34287..63c2ec91 100644
--- a/wram.asm
+++ b/wram.asm
@@ -233,6 +233,14 @@ wTempTilemap::
ds SCREEN_WIDTH * SCREEN_HEIGHT ; $168 = 360
NEXTU ; c508
+; unown puzzle
+wUnownPuzzle::
+ ds 200
+wPuzzlePieces:: ds 6 * 6
+ ds 244
+wUnownPuzzleEnd::
+
+NEXTU ; c508
; This union spans 200 bytes from c508 to c5d0.
UNION ; c508
@@ -392,6 +400,34 @@ wSlotsDataEnd::
wSlotsEnd::
NEXTU ; c5d0
+; card flip
+wCardFlip:: ; c5d0
+wDeck:: ds 24
+wDeckEnd::
+; c5e8
+wCardFlipNumCardsPlayed:: db
+wCardFlipFaceUpCard:: db
+wDiscardPile:: ds 24
+wDiscardPileEnd::
+wCardFlipEnd::
+
+NEXTU ; c5d0
+; dummy game
+wDummyGame:: ; c5d0
+wDummyGameCards:: ds 9 * 5
+wDummyGameCardsEnd::
+wDummyGameLastCardPicked:: db ; c5fd
+wDummyGameCard1:: db ; c5fe
+wDummyGameCard2:: db ; c5ff
+wDummyGameCard1Location:: db ; c600
+wDummyGameCard2Location:: db ; c601
+wDummyGameNumberTriesRemaining:: db ; c602
+wDummyGameLastMatches:: ds 5 ; c603
+wDummyGameCounter:: db ; c608
+wDummyGameNumCardsMatched:: db ; c609
+wDummyGameEnd::
+
+NEXTU ; c5d0
; unused (engine/gfx/color.asm)
ds 50
@@ -463,6 +499,25 @@ wPrinterExposureTime:: db ; cafb
wGameboyPrinterRAMEnd::
NEXTU ; c700
+; bill's pc data
+wBillsPCData::
+wBillsPCPokemonList::
+; (species, box number, list index) x30
+ ds 3 * 30
+ ds 720
+wBillsPC_ScrollPosition:: db
+wBillsPC_CursorPosition:: db
+wBillsPC_NumMonsInBox:: db
+wBillsPC_NumMonsOnScreen:: db
+wBillsPC_LoadedBox:: db ; 0 if party, 1 - 14 if box, 15 if active box
+wBillsPC_BackupScrollPosition:: db
+wBillsPC_BackupCursorPosition:: db
+wBillsPC_BackupLoadedBox:: db
+wBillsPC_MonHasMail:: db
+ ds 5
+wBillsPCDataEnd::
+
+NEXTU ; c700
; Hall of Fame data
wHallOfFamePokemonList:: hall_of_fame wHallOfFamePokemonList
@@ -1098,12 +1153,24 @@ wTrainerCardBadgeTileID:: db
wTrainerCardBadgeAttributes:: db
NEXTU ; ce64
+; card flip data
+wCardFlipCursorY:: db
+wCardFlipCursorX:: db
+wCardFlipWhichCard:: db
+
+NEXTU ; ce64
; magnet train
wMagnetTrainOffset:: db
wMagnetTrainPosition:: db
wMagnetTrainWaitCounter:: db
NEXTU ; ce64
+; unown puzzle data
+wHoldingUnownPuzzlePiece:: db
+wUnownPuzzleCursorPosition:: db
+wUnownPuzzleHeldPiece:: db
+
+NEXTU ; ce64
; miscellaneous
wFrameCounter::
wMomBankDigitCursorPosition::