Monorepo for Aesthetic.Computer aesthetic.computer
at main 100 lines 5.6 kB view raw
1; Sprite 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 tile 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, 16 ; Load the number of bytes to copy into B (16 bytes per tile) 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 ; Setup the two object palettes 41 ld a, %11100100 ; Define a 4-shade palette from darkest (11) to lightest (00) 42 ldh [rOBP0], a ; Set the onject palette 0 43 ld a, %00011011 ; Define a 4-shade palette from lightest (00) to darkest (11) 44 ldh [rOBP1], a ; Set the onject palette 1 45 46 ; Set the attributes for a two sprites in OAMRAM 47 ld hl, STARTOF(OAM) ; Load the destination address in OAM into HL 48 49 ; The first sprite is in the top-left corner of the screen and uses the "normal" palette 50 ld a, 16 ; Load the value 16 into the A register 51 ld [hli], a ; Set the Y coordinate (plus 16) for the sprite in OAMRAM, increment HL 52 sub 8 ; Subtract 8 from the value stored in A and store the result in A 53 ld [hli], a ; Set the X coordinate (plus 8) for the sprite in OAMRAM, increment HL 54 ld a, 0 ; Load the tile index 0 into the A register 55 ld [hli], a ; Set the tile index for the sprite in OAMRAM, increment HL 56 ld [hli], a ; Set the attributes (flips and palette) for the sprite in OAMRAM, increment HL 57 58 ; The second sprite is shifted slightly and uses the "inverted" palette 59 ld a, 19 ; Load the value 19 into the A register 60 ld [hli], a ; Set the Y coordinate (plus 16) for the sprite in OAMRAM, increment HL 61 sub 6 ; Subtract 6 from the value stored in A and store the result in A 62 ld [hli], a ; Set the X coordinate (plus 8) for the sprite in OAMRAM, increment HL 63 ld a, 0 ; Load the tile index 0 into the A register 64 ld [hli], a ; Set the tile index for the sprite in OAMRAM, increment HL 65 ld a, OAM_YFLIP | OAM_PAL1 ; Load the flags to Y flip and use OBP1 for this sprite into A 66 ld [hli], a ; Set the attributes (flips and palette) for the sprite in OAMRAM, increment HL 67 68 ; Zero the Y coordinates of the remaining entries to avoid garbage sprites 69 xor a ; XOR A with itself, which sets A to zero (and affects the flags) 70 ; Note: This is 1 cycle faster and 1 byte smaller than `ld a, 0` 71 ld b, OAM_COUNT - 2 ; Load B with the number of loops, which is the total OAM count minus one 72.oamClearLoop 73 ld [hli], a ; Set the Y coordinate of this entry to zero, increment HL 74 inc l ; Increment L to advance HL (three times) 75 inc l ; Note: Since OAMRAM is from $FE00->$FE9F we can safely increment 76 inc l ; only the L register and HL will stay a valid pointer 77 dec b ; Decrement the loop counter in B 78 jr nz, .oamClearLoop; If B isn't zero, continue looping 79 80 ; Combine flag constants defined in hardware.inc into a single value with logical ORs and load it into A 81 ; Note that some of these constants (LCDC_BG_OFF, LCDC_OBJ_8, LCDC_WIN_OFF) are zero, but are included for clarity 82 ld a, LCDC_ON | LCDC_BG_OFF | LCDC_OBJ_8 | LCDC_OBJ_ON | LCDC_WIN_OFF 83 ldh [rLCDC], a ; Enable and configure the LCD to show the background 84 85LoopForever: 86 jr LoopForever ; Loop forever 87 88; Our tile data in 2bpp planar format (https://gbdev.io/pandocs/Tile_Data.html) 89TileData: 90.ball ; For the ball tile we'll use a more verbose syntax so you can see how the tile is built 91 ; low byte high byte 92 db %00111100, %00111100 ; single row of 8 pixels 93 db %01011110, %01000010 94 db %10001101, %10000011 95 db %11011101, %10000011 96 db %11111101, %10000011 97 db %10111001, %11000111 98 db %01000010, %01111110 99 db %00111100, %00111100 100