Monorepo for Aesthetic.Computer
aesthetic.computer
1; Background Tile Example for the Nintendo Game Boy
2; by Dave VanEe 2022
3; Tested with RGBDS 1.0.0
4; License: CC0 (https://creativecommons.org/publicdomain/zero/1.0/)
5
6include "hardware.inc" ; Include hardware definitions so we can use nice names for things
7
8; Define a section that starts at the point the bootrom execution ends
9SECTION "Start", ROM0[$0100]
10 jp EntryPoint ; Jump past the header space to our actual code
11
12 ds $150-@, 0 ; Allocate space for RGBFIX to insert our ROM header by allocating
13 ; the number of bytes from our current location (@) to the end of the
14 ; header ($150)
15
16EntryPoint:
17 di ; Disable interrupts as we won't be using them
18 ld sp, $e000 ; Set the stack pointer to the end of WRAM
19
20 ; Turn off the LCD when it's safe to do so (during VBlank)
21.waitVBlank
22 ldh a, [rLY] ; Read the LY register to check the current scanline
23 cp SCREEN_HEIGHT_PX ; Compare the current scanline to the first scanline of VBlank
24 jr c, .waitVBlank ; Loop as long as the carry flag is set
25 ld a, 0 ; Once we exit the loop we're safely in VBlank
26 ldh [rLCDC], a ; Disable the LCD (must be done during VBlank to protect the LCD)
27
28 ; Copy our tiles to VRAM
29 ld hl, TileData ; Load the source address of our tiles into HL
30 ld de, STARTOF(VRAM); Load the destination address in VRAM into DE
31 ld b, 2 * TILE_SIZE ; Load the number of bytes to copy into B (2 * 16)
32.copyLoop
33 ld a, [hl] ; Load a byte from the address HL points to into the register A
34 ld [de], a ; Load the byte in the A register to the address DE points to
35 inc hl ; Increment the source pointer in HL
36 inc de ; Increment the destination pointer in DE
37 dec b ; Decrement the loop counter in B
38 jr nz, .copyLoop ; If B isn't zero, continue looping
39
40 ; This code writes 1 for our tile, and then fills the rest of the tilemap with zero
41 ld hl, TILEMAP0 ; Point HL to the first byte of the tilemap ($9800)
42 ld [hl], 1 ; Load one into the first byte of the tilemap, as pointed to by HL
43 inc hl ; Increment the destination pointer in HL
44
45 ld bc, TILEMAP1-TILEMAP0-1 ; Load the size of the remaining tilemap into BC (32x32=1024, or $400, minus 1)
46 ld d, 0 ; Load the value to fill the rest of the tilemap with into D
47.clearLoop
48 ld [hl], d ; Load the value in D into the location pointed to by HL
49 inc hl ; Increment the destination pointer in HL
50 dec bc ; Decrement the loop counter in BC
51 ld a, b ; Load the value in B into A
52 or c ; Logical OR the value in A (from B) with C
53 jr nz, .clearLoop ; If B and C are both zero, OR C will be zero, otherwise keep looping
54
55 ; Setup palettes and scrolling
56 ld a, %11100100 ; Define a 4-shade palette from darkest (11) to lightest (00)
57 ldh [rBGP], a ; Set the background palette
58
59 ld a, 0 ; Load zero into the register A
60 ldh [rSCX], a ; Set the background scroll registers to show the top-left
61 ldh [rSCY], a ; corner of the background in the top-left corner of the screen
62
63 ; Combine flag constants defined in hardware.inc into a single value with logical ORs and load it into A
64 ; Note that some of these constants (LCDC_OBJ_OFF, LCDC_WIN_OFF) are zero, but are included for clarity
65 ld a, LCDC_ON | LCDC_BLOCK01 | LCDC_BG_ON | LCDC_OBJ_OFF | LCDC_WIN_OFF
66 ldh [rLCDC], a ; Enable and configure the LCD to show the background
67
68LoopForever:
69 jr LoopForever ; Loop forever
70
71; Our tile data in 2bpp planar format (https://gbdev.io/pandocs/Tile_Data.html)
72TileData:
73.empty ; The empty tile is just a zero byte repeated 16 times, so we use REPT to simplify this
74 REPT TILE_SIZE
75 db $00
76 ENDR
77.block ; For the block tile we'll use a more verbose syntax so you can see how the tile is built
78 ; low byte high byte
79 db %00000000, %11111111 ; single row of 8 pixels
80 db %01000010, %10000001
81 db %00000000, %11111111
82 db %01000010, %10000001
83 db %00000000, %11111111
84 db %01000010, %10000001
85 db %00000000, %11111111
86 db %11111111, %11111111