|
| 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