Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

#1 2026-01-23 20:10:28

judgevorak
New member
Registered: 2026-01-23
Posts: 3

VRAM address and Bitmap management

Greetings,

Apologies if this question has already been answered; a brief search for "vram tilemap" didn't yield the answers I was hoping for, but please link me to a resource if I missed it.  My development environment consists of vi, vasm, and rgbfix -- no GBDK, mostly just following Keith's multi-platform Z80 tutorials at ChibiAkumas and referring to SM83 opcode charts at GBdev and PastRaiser.

My question: What is the best non-static method for obtaining a bitmap's initial byte address in VRAM?  I have a function that copies 2bpp bitmaps into VRAM, so creating a label has proved fruitless both before the copy and inside of it.  Those labels have just given me the address of my "incbin" and "call" opcodes respectively, and my instincts say that "org" in VRAM is a bad idea for maintainability.

The VRAM consists of a 96-character 1bpp font copied in per Keith's tutorial (&8000 - &85FF), then a couple of 2bpp spritemaps at &8600.  Without specifically referring to the Listing file, bgb debugger, or manually tracking bytes, is there a way to know and/or refer to each bitmap copied into VRAM?

I am very new to GB development and assembly in general, but have recently come to understand how bitplanes fit into &8000 - &8FFF VRAM and how the TileMap &9800 - &9BFF contains pointers to VRAM offsets.  I found the 16-bit bitshift routine below on ChilliAnt's website and use it to convert a VRAM address into its TileNumber offset:

Code:

ConvertVRAMtoTile:      ; Shifts HL 4 positions right (divides by 16?)
        srl     h       ; This bitshift courtesy of chilliant.com/z80shift.html
        rr      l
        srl     h
        rr      l
        srl     h
        rr      l
        srl     h
        rra
        rr      l
        ld      a, l
        ret

EDIT 1: found bugs with my original VRAM conversion, and didn't want future ASM seekers to get hung up on it.


EDIT 2: The 4-shift method broke after &87F0, so I came up with this hackiness:

Code:

ConvertVRAMtoTile:
    ; &87     1000 0111            &88     1000 1000
    ; &F0     1111 0000            &00     0000 0000
    ; need    0111 1111            need    1000 0000
    ;
    ;    1. zero top nibble of H
    ;    2. zero bottom nibble of L
    ;    3. XOR H and L together
    ;    4. swap L (it's in A)
    ;
    ld     a, h    ; zero top nibble of H
    and    a, %00001111
    ld     h, a

    ld     a, l    ; zero bottom nibble of L
    and    a, %11110000
    ld     l, a

    xor    a, h    ; A contains L, so XOR it with H
    swap   a       ; don't forget to SWAP!
    ret

In case anyone's counting, this AND/XOR/SWAP method takes up 10 bytes in ROM and 13 cycles (52 T-states?) whereas the 4xBITSHIFT function from ChilliAnt uses 19 bytes of ROM and takes 22 cycles -- according to PastRaiser's SM83 opcode chart, of course.


~JV

Last edited by judgevorak (2026-02-03 00:41:23)

Offline

 

#2 2026-01-24 14:43:18

judgevorak
New member
Registered: 2026-01-23
Posts: 3

Re: VRAM address and Bitmap management

I settled on managing memory locations for each bitmap copied into VRAM; this may not scale well when VRAM is full and needs shuffling, but I'll burn that bridge when I get to it.  In practice, I've copied all my bitmaps consecutively so the font is &8000 - &85FF, then Alien at &8600 - &863F, and Flower at &8640 - &86FF

Here's my hacky method of obtaining the initial byte of a bitmap copied into VRAM:

1. Declare two bytes of memory per bitmap

Code:

                bmpAlienH equ &c000
                bmpAlienL equ &c001

2. Store HL values just before CopyBitmapLoop

Code:

                ld de, AlienSprite      ; incbin label
                ld a, h         ; prepare to store bmpAlienH
                ld (bmpAlienH), a
                ld a, l         ; prepare to store bmpAlienL
                ld (bmpAlienL), a
                ld bc, AlienSpriteEnd-AlienSprite ; counter for CopyBitmapLoop
                call CopyBitmapLoop

3. Refer to those memory locations for DrawSprite functions

Code:

                ld a, (bmpAlienH)       ; ye olde 8-bit shufflee
                ld h, a
                ld a, (bmpAlienL)
                ld l, a                 ; now HL is AlienSprite VRAM addr
                call CalcTileOffset     ; bangs &8600 into &60
                call DrawFunction     ; render bitmap at VRAM addr HL

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson