Try to clean up PrepareOAMData.

This commit is contained in:
yenatch 2014-05-25 19:23:12 -07:00
parent 5a14234b49
commit f6038a3d52
3 changed files with 205 additions and 178 deletions

25
engine/oam_dma.asm Normal file
View file

@ -0,0 +1,25 @@
WriteDMACodeToHRAM:
; Since no other memory is available during OAM DMA,
; DMARoutine is copied to HRAM and executed there.
ld c, $ff80 % $100
ld b, DMARoutineEnd - DMARoutine
ld hl, DMARoutine
.copy
ld a, [hli]
ld [$ff00+c], a
inc c
dec b
jr nz, .copy
ret
DMARoutine:
; initiate DMA
ld a, $c3
ld [$ff46], a
; wait for DMA to finish
ld a, $28
.wait dec a
jr nz, .wait
ret
DMARoutineEnd:

178
engine/overworld/oam.asm Normal file
View file

@ -0,0 +1,178 @@
PrepareOAMData:
; Determine OAM data for currently visible
; sprites and write it to wOAMBuffer.
ld a, [$cfcb]
dec a
jr z, .asm_4b1e
cp 0 - 1
ret nz
ld [$cfcb], a
jp HideSprites
.asm_4b1e
xor a
ld [$ff90], a
.asm_4b21
ld [$ff8f], a
ld d, wSpriteStateData1 / $100
ld a, [$ff8f]
ld e, a
ld a, [de] ; c1x0
and a
jp z, .asm_4bad
inc e
inc e
ld a, [de] ; c1x2 (facing/anim)
ld [$d5cd], a
cp $ff ; off-screen (don't draw)
jr nz, .visible
call Func_4bd1
jr .asm_4bad
.visible
cp $a0
jr c, .usefacing
and $f
add $10
jr .asm_4b48
.usefacing
and $f
.asm_4b48
ld l, a
push de
inc d
ld a, e
add $5
ld e, a
ld a, [de] ; c2x7
and $80
ld [$ff94], a ; temp store sprite priority
pop de
ld h, 0
ld bc, SpriteFacingAndAnimationTable
add hl, hl
add hl, hl
add hl, bc
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
ld a, [hli]
ld h, [hl]
ld l, a
call Func_4bd1
ld a, [$ff90]
ld e, a
ld d, wOAMBuffer / $100
.tile
ld a, [$ff92] ; 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
ld a, [$ff91] ; temp for sprite X position
add $8 ; X=8 is left of screen (X=0 is invisible)
add [hl] ; add X offset from table
inc e
ld [de], a ; write new sprite OAM X position
inc e
ld a, [bc] ; read pattern number offset (accomodates orientation (offset 0,4 or 8) and animation (offset 0 or $80))
inc bc
push bc
ld b, a
ld a, [$d5cd] ; 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, .offset
ld a, $a * 12 + 4
jr .gotoffset
.offset
; a *= 12
sla a
sla a
ld c, a
sla a
add c
.gotoffset
add b ; which frame
pop bc
ld [de], a ; tile id
inc hl
inc e
ld a, [hl]
bit 1, a ; sprite priority
jr z, .fg
ld a, [$ff94] ; facing priority
or [hl]
.fg
inc hl
ld [de], a
inc e
bit 0, a ; OAMFLAG_ENDOFDATA
jr z, .tile
ld a, e
ld [$ff90], a
.asm_4bad
ld a, [$ff8f]
add $10
cp $100 % $100
jp nz, .asm_4b21
; Clear unused OAM.
ld a, [$ff90]
ld l, a
ld h, wOAMBuffer / $100
ld de, $4
ld b, $a0
ld a, [$d736]
bit 6, a
ld a, $a0
jr z, .clear
ld a, $90
.clear
cp l
ret z
ld [hl], b
add hl, de
jr .clear
Func_4bd1: ; 4bd1 (1:4bd1)
inc e
inc e
ld a, [de] ; c1x4
ld [$ff92], a
inc e
inc e
ld a, [de] ; c1x6
ld [$ff91], a
ld a, $4
add e
ld e, a
ld a, [$ff92]
add $4
and $f0
ld [de], a ; c1xa (y)
inc e
ld a, [$ff91]
and $f0
ld [de], a ; c1xb (x)
ret

180
main.asm
View file

@ -139,184 +139,8 @@ UnusedNames: ; 4a92 (1:4a92)
db "マスター@"
db "エクセレント"
; calculates the OAM data for all currently visible sprites and writes it to wOAMBuffer
PrepareOAMData: ; 4b0f (1:4b0f)
ld a, [$cfcb]
dec a
jr z, .asm_4b1e
cp $ff
ret nz
ld [$cfcb], a
jp HideSprites
.asm_4b1e
xor a
ld [$ff90], a
.asm_4b21
ld [$ff8f], a
ld d, $c1
ld a, [$ff8f]
ld e, a
ld a, [de] ; c1x0
and a
jp z, .asm_4bad
inc e
inc e
ld a, [de] ; c1x2 read combined orientation and animation info
ld [$d5cd], a
cp $ff
jr nz, .spriteVisible ; $ff -> offscreen, don't draw
call Func_4bd1
jr .asm_4bad
.spriteVisible
cp $a0
jr c, .considerOrientation ; if >= $a0, ignore the sprite orientation and animation (by using a different conversion table)
and $f
add $10
jr .asm_4b48
.considerOrientation
and $f ; the lower nybble contains orientation and animation info
.asm_4b48
ld l, a
push de
inc d
ld a, e
add $5
ld e, a
ld a, [de] ; c2x7
and $80
ld [$ff94], a ; temp store bit 7 for later use in OAM flags (draws sprite behind background (used for grass))
pop de
ld h, $0
ld bc, SpriteFacingAndAnimationTable
add hl, hl
add hl, hl
add hl, bc ; skip to the table location determined by orientation and animation
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
ld a, [hli]
ld h, [hl]
ld l, a
call Func_4bd1
ld a, [$ff90]
ld e, a
ld d, $c3 ; wOAMBuffer+x is buffer for OAM data
.spriteTilesLoop ; loops 4 times for the 4 tiles a sprite consists of
ld a, [$ff92] ; 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
ld a, [$ff91] ; temp for sprite X position
add $8 ; X=8 is left of screen (X=0 is invisible)
add [hl] ; add X offset from table
inc e
ld [de], a ; write new sprite OAM X position
inc e
ld a, [bc] ; read pattern number offset (accomodates orientation (offset 0,4 or 8) and animation (offset 0 or $80))
inc bc
push bc
ld b, a
ld a, [$d5cd] ; temp copy of c1x2
swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs)
and $f
cp $b ; sprites $a and $b have no orientation or animation and therefore only 4 tiles
jr nz, .calcTileOffset ; (instead of 12), so tile b's offset is a special case
ld a, $7c ; = $a * 12 + 4
jr .doneCalcTileOffset
.calcTileOffset
sla a
sla a
ld c, a
sla a
add c ; a *= 12 (each sprite consists of 12 tiles)
.doneCalcTileOffset
add b ; add orientation and animation offset
pop bc
ld [de], a ; write OAM sprite pattern number
inc hl
inc e
ld a, [hl]
bit 1, a ; bit 1 is ignored for OAM, it's used here as an "always in foregroud" flag.
jr z, .alwaysInForeground
ld a, [$ff94] ; load bit 7 (set to $80 if sprite is in grass and should be drawn behind it)
or [hl]
.alwaysInForeground
inc hl
ld [de], a ; write OAM sprite flags
inc e
bit 0, a ; test for OAMFLAG_ENDOFDATA
jr z, .spriteTilesLoop
ld a, e
ld [$ff90], a
.asm_4bad
ld a, [$ff8f]
add $10
cp $0
jp nz, .asm_4b21
ld a, [$ff90]
ld l, a
ld h, $c3
ld de, $4
ld b, $a0
ld a, [$d736]
bit 6, a
ld a, $a0
jr z, .clearUnusedOAMEntriesLoop
ld a, $90
.clearUnusedOAMEntriesLoop
cp l
ret z
ld [hl], b
add hl, de
jr .clearUnusedOAMEntriesLoop
Func_4bd1: ; 4bd1 (1:4bd1)
inc e
inc e
ld a, [de] ; c1x4
ld [$ff92], a
inc e
inc e
ld a, [de] ; c1x6
ld [$ff91], a
ld a, $4
add e
ld e, a
ld a, [$ff92]
add $4
and $f0
ld [de], a ; c1xa (sprite Y pos (snapped to whole steps (?))
inc e
ld a, [$ff91]
and $f0
ld [de], a ; c1xb (sprite X pos (snapped to whole steps (?))
ret
; copies DMA routine to HRAM. By GB specifications, all DMA needs to be done in HRAM (no other memory section is available during DMA)
WriteDMACodeToHRAM: ; 4bed (1:4bed)
ld c, $80
ld b, $a
ld hl, DMARoutine
.copyLoop
ld a, [hli]
ld [$ff00+c], a
inc c
dec b
jr nz, .copyLoop
ret
; this routine is copied to HRAM and executed there on every VBlank
DMARoutine: ; 4bfb (1:4bfb)
ld a, $c3
ld [$ff46], a ; start DMA
ld a, $28
.waitLoop ; wait for DMA to finish
dec a
jr nz, .waitLoop
ret
INCLUDE "engine/overworld/oam.asm"
INCLUDE "engine/oam_dma.asm"
PrintWaitingText:
FuncCoord 3, 10