Compare commits

..

10 commits

Author SHA1 Message Date
tA d2acd2e7fd updated readme 2020-08-02 11:19:30 +12:00
tA dad5998540 Merge branch 'master' of lain.church:tA/testingAnimation
cos i fuarked up my git repo lmao
2020-05-31 16:09:20 +12:00
tA ad72f02c91 cleaned up background, multiple palettes 2020-05-31 16:08:57 +12:00
Thorn Avery edfd4be25f Delete 'src/.animation.asm.swo'
whoops folgot to ignore this
2020-05-28 22:40:38 -04:00
tA 5a14e2f17f added second animation 2020-05-29 14:09:57 +12:00
tA 52492799db fixed gbc compat flag 2020-05-28 15:25:27 +12:00
tA 31327d35ee added more actors to demonstrate 2020-05-28 15:21:34 +12:00
tA 88ad5534c3 cleaned up animation code + fixed frame 0 bug 2020-05-28 15:12:01 +12:00
tA fa65a2b0b2 cleaned up header 2020-05-25 17:10:59 +12:00
tA c4ccba52d2 fixed scanline bug + removed old code 2020-05-25 15:49:17 +12:00
15 changed files with 426 additions and 314 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
build
*.swp
*.swo

View file

@ -11,7 +11,16 @@ ROM_OUTPUT=${BUILD}/${NAME}.gb
OBJECT_OUTPUT=${BUILD}/${NAME}.o
SYMFILE_OUTPUT=${BUILD}/${NAME}.sym
LICENSEE="tA"
OLDLIC="0x33"
MBC="0x00"
VERSION="0"
PAD="0xFF"
RAM="0x00"
PP_FLAGS=-f lhg -j -t ${NAME} -k ${LICENSEE} -l ${OLDLIC} -m ${MBC} -n ${VERSION} -p ${PAD} -r ${RAM}
all : ${ENTRY}
${ASSEMBLER} -o ${OBJECT_OUTPUT} ${ENTRY} \
&& ${LINKER} -o ${ROM_OUTPUT} -n ${SYMFILE_OUTPUT} ${OBJECT_OUTPUT} \
&& ${POSTPROC} -v -p 0 ${ROM_OUTPUT}
&& ${POSTPROC} -v ${PP_FLAGS} ${ROM_OUTPUT}

View file

@ -2,6 +2,17 @@
just me messing about trying to learn gameboy assembly
currently have an animation engine supporting:
* arbitary sized frames
* multiple actors
* multiple animation states per actor (up to 128)
* arbitary number of frames
* arbitary time per frame of animation
* distinct animation timers per actor
* distinct colour palletes per tile in frame (limit 2 as per hardware)
* arbitary position of tiles in the tile bank per actor type
* arbitary positioning of tiles in each frame, including overlapping
== requisites ==
built using `rgbds`, will need to be installed for makefile to compile
@ -11,3 +22,66 @@ built using `rgbds`, will need to be installed for makefile to compile
simply run `make` in the root directory to build the ROM
will appear as a `.gb` file in `./build`
== actor format ==
each actor has the following header:
```
ActorROM::
.structs:
dw ActorIdle
dw VillagerWaving
```
where each pointer under `.structs` is another structure in memory. these pointers may be shared between different actor definitions, however the tilesets for each actor will need to be compatible with the same animation for this to work.
each animation state has the following definition:
```
VillagerWaving::
db 90
db 15
dw .vwFrame01
db 15
dw .vwFrame02
db 15
dw .vwFrame03
db 15
dw .vwFrame04
db 15
dw .vwFrame05
db 15
dw .vwFrame06
```
the first byte contains the total number of frames this animation will run for, and then each following set of 3 bytes contains:
* the number of ticks this animation frame persists for
* a pointer to the frame data
each frame has the following data:
```
.vwFrame01
db (.vwFrame01End - @) / 4
db 8, -16, 17, 0
db 8, -8, 18, 0
db 0, -16, 19, OAMF_PAL1
db 0, -8, 20, OAMF_PAL1
db -8, -16, 21, 0
db -8, -8, 22, 0
.vwFrame01End
```
the first byte is the number of tiles present in this frame of animation (analogous to the number of lines in the frame struct).
each following line is 4 bytes, pertaining to (respectively):
* the x offset of this tile
* the y offset of this tile
* the tile offset
* the attributes byte
the position offsets do not need to take into account the gameboys blanket sprite offsets, and the tile offset is zero indexed, and will be added to another offset based on where this actors tiles lie in memory.
the attribute byte is `xor`ed with the defaults in order to facilitate other pallettes or tile flips.

