2014-05-22 22:13:20 +00:00
|
|
|
; Loads tile patterns for map's sprites.
|
|
|
|
; For outside maps, it loads one of several fixed sets of sprites.
|
|
|
|
; For inside maps, it loads each sprite picture ID used in the map header.
|
|
|
|
; This is also called after displaying text because loading
|
|
|
|
; text tile patterns overwrites half of the sprite tile pattern data.
|
|
|
|
; Note on notation:
|
2014-05-26 21:04:56 +00:00
|
|
|
; $C1X* and $C2X* are used to denote wSpriteStateData1-wSpriteStateData1 + $ff and wSpriteStateData2 + $00-wSpriteStateData2 + $ff sprite slot
|
2014-05-22 22:13:20 +00:00
|
|
|
; fields, respectively, within loops. The X is the loop index.
|
|
|
|
; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y*
|
|
|
|
; denote fields of the sprite slots interated over in the inner loop.
|
|
|
|
InitMapSprites: ; 1785b (5:785b)
|
|
|
|
call InitOutsideMapSprites
|
|
|
|
ret c ; return if the map is an outside map (already handled by above call)
|
|
|
|
; if the map is an inside map (i.e. mapID >= $25)
|
|
|
|
ld hl,wSpriteStateData1
|
2014-05-26 21:04:56 +00:00
|
|
|
ld de,wSpriteStateData2 + $0d
|
2014-05-22 22:13:20 +00:00
|
|
|
; Loop to copy picture ID's from $C1X0 to $C2XD for LoadMapSpriteTilePatterns.
|
|
|
|
.copyPictureIDLoop
|
|
|
|
ld a,[hl] ; $C1X0 (picture ID)
|
|
|
|
ld [de],a ; $C2XD
|
|
|
|
ld a,$10
|
|
|
|
add e
|
|
|
|
ld e,a
|
|
|
|
ld a,$10
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
jr nz,.copyPictureIDLoop
|
|
|
|
|
|
|
|
; This is used for both inside and outside maps, since it is called by
|
|
|
|
; InitOutsideMapSprites.
|
|
|
|
; Loads tile pattern data for sprites into VRAM.
|
|
|
|
LoadMapSpriteTilePatterns: ; 17871 (5:7871)
|
|
|
|
ld a,[W_NUMSPRITES]
|
|
|
|
and a ; are there any sprites?
|
|
|
|
jr nz,.spritesExist
|
|
|
|
ret
|
|
|
|
.spritesExist
|
|
|
|
ld c,a ; c = [W_NUMSPRITES]
|
|
|
|
ld b,$10 ; number of sprite slots
|
2014-05-26 21:04:56 +00:00
|
|
|
ld hl,wSpriteStateData2 + $0d
|
2014-05-22 22:13:20 +00:00
|
|
|
xor a
|
2015-07-18 15:17:29 +00:00
|
|
|
ld [hFourTileSpriteCount],a
|
2014-05-22 22:13:20 +00:00
|
|
|
.copyPictureIDLoop ; loop to copy picture ID from $C2XD to $C2XE
|
|
|
|
ld a,[hli] ; $C2XD (sprite picture ID)
|
|
|
|
ld [hld],a ; $C2XE
|
|
|
|
ld a,l
|
|
|
|
add a,$10
|
|
|
|
ld l,a
|
|
|
|
dec b
|
|
|
|
jr nz,.copyPictureIDLoop
|
2014-05-26 21:04:56 +00:00
|
|
|
ld hl,wSpriteStateData2 + $1e
|
2014-05-22 22:13:20 +00:00
|
|
|
.loadTilePatternLoop
|
2014-05-26 21:04:56 +00:00
|
|
|
ld de,wSpriteStateData2 + $1d
|
2014-05-22 22:13:20 +00:00
|
|
|
; Check if the current picture ID has already had its tile patterns loaded.
|
|
|
|
; This done by looping through the previous sprite slots and seeing if any of
|
|
|
|
; their picture ID's match that of the current sprite slot.
|
|
|
|
.checkIfAlreadyLoadedLoop
|
|
|
|
ld a,e
|
|
|
|
and a,$f0
|
|
|
|
ld b,a ; b = offset of the wSpriteStateData2 sprite slot being checked against
|
|
|
|
ld a,l
|
|
|
|
and a,$f0 ; a = offset of current wSpriteStateData2 sprite slot
|
|
|
|
cp b ; done checking all previous sprite slots?
|
|
|
|
jr z,.notAlreadyLoaded
|
|
|
|
ld a,[de] ; picture ID of the wSpriteStateData2 sprite slot being checked against
|
|
|
|
cp [hl] ; do the picture ID's match?
|
|
|
|
jp z,.alreadyLoaded
|
|
|
|
ld a,e
|
|
|
|
add a,$10
|
|
|
|
ld e,a
|
|
|
|
jr .checkIfAlreadyLoadedLoop
|
|
|
|
.notAlreadyLoaded
|
2014-05-26 21:04:56 +00:00
|
|
|
ld de,wSpriteStateData2 + $0e
|
2014-05-22 22:13:20 +00:00
|
|
|
ld b,$01
|
|
|
|
; loop to find the highest tile pattern VRAM slot (among the first 10 slots) used by a previous sprite slot
|
|
|
|
; this is done in order to find the first free VRAM slot available
|
|
|
|
.findNextVRAMSlotLoop
|
|
|
|
ld a,e
|
|
|
|
add a,$10
|
|
|
|
ld e,a
|
|
|
|
ld a,l
|
|
|
|
cp e ; reached current slot?
|
|
|
|
jr z,.foundNextVRAMSlot
|
|
|
|
ld a,[de] ; $C2YE (VRAM slot)
|
|
|
|
cp a,11 ; is it one of the first 10 slots?
|
|
|
|
jr nc,.findNextVRAMSlotLoop
|
|
|
|
cp b ; compare the slot being checked to the current max
|
|
|
|
jr c,.findNextVRAMSlotLoop ; if the slot being checked is less than the current max
|
|
|
|
; if the slot being checked is greater than or equal to the current max
|
|
|
|
ld b,a ; store new max VRAM slot
|
|
|
|
jr .findNextVRAMSlotLoop
|
|
|
|
.foundNextVRAMSlot
|
|
|
|
inc b ; increment previous max value to get next VRAM tile pattern slot
|
|
|
|
ld a,b ; a = next VRAM tile pattern slot
|
|
|
|
push af
|
|
|
|
ld a,[hl] ; $C2XE (sprite picture ID)
|
|
|
|
ld b,a ; b = current sprite picture ID
|
|
|
|
cp a,SPRITE_BALL ; is it a 4-tile sprite?
|
|
|
|
jr c,.notFourTileSprite
|
|
|
|
pop af
|
2015-07-18 15:17:29 +00:00
|
|
|
ld a,[hFourTileSpriteCount]
|
2014-05-22 22:13:20 +00:00
|
|
|
add a,11
|
|
|
|
jr .storeVRAMSlot
|
|
|
|
.notFourTileSprite
|
|
|
|
pop af
|
|
|
|
.storeVRAMSlot
|
|
|
|
ld [hl],a ; store VRAM slot at $C2XE
|
2015-07-18 15:17:29 +00:00
|
|
|
ld [hVRAMSlot],a ; used to determine if it's 4-tile sprite later
|
2014-05-22 22:13:20 +00:00
|
|
|
ld a,b ; a = current sprite picture ID
|
|
|
|
dec a
|
|
|
|
add a
|
|
|
|
add a
|
|
|
|
push bc
|
|
|
|
push hl
|
|
|
|
ld hl,SpriteSheetPointerTable
|
|
|
|
jr nc,.noCarry
|
|
|
|
inc h
|
|
|
|
.noCarry
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
jr nc,.noCarry2
|
|
|
|
inc h
|
|
|
|
.noCarry2
|
|
|
|
push hl
|
|
|
|
call ReadSpriteSheetData
|
|
|
|
push af
|
|
|
|
push de
|
|
|
|
push bc
|
2014-05-29 08:31:46 +00:00
|
|
|
ld hl,vNPCSprites ; VRAM base address
|
2014-05-22 22:13:20 +00:00
|
|
|
ld bc,$c0 ; number of bytes per VRAM slot
|
2015-07-18 15:17:29 +00:00
|
|
|
ld a,[hVRAMSlot]
|
2014-05-22 22:13:20 +00:00
|
|
|
cp a,11 ; is it a 4-tile sprite?
|
|
|
|
jr nc,.fourTileSpriteVRAMAddr
|
|
|
|
ld d,a
|
|
|
|
dec d
|
|
|
|
; Equivalent to multiplying $C0 (number of bytes in 12 tiles) times the VRAM
|
|
|
|
; slot and adding the result to $8000 (the VRAM base address).
|
|
|
|
.calculateVRAMAddrLoop
|
|
|
|
add hl,bc
|
|
|
|
dec d
|
|
|
|
jr nz,.calculateVRAMAddrLoop
|
|
|
|
jr .loadStillTilePattern
|
|
|
|
.fourTileSpriteVRAMAddr
|
2014-05-29 08:31:46 +00:00
|
|
|
ld hl,vSprites + $7c0 ; address for second 4-tile sprite
|
2015-07-18 15:17:29 +00:00
|
|
|
ld a,[hFourTileSpriteCount]
|
|
|
|
and a
|
2014-05-22 22:13:20 +00:00
|
|
|
jr nz,.loadStillTilePattern
|
|
|
|
; if it's the first 4-tile sprite
|
2014-05-29 08:31:46 +00:00
|
|
|
ld hl,vSprites + $780 ; address for first 4-tile sprite
|
2014-05-22 22:13:20 +00:00
|
|
|
inc a
|
2015-07-18 15:17:29 +00:00
|
|
|
ld [hFourTileSpriteCount],a
|
2014-05-22 22:13:20 +00:00
|
|
|
.loadStillTilePattern
|
|
|
|
pop bc
|
|
|
|
pop de
|
|
|
|
pop af
|
|
|
|
push hl
|
|
|
|
push hl
|
|
|
|
ld h,d
|
|
|
|
ld l,e
|
|
|
|
pop de
|
|
|
|
ld b,a
|
2015-02-09 02:40:08 +00:00
|
|
|
ld a,[wFontLoaded]
|
2014-05-22 22:13:20 +00:00
|
|
|
bit 0,a ; reloading upper half of tile patterns after displaying text?
|
|
|
|
jr nz,.skipFirstLoad ; if so, skip loading data into the lower half
|
|
|
|
ld a,b
|
|
|
|
ld b,0
|
|
|
|
call FarCopyData2 ; load tile pattern data for sprite when standing still
|
|
|
|
.skipFirstLoad
|
|
|
|
pop de
|
|
|
|
pop hl
|
2015-07-18 15:17:29 +00:00
|
|
|
ld a,[hVRAMSlot]
|
2014-05-22 22:13:20 +00:00
|
|
|
cp a,11 ; is it a 4-tile sprite?
|
|
|
|
jr nc,.skipSecondLoad ; if so, there is no second block
|
|
|
|
push de
|
|
|
|
call ReadSpriteSheetData
|
|
|
|
push af
|
|
|
|
ld a,$c0
|
|
|
|
add e
|
|
|
|
ld e,a
|
|
|
|
jr nc,.noCarry3
|
|
|
|
inc d
|
|
|
|
.noCarry3
|
2015-02-09 02:40:08 +00:00
|
|
|
ld a,[wFontLoaded]
|
2014-05-22 22:13:20 +00:00
|
|
|
bit 0,a ; reloading upper half of tile patterns after displaying text?
|
|
|
|
jr nz,.loadWhileLCDOn
|
|
|
|
pop af
|
|
|
|
pop hl
|
|
|
|
set 3,h ; add $800 to hl
|
|
|
|
push hl
|
|
|
|
ld h,d
|
|
|
|
ld l,e
|
|
|
|
pop de
|
|
|
|
call FarCopyData2 ; load tile pattern data for sprite when walking
|
|
|
|
jr .skipSecondLoad
|
|
|
|
; When reloading the upper half of tile patterns after diplaying text, the LCD
|
|
|
|
; will be on, so CopyVideoData (which writes to VRAM only during V-blank) must
|
|
|
|
; be used instead of FarCopyData2.
|
|
|
|
.loadWhileLCDOn
|
|
|
|
pop af
|
|
|
|
pop hl
|
|
|
|
set 3,h ; add $800 to hl
|
|
|
|
ld b,a
|
|
|
|
swap c
|
|
|
|
call CopyVideoData ; load tile pattern data for sprite when walking
|
|
|
|
.skipSecondLoad
|
|
|
|
pop hl
|
|
|
|
pop bc
|
|
|
|
jr .nextSpriteSlot
|
|
|
|
.alreadyLoaded ; if the current picture ID has already had its tile patterns loaded
|
|
|
|
inc de
|
|
|
|
ld a,[de] ; a = VRAM slot for the current picture ID (from $C2YE)
|
|
|
|
ld [hl],a ; store VRAM slot in current wSpriteStateData2 sprite slot (at $C2XE)
|
|
|
|
.nextSpriteSlot
|
|
|
|
ld a,l
|
|
|
|
add a,$10
|
|
|
|
ld l,a
|
|
|
|
dec c
|
|
|
|
jp nz,.loadTilePatternLoop
|
2014-05-26 21:04:56 +00:00
|
|
|
ld hl,wSpriteStateData2 + $0d
|
2014-05-22 22:13:20 +00:00
|
|
|
ld b,$10
|
|
|
|
; the pictures ID's stored at $C2XD are no longer needed, so zero them
|
|
|
|
.zeroStoredPictureIDLoop
|
|
|
|
xor a
|
|
|
|
ld [hl],a ; $C2XD
|
|
|
|
ld a,$10
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
dec b
|
|
|
|
jr nz,.zeroStoredPictureIDLoop
|
|
|
|
ret
|
|
|
|
|
|
|
|
; reads data from SpriteSheetPointerTable
|
|
|
|
; INPUT:
|
|
|
|
; hl = address of sprite sheet entry
|
|
|
|
; OUTPUT:
|
|
|
|
; de = pointer to sprite sheet
|
|
|
|
; bc = length in bytes
|
|
|
|
; a = ROM bank
|
|
|
|
ReadSpriteSheetData: ; 17971 (5:7971)
|
|
|
|
ld a,[hli]
|
|
|
|
ld e,a
|
|
|
|
ld a,[hli]
|
|
|
|
ld d,a
|
|
|
|
ld a,[hli]
|
|
|
|
ld c,a
|
|
|
|
xor a
|
|
|
|
ld b,a
|
|
|
|
ld a,[hli]
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Loads sprite set for outside maps (cities and routes) and sets VRAM slots.
|
|
|
|
; sets carry if the map is a city or route, unsets carry if not
|
|
|
|
InitOutsideMapSprites: ; 1797b (5:797b)
|
|
|
|
ld a,[W_CURMAP]
|
|
|
|
cp a,REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)?
|
|
|
|
ret nc ; if not, return
|
|
|
|
ld hl,MapSpriteSets
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
jr nc,.noCarry
|
|
|
|
inc h
|
|
|
|
.noCarry
|
|
|
|
ld a,[hl] ; a = spriteSetID
|
|
|
|
cp a,$f0 ; does the map have 2 sprite sets?
|
|
|
|
call nc,GetSplitMapSpriteSetID ; if so, choose the appropriate one
|
|
|
|
ld b,a ; b = spriteSetID
|
2015-02-09 02:40:08 +00:00
|
|
|
ld a,[wFontLoaded]
|
2014-05-22 22:13:20 +00:00
|
|
|
bit 0,a ; reloading upper half of tile patterns after displaying text?
|
|
|
|
jr nz,.loadSpriteSet ; if so, forcibly reload the sprite set
|
|
|
|
ld a,[W_SPRITESETID]
|
|
|
|
cp b ; has the sprite set ID changed?
|
|
|
|
jr z,.skipLoadingSpriteSet ; if not, don't load it again
|
|
|
|
.loadSpriteSet
|
|
|
|
ld a,b
|
|
|
|
ld [W_SPRITESETID],a
|
|
|
|
dec a
|
|
|
|
ld b,a
|
|
|
|
sla a
|
|
|
|
ld c,a
|
|
|
|
sla a
|
|
|
|
sla a
|
|
|
|
add c
|
|
|
|
add b ; a = (spriteSetID - 1) * 11
|
|
|
|
ld de,SpriteSets
|
|
|
|
; add a to de to get offset of sprite set
|
|
|
|
add e
|
|
|
|
ld e,a
|
|
|
|
jr nc,.noCarry2
|
|
|
|
inc d
|
|
|
|
.noCarry2
|
2014-05-26 21:04:56 +00:00
|
|
|
ld hl,wSpriteStateData2 + $0d
|
2014-05-22 22:13:20 +00:00
|
|
|
ld a,SPRITE_RED
|
|
|
|
ld [hl],a
|
|
|
|
ld bc,W_SPRITESET
|
|
|
|
; Load the sprite set into RAM.
|
|
|
|
; This loop also fills $C2XD (sprite picture ID) where X is from $0 to $A
|
|
|
|
; with picture ID's. This is done so that LoadMapSpriteTilePatterns will
|
|
|
|
; load tile patterns for all sprite pictures in the sprite set.
|
|
|
|
.loadSpriteSetLoop
|
|
|
|
ld a,$10
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
ld a,[de] ; sprite picture ID from sprite set
|
|
|
|
ld [hl],a ; $C2XD (sprite picture ID)
|
|
|
|
ld [bc],a
|
|
|
|
inc de
|
|
|
|
inc bc
|
|
|
|
ld a,l
|
|
|
|
cp a,$bd ; reached 11th sprite slot?
|
|
|
|
jr nz,.loadSpriteSetLoop
|
|
|
|
ld b,4 ; 4 remaining sprite slots
|
|
|
|
.zeroRemainingSlotsLoop ; loop to zero the picture ID's of the remaining sprite slots
|
|
|
|
ld a,$10
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
xor a
|
|
|
|
ld [hl],a ; $C2XD (sprite picture ID)
|
|
|
|
dec b
|
|
|
|
jr nz,.zeroRemainingSlotsLoop
|
|
|
|
ld a,[W_NUMSPRITES]
|
|
|
|
push af ; save number of sprites
|
|
|
|
ld a,11 ; 11 sprites in sprite set
|
|
|
|
ld [W_NUMSPRITES],a
|
|
|
|
call LoadMapSpriteTilePatterns
|
|
|
|
pop af
|
|
|
|
ld [W_NUMSPRITES],a ; restore number of sprites
|
2014-05-26 21:04:56 +00:00
|
|
|
ld hl,wSpriteStateData2 + $1e
|
2014-05-22 22:13:20 +00:00
|
|
|
ld b,$0f
|
|
|
|
; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the
|
|
|
|
; order of the map's sprite set, not the order of the actual sprites loaded
|
|
|
|
; for the current map. So, they are not needed and are zeroed by this loop.
|
|
|
|
.zeroVRAMSlotsLoop
|
|
|
|
xor a
|
|
|
|
ld [hl],a ; $C2XE (VRAM slot)
|
|
|
|
ld a,$10
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
dec b
|
|
|
|
jr nz,.zeroVRAMSlotsLoop
|
|
|
|
.skipLoadingSpriteSet
|
2014-05-26 21:04:56 +00:00
|
|
|
ld hl,wSpriteStateData1 + $10
|
2014-05-22 22:13:20 +00:00
|
|
|
; This loop stores the correct VRAM tile pattern slots according the sprite
|
|
|
|
; data from the map's header. Since the VRAM tile pattern slots are filled in
|
|
|
|
; the order of the sprite set, in order to find the VRAM tile pattern slot
|
|
|
|
; for a sprite slot, the picture ID for the sprite is looked up within the
|
|
|
|
; sprite set. The index of the picture ID within the sprite set plus one
|
|
|
|
; (since the Red sprite always has the first VRAM tile pattern slot) is the
|
|
|
|
; VRAM tile pattern slot.
|
|
|
|
.storeVRAMSlotsLoop
|
|
|
|
ld c,0
|
|
|
|
ld a,[hl] ; $C1X0 (picture ID) (zero if sprite slot is not used)
|
|
|
|
and a ; is the sprite slot used?
|
|
|
|
jr z,.skipGettingPictureIndex ; if the sprite slot is not used
|
|
|
|
ld b,a ; b = picture ID
|
|
|
|
ld de,W_SPRITESET
|
|
|
|
; Loop to find the index of the sprite's picture ID within the sprite set.
|
|
|
|
.getPictureIndexLoop
|
|
|
|
inc c
|
|
|
|
ld a,[de]
|
|
|
|
inc de
|
|
|
|
cp b ; does the picture ID match?
|
|
|
|
jr nz,.getPictureIndexLoop
|
|
|
|
inc c
|
|
|
|
.skipGettingPictureIndex
|
|
|
|
push hl
|
|
|
|
inc h
|
|
|
|
ld a,$0e
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
ld a,c ; a = VRAM slot (zero if sprite slot is not used)
|
|
|
|
ld [hl],a ; $C2XE (VRAM slot)
|
|
|
|
pop hl
|
|
|
|
ld a,$10
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
and a
|
|
|
|
jr nz,.storeVRAMSlotsLoop
|
|
|
|
scf
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Chooses the correct sprite set ID depending on the player's position within
|
|
|
|
; the map for maps with two sprite sets.
|
|
|
|
GetSplitMapSpriteSetID: ; 17a1a (5:7a1a)
|
|
|
|
cp a,$f8
|
|
|
|
jr z,.route20
|
|
|
|
ld hl,SplitMapSpriteSets
|
|
|
|
and a,$0f
|
|
|
|
dec a
|
|
|
|
sla a
|
|
|
|
sla a
|
|
|
|
add l
|
|
|
|
ld l,a
|
|
|
|
jr nc,.noCarry
|
|
|
|
inc h
|
|
|
|
.noCarry
|
|
|
|
ld a,[hli] ; determines whether the map is split East/West or North/South
|
|
|
|
cp a,$01
|
|
|
|
ld a,[hli] ; position of dividing line
|
|
|
|
ld b,a
|
|
|
|
jr z,.eastWestDivide
|
|
|
|
.northSouthDivide
|
|
|
|
ld a,[W_YCOORD]
|
|
|
|
jr .compareCoord
|
|
|
|
.eastWestDivide
|
|
|
|
ld a,[W_XCOORD]
|
|
|
|
.compareCoord
|
|
|
|
cp b
|
|
|
|
jr c,.loadSpriteSetID
|
|
|
|
; if in the East side or South side
|
|
|
|
inc hl
|
|
|
|
.loadSpriteSetID
|
|
|
|
ld a,[hl]
|
|
|
|
ret
|
|
|
|
; Uses sprite set $01 for West side and $0A for East side.
|
|
|
|
; Route 20 is a special case because the two map sections have a more complex
|
|
|
|
; shape instead of the map simply being split horizontally or vertically.
|
|
|
|
.route20
|
|
|
|
ld hl,W_XCOORD
|
|
|
|
ld a,[hl]
|
|
|
|
cp a,$2b
|
|
|
|
ld a,$01
|
|
|
|
ret c
|
|
|
|
ld a,[hl]
|
|
|
|
cp a,$3e
|
|
|
|
ld a,$0a
|
|
|
|
ret nc
|
|
|
|
ld a,[hl]
|
|
|
|
cp a,$37
|
|
|
|
ld b,$08
|
|
|
|
jr nc,.next
|
|
|
|
ld b,$0d
|
|
|
|
.next
|
|
|
|
ld a,[W_YCOORD]
|
|
|
|
cp b
|
|
|
|
ld a,$0a
|
|
|
|
ret c
|
|
|
|
ld a,$01
|
|
|
|
ret
|
|
|
|
|
|
|
|
INCLUDE "data/sprite_sets.asm"
|