859 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			859 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ; 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
 | |
| def CARD_PRINT_PREP equ CARD_DRAW + 4
 | |
| 
 | |
| println "Card Draw is ", CARD_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 $cb00 ; location for the shuffled deck
 | |
| def DECK_FLIPS equ $cb80 ; location for the flips
 | |
| 
 | |
| 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
 | |
| rDeviceType: db ; 0 if we're on dmg, 1 if we're on cgb
 | |
| POPS
 | |
| 
 | |
| 
 | |
| def SAFE_DMA_LOCATION equ $ff80
 | |
| 
 | |
| 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 $143 - @, 0
 | |
|   db $80 ; mark this game as gbc compatible
 | |
|   ds $147 - @, 0 ; skip to the mbc byte
 | |
|   db CART_ROM_MBC1 ; MBC1 with no ram or battery :)
 | |
|   db CART_ROM_128KB 
 | |
|   ds $150 - @, 0 ; Make room for the header
 | |
| 
 | |
| SECTION "Main Program", ROM0[$150]
 | |
| EntryPoint:
 | |
|   cp a, BOOTUP_A_CGB
 | |
|   jp z, .SetupForCGB
 | |
| .SetupForDMG:
 | |
|   ld a, $0
 | |
|   ld [rDeviceType], a 
 | |
|   jp .doneWithSetup
 | |
| .SetupForCGB:
 | |
|   ld a, $1
 | |
|   ld [rDeviceType], a 
 | |
| .doneWithSetup:
 | |
|   ; Shut things down
 | |
|   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, [rDeviceType]
 | |
|   cp a, 0
 | |
|   jp z, .doneWithSpeedMode
 | |
|     di
 | |
|     ld a, 1
 | |
|     ld [rSPD], a 
 | |
|     stop
 | |
|     ei
 | |
| .doneWithSpeedMode
 | |
|   
 | |
|   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 
 | |
|   
 | |
|   ; set up the SHUFFLED_DECK
 | |
|   ld hl, Cards 
 | |
|   ld b, [hl] ; b holds the length of the card array
 | |
|   ld hl, SHUFFLED_DECK
 | |
|   ld [hl], b
 | |
|   inc hl
 | |
|   .writeCard
 | |
|     ld [hl+], a 
 | |
|     inc a 
 | |
|     cp a, b
 | |
|     jr nz, .writeCard
 | |
|   
 | |
|   ld c, 0 ; c holds the thing to write to each flip
 | |
|   ld a, b ; a holds the length of the array
 | |
|   ld hl, DECK_FLIPS
 | |
|   ld [hl+], a
 | |
|   .writeFlip
 | |
|     ld [hl], c ; write a zero to a spot in the array
 | |
|     inc hl 
 | |
|     dec a ; decrement our length counter
 | |
|     jr nz, .writeFlip
 | |
|   
 | |
|   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, CARD_PRINT_PREP - 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, CARD_PRINT_PREP
 | |
|   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, CARD_PRINT_PREP + 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
 | |
|   ld hl, CARD_PRINT_PREP + 2
 | |
|   ld [hl], a
 | |
| 
 | |
|   ld a, %11100100
 | |
|   ldh [rBGP], a
 | |
|   ldh [rOBP0], a
 | |
|   call AdjustBGP
 | |
|   call AdjustOBP0
 | |
|  
 | |
|   ld a, LCDCF_BLK21 | LCDCF_ON | LCDCF_BGON | LCDCF_OBJON
 | |
|   ldh [rLCDC], 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 a, P1F_GET_DPAD
 | |
|   ldh [rP1], a
 | |
|   ldh a, [rP1]
 | |
|   ldh a, [rP1]
 | |
|   ldh a, [rP1]
 | |
|   cpl
 | |
|   and a, %00001111
 | |
|   ld b, a
 | |
|   ld a, P1F_GET_BTN
 | |
|   ldh [rP1], a
 | |
|   ldh a, [rP1]
 | |
|   ldh a, [rP1]
 | |
|   ldh a, [rP1]
 | |
|   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
 | |
|   call SCENE_UPDATE - 1 ; hope this takes not too many scanlines!
 | |
| 
 | |
|   di
 | |
|   ld hl, rIE
 | |
|   set 0, [hl] ; IEF_VBLANK
 | |
|   ei
 | |
|   
 | |
|   halt
 | |
|   
 | |
|   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, 3
 | |
|   call AwaitLine
 | |
|   
 | |
|   jp Loop
 | |
| 
 | |
| 
 | |
| 
 | |
|   
 | |
| ChangeScene: ; hl should be a pointer to, in sequence, setup update draw teardown
 | |
|   di
 | |
|   ;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 Async_Kill
 | |
|   call SCENE_SETUP - 1
 | |
|   
 | |
|   ei
 | |
|   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
 | |
| 
 | |
| AdjustBGP: ; copies the palettes from the DMG mode to the CGB mode
 | |
|   ld a, [rDeviceType]
 | |
|   cp a, 0
 | |
|   ret z ; if we're in DMG mode, we don't need to do anything. else...
 | |
|   
 | |
|   ld a, %1000_0000 ; we want to start at bgp color zero and autoincrement BGPI_AUTOINC
 | |
|   ldh [rBCPS], a ; set that
 | |
|   
 | |
|   
 | |
|   ; assume we've just set rBGP to something like %11_10_01_00
 | |
|   ld b, 0 
 | |
|   ldh a, [rBGP]
 | |
|   and a, %00000011
 | |
|   ld c, a 
 | |
|   sla c
 | |
|   ld hl, DefaultPaletteBGP
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x0 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rBCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rBCPD], a
 | |
|   
 | |
|   ld b, 0 
 | |
|   ldh a, [rBGP]
 | |
|   and a, %00001100
 | |
|   ld c, a 
 | |
|   sra c
 | |
|   ld hl, DefaultPaletteBGP
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x1 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rBCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rBCPD], a
 | |
|   
 | |
|   ld b, 0 
 | |
|   ldh a, [rBGP]
 | |
|   and a, %00110000
 | |
|   ld c, a 
 | |
|   swap c
 | |
|   sla c
 | |
|   ld hl, DefaultPaletteBGP
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x2 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rBCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rBCPD], a
 | |
|   
 | |
|   ld b, 0 
 | |
|   ldh a, [rBGP]
 | |
|   and a, %11000000
 | |
|   ld c, a 
 | |
|   swap c
 | |
|   sra c
 | |
|   ld hl, DefaultPaletteBGP
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x3 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rBCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rBCPD], a
 | |
|   
 | |
|   ret
 | |
| 
 | |
| AdjustOBP0:
 | |
|   ld a, [rDeviceType]
 | |
|   cp a, 0
 | |
|   ret z ; if we're in DMG mode, we don't need to do anything. else...
 | |
|   
 | |
|   ld a, %1000_0000 ; we want to start at obp color zero and autoincrement BGPI_AUTOINC
 | |
|   ldh [rOCPS], a ; set that
 | |
|   
 | |
|   ld b, 0 
 | |
|   
 | |
|   ; assume we've just set rOBP0 to something like %11_10_01_00
 | |
|   ldh a, [rOBP0]
 | |
|   and a, %00000011
 | |
|   ld c, a 
 | |
|   sla c
 | |
|   ld hl, DefaultPaletteOBP0
 | |
|   add hl, bc 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ld a, [rOBP0]
 | |
|   and a, %00001100
 | |
|   ld c, a 
 | |
|   sra c
 | |
|   ld hl, DefaultPaletteOBP0
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x1 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ldh a, [rOBP0]
 | |
|   and a, %00110000
 | |
|   ld c, a 
 | |
|   swap c
 | |
|   sla c
 | |
|   ld hl, DefaultPaletteOBP0
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x2 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ldh a, [rOBP0]
 | |
|   and a, %11000000
 | |
|   ld c, a 
 | |
|   swap c
 | |
|   sra c
 | |
|   ld hl, DefaultPaletteOBP0
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x3 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ret
 | |
|   
 | |
| AdjustOBP1:
 | |
|   ldh a, [rOBP1]
 | |
|   ld d, a  ; take d from a, assuming a is a palette we wanted to use
 | |
|   
 | |
|   ld a, [rDeviceType]
 | |
|   cp a, 0
 | |
|   ret z ; if we're in DMG mode, we don't need to do anything. else...
 | |
|   
 | |
|   ld a, %1000_1000 ; we want to start at obp palette 0b1000 (byte 8, bc 4 colors and 2 bytes per color?) and autoincrement BGPI_AUTOINC
 | |
|   ldh [rOCPS], a ; set that
 | |
|   
 | |
|   ld b, 0 
 | |
|   
 | |
|   ;ldh a, [rOBP1]
 | |
|   ;ld d, a 
 | |
|   
 | |
|   ; assume we've just set rOBP1 to something like %11_10_01_00
 | |
|   ld a, d
 | |
|   and a, %00000011
 | |
|   ld c, a 
 | |
|   sla c
 | |
|   ld hl, DefaultPaletteOBP1
 | |
|   add hl, bc 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ld a, d
 | |
|   and a, %00001100
 | |
|   ld c, a 
 | |
|   sra c
 | |
|   ld hl, DefaultPaletteOBP1
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x1 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ld a, d
 | |
|   and a, %00110000
 | |
|   ld c, a 
 | |
|   swap c
 | |
|   sla c
 | |
|   ld hl, DefaultPaletteOBP1
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x2 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ld a, d
 | |
|   and a, %11000000
 | |
|   ld c, a 
 | |
|   swap c
 | |
|   sra c
 | |
|   ld hl, DefaultPaletteOBP1
 | |
|   add hl, bc ; index into bgp palette so now hl points to color x3 of default bgp 
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ldh [rOCPD], a 
 | |
|   ld a, [hl]
 | |
|   ldh [rOCPD], a
 | |
|   
 | |
|   ret
 | |
| 
 | |
| DefaultPaletteBGP:
 | |
| DefaultPaletteOBP0:
 | |
| DefaultPaletteOBP1:
 | |
|   ; colors are dw %0_Bbbbb_Ggggg_Rrrrr (capitals indicate MSB)
 | |
| ; palette to use for everything
 | |
|   dw %0_11111_11111_11111 ;GBCColorFromRGB(0xFFFFFF)
 | |
|   dw %0_11101_10000_10010 ;GBCColorFromRGB(0x63A5FF)
 | |
|   dw %0_11011_00000_01110 ;GBCColorFromRGB(0x0000FF)
 | |
|   dw %0_00000_00000_00000 ;GBCColorFromRGB(0x000000)
 | |
| ; a different reddish palette
 | |
| 
 | |
|   dw %0_11111_11111_11111 ; GBCColorFromRGB(0xFFFFFF)
 | |
|   dw %0_10000_10000_11111 ; GBCColorFromRGB(0xFF8484)
 | |
|   dw %0_00111_00111_10010 ;GBCColorFromRGB(0x943A3A)
 | |
|   dw %0_00000_00000_00000 ; GBCColorFromRGB(0x000000)
 | |
|   
 | |
| 
 | |
| 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"
 | |
| 
 |