5
ass/grass.ass Normal file
View file

@ -0,0 +1,5 @@
SECTION "Grass Tile", ROM0
grassTiles::
DB $00,$00,$00,$00,$20,$00,$02,$00
DB $04,$00,$44,$00,$20,$00,$00,$00
grassTilesEnd::

32
ass/villager.ass Normal file
View file

@ -0,0 +1,32 @@
SECTION "VillagerWaving", ROM0
VillagerTiles::
DB $1F,$18,$3F,$20,$7F,$48,$74,$57
DB $26,$25,$0E,$09,$0E,$0A,$1E,$12
DB $F8,$18,$FC,$04,$FE,$12,$2E,$EA
DB $64,$A4,$70,$90,$70,$50,$78,$48
DB $0F,$08,$1F,$12,$1D,$16,$1F,$10
DB $0F,$09,$07,$04,$03,$02,$07,$04
DB $F0,$10,$F8,$48,$B8,$68,$F8,$08
DB $F0,$90,$E0,$20,$C0,$40,$E0,$20
DB $00,$00,$00,$00,$00,$00,$00,$00
DB $01,$01,$03,$02,$03,$02,$07,$04
DB $00,$00,$00,$00,$00,$00,$00,$00
DB $80,$80,$C0,$40,$C0,$40,$E0,$20
DB $0F,$08,$1F,$10,$1F,$12,$1D,$16
DB $0F,$08,$07,$05,$03,$02,$07,$04
DB $F0,$10,$F8,$08,$F8,$48,$B8,$68
DB $F0,$10,$E0,$A0,$C0,$40,$E0,$20
DB $07,$04,$1F,$18,$3F,$20,$7C,$4F
DB $76,$55,$2E,$29,$0E,$0A,$1E,$12
DB $E0,$20,$F8,$18,$FC,$04,$3E,$F2
DB $6E,$AA,$74,$94,$70,$50,$78,$48
DB $0F,$08,$1F,$12,$1D,$16,$1F,$10
DB $0F,$09,$07,$04,$03,$02,$1F,$1C
DB $F0,$10,$F8,$48,$B8,$68,$F8,$08
DB $F0,$90,$E0,$20,$C0,$40,$F8,$38
DB $3F,$20,$7F,$48,$77,$54,$24,$27
DB $06,$05,$0E,$09,$0E,$0A,$1E,$12
DB $FC,$04,$FE,$12,$EE,$2A,$24,$E4
DB $60,$A0,$70,$90,$70,$50,$78,$48
VillagerTilesEnd::

View file

@ -7,7 +7,7 @@ SECTION "Actor", ROM0
ActorROM::
.structs:
dw ActorIdle
.tiles:
dw VillagerWaving
ActorIdle::
db 60
db 15
@ -49,3 +49,77 @@ ActorIdle::
db 0, -8, 15, 0
db 0, 0, 16, 0
.frameVoEnd
VillagerWaving::
db 90
db 15
dw .vwFrame01
db 15
dw .vwFrame02
db 15
dw .vwFrame03
db 15
dw .vwFrame04
db 15
dw .vwFrame05
db 15
dw .vwFrame06
.vwFrame01
db (.vwFrame01End - @) / 4
db 8, -16, 17, 0
db 8, -8, 18, 0
db 0, -16, 19, OAMF_PAL1
db 0, -8, 20, OAMF_PAL1
db -8, -16, 21, 0
db -8, -8, 22, 0
.vwFrame01End
.vwFrame02
db (.vwFrame02End - @) / 4
db 8, -16, 17, 0
db 8, -8, 18, 0
db 0, -16, 23, OAMF_PAL1
db 0, -8, 24, OAMF_PAL1
db -8, -16, 21, 0
db -8, -8, 22, 0
.vwFrame02End
.vwFrame03
db (.vwFrame03End - @) / 4
db 8, -16, 25, 0
db 8, -8, 26, 0
db 0, -16, 23, OAMF_PAL1
db 0, -8, 24, OAMF_PAL1
db -8, -16, 21, 0
db -8, -8, 22, 0
.vwFrame03End
.vwFrame04
db (.vwFrame04End - @) / 4
db 8, -16, 17, 0
db 8, -8, 18, 0
db 0, -16, 23, OAMF_PAL1
db 0, -8, 24, OAMF_PAL1
db -8, -16, 21, 0
db -8, -8, 22, 0
.vwFrame04End
.vwFrame05
db (.vwFrame05End - @) / 4
db 8, -16, 17, 0
db 8, -8, 18, 0
db 0, -16, 19, OAMF_PAL1
db 0, -8, 20, OAMF_PAL1
db -8, -16, 21, 0
db -8, -8, 22, 0
.vwFrame05End
.vwFrame06
db (.vwFrame06End - @) / 4
db 8, -16, 29, 0
db 8, -8, 30, 0
db 0, -16, 27, OAMF_PAL1
db 0, -8, 28, OAMF_PAL1
db -8, -16, 21, 0
db -8, -8, 22, 0
.vwFrame06End

