726 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			726 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| ; CARD_HELPER_VARS_START defines the beginning of the $100 bytes set aside for system usage
 | |
| PUSHS "Card Helper Vars", WRAM0[CARD_HELPER_VARS_START]
 | |
| cvCardBank: db
 | |
| cvCardAddress: dw
 | |
| cvNeedsCleanup: db
 | |
| POPS
 | |
| 
 | |
| FindCardTileMap: ; puts the tilemap into hl
 | |
|   ld hl, cvCardAddress
 | |
|   ld c, [hl] 
 | |
|   inc hl 
 | |
|   ld b, [hl]
 | |
|   ld l, c 
 | |
|   ld h, b 
 | |
|   ld bc, Card_Offset_tilemap
 | |
|   add hl, bc ; address of the length and address of the tilemap
 | |
|   
 | |
|   inc hl 
 | |
|   inc hl ; step past the two-byte length of the tilemap
 | |
|   
 | |
|   ld c, [hl]
 | |
|   inc hl
 | |
|   ld b, [hl]
 | |
|   
 | |
|   ld h, b
 | |
|   ld l, c
 | |
|   
 | |
|   ret
 | |
| FindCardKeyTiles: 
 | |
|   ld hl, cvCardAddress
 | |
|   ld c, [hl] 
 | |
|   inc hl 
 | |
|   ld b, [hl]
 | |
|   ld l, c 
 | |
|   ld h, b 
 | |
|   ld bc, Card_Offset_keytiles
 | |
|   add hl, bc ; address of the length and address of the key tilels
 | |
|   
 | |
|   inc hl 
 | |
|   inc hl ; step past the two-byte length of the key tiles
 | |
|   
 | |
|   ld c, [hl]
 | |
|   inc hl
 | |
|   ld b, [hl]
 | |
|   
 | |
|   ld h, b
 | |
|   ld l, c
 | |
|   
 | |
|   ret
 | |
| FindCardSpriteTiles:
 | |
|   ld hl, cvCardAddress
 | |
|   ld c, [hl] 
 | |
|   inc hl 
 | |
|   ld b, [hl]
 | |
|   ld l, c 
 | |
|   ld h, b 
 | |
|   ld bc, Card_Offset_spritetiles
 | |
|   add hl, bc ; address of the length and address of the sprite tile data
 | |
|   
 | |
|   inc hl 
 | |
|   inc hl ; step past the two-byte length of the sprite tile data
 | |
|   
 | |
|   ld c, [hl]
 | |
|   inc hl
 | |
|   ld b, [hl]
 | |
|   
 | |
|   ld h, b
 | |
|   ld l, c 
 | |
|   ret
 | |
| 
 | |
| CardPreload: ; maybe we should do a non-async preload task that empties the handles and banks the rom?
 | |
|   ; first and foremost, clear the card init, update, and draw handles, so there's 
 | |
|   ; no chance of trying to jump into code from a previous card.
 | |
|   di
 | |
|   ld bc, Instructions.rett
 | |
|   ld hl, CARD_INIT
 | |
|   ld [hl], c
 | |
|   inc hl 
 | |
|   ld [hl], b
 | |
|   ld hl, CARD_UPDATE
 | |
|   ld [hl], c
 | |
|   inc hl 
 | |
|   ld [hl], b
 | |
|   ld hl, CARD_DRAW
 | |
|   ld [hl], c
 | |
|   inc hl 
 | |
|   ld [hl], b
 | |
|   ld hl, CARD_PRINT_PREP
 | |
|   ld [hl], c
 | |
|   inc hl 
 | |
|   ld [hl], b
 | |
|   
 | |
|   ld a, [vSelectedCardIndex]
 | |
|   ld [vPreviousCardIndex], a 
 | |
|   
 | |
|   ld b, 0
 | |
|   ld c, a ; load bc from a, the number of the card in the cards list
 | |
|   ld hl, Cards + 1 ; skip the length prefix
 | |
|   add hl, bc
 | |
|   add hl, bc
 | |
|   add hl, bc ; triple add bc entries are bank, addr, addr
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ld [cvCardBank], a 
 | |
|   ld [rROMB0], a ; select the specified bank
 | |
|   ; follow the pointer we're looking at, and write it to cvCardAddress
 | |
|   ld a, [hl+]
 | |
|   ld [cvCardAddress], a 
 | |
|   ld a, [hl+]
 | |
|   ld [cvCardAddress + 1], a 
 | |
| 
 | |
|   reti
 | |
| 
 | |
