; infinite thanks to: ; gbdev.io and the pandocs for everything ; alex for consulting on tarot endlessly ; moss for keeping me from working sixteen hours a day and burning out ; yuri for letting me bounce ideas off you at all times ; sara for being a perfect light ; fae for all your help on music and sound and sunday mornings ; sadie for hardware and packaging help def MY_OAM equ $c000 ; $c100 - c120 call handles, scene stack, interrupt, card functions ; 0xc100 CALL ; 0xc101 LOW - SCENE_SETUP points to this ; 0xc102 HIGH ; 0xc103 RET ; 0xc104 CALL ... DEF SCENE_SETUP EQU $c101 DEF SCENE_UPDATE EQU SCENE_SETUP + 4 ; call then ret is 3+1 bytes DEF SCENE_DRAW EQU SCENE_UPDATE + 4 DEF SCENE_TEARDOWN EQU SCENE_DRAW + 4 DEF INTERRUPT_LCD EQU SCENE_TEARDOWN + 4 def CARD_INIT equ INTERRUPT_LCD + 4 def CARD_UPDATE equ CARD_INIT + 4 def CARD_DRAW equ CARD_UPDATE + 4 println "Card Draw is ", SCENE_DRAW ; each of these sections is way bgger than it needs to be ; i doubt any of them will hold more than $20 bytes at all ; but might as well put them at round numbers for now def ASYNC_VARS_START equ $c200 ; this space's layout defined manually in async.inc def SYSTEM_VARS_START equ $c300 ; system variables like buttons pressed, rng, dtime def GLOBAL_VARS_START equ $c400 ; program-wide state defined mostly in mainmenu def SCREEN_VARS_START equ $c500 ; per-screen variables like animation stuff def CARD_HELPER_VARS_START equ $c600 ; variables for card data def CARD_VARS_START equ $c700 ; variables for animation of individual cards def CVS equ CARD_VARS_START ; handy to be able to refer to CVS by a short name def AUDIO_VARS_START equ $c800 ; variables for the audio subsystem def PRINTER_VARS_START equ $c900 def SHUFFLED_DECK equ $ca00 ; location for the shuffled deck pushs "work spaces", WRAMX[$D000] ZEROES: ds $200 ONES: ds $200 BUFFER_ONE: ds $300 BUFFER_TWO: ds $300 pops ; system variables, which are like program-wide state vars but More Different PUSHS "System Variables", WRAM0[SYSTEM_VARS_START] rMYBTN: db ; EQU SYSTEM_VARS_START rMYBTNP: db ;EQU rMYBTN + 1 rDELTAT: db ; EQU rMYBTNP + 1 ; delta_t where $1000 = 1 second rLFSR: dw ; equ rDELTAT + 1 ; 16 bit POPS def SAFE_DMA_LOCATION equ $ffc0 def VARIABLE_TILES_START equ 26 ; where in VRAM the variable tiles start ; (i.e. we allocate VARIABLE_TILES_START-1 slots out of that block of 128 ; for ever-present ui tiles) INCLUDE "hardware.inc" SECTION "Interrupts", ROM0[$0] ds INT_HANDLER_VBLANK - @, 0 reti ds INT_HANDLER_STAT - @, 0 call INTERRUPT_LCD - 1 ret SECTION "Header", ROM0[$100] jp EntryPoint ds $147 - @, 0 ; skip to the mbc byte db $01 ; MBC1 with no ram or battery :) db $01 ; 64kb rom :) ds $150 - @, 0 ; Make room for the header EntryPoint: ; Shut down audio circuitry ld a, 0 ldh [rNR52], a ; shut down audio ldh [rDIV], a ; reset timer just in case?? ldh [rLCDC], a ; shut down screen ldh [rIE], a ldh [rIF], a ld a, 0 ld hl, ZEROES ld bc, $200 .buildZeros ld a, 0 ld [hl+], a ld a, b or a, c dec bc ; we still need to do the `or` to set the zero flag bc dec r16 doesn't do that jp nz, .buildZeros ld a, 1 ld hl, ONES ld bc, $200 .buildOnes ld a, 1 ld [hl+], a ld a, b or a, c dec bc ; we still need to do the `or` to set the zero flag bc dec r16 doesn't do that jp nz, .buildOnes ld hl, UITiles ld de, _VRAM + $1000 ld bc, UITiles.end - UITiles call CopyRange ld hl, LetterTiles ; map the small font into vram at ascii locations ld de, _VRAM + $800 + ($10)*16 ld bc, LetterTiles.end - LetterTiles call CopyRange ; initialize global variables ld a, 0 ld [vSelectedSpreadIndex], a ld [vSelectedCardIndex], a ld hl, Cards ld b, [hl] ld hl, SHUFFLED_DECK ld [hl], b inc hl .writeCard ld [hl+], a inc a cp a, b jr nz, .writeCard ld a, %1010_1010 ld [rLFSR], a ; move on to framework stuff ; set up the scene and interrupt vectors ld hl, Instructions ld a, [hl] ; get the value of a call instruction so we can shove it into our handles ld hl, SCENE_SETUP - 1 ld [hl], a ld hl, SCENE_UPDATE - 1 ld [hl], a ld hl, SCENE_DRAW - 1 ld [hl], a ld hl, SCENE_TEARDOWN - 1 ld [hl], a ld hl, INTERRUPT_LCD - 1 ld [hl], a ld hl, CARD_INIT - 1 ld [hl], a ld hl, CARD_UPDATE - 1 ld [hl], a ld hl, CARD_DRAW - 1 ld [hl], a ld hl, Instructions inc hl ld a, [hl] ; get the value of a call instruction so we can shove it into our handles ld hl, SCENE_SETUP ld [hl], a ld hl, SCENE_UPDATE ld [hl], a ld hl, SCENE_DRAW ld [hl], a ld hl, SCENE_TEARDOWN ld [hl], a ld hl, INTERRUPT_LCD ld [hl], a ld hl, CARD_INIT ld [hl], a ld hl, CARD_UPDATE ld [hl], a ld hl, CARD_DRAW ld [hl], a ld hl, Instructions inc hl inc hl ld a, [hl] ; get the value of a call instruction so we can shove it into our handles ld hl, SCENE_SETUP + 1 ld [hl], a ld hl, SCENE_UPDATE + 1 ld [hl], a ld hl, SCENE_DRAW + 1 ld [hl], a ld hl, SCENE_TEARDOWN + 1 ld [hl], a ld hl, INTERRUPT_LCD + 1 ld [hl], a ld hl, CARD_INIT + 1 ld [hl], a ld hl, CARD_UPDATE + 1 ld [hl], a ld hl, CARD_DRAW + 1 ld [hl], a ld hl, Instructions inc hl inc hl inc hl ld a, [hl] ; get the value of a ret instruction so we can shove it into our handles ld hl, SCENE_SETUP + 2 ld [hl], a ld hl, SCENE_UPDATE + 2 ld [hl], a ld hl, SCENE_DRAW + 2 ld [hl], a ld hl, SCENE_TEARDOWN + 2 ld [hl], a ld hl, INTERRUPT_LCD + 2 ld [hl], a ld hl, CARD_INIT + 2 ld [hl], a ld hl, CARD_UPDATE + 2 ld [hl], a ld hl, CARD_DRAW + 2 ld [hl], a ; set up our scene handle ld hl, ScreenMainMenu call ChangeScene call SoundSetup call PrepNetwork Loop: ; okay this is kinda sketchy. we want a delta time variable. ; we've got two eight-bit counters, one at 4096hz and one at 16384hz ; we can definitely reset the faster counter. ; but! that's gonna overflow every frame. ; however! it should always overflow the same amount ; because we're basically running once per frame (AwaitLine call later) ; if we assume it overflows once per frame, then the total value should be ; 256 + [rDIV]. so if we divide by two (or more!) the total value will be ; 256/2 + [rDIV]/2. so we just have to right shift and add 128. ; or right shift twice and add 64. this loses us precision but we didn't need ; it anyway. ldh a, [rDIV] ldh [rDIV], a ; this will reset the timer sra a sra a add a, 64 ld [rDELTAT], a xor a, a ; zero a out in one cycle ; store dpad and btn state in the rMYBTN register ld hl, rP1 ld [hl], P1F_GET_DPAD ld a, [hl] ld a, [hl] ld a, [hl] ld a, [hl] cpl and a, %00001111 ld b, a ld [hl], P1F_GET_BTN ld a, [hl] ld a, [hl] ld a, [hl] ld a, [hl] cpl and a, %00001111 swap a or a, b ld b, a ; put new input state in b ld a, [rMYBTN] ; previous input state in a cpl ; a holds buttons which weren't pressed last frame and a, b ; select buttons which were pressed this frame, but not last frame ld [rMYBTNP], a ; save that as btnp state ld a, b ; select buttons which were pressed this frame ld [rMYBTN], a ; save that as btn state call SoundUpdate println "scene update is ", SCENE_UPDATE - 1 call SCENE_UPDATE - 1 ; hope this takes not too many scanlines! di ld a, [rIE] or a, IEF_VBLANK ld [rIE], a ei halt println "scene draw is ", SCENE_DRAW - 1 call SCENE_DRAW - 1 ; hope this takes fewer than 9 scanlines! ; either way it's going to eat into the update timing ; at this point we want to make sure that scanline 153 has passed ; we should check if we're past there and skip this await if necessary ld b, 5 call AwaitLine jp Loop ChangeScene: ; hl should be a pointer to, in sequence, setup update draw teardown ;call SCENE_TEARDOWN - 1 ld a, [hl+] ld [SCENE_SETUP], a ld a, [hl+] ld [SCENE_SETUP+1], a ld a, [hl+] ld [SCENE_UPDATE], a ld a, [hl+] ld [SCENE_UPDATE+1], a ld a, [hl+] ld [SCENE_DRAW], a ld a, [hl+] ld [SCENE_DRAW+1], a ld a, [hl+] ld [SCENE_TEARDOWN], a ld a, [hl+] ld [SCENE_TEARDOWN+1], a call SCENE_SETUP - 1 ret AwaitLine: ; put the line you want to reach in b ld a, [rLY] cp b jp nz, AwaitLine ret ArrayClampLoopingB: cp a, b jp nz, :+ ld a, 0 : cp a, $FF jp nz, :+ ld a, b dec a : ret ArrayClampLooping: ; loops a to be in the array, assuming hl points to the length cp a, [hl] ; if a == length... jp nz, :+ ld a, 0 ; set it to 0 : cp a, $FF ; otherwise if a == $FF... jp nz, :+ ld a, [hl] dec a ; then set it to length-1 : ret ; a is return value ArrayClamp: cp a, $FF jp nz, :+ ld a, 0 ret : cp a, [hl] ret c : ld a, [hl] dec a ret : PassList: ; hl has the address of a list. step past it. ld b, 0 ld c, [hl] ; bc has length inc hl ; step over length add hl, bc ; step past all the entries ret PrintString: ; write ascii string which has been prefixed by its length. at hl ; de should be location in tile map to write ld b, [hl] ld a, b cp a, 0 ret z inc hl PrintBChars: ;write ascii characters. will not respect newlines or anything like that ; hl should be the source of ascii text ; de should be the location in the tile map to start writing at ; b should be the length ld a, [hli] or a, %10000000 sub a, $10 ld [de], a inc de dec b jp nz, PrintBChars ret ;thanks to https://gbdev.io/pandocs/OAM_DMA_Transfer.html for this routine ; a should be the high byte of where we're DMAing from (ld a, $c0 in my case probably) ; de should have the address in hram for where to paste to (SAFE_DMA_LOCATION probably) RunDMA: di push de push af ld hl, run_dma_tail ld bc, run_dma_tail.run_dma_tail_end - run_dma_tail call CopyRange pop af run_dma: ; This part must be in ROM. ld bc, $2846 ; B: wait time; C: LOW($FF46) ret ; we pushed de before, so this should "return" to execute that (HRAM) address run_dma_tail: ; This part must live in HRAM. ldh [c], a .wait dec b jr nz, .wait ei ret z ; Conditional `ret` is 1 M-cycle slower, which avoids reading from the ; stack on the last M-cycle of DMA. .run_dma_tail_end nop nop nop halt nop nop Instructions: call .rett .rett: ret EndOfInstructions: UITiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $05,$00,$05,$00,$05,$00,$05,$00,$05,$00,$fd,$00,$00,$00,$fd,$00 db $00,$ff,$ff,$ff,$ff,$ff,$ff,$00,$00,$ff,$00,$00,$00,$00,$00,$00 db $70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8 db $0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17 db $00,$00,$00,$00,$00,$00,$00,$ff,$ff,$00,$ff,$ff,$ff,$ff,$00,$ff db $70,$e8,$70,$e8,$70,$e8,$70,$ef,$7f,$f0,$3f,$7f,$1f,$3f,$00,$1f db $0e,$17,$0e,$17,$0e,$17,$0e,$f7,$fe,$0f,$fc,$fe,$f8,$fc,$00,$f8 db $00,$f8,$f8,$fc,$fc,$fe,$fe,$0f,$0e,$f7,$0e,$17,$0e,$17,$0e,$17 db $00,$1f,$1f,$3f,$3f,$7f,$7f,$f0,$70,$ef,$70,$e8,$70,$e8,$70,$e8 db $00,$00,$ff,$00,$ff,$00,$aa,$55,$00,$ff,$00,$ff,$ff,$ff,$ff,$ff db $63,$1f,$73,$0f,$63,$1f,$73,$0f,$63,$1f,$73,$0f,$63,$1f,$73,$0f db $ce,$f0,$c6,$f8,$ce,$f0,$c6,$f8,$ce,$f0,$c6,$f8,$ce,$f0,$c6,$f8 db $ff,$ff,$ff,$ff,$00,$ff,$00,$ff,$55,$aa,$ff,$00,$ff,$00,$00,$00 db $00,$00,$3f,$00,$7f,$00,$7a,$05,$68,$17,$70,$0f,$63,$1f,$73,$0f db $00,$00,$fc,$00,$fe,$00,$ae,$50,$1e,$e0,$06,$f8,$ce,$f0,$c6,$f8 db $ce,$f0,$c6,$f8,$0e,$f0,$16,$e8,$5e,$a0,$fe,$00,$fc,$00,$00,$00 db $63,$1f,$73,$0f,$60,$1f,$78,$07,$75,$0a,$7f,$00,$3f,$00,$00,$00 db $00,$77,$00,$88,$00,$88,$00,$88,$00,$88,$00,$88,$00,$88,$00,$77 db $00,$00,$00,$80,$00,$80,$00,$80,$00,$80,$00,$80,$00,$80,$00,$00 db $00,$77,$00,$88,$20,$a8,$20,$a8,$20,$a8,$20,$a8,$00,$88,$00,$77 db $00,$77,$00,$88,$02,$8a,$02,$8a,$02,$8a,$02,$8a,$00,$88,$00,$77 db $56,$c3,$6a,$c3,$56,$c3,$6a,$c3,$56,$c3,$6a,$c3,$7e,$ff,$00,$ff db $00,$ff,$7e,$ff,$56,$c3,$6a,$c3,$56,$c3,$6a,$c3,$56,$c3,$6a,$c3 db $99,$5a,$99,$5a,$99,$5a,$99,$5a,$99,$5a,$81,$42,$81,$7e,$ff,$00 db $ff,$00,$81,$7e,$81,$42,$99,$5a,$99,$5a,$99,$5a,$99,$5a,$99,$5a .end LetterTiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $03,$03,$07,$07,$0f,$0f,$0e,$0e,$1c,$1c,$30,$30,$c0,$c0,$c0,$c0 db $24,$24,$6c,$6c,$6c,$6c,$48,$48,$00,$00,$00,$00,$00,$00,$00,$00 db $1a,$1a,$1a,$1a,$7f,$7f,$34,$34,$34,$34,$fe,$fe,$68,$68,$68,$68 db $08,$08,$3c,$3c,$6a,$6a,$68,$68,$3c,$3c,$0a,$0a,$6a,$6a,$3c,$3c db $63,$63,$a6,$a6,$ac,$ac,$d8,$d8,$1b,$1b,$35,$35,$65,$65,$c6,$c6 db $18,$18,$24,$24,$28,$28,$18,$18,$2c,$2c,$66,$66,$67,$67,$39,$39 db $18,$18,$18,$18,$18,$18,$30,$30,$00,$00,$00,$00,$00,$00,$00,$00 db $04,$04,$0c,$0c,$18,$18,$10,$10,$10,$10,$18,$18,$0c,$0c,$04,$04 db $20,$20,$30,$30,$18,$18,$08,$08,$08,$08,$18,$18,$30,$30,$20,$20 db $00,$00,$08,$08,$28,$28,$1e,$1e,$78,$78,$14,$14,$10,$10,$00,$00 db $00,$00,$00,$00,$18,$18,$18,$18,$7e,$7e,$18,$18,$18,$18,$00,$00 db $00,$00,$00,$00,$00,$00,$00,$00,$0c,$0c,$0c,$0c,$0c,$0c,$18,$18 db $00,$00,$00,$00,$00,$00,$1c,$1c,$38,$38,$00,$00,$00,$00,$00,$00 db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$18,$18,$00,$00 db $04,$04,$0c,$0c,$0c,$0c,$18,$18,$18,$18,$30,$30,$30,$30,$20,$20 db $00,$00,$38,$38,$64,$64,$64,$64,$64,$64,$64,$64,$64,$64,$38,$38 db $08,$08,$18,$18,$38,$38,$18,$18,$18,$18,$18,$18,$18,$18,$3c,$3c db $00,$00,$38,$38,$4c,$4c,$0c,$0c,$0c,$0c,$18,$18,$30,$30,$7c,$7c db $00,$00,$3c,$3c,$06,$06,$06,$06,$1c,$1c,$06,$06,$06,$06,$3c,$3c db $00,$00,$04,$04,$26,$26,$26,$26,$3e,$3e,$06,$06,$06,$06,$04,$04 db $00,$00,$7c,$7c,$64,$64,$60,$60,$78,$78,$44,$44,$04,$04,$38,$38 db $00,$00,$20,$20,$30,$30,$30,$30,$3c,$3c,$32,$32,$32,$32,$1c,$1c db $00,$00,$7c,$7c,$4c,$4c,$0c,$0c,$3e,$3e,$18,$18,$30,$30,$20,$20 db $00,$00,$78,$78,$64,$64,$64,$64,$38,$38,$64,$64,$64,$64,$3c,$3c db $00,$00,$38,$38,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$0c,$0c,$18,$18 db $00,$00,$00,$00,$18,$18,$18,$18,$00,$00,$18,$18,$18,$18,$00,$00 db $00,$00,$00,$00,$0c,$0c,$0c,$0c,$00,$00,$0c,$0c,$0c,$0c,$18,$18 db $00,$00,$0c,$0c,$18,$18,$30,$30,$60,$60,$30,$30,$18,$18,$0c,$0c db $00,$00,$00,$00,$3c,$3c,$3c,$3c,$00,$00,$3c,$3c,$3c,$3c,$00,$00 db $00,$00,$30,$30,$18,$18,$0c,$0c,$06,$06,$0c,$0c,$18,$18,$30,$30 db $38,$38,$6c,$6c,$24,$24,$0c,$0c,$18,$18,$18,$18,$00,$00,$18,$18 db $3c,$3c,$62,$62,$59,$59,$45,$45,$5d,$5d,$5d,$5d,$63,$63,$38,$38 db $00,$00,$38,$38,$34,$34,$32,$32,$3e,$3e,$32,$32,$32,$32,$32,$32 db $00,$00,$7c,$7c,$32,$32,$32,$32,$3c,$3c,$32,$32,$32,$32,$1c,$1c db $00,$00,$3c,$3c,$72,$72,$62,$62,$60,$60,$60,$60,$62,$62,$3c,$3c db $00,$00,$f8,$f8,$64,$64,$62,$62,$62,$62,$62,$62,$62,$62,$3c,$3c db $00,$00,$fc,$fc,$60,$60,$60,$60,$78,$78,$60,$60,$60,$60,$3c,$3c db $00,$00,$fc,$fc,$60,$60,$60,$60,$78,$78,$60,$60,$60,$60,$20,$20 db $00,$00,$78,$78,$64,$64,$60,$60,$60,$60,$6e,$6e,$64,$64,$3c,$3c db $00,$00,$40,$40,$62,$62,$62,$62,$7e,$7e,$62,$62,$62,$62,$22,$22 db $00,$00,$10,$10,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$08,$08 db $00,$00,$08,$08,$0c,$0c,$0c,$0c,$0c,$0c,$4c,$4c,$6c,$6c,$3c,$3c db $00,$00,$40,$40,$64,$64,$68,$68,$70,$70,$68,$68,$64,$64,$22,$22 db $00,$00,$20,$20,$30,$30,$30,$30,$30,$30,$30,$30,$32,$32,$1e,$1e db $00,$00,$3e,$3e,$6a,$6a,$6a,$6a,$6a,$6a,$62,$62,$62,$62,$22,$22 db $00,$00,$72,$72,$6a,$6a,$6a,$6a,$6a,$6a,$66,$66,$62,$62,$22,$22 db $00,$00,$3c,$3c,$66,$66,$62,$62,$62,$62,$62,$62,$32,$32,$1e,$1e db $00,$00,$f8,$f8,$64,$64,$64,$64,$7c,$7c,$60,$60,$60,$60,$20,$20 db $00,$00,$38,$38,$64,$64,$62,$62,$62,$62,$6a,$6a,$64,$64,$3b,$3b db $00,$00,$f8,$f8,$64,$64,$64,$64,$7c,$7c,$68,$68,$64,$64,$23,$23 db $00,$00,$38,$38,$64,$64,$60,$60,$38,$38,$04,$04,$64,$64,$38,$38 db $00,$00,$7e,$7e,$5a,$5a,$18,$18,$18,$18,$18,$18,$18,$18,$08,$08 db $00,$00,$40,$40,$62,$62,$62,$62,$62,$62,$62,$62,$62,$62,$3c,$3c db $00,$00,$40,$40,$62,$62,$62,$62,$62,$62,$24,$24,$34,$34,$18,$18 db $00,$00,$c3,$c3,$62,$62,$62,$62,$6a,$6a,$6a,$6a,$6a,$6a,$34,$34 db $00,$00,$42,$42,$62,$62,$34,$34,$18,$18,$3c,$3c,$66,$66,$42,$42 db $00,$00,$4c,$4c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$4c,$4c,$78,$78 db $00,$00,$7e,$7e,$46,$46,$0c,$0c,$18,$18,$30,$30,$62,$62,$7e,$7e db $7c,$7c,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$7c,$7c db $20,$20,$30,$30,$30,$30,$18,$18,$18,$18,$0c,$0c,$0c,$0c,$04,$04 db $3e,$3e,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$3e,$3e db $18,$18,$3c,$3c,$66,$66,$42,$42,$00,$00,$00,$00,$00,$00,$00,$00 db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$7c,$3e,$3e db $30,$30,$18,$18,$0c,$0c,$04,$04,$00,$00,$00,$00,$00,$00,$00,$00 db $00,$00,$00,$00,$38,$38,$0c,$0c,$3c,$3c,$4c,$4c,$3a,$3a,$00,$00 db $00,$00,$30,$30,$30,$30,$3c,$3c,$32,$32,$32,$32,$3c,$3c,$00,$00 db $00,$00,$00,$00,$1c,$1c,$30,$30,$30,$30,$30,$30,$1c,$1c,$00,$00 db $00,$00,$0c,$0c,$0c,$0c,$3c,$3c,$4c,$4c,$4c,$4c,$3c,$3c,$00,$00 db $00,$00,$00,$00,$38,$38,$64,$64,$78,$78,$60,$60,$3c,$3c,$00,$00 db $00,$00,$0e,$0e,$18,$18,$3c,$3c,$18,$18,$18,$18,$18,$18,$00,$00 db $00,$00,$00,$00,$3c,$3c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$38,$38 db $00,$00,$60,$60,$60,$60,$78,$78,$64,$64,$64,$64,$64,$64,$00,$00 db $00,$00,$10,$10,$00,$00,$38,$38,$18,$18,$18,$18,$3c,$3c,$00,$00 db $00,$00,$08,$08,$00,$00,$0c,$0c,$0c,$0c,$0c,$0c,$2c,$2c,$18,$18 db $00,$00,$60,$60,$68,$68,$68,$68,$70,$70,$68,$68,$64,$64,$00,$00 db $00,$00,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$18,$18,$00,$00 db $00,$00,$00,$00,$74,$74,$6a,$6a,$6a,$6a,$6a,$6a,$6a,$6a,$00,$00 db $00,$00,$00,$00,$78,$78,$64,$64,$64,$64,$64,$64,$64,$64,$00,$00 db $00,$00,$00,$00,$38,$38,$64,$64,$64,$64,$64,$64,$38,$38,$00,$00 db $00,$00,$00,$00,$78,$78,$64,$64,$64,$64,$78,$78,$60,$60,$60,$60 db $00,$00,$00,$00,$3c,$3c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$0e,$0e db $00,$00,$00,$00,$1c,$1c,$30,$30,$30,$30,$30,$30,$30,$30,$00,$00 db $00,$00,$00,$00,$38,$38,$60,$60,$38,$38,$0c,$0c,$78,$78,$00,$00 db $00,$00,$30,$30,$78,$78,$30,$30,$30,$30,$30,$30,$1c,$1c,$00,$00 db $00,$00,$00,$00,$64,$64,$64,$64,$64,$64,$64,$64,$3c,$3c,$00,$00 db $00,$00,$00,$00,$64,$64,$64,$64,$64,$64,$28,$28,$10,$10,$00,$00 db $00,$00,$00,$00,$62,$62,$6a,$6a,$6a,$6a,$6a,$6a,$34,$34,$00,$00 db $00,$00,$00,$00,$64,$64,$38,$38,$18,$18,$2c,$2c,$46,$46,$00,$00 db $00,$00,$00,$00,$4c,$4c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$38,$38 db $00,$00,$00,$00,$7e,$7e,$0c,$0c,$18,$18,$30,$30,$7e,$7e,$00,$00 db $3c,$3c,$60,$60,$30,$30,$60,$60,$60,$60,$30,$30,$60,$60,$3c,$3c db $20,$20,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$10,$10 db $3c,$3c,$06,$06,$0c,$0c,$06,$06,$06,$06,$0c,$0c,$06,$06,$3c,$3c db $00,$00,$00,$00,$31,$31,$7b,$7b,$de,$de,$8c,$8c,$00,$00,$00,$00 db $c0,$c0,$a0,$a0,$b8,$b8,$b0,$b0,$da,$da,$12,$12,$1a,$1a,$03,$03 .end INCLUDE "CopyRange.inc" INCLUDE "CopyTiles.inc" INCLUDE "Async.inc" INCLUDE "Random.inc" INCLUDE "RecreatingCards.inc" INCLUDE "GraphicsManipulation.inc" INCLUDE "Printing.inc" INCLUDE "ScreenMainMenu.inc" INCLUDE "ScreenSpreadSelect.inc" INCLUDE "CardHelpers.inc" INCLUDE "ScreenCardRead.inc" INCLUDE "ScreenCardBrowse.inc" INCLUDE "ScreenShuffle.inc" INCLUDE "CardLibrary.inc" INCLUDE "Audio.inc"