View file

@ -7,28 +7,32 @@
bytes 1, XPos
bytes 1, GFXCounter
bytes 1, GFXState
words 1, GFXData
bytes 1, TileData
words 1, GFXData
end_struct
SECTION "Actor STructs", WRAM0
dstruct Actor, Player
dstruct Actor, NPC01
dstruct Actor, NPC02
dstruct Actor, NPC03
dstruct Actor, NPC04
dstruct Actor, NPC05
SECTION "Animation Variables", WRAM0
SECTION "Animation Variables", HRAM
wCameraX: dw
wCameraY: dw
hCameraX: dw
hCameraY: dw
wWorkingX: dw
wWorkingY: dw
wWorkingScreenX: db
wWorkingScreenY: db
wWorkingState: db
wWorkingCounter: db
wWorkingData: dw
wWorkingTile: db
wWorkingEnd:
hWorkingX: dw
hWorkingY: dw
hWorkingScreenX: db
hWorkingScreenY: db
hWorkingState: db
hWorkingCounter: db
hWorkingData: dw
hWorkingTile: db
SECTION "Animations Subs", ROM0
@ -47,117 +51,105 @@ SECTION "Animations Subs", ROM0
RenderActor::
; @input: hl <- Player
; @input: de <- ShadowOAM place
; clobbers af, bc, de, hl
ld a, [hli] ; a <- YPos
ld [wWorkingScreenY], a
ldh [hWorkingScreenY], a
ld a, [hli] ; a <- XPos
ld [wWorkingScreenX], a
push hl
ldh [hWorkingScreenX], a
push hl ; save counter pointer on stack
ld a, [hli] ; a <- GFXCounter
ld [wWorkingCounter], a
ldh [hWorkingCounter], a
ld a, [hli] ; a <- GFXState
ld [wWorkingState], a
ldh [hWorkingState], a
ld a, [hli] ; a <- TileData
ldh [hWorkingTile], a
ld a, [hli] ; a <- GFXData(Low)
ld [wWorkingData+1], a
ld a, [hli] ; a <- GFXData (High)
ld [wWorkingData], a
ld a, [hl] ; a <- TileData
ld [wWorkingTile], a
; fin loading data
ld a, [wWorkingData]
ld h, [hl] ; a <- GFXData (High)
ld l, a
ld a, [wWorkingData+1]
ld h, a
; add actor struct offset saved in wWorkingState
ld a, [wWorkingState]
ld a, [hWorkingState] ; add actor struct offset saved in wWorkingState
rlca ; double state offset because of word length
add a, l
ld l, a
adc a, h
sub l
ld h, a ; hl contains state struct pointer
ld a, [hli]
ld b, a
ld a, [hl]
ld l, b
ld h, a
ld a, [hli] ; a <- state frame limit
ld b, a
ld a, [wWorkingCounter]
ld a, [hli] ;
ld h, [hl] ; derefence [hl]
ld l, a ;
ld a, [hWorkingCounter]
inc a
ld c, a
ld a, b
ld b, c
ld b, a
ld a, [hli] ; a <- state frame limit
cp b
ld a, b
jr nc, .continueAnimation
xor a
.continueAnimation
; TODO: make counter 0 indexed so doesnt skip first frame
ld [wWorkingCounter], a
ld b, h
ld c, l
pop hl
ld [hl], a
ld h, b
ld l, c
.loopFrameFind
ld b, a ; b <- current frame count
ld a, [hli] ; a <- next frame block
ld c, a
ld a, b
ld b, c
sub b
jr z, .foundFrame
jr c, .foundFrame
ldh [hWorkingCounter], a
ld b, h ;
ld c, l ; save current hl
pop hl ; restore counter wram pointer
ld [hl], a ;
ld h, b ; restore hl
ld l, c ;
ld c, a ; save current frame in c
xor a ; set a = 0
.loopFrameFind ;
ld b, a ; b <- current total
ld a, [hli] ; a <- next frame tick limit
add b ; add to limit
cp c ; compare to limit
jr nc, .foundFrame ; if no carry, cum total > current frame
inc hl
inc hl
jr .loopFrameFind
.foundFrame
ld a, [hli]
ld b, a
ld a, [hl]
ld h, a
ld l, b ; hl <- pointer to frame data
ld h, [hl]
ld l, a ; hl <- pointer to frame data
ld a, [hli]
ld b, a ; b <- sprite counter
.spriteLoop
; load Y position, then offset by -16
ld a, [hli]
ld a, [hli] ; load Y position, then offset by -16
ld c, a
ld a, [wWorkingScreenY]
ld a, [hWorkingScreenY]
add c
ld c, 16
add c
ld [de], a ; store YPos in shadowOAM
inc de
; load X position, then offset by -8
ld a, [hli]
ld a, [hli] ; load X position, then offset by -8
ld c, a
ld a, [wWorkingScreenX]
ld a, [hWorkingScreenX]
add c
ld c, 8
add c
ld [de], a ; store YPos in shadowOAM
ld [de], a ; store XPos in shadowOAM
inc de
; load tile offset, and add to base tile pointer
ld a, [hli]
ld a, [hli] ; load tile offset, and add to base tile pointer
ld c, a
ld a, [wWorkingTile]
ld a, [hWorkingTile]
add c
ld [de], a
inc de
; load attributes and xor them
ld a, [hli]
ld a, [hli] ; load attributes and xor them
ld c, a
ld a, 0 ; TO DO: set base attributes
xor c
ld [de], a
inc de
; end of single sprite
dec b
dec b ; end of single sprite
jr nz, .spriteLoop
ret
BUFFER EQU 160
TRUE EQU $42
FALSE EQU $69