| LoadCardData:
 | |
| LoadCardDataAsync: 
 | |
|   ld a, [vSelectedCardIndex]
 | |
|   ld b, 0
 | |
|   ld c, a ; bc from a, the number of the card in the cards list
 | |
|   ld hl, DECK_FLIPS + 1
 | |
|   add hl, bc
 | |
|   ld a, [hl]
 | |
|   ld [vCurrentCardReversed], a 
 | |
|   
 | |
|   cp a, 0
 | |
|   jp z, LoadUpright
 | |
|   jp nz, LoadReversed
 | |
|   ret ; shouldn't ever get here
 | |
| 
 | |
| 
 | |
| LoadUpright:
 | |
|   ; card struct starts with a sequence of length-prefixed strings in memory
 | |
|   ; so when we're done writing one, hl will be correctly placed to read the next
 | |
|   ; length-prefixed print doesn't require passing a length
 | |
|   ; so all we have to set is the destination for each
 | |
|   
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   ;ld bc, Card_Offset_title
 | |
|   ;add hl, bc ; unnecessary because card_offset_tile is zero bc the title is first
 | |
|   ; print six texts
 | |
|   ld de, _SCRN0 + 32*11 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*12 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*13 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*14 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*15 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*16 + 10
 | |
|   call PrintString
 | |
|   
 | |
|   ; load tilemap
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   ld bc, Card_Offset_tilemap ; jump straight to sprite tiles length and location!
 | |
|   add hl, bc
 | |
|   ; [hl+] and [hl+] read the length first, into bc
 | |
|   ld a, [hl+]
 | |
|   ld c, a
 | |
|   ld a, [hl+]
 | |
|   ld b, a ; bc has length
 | |
|   ld a, [hl+]
 | |
|   ld e, a
 | |
|   ld a, [hl+]
 | |
|   ld d, a ; de has source of tile range copy
 | |
|   
 | |
|   ld h, d 
 | |
|   ld l, e  ; source
 | |
|   ld de, _SCRN0 + 32 + 1 ; destination
 | |
|   ld b, 16 ; height
 | |
|   ld c, 8 ; width
 | |
|   
 | |
|   call CopyTilesToMap
 | |
|   
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   
 | |
|   ld bc, Card_Offset_functions ; jump straight to function handles
 | |
|   add hl, bc ; hl now points to the card functions
 | |
|   
 | |
|   di ; make sure we never call any callbacks without them being fully set
 | |
|   nop
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_INIT], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_INIT+1], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_UPDATE], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_UPDATE+1], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_DRAW], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_DRAW+1], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_PRINT_PREP], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_PRINT_PREP+1], a
 | |
|   ei
 | |
|   
 | |
|   call CardInit
 | |
|   
 | |
| 
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   
 | |
|   ld bc, Card_Offset_keytiles ; jump straight to keytiles length and location!
 | |
|   add hl, bc
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ld c, a
 | |
|   ld a, [hl+]
 | |
|   ld b, a ; bc has length of tile data
 | |
|   ld a, [hl+]
 | |
|   ld e, a
 | |
|   ld a, [hl+]
 | |
|   ld d, a ; de has source of tile range copy
 | |
| 
 | |
|   ld h, d
 | |
|   ld l, e ; hl takes the source
 | |
| 
 | |
|   ld de, _VRAM + $1000 + VARIABLE_TILES_START*$10 ; always load tile data into the same spot in vram
 | |
|   call CopyRangeBy8s
 | |
|   
 | |
|   
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   
 | |
|   ld bc, Card_Offset_spritetiles ; jump straight to sprite tiles length and location!
 | |
|   add hl, bc
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ld c, a
 | |
|   ld a, [hl+]
 | |
|   ld b, a ; bc has length of tile data
 | |
|   ld a, [hl+]
 | |
|   ld e, a
 | |
|   ld a, [hl+]
 | |
|   ld d, a ; de has source of tile range copy
 | |
| 
 | |
|   ld h, d
 | |
|   ld l, e ; hl takes the source
 | |
| 
 | |
|   ld de, _VRAM ; sprite tiles get loaded into the bottom of vram 
 | |
|   call CopyRangeBy8s
 | |
|   
 | |
|   ret
 | |
| LoadReversed: ; same as LoadRightSideUp but loads in the reversed data
 | |
|   ; card struct starts with a sequence of length-prefixed strings in memory
 | |
|   ; so when we're done writing one, hl will be correctly placed to read the next
 | |
|   ; length-prefixed print doesn't require passing a length
 | |
