Monorepo for Aesthetic.Computer aesthetic.computer
at main 86 lines 4.4 kB view raw
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