View file

@ -12,19 +12,8 @@ P1F_DPAD EQU $20
SECTION "ROM Vars", ROM0
dPlayerWidth: db 2
dPlayerHeight: db 2
dPlayerSpriteTiles: db $01, $02, $09, $0A
SECTION "WRAM Vars", WRAM0[$C000]
X: dw
N: dw
ANS: db
rPlayerX: db
rPlayerY: db
SECTION "HRAM Vars", HRAM
hVBlankFlag: db

View file

@ -6,9 +6,9 @@ INCLUDE "src/actor.asm"
SECTION "Program Start", ROM0[$150]
Start:
ei
ld a, IEF_VBLANK
ld [rIE], a
ei
xor a
ld [hVBlankFlag], a
call Wait_VBlank
@ -17,40 +17,130 @@ Start:
call Clear_Map
call Clear_OAM
call Load_Tiles
; call Load_Map
call Load_Map
ld a, %11100100
ld [rBGP], a
ld [rOBP0], a
ld a, %11000100
ld [rOBP1], a
xor a
ld [rSCY], a
ld [rSCX], a
ld [rNR52], a
ld a, LCDCF_ON | LCDCF_OBJON | LCDCF_BGON
ld [rLCDC], a
call CopyDMARoutine
ld a, 72
ld a, $3F
ld [Player_YPos], a
ld a, 80
ld a, $3A
ld [Player_XPos], a
xor a
ld a, $FF
ld [Player_GFXCounter], a
ld a, 1
ld [Player_GFXState], a
xor a
ld [Player_TileData], a
ld a, HIGH(ActorROM)
ld [Player_GFXData], a
ld [Player_GFXData+1], a
ld a, LOW(ActorROM)
ld [Player_GFXData + 1], a
ld [Player_GFXData], a
ld a, $71
ld [NPC01_YPos], a
ld a, $8C
ld [NPC01_XPos], a
ld a, 20
ld [NPC01_GFXCounter], a
ld a, 1
ld [NPC01_GFXState], a
xor a
ld [NPC01_TileData], a
ld a, HIGH(ActorROM)
ld [NPC01_GFXData+1], a
ld a, LOW(ActorROM)
ld [NPC01_GFXData], a
ld a, $15
ld [NPC02_YPos], a
ld a, $1C
ld [NPC02_XPos], a
ld a, 30
ld [NPC02_GFXCounter], a
ld a, 1
ld [NPC02_GFXState], a
xor a
ld [NPC02_TileData], a
ld a, HIGH(ActorROM)
ld [NPC02_GFXData+1], a
ld a, LOW(ActorROM)
ld [NPC02_GFXData], a
ld a, $29
ld [NPC03_YPos], a
ld a, $90
ld [NPC03_XPos], a
ld a, 40
ld [NPC03_GFXCounter], a
ld a, 1
ld [NPC03_GFXState], a
xor a
ld [NPC03_TileData], a
ld a, HIGH(ActorROM)
ld [NPC03_GFXData+1], a
ld a, LOW(ActorROM)
ld [NPC03_GFXData], a
ld a, $71
ld [NPC04_YPos], a
ld a, $4F
ld [NPC04_XPos], a
ld a, 50
ld [NPC04_GFXCounter], a
ld a, 1
ld [NPC04_GFXState], a
xor a
ld [NPC04_TileData], a
ld a, HIGH(ActorROM)
ld [NPC04_GFXData+1], a
ld a, LOW(ActorROM)
ld [NPC04_GFXData], a
ld a, $4A
ld [NPC05_YPos], a
ld a, $67
ld [NPC05_XPos], a
ld a, $FF
ld [NPC05_GFXCounter], a
ld a, 1
ld [NPC05_GFXState], a
xor a
ld [NPC05_TileData], a
ld a, HIGH(ActorROM)
ld [NPC05_GFXData+1], a
ld a, LOW(ActorROM)
ld [NPC05_GFXData], a
ld a, LCDCF_ON | LCDCF_OBJON | LCDCF_BGON
ld [rLCDC], a
game_loop:
call Wait_VBlank
call Hide_OAM
call Read_Pad
call PC_Update
call Clear_OAM
ld de, wShadowOAM
ld hl, Player
call RenderActor
ld hl, NPC01
call RenderActor
ld hl, NPC02
call RenderActor
ld hl, NPC03
call RenderActor
ld hl, NPC04
call RenderActor
ld hl, NPC05
call RenderActor
call Wait_VBlank
ld a, HIGH(wShadowOAM)
call hOAMDMA
jr game_loop

View file

@ -2,44 +2,9 @@
; Gameboy Header
;-----------------
SECTION "Header", ROM0[$100]
; Jump to the "Start" label
; which we must define ourselves
EntryPoint:
nop
SECTION "Entry", ROM0[$100]
di
jp Start;
; ROM Header $104 to $150
RomHeader:
; Nintendo Logo $104-$133
db $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D
db $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
db $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E
; Title (11 characters) $134-$13E
db "ANIMATION",$00,$00
; Manufacturer Code (4 characters) $13F-$142
db "LATA"
; CGB Flag $143
db $00
; Licensee Code (2 characters) $144-$145
db "00"
; SGB Flag $146
db $00
; Cartridge Type $147
db $00
; ROM Size $148
db $00
; RAM Size $149
db $00
; Destination Code $14A
db $01
; Depreciated Licensee Code $14B
db $33
; Version Number $14C
db $00
; Header Checksum $14D
db $00
; Global Checksum $14E-$14F
db $00, $00
; Reserve space for header
ds $150 - @, 0

View file

@ -2,6 +2,8 @@ INCLUDE "inc/hardware.inc"
INCLUDE "inc/structs.asm"
INCLUDE "ass/parecivo.ass"
INCLUDE "ass/tiles.ass"
INCLUDE "ass/grass.ass"
INCLUDE "ass/villager.ass"
INCLUDE "ass/map.ass"
INCLUDE "src/animation.asm"
INCLUDE "src/entry.asm"

View file