|   ; so all we have to set is the destination for each
 | |
|   
 | |
|   
 | |
|   ; draw the title
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   ld bc, Card_Offset_reverse
 | |
|   add hl, bc ; jump to the reverse texts and print
 | |
|   ld de, _SCRN0 + 32*11 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*12 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*13 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*14 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*15 + 10
 | |
|   call PrintString
 | |
|   ld de, _SCRN0 + 32*16 + 10
 | |
|   call PrintString
 | |
|  
 | |
|   
 | |
|   ; move the tilemap into memory
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   ld bc, Card_Offset_tilemap ; jump straight to tilemap location!
 | |
|   add hl, bc
 | |
|   
 | |
|   ; [hl+] and [hl+] read the length first, into bc
 | |
|   ld a, [hl+]
 | |
|   ld c, a
 | |
|   ld a, [hl+]
 | |
|   ld b, a ; bc has length
 | |
|   ld a, [hl+]
 | |
|   ld e, a
 | |
|   ld a, [hl+]
 | |
|   ld d, a ; de has source of tile range copy
 | |
|   
 | |
|   ld h, d 
 | |
|   ld l, e  ; source
 | |
|   ld de, _SCRN0 + 32 + 1 ; destination
 | |
|   ld b, 16 ; height
 | |
|   ld c, 8 ; width
 | |
|   
 | |
|   call CopyTilesToMapButRotated
 | |
|   
 | |
|   ; move key tile data into vram
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   ld bc, Card_Offset_functions ; jump straight to function handles
 | |
|   add hl, bc ; hl now points to the card functions
 | |
|   
 | |
|   di ; make sure we never call any callbacks without them being fully set
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_INIT], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_INIT+1], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_UPDATE], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_UPDATE+1], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_DRAW], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_DRAW+1], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_PRINT_PREP], a 
 | |
|   ld a, [hl+]
 | |
|   ld [CARD_PRINT_PREP+1], a
 | |
|   ei
 | |
|   
 | |
|   call CardInit
 | |
|   
 | |
| 
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   
 | |
|   ld bc, Card_Offset_keytiles ; jump straight to keytiles length and location!
 | |
|   add hl, bc
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ld c, a
 | |
|   ld a, [hl+]
 | |
|   ld b, a ; bc has length of tile data
 | |
|   ld a, [hl+]
 | |
|   ld e, a
 | |
|   ld a, [hl+]
 | |
|   ld d, a ; de has source of tile range copy
 | |
| 
 | |
|   ld h, d
 | |
|   ld l, e ; hl takes the source
 | |
| 
 | |
|   ld de, _VRAM + $1000 + VARIABLE_TILES_START*$10 ; always load tile data into the same spot in vram
 | |
|   call CopyRangeOfTilesButRotated
 | |
|   
 | |
|   
 | |
|   ld a, [cvCardAddress]
 | |
|   ld l, a 
 | |
|   ld a, [cvCardAddress + 1]
 | |
|   ld h, a ; hl now contains the address of the card data.
 | |
|   
 | |
|   ld bc, Card_Offset_spritetiles ; jump straight to sprite tiles length and location!
 | |
|   add hl, bc
 | |
|   
 | |
|   ld a, [hl+]
 | |
|   ld c, a
 | |
|   ld a, [hl+]
 | |
|   ld b, a ; bc has length of tile data
 | |
|   ld a, [hl+]
 | |
|   ld e, a
 | |
|   ld a, [hl+]
 | |
|   ld d, a ; de has source of tile range copy
 | |
| 
 | |
|   ld h, d
 | |
|   ld l, e ; hl takes the source
 | |
| 
 | |
|   ld de, _VRAM ; sprite tiles get loaded into the bottom of vram 
 | |
|   call CopyRangeOfTilesButRotated
 | |
|   
 | |
|   ret
 | |
|   
 | |
| ReverseString:
 | |
|   db 10, "(reversed)"
 | |
| EmptyString:
 | |
|   db 10, "          "
 | |
| 
 | |
| CardInit:
 | |
|   ldh a, [rLCDC]
 | |
|   and a, %1111_1011
 | |
|   ldh [rLCDC], a 
 | |
|   
 | |
|   ld hl, ZEROES
 | |
|   ld de, MY_OAM
 | |
|   ld bc, $100
 | |
|   call CopyRange
 | |
|   
 | |
|   ld a, %11100100
 | |
|   ldh [rOBP1], a
 | |
|   call AdjustOBP1
 | |
