458 lines
10 KiB
PHP
458 lines
10 KiB
PHP
; CARD_HELPER_VARS_START defines the beginning of the $100 bytes set aside for system usage
|
|
def cvCardBank equ 0
|
|
def cvCardAddress equ 1 ; location of the current card's struct
|
|
|
|
LoadCardData:
|
|
LoadCardDataAsync:
|
|
; 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
|
|
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
|
|
ei
|
|
|
|
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 [CARD_HELPER_VARS_START + 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 [CARD_HELPER_VARS_START + cvCardAddress], a
|
|
ld c, a
|
|
ld a, [hl+]
|
|
ld [CARD_HELPER_VARS_START + cvCardAddress + 1], a
|
|
ld b, a
|
|
|
|
ld h, b
|
|
ld l, c ; hl now contains the address of the card 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
|
|
ld de, $9800 + 32*11 + 10
|
|
call PrintString
|
|
ld de, $9800 + 32*12 + 10
|
|
call PrintString
|
|
ld de, $9800 + 32*14 + 10
|
|
call PrintString
|
|
ld de, $9800 + 32*15 + 10
|
|
call PrintString
|
|
ld de, $9800 + 32*16 + 10
|
|
call PrintString
|
|
|
|
; hl now contains the address after all the strings.
|
|
; [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, $9800 + 32 + 1 ; destination
|
|
ld b, 16 ; height
|
|
ld c, 8 ; width
|
|
|
|
call CopyTilesToMap
|
|
|
|
ld a, [CARD_HELPER_VARS_START + cvCardAddress]
|
|
ld l, a
|
|
ld a, [CARD_HELPER_VARS_START + cvCardAddress + 1]
|
|
ld h, a ; hl now contains the address of the card data.
|
|
|
|
ld b, 0
|
|
ld c, Card_Offset_functions ; jump straight to function handles
|
|
add hl, bc ; hl now points to the card functions
|
|
|
|
di ; make sure we never call card_update and card_draw 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
|
|
ei
|
|
|
|
call CardInit
|
|
|
|
|
|
ld a, [CARD_HELPER_VARS_START + cvCardAddress]
|
|
ld l, a
|
|
ld a, [CARD_HELPER_VARS_START + cvCardAddress + 1]
|
|
ld h, a ; hl now contains the address of the card data.
|
|
|
|
ld b, 0
|
|
ld c, 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, $9000 + VARIABLE_TILES_START*$10 ; always load tile data into the same spot in vram
|
|
call CopyRange
|
|
|
|
|
|
ld a, [CARD_HELPER_VARS_START + cvCardAddress]
|
|
ld l, a
|
|
ld a, [CARD_HELPER_VARS_START + cvCardAddress + 1]
|
|
ld h, a ; hl now contains the address of the card data.
|
|
|
|
ld b, 0
|
|
ld c, 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, $8000 ; sprite tiles get loaded into the bottom of vram
|
|
call CopyRange
|
|
|
|
ret
|
|
|
|
CardInit:
|
|
ld a, [rLCDC]
|
|
and a, %1111_1011
|
|
ld [rLCDC], a
|
|
|
|
ld hl, ZEROES
|
|
ld de, MY_OAM
|
|
ld bc, $100
|
|
call CopyRange
|
|
|
|
ld a, %11100100
|
|
ld [rOBP0], a
|
|
ld [rOBP1], a
|
|
|
|
|
|
call CARD_INIT - 1
|
|
ret
|
|
|
|
CardUpdate:
|
|
di
|
|
nop
|
|
call CARD_UPDATE - 1
|
|
ei
|
|
ret
|
|
|
|
CardDraw:
|
|
di
|
|
nop
|
|
call CARD_DRAW - 1
|
|
ei
|
|
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
|
|
|
|
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
|
|
|
|
.processSprite
|
|
;hl points at an OAM entry's y value
|
|
ld a, 17 ; sprites are visible if y value >= 17
|
|
cp a, [hl]
|
|
jp c, :+ ; skip if 17-y < 0
|
|
ld [hl], 0
|
|
:
|
|
ld a, 152 ; sprites are visible if y value is < 152
|
|
cp a, [hl]
|
|
jp nc, :+ ; skip if 152 - y < 0
|
|
ld [hl], 0
|
|
:
|
|
inc hl ; look at x value
|
|
ld a, 8 ; sprites are visible if y value >= 8
|
|
cp a, [hl]
|
|
jp c, :+ ; skip if 8-y <= 0
|
|
ld [hl], 0
|
|
:
|
|
ld a, 80 ; sprites are visible if x value < 80
|
|
cp a, [hl]
|
|
jp nc, :+
|
|
ld [hl], 0
|
|
:
|
|
inc hl ; now pointing at tile ID
|
|
inc hl ; now pointing at attributes
|
|
inc hl ; now pointing at next OAM y value
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .processSprite
|
|
|
|
|
|
|
|
; now we hide the overlapping edges
|
|
ld hl, MY_OAM + 10*4
|
|
ld de, MY_OAM
|
|
.hideEdges
|
|
ld a, 0 ; check if y value is zero; if so, skip this sprite
|
|
cp a, [hl]
|
|
jp nz, :+
|
|
inc hl ; x
|
|
inc hl ; tile id
|
|
inc hl ; attr
|
|
inc hl ; next y
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .hideEdges
|
|
ret
|
|
:
|
|
inc hl ; check if x value is zero; if so, skip this
|
|
ld a, 0
|
|
cp a, [hl]
|
|
jp nz, :+
|
|
inc hl
|
|
inc hl
|
|
inc hl
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .hideEdges
|
|
ret
|
|
: dec hl
|
|
|
|
;hl points at an OAM entry's y value
|
|
ld a, 24 ; sprites are clear if y value > 24
|
|
cp a, [hl]
|
|
jp 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 de ;write head moves forward to x
|
|
inc hl ; read head moves forward to x
|
|
ld a, [hl] ; x value matches the sprite we're mirroring
|
|
ld [de], a
|
|
|
|
inc de ; write head moves forward to tile ID
|
|
inc hl ; read head moves forward to tile id
|
|
ld a, 8*16 + 8
|
|
ld [de], a ; tile ID 1 for the hidden ones
|
|
|
|
inc de ; write head moves forward to attribute
|
|
inc hl ; read head moves forward to attributes
|
|
ld a, [de]
|
|
set OAMB_PRI, a
|
|
set OAMB_PAL1, a
|
|
ld [de], a
|
|
|
|
inc de ; point at next slot for both mask and source
|
|
inc hl
|
|
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .hideEdges
|
|
ret
|
|
:
|
|
ld a, 145 ; sprites don't overlap edge if y value is <= 145
|
|
cp a, [hl]
|
|
jp 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 de ;write head moves forward to x
|
|
inc hl ; read head moves forward to x
|
|
ld a, [hl] ; x value matches the sprite we're mirroring
|
|
ld [de], a
|
|
|
|
inc de ; write head moves forward to tile ID
|
|
inc hl ; read head moves forward to tile id
|
|
ld a, 8*16 + 8
|
|
ld [de], a ; tile ID 1 for the hidden ones
|
|
|
|
inc de ; write head moves forward to attribute
|
|
inc hl ; read head moves forward to attributes
|
|
ld a, [de]
|
|
set OAMB_PRI, a
|
|
set OAMB_PAL1, a
|
|
ld [de], a
|
|
|
|
inc de
|
|
inc hl
|
|
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .hideEdges
|
|
ret
|
|
:
|
|
inc hl ; look at x value
|
|
ld a, 16 ; sprites dno't need coverage if x value > 16
|
|
cp a, [hl]
|
|
jp c, :+ ; skip if 16-y < 0
|
|
|
|
|
|
|
|
|
|
; else write an edge mask on the LEFT
|
|
dec hl ; step back so we're looking at y
|
|
ld a, [hl] ; copy y over from sprite
|
|
ld [de], a
|
|
|
|
inc hl ; point at x now
|
|
inc de ; point at x now
|
|
|
|
ld a, 8 ; x value should be 8 (covers left edge)
|
|
ld [de], a ; x value
|
|
|
|
inc de ; write head moves forward to tile ID
|
|
inc hl ; read head moves forward to tile id
|
|
ld a, 1
|
|
ld [de], a ; tile ID 1 for the hidden ones
|
|
|
|
inc de ; write head moves forward to attribute
|
|
inc hl ; read head moves forward to attributes
|
|
ld a, [de]
|
|
set OAMB_PRI, a
|
|
set OAMB_PAL1, a
|
|
ld [de], a
|
|
|
|
inc de
|
|
inc hl
|
|
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .hideEdges
|
|
ret
|
|
|
|
:
|
|
ld a, 72 ; sprites dont needd coverage if x value < 72
|
|
cp a, [hl]
|
|
jp nc, :+
|
|
|
|
|
|
|
|
; else write an edge mask on the RIGHT
|
|
dec hl ; step back so we're looking at y
|
|
ld a, [hl] ; copy y over from sprite
|
|
ld [de], a
|
|
|
|
inc hl ; point at x now
|
|
inc de ; point at x now
|
|
|
|
ld a, [hl] ; x value should match the sprite we're masking...
|
|
ld [de], a ; x value
|
|
|
|
inc de ; write head moves forward to tile ID
|
|
inc hl ; read 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 de ; write head moves forward to attribute
|
|
inc hl ; read head moves forward to attributes
|
|
ld a, [de]
|
|
set OAMB_PRI, a
|
|
set OAMB_PAL1, a
|
|
ld [de], a
|
|
|
|
inc de
|
|
inc hl
|
|
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .hideEdges
|
|
ret
|
|
:
|
|
inc hl ; now pointing at tile ID
|
|
inc hl ; now pointing at attributes
|
|
inc hl ; now pointing at next OAM y value
|
|
ld a, l
|
|
cp a, $A0
|
|
jp nz, .hideEdges
|
|
ret
|
|
|