Skip to content

Commit 84a1c64

Browse files
committed
add sprite movement example
sprite movement is accomplished through bad practices. Gameboy code rarely directly accesses the sprite properties (this example does). Instead they use DMA to copy a chunk of RAM representing the sprites to OAM. Waiting 2 frames before pushing data to OAM seems necessary. Otherwise the OAM updates occasionally don't work
1 parent 118b07c commit 84a1c64

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

02_ugly_sprite_moves.asm

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
include "gbhw.inc"
2+
3+
;-------------- INTERRUPT VECTORS ------------------------
4+
; specific memory addresses are called when a hardware interrupt triggers
5+
6+
; Vertical-blank triggers each time the screen finishes drawing. Video-RAM
7+
; (VRAM) is only available during VBLANK. So this is when updating OAM /
8+
; sprites is executed.
9+
SECTION "Vblank", ROM0[$0040]
10+
reti
11+
12+
SECTION "LCDC", ROM0[$0048]
13+
reti
14+
15+
SECTION "Timer", ROM0[$0050]
16+
reti
17+
18+
SECTION "Serial", ROM0[$0058]
19+
reti
20+
21+
SECTION "Joypad", ROM0[$0060]
22+
reti
23+
;----------- END INTERRUPT VECTORS -------------------
24+
25+
SECTION "ROM_entry_point", ROM0[$0100] ; ROM is given control from boot here
26+
nop
27+
jp code_begins
28+
29+
;------------- BEGIN ROM HEADER ----------------
30+
; The gameboy reads this info (before handing control over to ROM)
31+
SECTION "rom header", ROM0[$0104]
32+
NINTENDO_LOGO
33+
ROM_HEADER "0123456789ABCDE"
34+
35+
; safe to include other files begining here. INCLUDE'd files often immediately
36+
; add more code to the compiled ROM. It's critical that your code does not
37+
; step over the first $0000 - $014E bytes
38+
39+
40+
code_begins:
41+
di ; disable interrupts
42+
ld SP, $FFFF ; set stack to top of HRAM
43+
; background image is just the nintendo logo. Tile 0x19 is the (R).
44+
; You can find it on BGB's VRAM Tiles: (right-click) -> other -> VRAM -> Tiles
45+
; Let's use the (R) as a sprite and move it
46+
47+
48+
ld a, IEF_VBLANK ; --
49+
ld [rIE], a ; Set only Vblank interrupt flag
50+
ei ; enable interrupts. Only vblank will trigger
51+
52+
53+
halt ; wait a frame
54+
nop
55+
halt
56+
nop ; wait two frames before pushing bytes -- critical timing here
57+
; if we mess up timing, writes to OAM will fail. Thus the sprite will
58+
; NOT be updated. Try removing these two halts to see what happens.
59+
60+
61+
; ----
62+
; OAM aka Sprite memory on the gameboy begins at memory address $FE00.
63+
; There are a total of 40 sprites available to manipulate.
64+
; Each sprite has 4 attributes that are set in sequential bytes in memory:
65+
; X coordinate
66+
; Y coordinate
67+
; Tile # (relative to start of tiles in VRAM: $8000)
68+
; Sprite Flags (such as, visible, priority, X & Y flip)
69+
70+
ld hl, _OAMRAM ; point to 1st sprite's 1st property: X
71+
ld [hl], 20 ; set X to 20
72+
ld hl, _OAMRAM + 1 ; HL points to sprite's Y
73+
ld [hl], 10 ; set Y to 10
74+
ld hl, _OAMRAM + 2 ; HL points to sprite's tile (from BG map)
75+
ld [hl], $19 ; set Tile to the (R) graphic
76+
ld hl, _OAMRAM + 3 ; HL points to sprite's flags
77+
ld [hl], 0 ; set all flags to 0. X,Y-flip, palette, etc.
78+
79+
ld a, [rLCDC] ; fetch LCD Config. (Each bit is a flag)
80+
or LCDCF_OBJON ; enable sprites through "OBJects ON" flag
81+
or LCDCF_OBJ8 ; enable 8bit wide sprites (vs. 16-bit wide)
82+
ld [rLCDC], a ; save LCD Config. Sprites are now visible.
83+
84+
.loop
85+
halt ; halts cpu until interrupt triggers (vblank)
86+
; by halting, we ensure that .loop only runs only each screen-refresh,
87+
; so only 60fps. That makes the sprite movement here manageable
88+
nop
89+
90+
ld hl, _OAMRAM
91+
ld a, [hl]
92+
inc a ; X += 1
93+
ld [hl], a ; save new X coordinates
94+
ld hl, _OAMRAM + 1
95+
inc [hl] ; set Y += 1
96+
97+
jp .loop ; start up at top of .loop label. Repeats each vblank
98+
99+
; ================ QUESTIONS FOR STUDENT ===========================
100+
; why is there visual junk on the screen?
101+
; can you change this so that Y moves twice as fast as X?
102+
; can you change this so that sprite moves half as fast?
103+
; what happens if you remove the "halt" command in the .loop? Why?

0 commit comments

Comments
 (0)