|   ld a, %11100100
 | |
|   ldh [rOBP0], a 
 | |
|   call AdjustOBP0
 | |
|   
 | |
|   call CARD_INIT - 1
 | |
|   
 | |
|   ld a, [vCurrentCardReversed]
 | |
|   cp a, 0 
 | |
|   call nz, RotateSprites180
 | |
|   ret 
 | |
|   
 | |
| CardUpdate:
 | |
|   ld a, 0
 | |
|   ld [cvNeedsCleanup], a 
 | |
|   
 | |
|   ld a, [vCurrentCardReversed]
 | |
|   cp a, 0 
 | |
|   call nz, RotateSprites180
 | |
|   
 | |
|   call CARD_UPDATE - 1
 | |
|   
 | |
|   ld a, [vCurrentCardReversed]
 | |
|   cp a, 0 
 | |
|   call nz, RotateSprites180
 | |
|   
 | |
|   ld a, [cvNeedsCleanup]
 | |
|   cp a, 0
 | |
|   call nz, CleanUpOutsideSprites
 | |
|   
 | |
|   ret
 | |
|   
 | |
| CardDraw:
 | |
|   call CARD_DRAW - 1
 | |
|   ret  
 | |
|   
 | |
| CardPrintPrep:
 | |
|   call CARD_PRINT_PREP - 1
 | |
|   ret  
 | |
|   
 | |
| RotateSprites180:
 | |
|   ld hl, MY_OAM
 | |
|   
 | |
|   .loop
 | |
|     ld a, 0 
 | |
|     cp a, [hl] ; if y value is nonzero, 
 | |
|     jr nz, :+ ; if y value is nonzero, skip this block where we jump to the next oam entry
 | |
|       inc l 
 | |
|       inc l 
 | |
|       inc l 
 | |
|       inc l 
 | |
|       
 | |
|       ld a, l
 | |
|       cp a, $A0 ; this indicates we've reached the end of the mirror OAM 
 | |
|       jr nz, .loop
 | |
|       ret
 | |
|     :
 | |
|     
 | |
|     ld a, 168
 | |
|     sub a, [hl] 
 | |
|     ld [hl+], a 
 | |
|     
 | |
|     ld b, [hl]
 | |
|     ld a, 0 
 | |
|     cp a, [hl]
 | |
|     jr nz, :+ ; if x value is nonzero, skip this block where we jump to the next oam entry
 | |
|       inc l 
 | |
|       inc l 
 | |
|       inc l 
 | |
|       
 | |
|       ld a, l
 | |
|       cp a, $A0 ; this indicates we've reached the end of the mirror OAM 
 | |
|       jr nz, .loop
 | |
|       ret
 | |
|     :
 | |
|     ld a, 88
 | |
|     sub a, [hl]
 | |
|     ld [hl+], a 
 | |
|     
 | |
|     inc l
 | |
|     inc l 
 | |
|     
 | |
|     ld a, l
 | |
|     cp a, $A0 ; this indicates we've reached the end of the mirror OAM 
 | |
|     jp nz, .loop
 | |
|   
 | |
|   ret
 | |
| 
 | |
| IncrementTimer:
 | |
|   ; hl is the location in memory of a timer
 | |
|   ; squashes a and de
 | |
|   ; uses the value from rDELTAT
 | |
|   ld d, h 
 | |
|   ld e, l 
 | |
|   inc de
 | |
|   ld a, [rDELTAT]
 | |
|   add a, [hl]
 | |
|   ld [hl], a 
 | |
|   ld h, d 
 | |
|   ld l, e 
 | |
|   ld a, [hl] 
 | |
|   adc a, 0 
 | |
|   ld [hl], a 
 | |
|   dec hl 
 | |
|   ret
 | |
| 
 | |
| ; this set of functions and data are for masking sprites off at the edge of the 
 | |
| ; frame, which is afaik only used on one card (the moon). whee!
 | |
| ; set cvNeedsCleanup each frame to enable these, and call SetUpEdgeMasks
 | |
| ; in your card init function
 | |
| SetUpEdgeMasks: 
 | |
|   ld hl, EdgeMasks
 | |
|   ld de, _VRAM + 8*16*16 ; 8 rows of 16 tiles each, 16 bytes per tile
 | |
|   ld bc, EdgeMasks.end - EdgeMasks
 | |
|   call CopyRange
 | |
|   
 | |
|   ld a, %00_00_00_00
 | |
|   ld [rOBP1], a 
 | |
|   ret
 | |
|   
 | |
