PrepareOAMData: ; 499b (1:499b)
; 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 $ff
	ret nz
	ld [wUpdateSpritesEnabled], a
	jp HideSprites

.updateEnabled
	xor a
	ld [hOAMBufferOffset], a

.spriteLoop
	ld [hSpriteOffset2], a
	
	ld e, a
	ld d, wSpriteStateData1 / $100
	
	ld a, [de] ; c1x0
	and a
	jp z, .nextSprite

	inc e
	inc e
	ld a, [de] ; c1x2 (facing/anim)
	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] ; c2x7
	and $80
	ld [hSpritePriority], a ; temp store sprite priority
	pop de


	call GetSpriteScreenXY

	ld a, [hOAMBufferOffset]
	add [hl]
	cp $a0
	jr z, .hidden
	jr nc, .asm_4a41
.hidden
	call Func_4a7b
	ld [wd5cd], a
	ld a, [hOAMBufferOffset]
	
	ld e, a
	ld d, wOAMBuffer / $100

.tileLoop
	ld a, [hli]
	ld c, a
.loop
	ld 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
	ld 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
	ld a, [$fffc]
	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
	ld 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
	ld [hOAMBufferOffset], a
.nextSprite
	ld a, [hSpriteOffset2]
	add $10
	cp $100 % $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
	ld a, [hOAMBufferOffset]
	cp c
	ret nc
	ld l, a
	ld h, wOAMBuffer / $100
	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: ; 4a5f (1:4a5f)
	inc e
	inc e
	ld a, [de] ; c1x4
	ld [hSpriteScreenY], a
	inc e
	inc e
	ld a, [de] ; c1x6
	ld [hSpriteScreenX], a
	ld a, 4
	add e
	ld e, a
	ld a, [hSpriteScreenY]
	add 4
	and $f0
	ld [de], a ; c1xa (y)
	inc e
	ld a, [hSpriteScreenX]
	and $f0
	ld [de], a  ; c1xb (x)
	ret
	
Func_4a7b: ; 4a7b (1:4a7b)
	push bc
	ld a, [wd5cd]            ; temp copy of c1x2
	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/oam_dma.asm"

_IsTilePassable:: ; 4aaa (1:4aaa)
	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 a,$ff
	jr z,.tileNotPassable
	cp c
	jr nz,.loop
	xor a
	ret
.tileNotPassable
	scf
	ret
	
INCLUDE "data/collision.asm" ; probably