pokeyellow/engine/gfx/sprite_oam.asm
2020-11-05 10:51:02 -05:00

233 lines
4.1 KiB
NASM

PrepareOAMData::
; Determine OAM data for currently visible
; sprites and write it to wOAMBuffer.
; Yellow code has been changed to use registers more efficiently
; as well as tweaking the code to show gbc palettes
ld a, [wUpdateSpritesEnabled]
dec a
jr z, .updateEnabled
cp -1
ret nz
ld [wUpdateSpritesEnabled], a
jp HideSprites
.updateEnabled
xor a
ldh [hOAMBufferOffset], a
.spriteLoop
ldh [hSpriteOffset2], a
ld e, a
ld d, HIGH(wSpriteStateData1)
ld a, [de] ; [x#SPRITESTATEDATA1_PICTUREID]
and a
jp z, .nextSprite
inc e
inc e
ld a, [de] ; [x#SPRITESTATEDATA1_IMAGEINDEX]
ld [wd5cd], a
cp $ff ; off-screen (don't draw)
jr nz, .visible
call GetSpriteScreenXY
jr .nextSprite
.visible
cp $a0 ; is the sprite unchanging like an item ball or boulder?
jr c, .usefacing
; unchanging
ld a, $0
jr .next
.usefacing
and $f
.next
; read the entry from the table
ld c, a
ld b, 0
ld hl, SpriteFacingAndAnimationTable
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
; get sprite priority
push de
inc d
ld a, e
add $5
ld e, a
ld a, [de] ; [x#SPRITESTATEDATA2_GRASSPRIORITY]
and $80
ldh [hSpritePriority], a ; temp store sprite priority
pop de
call GetSpriteScreenXY
ldh a, [hOAMBufferOffset]
add [hl]
cp $a0
jr z, .hidden
jr nc, .asm_4a41
.hidden
call Func_4a7b
ld [wd5cd], a
ldh a, [hOAMBufferOffset]
ld e, a
ld d, HIGH(wOAMBuffer)
.tileLoop
ld a, [hli]
ld c, a
.loop
ldh a, [hSpriteScreenY] ; temp for sprite Y position
add $10 ; Y=16 is top of screen (Y=0 is invisible)
add [hl] ; add Y offset from table
ld [de], a ; write new sprite OAM Y position
inc hl
inc e
ldh a, [hSpriteScreenX] ; temp for sprite X position
add $8 ; X=8 is left of screen (X=0 is invisible)
add [hl] ; add X offset from table
ld [de], a
inc hl
inc e
ld a, [wd5cd]
add [hl]
cp $80
jr c, .asm_4a1c
ld b, a
ldh a, [hFFFC]
add b
.asm_4a1c
ld [de], a ; tile id
inc hl
inc e
ld a, [hl]
bit 1, a ; is the tile allowed to set the sprite priority bit?
jr z, .skipPriority
ldh a, [hSpritePriority]
or [hl]
.skipPriority
and $f0
bit 4, a ; OBP0 or OBP1
jr z, .spriteusesOBP0
or %100 ; palettes 4-7 are OBP1
.spriteusesOBP0
ld [de], a
inc hl
inc e
dec c
jr nz, .loop
ld a, e
ldh [hOAMBufferOffset], a
.nextSprite
ldh a, [hSpriteOffset2]
add $10
cp LOW($100)
jp nz, .spriteLoop
; Clear unused OAM.
.asm_4a41
ld a, [wd736]
bit 6, a ; jumping down ledge or fishing animation?
ld c, $a0
jr z, .clear
; Don't clear the last 4 entries because they are used for the shadow in the
; jumping down ledge animation and the rod in the fishing animation.
ld c, $90
.clear
ldh a, [hOAMBufferOffset]
cp c
ret nc
ld l, a
ld h, HIGH(wOAMBuffer)
ld a, c
ld de, $4 ; entry size
ld b, $a0
.clearLoop
ld [hl], b
add hl, de
cp l
jr nz, .clearLoop
ret
GetSpriteScreenXY:
inc e
inc e
ld a, [de] ; [x#SPRITESTATEDATA1_YPIXELS]
ldh [hSpriteScreenY], a
inc e
inc e
ld a, [de] ; [x#SPRITESTATEDATA1_XPIXELS]
ldh [hSpriteScreenX], a
ld a, 4
add e
ld e, a
ldh a, [hSpriteScreenY]
add 4
and $f0
ld [de], a ; [x#SPRITESTATEDATA1_YADJUSTED]
inc e
ldh a, [hSpriteScreenX]
and $f0
ld [de], a ; [x#SPRITESTATEDATA1_XADJUSTED]
ret
Func_4a7b:
push bc
ld a, [wd5cd] ; temp copy of [x#SPRITESTATEDATA1_IMAGEINDEX]
swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs)
and $f
; Sprites $a and $b have one face (and therefore 4 tiles instead of 12).
; As a result, sprite $b's tile offset is less than normal.
cp $b
jr nz, .notFourTileSprite
ld a, $a * 12 + 4 ; $7c
jr .done
.notFourTileSprite
; a *= 12
add a
add a
ld c, a
add a
add c
.done
pop bc
ret
INCLUDE "engine/gfx/oam_dma.asm"
_IsTilePassable::
ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
ld a, [hli]
ld h, [hl]
ld l, a ; hl now points to passable tiles
.loop
ld a, [hli]
cp $ff
jr z, .tileNotPassable
cp c
jr nz, .loop
xor a
ret
.tileNotPassable
scf
ret
INCLUDE "data/tilesets/collision_tile_ids.asm"