|   
 | |
| EdgeMasks:
 | |
|   dw `00000000, `00000000, `00000000, `00000000, `00000000, `00000000, `00000000, `00000000, 
 | |
|   dw `00000003, `00000003, `00000003, `00000003, `00000003, `00000003, `00000003, `00000003,
 | |
|   dw `00000033, `00000033, `00000033, `00000033, `00000033, `00000033, `00000033, `00000033, 
 | |
|   dw `00000333, `00000333, `00000333, `00000333, `00000333, `00000333, `00000333, `00000333, 
 | |
|   dw `00003333, `00003333, `00003333, `00003333, `00003333, `00003333, `00003333, `00003333,
 | |
|   dw `00033333, `00033333, `00033333, `00033333, `00033333, `00033333, `00033333, `00033333,
 | |
|   dw `00333333, `00333333, `00333333, `00333333, `00333333, `00333333, `00333333, `00333333,
 | |
|   dw `03333333, `03333333, `03333333, `03333333, `03333333, `03333333, `03333333, `03333333,
 | |
|   dw `33333333, `33333333, `33333333, `33333333, `33333333, `33333333, `33333333, `33333333, 
 | |
| .end
 | |
| 
 | |
| CleanUpOutsideSprites:
 | |
|   ld hl, MY_OAM + 10*4
 | |
|   call HideObviousTiles
 | |
| 
 | |
|   ; now we hide the overlapping edges
 | |
|   ld hl, MY_OAM + 10*4
 | |
|   ld de, MY_OAM
 | |
|   .hideEdgesOfSprite
 | |
|     ld a, 0 
 | |
|     cp a, [hl]
 | |
|     jp z, .skipFromY
 | |
|     
 | |
|     inc l 
 | |
|     cp a, [hl]
 | |
|     jp z, .skipFromX
 | |
|     
 | |
|     ; now we know that the sprite does not have y=0 or x=0.
 | |
|     ;dec hl 
 | |
|     
 | |
|     ;call WriteTopEdgeMaskIfNecessary
 | |
|     ;call WriteBottomEdgeMaskIfNecessary
 | |
|     ;inc hl
 | |
|     call WriteLeftEdgeMaskIfNecessary
 | |
|     dec l 
 | |
|     inc l
 | |
|     call WriteRightEdgeMaskIfNecessary
 | |
|     dec l
 | |
|     
 | |
|     .skipFromY
 | |
|     inc l
 | |
|     .skipFromX
 | |
|     inc l
 | |
|     inc l 
 | |
|     inc l 
 | |
|     ld a, $A0
 | |
|     cp a, l 
 | |
|     jp nz, .hideEdgesOfSprite
 | |
|   ret
 | |
| 
 | |
|   
 | |
| HideObviousTiles:
 | |
| .processSprite
 | |
|   ;hl points at an OAM entry's y value
 | |
|   ld a, 16 ; sprites are visible if y value >= 17
 | |
|   cp a, [hl]
 | |
|   jr c, :+ ; skip if 17-y < 0
 | |
|     ld [hl], 0 
 | |
|   : 
 | |
|   ld a, 152 ; sprites are visible if y value is < 152
 | |
|   cp a, [hl]
 | |
|   jr nc, :+ ; skip if 152 - y < 0
 | |
|     ld [hl], 0
 | |
|   :
 | |
|   inc hl ; look at x value
 | |
|   ld a, 8 ; sprites are visible if x value >= 8
 | |
|   cp a, [hl]
 | |
|   jr c, :+ ; skip if 8-y <= 0
 | |
|     ld [hl], 0
 | |
|   :
 | |
|   ld a, 79 ; sprites are visible if x value < 80
 | |
|   cp a, [hl]
 | |
|   jr nc, :+
 | |
|     ld [hl], 0
 | |
|   :
 | |
|   inc l ; now pointing at tile ID
 | |
|   inc l ; now pointing at attributes
 | |
|   inc l ; now pointing at next OAM y value
 | |
|   ld a, l 
 | |
|   cp a, $A0
 | |
|   jr nz, .processSprite
 | |
|   
 | |
|   ret
 | |
|   
 | |
| WriteTopEdgeMaskIfNecessary:
 | |
|   ;hl points at an OAM entry, de points at an empty OAM spot for masks
 | |
|   ld a, 24 ; sprites are clear if y value > 24
 | |
|   cp a, [hl]
 | |
|   ret c ; skip if 24-y < 0
 | |
| 
 | |
|   ; writing an edge mask on the TOP  
 | |
|   ; else write an edge sprite
 | |
|   ld a, 16 ; y value should be 16 (covers top row)
 | |
|   ld [de], a ; y value in first slot
 | |
|   inc e ;write head moves forward to x
 | |
|   inc l ; read head moves forward to x
 | |
|   ld a, [hl] ; x value matches the sprite we're mirroring
 | |
|   ld [de], a 
 | |
|   
 | |
|   inc e ; write head moves forward to tile ID
 | |
|   ld a, 8*16 + 8
 | |
|   ld [de], a 
 | |
|   
 | |
|   inc e ; write head moves forward to attribute
 | |
|   ld a, OAMF_PRI | OAMF_PAL1
 | |
|   ld [de], a 
 | |
|   
 | |
|   dec l
 | |
|   inc e
 | |
| 
 | |
|   ret
 | |
| 
 | |
| WriteBottomEdgeMaskIfNecessary:
 | |
|   ld a, 145 ; sprites don't overlap edge if y value is <= 145
 | |
|   cp a, [hl]
 | |
|   ret nc ; skip if 145 - y >= 0
 | |
|   
 | |
|   ; writing an edge mask on the BOTTOM
 | |
|   ld a, 144 ; y value should be 144 (covers bottom row)
 | |
|   ld [de], a ; y value in first slot
 | |
|   inc e ;write head moves forward to x
 | |
|   inc l ; read head moves forward to x
 | |
|   ld a, [hl] ; x value matches the sprite we're mirroring
 | |
|   ld [de], a 
 | |
|   
 | |
|   inc e ; write head moves forward to tile ID
 | |
|   ld a, 8*16 + 8
 | |
|   ld [de], a ; tile ID 1 for the hidden ones
 | |
|   
 | |
|   inc e ; write head moves forward to attribute
 | |
|   ld a, OAMF_PRI | OAMF_PAL1 ;OAM_PRIO | OAM_PAL1
 | |
|   ld [de], a 
 | |
|   
 | |
|   dec l
 | |
|   inc e
 | |
|   
 | |
|   ret
 | |
|   
 | |
| WriteLeftEdgeMaskIfNecessary:
 | |
|   ld a, 16 ; sprites dno't need coverage if x value > 16
 | |
|   cp a, [hl]
 | |
|   ret c ; skip if 16-y < 0
 | |
|   
 | |
|   ; else write an edge mask on the LEFT
 | |
|   dec l
 | |
|   ld a, [hl] ; copy y over from sprite
 | |
|   ld [de], a 
 | |
|   
 | |
|   inc l ; point at x now
 | |
|   inc e ; point at x now
 | |
|   
 | |
|   ld a, 8 ; x value should be 8 (covers left edge)
 | |
|   ld [de], a ; x value
 | |
|   
 | |
|   inc e ; write head moves forward to tile ID
 | |
|   ld a, 8*16+7
 | |
|   ld [de], a ; tile ID 1 for the hidden ones
 | |
|   
 | |
|   inc e ; write head moves forward to attribute
 | |
|   ld a, OAMF_PRI | OAMF_PAL1  
 | |
|   ld [de], a 
 | |
|   
 | |
|   inc e
 | |
|   
 | |
|   ret
 | |
|   
 | |
| WriteRightEdgeMaskIfNecessary:
 | |
|   ld a, 72 ; sprites dont needd coverage if x value < 72
 | |
|   cp a, [hl]
 | |
|   ret nc
 | |
|   
 | |
|   ; else write an edge mask on the RIGHT
 | |
|   dec l
 | |
|   ld a, [hl] ; copy y over from sprite
 | |
|   ld [de], a 
 | |
|   
 | |
|   inc l ; point at x now
 | |
|   inc e ; point at x now
 | |
|   
 | |
|   ld a, [hl] ; x value should match the sprite we're masking...
 | |
|   ld [de], a ; x value
 | |
|   
 | |
|   inc e ; write head moves forward to tile ID
 | |
|   ; a currently holds the x coordinate
 | |
|   sub a, 72 ; subtract off 72 to get the amount that we're overlapping
 | |
|   add a, 8*16 ; add the offset for the mask sprites...
 | |
|   ld [de], a ; that makes the tile ID for the mask we want!
 | |
|   
 | |
|   inc e ; write head moves forward to attribute
 | |
|   ld a, OAMF_PRI | OAMF_PAL1
 | |
|   ld [de], a 
 | |
|   
 | |
|   inc e
 | |
|   
 | |
|   ret |