@ -1,102 +1,3 @@
Player_To_OAM:
; -- first loop --
ld hl, wShadowOAM
ld a, [dPlayerHeight]
ld b, a
ld d, 16
ld a, [rPlayerY]
add d ; d has the base Y value (counting offsets)
ld d, a
.fouter
ld a, [dPlayerWidth]
ld c, a ; c is finner counter
.finner
ld a, d
ld [hl], a
ld a, 4
call .add4hl
; end of finner loop
dec c
jr nz, .finner
ld a, d
ld d, 8
add d
ld d, a
; end of fouter loop
dec b
jr nz, .fouter
; -- second loop --
ld hl, wShadowOAM+1
ld a, [dPlayerHeight]
ld b, a
.souter
ld d, 8
ld a, [rPlayerX]
add d
ld d, a
ld a, [dPlayerWidth]
ld c, a
.sinner
ld a, d
ld [hl], a
add 8
ld d, a
ld a, 4
call .add4hl
dec c
jr nz, .sinner
dec b
jr nz, .souter
; -- third loop --
ld hl, wShadowOAM+2
ld de, dPlayerSpriteTiles
ld a, [dPlayerHeight]
ld b, a
ld a, [dPlayerWidth]
ld c, a
xor a
.tloop1
add b
dec c
jr nz, .tloop1
ld c, a
.tloop2
ld a, [de]
ld [hl], a
ld a, 4
call .add4hl
inc de
dec c
jr nz, .tloop2
; -- fourth loop --
ld hl, wShadowOAM+3
ld a, [dPlayerHeight]
ld b, a
ld a, [dPlayerWidth]
ld c, a
xor a
.lloop1
add b
dec c
jr nz, .lloop1
ld c, a
.lloop2
xor a
ld [hl], a
ld a, 4
call .add4hl
dec c
jr nz, .lloop2
ret
.add4hl:
add a, l ; a = low + old_l
ld l, a ; a = low + old_l = new_l
adc a, h ; a = new_l + old_h + carry
sub l ; a = old_h + carry
ld h, a
ret
PC_Update:
ld b, 0
ld c, 0
@ -130,6 +31,14 @@ PC_Update:
ld a, [Player_YPos]
add b
ld [Player_YPos], a
.a:
ld a, [hNewKeys]
and %00000001 ; a pressed
cp %00000001
jr nz, .end
ld a, [Player_GFXState]
xor %00000001
ld [Player_GFXState], a
.end:
ret
@ -146,6 +55,20 @@ Clear_OAM:
jr nz, .loop
ret
Hide_OAM:
ld hl, wShadowOAM
ld c, (wShadowOAMEnd - wShadowOAM) / 4
.loop:
xor a
ld [hl], a
ld a, l
or 3
inc a
ld l, a
dec c
jr nz, .loop
ret
Clear_Map:
ld hl, _SCRN0
ld bc, _SCRN0_END - _SCRN0
@ -160,20 +83,24 @@ Clear_Map:
Load_Tiles:
ld hl, _BGTILES
ld de, parecivo_tile_data
ld bc, parecivo_tile_data_size
ld de, grassTiles
ld bc, grassTilesEnd - grassTiles
call MemCpy
ld hl, _VRAM
ld de, parecivo_tile_data
ld bc, parecivo_tile_data_size
call MemCpy
ret
Load_Map:
ld hl, _SCRN0
ld de, Map
ld bc, Map_Size
ld de, VillagerTiles
ld bc, VillagerTilesEnd - VillagerTiles
call MemCpy
ret
Load_Map:
xor a
ld hl, _SCRN0
ld c, 0
.loop
ld [hl], a
dec c
jr nz, .loop
ret

6
src/textRendering.asm Normal file
View file

@ -0,0 +1,6 @@
;----------------
; Text Rendering
;----------------
; Aims
; Get a renderable text to the graphics window,

View file

@ -1,54 +0,0 @@
PlayerGfx::
INCLUDE "res/actors/player.pal.asm" ; CGB palette
db OAMF_PAL1 ; Additional attr
dw PlayerTiles
PlayerTiles:
; number of tiles:
db (.displayStructs - .tiles) / 16
.tiles
INCBIN "res/actors/player.2bpp"
.displayStructs
dw PlayerStandingUp
dw PlayerWalkingUp
dw PlayerStandingDown
dw PlayerWalkingDown
dw PlayerStandingLeft
dw PlayerWalkingLeft
dw PlayerStandingRight
dw PlayerWalkingRight
PlayerWalkingDown:
db $20
db 8
dw .frame0
db 8
dw .frame1
db 8
dw .frame0
db 8
dw .frame2
.frame0
db (.frame0End - @) / 4
db -31, -8, 0, 0
db -15, -8, 2, 0
db -31, 0, 4, 0
db -15, 0, 6, 0
.frame0End
.frame1
db (.frame1End - @) / 4
db -31, -8, 8, 0
db -15, -8, 10, 0
db -31, 0, 12, 0
db -15, 0, 14, 0
.frame1End
.frame2
db (.frame2End - @) / 4
db -31, -8, 16, 0
db -15, -8, 18, 0
db -31, 0, 20, 0
db -15, 0, 22, 0
.frame2End