(almost) Z80 Assembly
programming for the Gameboy and Gameboy Color
The Gameboys do not use a Z80...
some people say they do, but those people are wrong! it has MANY
features of a Z80... but MANY others are weird... and some are even
BUGGY!
So why might we want to use it... well, the gameboy+GBC sold
118 MILLION!... compared to the ZX spectrum's puny 5 million... the
gamegears 10 million, the Master system's 13 million... the Gameboy
gives the 'real z80' systems a spanking!
We can't use a normal Z80 assembler to develop for it, but Vasm in
'OldStyle' mode will compile for it, just use the switch '-gbz80'
and it will compile compatible code!
The Gameboy Color is just a Gameboy
with a few 'power ups', The best thing is, if we limit ourselves a
bit, we can write games that have full color on the GBC, but still
play the same on the Classic Gameboy!
Lets take a look at the GB and GBC specs!
Specs:
Gameboy
Gameboy Color
Cpu
4mhz
8mhz
Ram
8k
32k
Vram
8k
16k
Resolution
160x144
160x144
Max Tiles
256 (8x8 px) - 360 onscreen
512 (8x8 px) - 360 onscreen
Max Sprites
40 (10 per line)
8x8px or 8x16px
40 (10 per line)
8x8px or 8x16px
Colors
4
4 per palette -
8 palettes (0-7) from 32768 colors for tiles
separate 8 palettes (0-7) from 32768 colors for sprites
Sound chip
GBZ80 PAPU
GBZ80 PAPU
If
you
want to learn GBZ80 get the Cheatsheet!
it has all the Z80 commands, but higlights the ones missing
on the GBZ80 - as well as the extra commands that the GBZ80
posesses, and the commands with different bytecode...
You can use it for both your Z80 and GBZ80 development!
So what's actually different, well, first you've got less
registers... the 'GBZ80' (as we'll call it) has no shadow registers, I
or R... and no index registers either!
Normal Registers
Shadow Registers
Accumulator
A
A'
flags
F
F'
HighLow Memory Location
H
L
H
L
ByteCount
B
C
B
C
DEstinaton
D
E
D
E
Indirect X - IX
IXH
IXL
Indirect Y - IY
IYH
IYL
Program Counter
PC
Stack Pointer
SP
Refresh
R
Interrupt point
I
LDIRtype commands are gone, but we can always fake
them!
Commands that load 2 bytes from a memory address like LD BC,(&1234) do not exist, we have
to read in the bytes separately
There's no IN or OUT commands, not that
it matters, as devices are memory mapped, so we just read or write to them
in their memory locations.
oh and thanks to a bug,INC
xxand DEC
xx with BC, DE or HL can corrupt the sprite memory, just for good
measure!... this will occur if the regpair contains a value between
$fe00-$feff . (The sprite memory)
The HALT command
also has a quirk!, if interrupts are disabled, the command will skip,
however the CPU also skips the following command, so put a NOP after HALT
We do have some new exciting commands... SWAP
A will swap the top nibble and bottom nibble of A (or any other register!)
LD ($FF00+C),A ... will
use C as part of the address to write to - this is the equivalent of OUT
(C),a... as the memory mapped devices are in the &FF00-&FF80 range.
We also have LDI for
Load and Increment, and LDD
for load and decriment... it kind of makes up for losing LDIR!
I've started making a Cheatsheet, which already
contains all the new and changed commands...but if you're careful, and only
use commands supported by the Z80 and GBZ80, you can create common code that
can compile for either system!
There are interrupts, but there is no interrupt mode 1 or 2... RST0-7 exist,
but &0038 is not called by any interrupts... GBZ80 interrupts call
addresses &0040-&0060 in rom.
Console graphics hardware
- Tiles and Sprites! This section is a general description, and not Gameboy
specific, skip to the next chapter if you know the concept of tiles and
sprite layers!
The Gameboy,Gamegear and Mastersystem
screens do not work like they do on computers like the CPC
Graphics are not just 'bytes' in a memory address... The
screen is made up of a 'Tile Layer' and a 'Sprite Layer'
To explain Tiles and sprites, lets look at our imaginary game shown
to the right 'The Super Yuusha Siblings', on a theoretical game
system the 'GameChibi'... Just to be very clear, we looking at this
as a concept, not the actual layout of the gameboy!
Looking at our example, We have a level with some grass, blocks, and
some collectable 'stars'... our hero, Yume is controlled by the
player...
The screen is made up of the Tile
layer, and the Sprite Layer,
Usually Sprites are drawn above the Tiles... but sometimes they may
be drawn below.
It's also possible we could use sprites for the stars.. but sprites
are very limited, so the object doesn't move, then tiles will do the
job... we can even animate the stars by switching the tile between
different patterns
The tile array on the systems we'll
be looking at is made up of 8x8 tiles... the array is a 'grid' of
these tiles, so the tiles must line up, a block cannot be at a 'half
way boundary'
Tiles are defined by a number (usually 0-255)... we define the
bitmap (image) data for that tile (we'll call it a pattern), then
tell the hardware what positions in the tile array to use that
pattern.
In our example, the black background is pattern 0 ... the blocks are
pattern 1... the grass is pattern 2... and the stars are pattern 3
Our 'GameChibi' console has a tile array of 8x8... and 64 bytes is
used to define the tile grid...
So to define the stars, we need to set memory locations 10,20 and 15
of the tile array to byte '3'
A real system usually has a tile array bigger than the screen (maybe
just by one row and one coumn)... this is to allow smooth scrolling
of the screen, where two tiles are 'half shown'
Now in the case of our 'GameChibi' system, with it's 64 tile
screen, and 256 pattern definitions, we could just set every visible
tile to a different pattern, and treat the screen as a plain bitmap
again... We can do that on the MSX1, but unfortunately the Gameboy
and Mastersystem have too few tiles for their screen size, so some
parts of the screen must contain the same tile!
Because our system is using hardware sprites, we have to design
our game sprites in a way that can be drawn with the hardware
sprites... for example lets look at our Yume sprite... if our
'GameChibi' used 8x8 hardware sprites, we would have to use 48 of
them to make this image!... we can save 6 (marked green)... these
have no data, so we can just not draw them...
When it comes to moving our character, the software will have to
move the hardware sprites all together, so the user does not realise
they are made up of many sprites!... on systems with more onscreen
colors than sprite colors, two or more sprites may be overlapped to
make the sprite appear more colorful
Most systems will have one color (usually 0) which marks the
transparent colour.
but there is a problem! with software sprites on a bitmap screen, we
can draw as much as we want, it will just get slow.... but with
hardware sprites, we have a fixed limit of how many sprites can be
shown onscreen at once! sounds bad? well actually it's worse, even
though a system like the gameboy can show 40 sprites onscreen, there
can only be 10 on a line... if more than 10 appear on the same line,
some will flicker, or not appear... there's nothing we can do about
it, we just have to design our game to avoid this problem!
The Gameboy Color, for
extra power!
The gameboy color has many enhancements,
We can switch the CPU into high speed mode, for twice the CPU power
and we have extra ram banks we can page in.
Most importantly the GBC adds more graphics ability, with twice the
tile definitions (512) and 8 'palettes' of four colours
Colour palettes are defined with a 5 bits per channel in the format
-BBBBBGG GGGRRRRR
Turning on the 'Second bank of tiles' (the extra 256) and setting
the color palette is done by paging in the second 'GBC only' Vram
Bank
The second bank of the tilemap is in
the format: PVH_RCCC
_
No function
P
Priority (1=Tile in front of Sprites... 0=behind)
C
Color palette (0=normal 1=Sprite palette)
V
Vertical Flip (1=on)
H
Horizontal flip (1=on)
R
Ram bank for tiles (1= GBC for tiles numbered
257-511)
Gameboy Cartridge Rom format - and Interrupt calls!
The cartridge is loaded into the
system memory as the ROM... The first &160 bytes of the
cartridge contain the RST calls and GBZ80 Interrupt calls
Next come the header, which tells the gameboy what the cartridge
contains... there is also a checksum, which must be correct for the
game to work on a real gameboy - though it should work on emulators
without it! (the tool rgbfix.exe will work out the checksum for
you!)
A note on the interrupts between &0040-&0060:
Interrupts can be enabled or disabled as needed, but it's best to
put a 'RETI' (Return and enable interupts) at
&0040-&0060
From
To
Meaning
0000
0007
Z80
RST0
0008
000F
Z80
RST1
0010
0017
Z80
RST2
0018
001F
Z80
RST3
0020
0027
Z80
RST4
0028
002F
Z80
RST5
0030
0037
Z80
RST6
0038
003F
Z80
RST7
0040
0047
Interrupt:Vblank
0048
004F
Interrupt:LCD-Stat
0050
0057
Interrupt:Timer
0058
005F
Interrupt:Serial
0060
0067
Interrupt:Joypad
0068
00FF
unused
0100
0103
Entry
point
(start of program)
0104
0133
Nintendo
logo
(must match rom logo)
0134
0142
Game
Name
(Uppercase)
0143
0143
Color
gameboy
flag (&80 = GB+CGB,&C0 = CGB only)
0144
0145
Game
Manufacturer
code
0146
0146
Super
GameBoy
flag (&00=normal, &03=SGB)
0147
0147
Cartridge
type
(special upgrade hardware) (0=normal ROM)
0148
0148
Rom
size
(0=32k, 1=64k,2=128k etc)
0149
0149
Cart
Ram
size (0=none,1=2k 2=8k, 3=32k)
014A
014A
Destination
Code
(0=JPN 1=EU/US)
014B
014B
Old
Licensee
code (must be &33 for SGB)
014C
014C
Rom
Version
Number (usually 0)
014D
014D
Header
Checksum
- �ones complement� checksum of bytes 0134-014C
not needed for emulators
014E
014F
Global
Checksum
� 16 bit sum of all rom bytes (except 014E-014F)
unused by gameboy
0150
�
Game
Code!
Gameboy Memory Map
The Rom cartridge (and its header)
take up the first &8000 bytes of memory,
The 8k of ram is accessible at &C000-&DFFF... a 'shadow
copy' is also at &E000-&FDFF (some cartridges have extra ram
at this address)
0000
3FFF
16KB
ROM Bank 00 (in cartridge, fixed at bank 00)
4000-
7FFF
16KB
ROM Bank 01..NN (in cartridge, switchable bank number)
8000
8FFF
VRAM:
Tiles
/ Sprites
9000
97FF
VRAM:
Tiles
Alt
9800
9BFF
VRAM:
Tilemap
1
9C00
9FFF
VRAM:
Tilemap
2
A000
BFFF
8KB
External RAM (in cartridge, switchable bank, if any)
C000
CFFF
4KB Work RAM Bank 0
(WRAM)
D000
DFFF
4KB Work RAM Bank 1
(WRAM) (switchable bank 1-7 in CGB Mode)
E000
FDFF
Same as C000-DDFF
(ECHO) (typically not used)
FE00
FE9F
Sprite Attribute Table
(OAM) (Can�t change during screen redraw)
FEA0
FEFF
Not Usable
FF00
FF7F
I/O Ports
FF80
FFFE
High RAM (HRAM) (Stack)
FFFF
FFFF
Interrupt Enable
Register
Hardware ports - AKA 'Where's my OUT command gone?' As mentioned before, the Gameboy has no IN or Out commands,
there is a bank of hardware regsiters memory mapped between &FF00 and
&FF80... just write or read from these memory locations to have the
hardware effect... we'll cover the details of these in later tutorials
Ly
coincidence interrupt on, Oam Interrupt on, Vblank interrupt on,
Hblank interrupt on, Coincidence flag, MM=video mode (0/1 =Vram
available)
Tile
FF42
SCY � Tile
Scroll Y
0= default
Tile
FF43
SCX � Tile
Scroll X
0= default
LCD
FF44
LY - LCDC
Y-Coordinate (R) - LCD Y Line (0-153 144+ are V-Blank)
LCD
FF45
LYC - LY
Compare (R/W)
RAM
FF46
DMA - DMA
Transfer and Start Address (W)
Sprite DMA -
High byte of DMA - must be executed from &FF80-FFFE
Tile
FF47
BGP - BG
Palette Data (R/W) - Non CGB Mode Only
Sprite
FF48
OBP0 -
Object Palette 0 Data (R/W) - Non CGB Mode Only
Sprite
FF49
OBP1 -
Object Palette 1 Data (R/W) - Non CGB Mode Only
Tile
FF4A
WY -
Window Y Position (R/W)
Tile
FF4B
WX- Window
X Position minus 7 (R/W)
CPU
FF4D
KEY1 - CGB
Mode Only - Prepare Speed Switch
C------P
C=Current
speed P=prepare switch
VRAM
FF4F
VBK - CGB
Mode Only - VRAM Bank
-------B
B=Bank
COM
FF56
RP - CGB
Mode Only - Infrared Communications Port
Tile
FF68
BCPS/BGPI
- CGB Mode Only - Background Palette Index
Select
background palette byte
Tile
FF69
BCPD/BGPD
- CGB Mode Only - Background Palette Data
Write background palette byte
Sprite
FF6A
OCPS/OBPI
- CGB Mode Only - Sprite Palette Index
Select sprite palette byte
Sprite
FF6B
OCPD/OBPD
- CGB Mode Only - Sprite Palette Data
Write sprite palette byte
RAM
FF70
SVBK - CGB
Mode Only - WRAM Bank (bits 0-3 =0-2)
-----BBB
BBB=Bank 1-7
(0 also pages in bank 1)
INT
FFFF
IE -
Interrupt Enable (R/W)
---JSTLV
J=Joypad
S=Serial T=Timer L=Lcd stat V=vblank
Bankswitching on
cartridges with MBC1+
Larger cartridges can have more than
32k rom, and even extra RAM built into them (With battery backup!)
We switch cartridge RAM/ROM bank by writing to specific address
ranges within the 'ROM'... this tells the cartridge to change
bank...
Good example addresses are shown below... though actually a range of
addresses will have the same effect
MBC1 Bank Swapper
0000 (Write) � Ram enable (&0A)
2000 (Write) � Rom Bank Number
3000 (Write) � Bit 8 of MBC5 ROM Bank
4000 (Write) � Ram Bank Number
6000 (Write) � Rom/Ram Mode Select
Gameboy Joystick port
Joypad reading is all done with
memory address &FF00
Only Bits 0-3 in this address contain the state of the buttons, we
first need to select which half of the joystick we want to read.
If we write %11101111 to &FF00 (Bit 4 is zero) we will select
the direction controls. We can then read from &FF00 to
get Down, Up, Left, Right in bits 0-3
If we write %11011111 to &FF00 (Bit 5 is zero) we will select
the button controls. We can then read from &FF00 will get
Start, Select, Button B, Button A in bits 0-3
Address
Bit
Purpose
&FF00
7
Unused
6
Unused
5
Read
Buttons
4
Read
Directions
3
Down
Start
2
Up
Select
1
Left
Button
B
0
Right
Button
A
Gameboy Sprite Memory
Sprite Data is stored from &FE00 onwards, there are 40
sprites, and each definition uses 4 consecutive bytes...
For Example, Sprite 0's bytes are highlighted in black... it has a Y
co-ordinate, an X co-ordinate, a Tile Number, and tile Attributes
Y and X are offset, so you can have a sprite partially off the
screen, You need to set XY to (8,16) to get the top corner of the
screen (0,0)
Attributes:
7
6
5
4
3
2
1
0
Tile-Sprite
Priority
Y-flip
X-flip
GB-Pal
CGB-Vbank
CGB-Palette
On GBC sprites use an alternate 8 palettes to background tiles.
Sprites are all 8x8 or 8x16, which is define by bit 2 of &FF40
(LCDC - LCD Control)
Gameboy & Gameboy Color Links Visual Boy Advance -
Emulates the Gameboy , Gameboy Color, and others! GameBoy Dev'rs -
Gameboy programming website Color
Programming - The only site I can find with examples about Color on
the gameboy! Vasm - You can't easilly
compile for the gameboy with a standard Z80 assembler like WinApe...
but VASM in 'OldStyle' mode is pretty similar to WinApe