Unofficial documentation for the CowBite GBA emulator
by Tom Happ
Sun Aug 4 17:21:40 2002
The most recent version is kept at
http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm
and http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.zip.
Available
With Frames and Without Frames
1. Introduction
2. CPU
3. Memory
4. Graphics Hardware
Overview
5. Backgrounds
6. OAM/Sprites
7. Windowing
8. Hardware Interrupts
9. BIOS
10. Memory-Mapped
Hardware Registers
11. Miscellaneous/Weirdness
12. Links
13. Thanks
This document began as a scratchpad of notes that I added onto "Agent Q's GBA Spec" as I came across
new information and ideas while building the CowBite emulator. Agent Q is no longer able to maintain that document.
Because there is so much additional information here, I thought it would be a shame to keep it to myself, and thus
I'm releasing it again as a CowBite technical reference document. Though it has the name of the CowBite emulator
on it, the information should still be more or less (and unofficially) valid on actual hardware.
I've tried to organize this document in a way that will be easy to navigate to the section you are looking for.
I also try to update whenever I find that something is missing or erroneous. However, I can't catch everything
without your feedback. If you find an error, have information not listed in this doc (and there is lots of that),
or think that something could be improved upon, please contact me.
For the most part, this document is a reference and not a tutorial or instruction manual. I have done my best to
provide samples and hints wherever I can, but if you are looking for a step-by-step guide, you will probably find
it easier to begin with a tutorial like Dovoto's Pern
Project, or one of the other tutorials on http://www.gbadev.org/ or in
the links section of this page.
All of this information has been obtained legally by piecing together information from the ARM docs, gbadev.org,
the gbadev mailing list, public domain demos, and other information such as the debug info from various emulators.
My sincerest thanks to all of those
who have mailed me with info and corrections!
Send me mail<EMAIL_ADDRESS>with your comments and especially
with info and corrections.
Tom Happ
Revision 3.5 - (Colorful Version) Begun May 18th 2002 (Though updates are continuous)
Revision 3.0 - (HTML Version) Begun December 19th 2001
Revision 2.1 - I decided to rename this 3.0, as it turned out to be a major overhaul
Revision 2.0 - Begun July 23, 2001 (by me)
Revision 1.0 - (by Agent Q) 08/02/2001
I keep the most recent doc update at
http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm
From the programmer's perspective, the system is composed of the following:
CPU - A 16.78 Mhz ARM7tdmi
Memory - 8 to 11 distinct areas
of memory (depending on the Game Pak).
IO - Special
hardware functions available to the programmer, primarily pertaining to graphics, sound, DMA, timers, serial communication,
key input, and interrupts.
Programs run on the GBA are usually contained in a "Game Pak". A "Game Pak" consists mainly
of ROM and possibly Cart
RAM (in the form of SRAM, Flash ROM, or EEPROM, used mainly for save game info). The ROM is where compiled
code and data is stored. Unlike home computers, workstations, or servers, there are no disks or other drives, so
everything that might otherwise have been stored as separate resource files must be compiled into the program ROM
itself. Luckily there are tools to aid in this process.
The primary means a program accesses specialized hardware for graphics, sound, and other IO is through the memory-mapped
IO. Memory mapped IO is a means of communicating with hardware by writing to/reading from specific memory addresses
that are "mapped" to internal hardware functions. For example, you might write to address 0x4000000
with the value "0x0100", which tells the hardware "enable background 0 and graphics mode 0".
A secondary means is through the BIOS,
which is embedded in the internal GBA system ROM. Using software
interrupts it is possible to access pre-programmed (and hopefully optimized) routines lying in the the system
ROM. These routines then access the hardware through the memory-mapped IO.
Other regions of memory that are directly mapped to the hardware are Palette
RAM (which is a table consisting of all the available colors), VRAM
(which performs a similar function to the video RAM on a PC - and thensome), and OAM
(which contains the attributes for hardware accelerated sprites).
For those wishing to learn how to write a program for the GBA, this is not really the right place. This document
is more like a reference that you can keep open in the background and quickly thumb through as questions arise.
Consider the following to be a generalization of how games are developed for the GBA.
C, C++, and ARM/Thumb assembly are the most common languages used in GBA development, mainly because they are fast
and relatively low level (i.e. there is a large degree of correspondance between the structure of the language
and underlying instruction set of the architecture). Members of the GBA development
community have put together some development kits that greatly simplify the task of configuring a C/C++ compiler
for GBA development. Two that I know of are Devkit Advance and HAM.
Most GBA programs are structured around the timing of the CPU and graphics hardware. The LCD has a refresh rate
of about 59.73 hz, with each refresh consisting of a vertical
draw period (when the GBA is drawing the screen) followed by a vertical
blank period (when nothing is being drawn). The vertical draw and vertical blank periods are further subdivided
into horizontal draw and blank periods.
Programs typically use the VBlank and possibly the HBlank periods to update VRAM or graphics hardware registers
in order to avoid unwanted visual artifacts, leaving the VDraw and HDraw periods to perform any software processing
that will not effect the display. Common methods of syncing to VBlank include polling REG_DISPSTAT
or REG_VCOUNT, calling the VBlankIntrWait
BIOS function,
or setting up an interrupt.
I suggest the following resources as being invaluable to homebrew (and even commercial) developers:
http://www.gbadev.org/ - This is one of the main hubs for GBA development
on the web, containing numerous docs, tutorials, demos (many with source code), tools, and news.
http://www.devrs.com/gba - This is Jeff Frohwein's GBA site. Jeff Frohwein
is something of a GBA dev guru; you will likely hear his name mentioned often throghout the community. His site
contains many good links, documents, and tools, many of which he wrote himself.
http://groups.yahoo.com/group/gbadev/ -A forum on yahoo with
a large archive of back posts.
PERN project tutorials - These great tutorials
by Dovoto explain everything in an easy-to-understand, step-by-step fashion.
The Audio Advance - Documents and tutorials on the formerly enigmatic
GBA sound system. Courtesy of Uze.
Unofficial GBA Software Development Kit (AKA Devkit Advance)
- The most popular free devkit available.
HAM - If you want to get started right now, Emanuel's HAM devkit
is especially easy to install, and can have you up and running in minutes.
16 registers are visible to the user at any given time, though there are 20 banked registers which get swapped in whenever the CPU changes to various priveleged modes. The registers visible in user mode are as follows:
r0-r12: General purpose registers, for use in every day operations
r13 (SR): Stack pointer Register. Used primarily for maintaining the address of the stack. This default value (initialized by the BIOS) differs depending on the current processor mode, as follows:User/System: 0x03007F00 IRQ: 0x03007FA0 Supervisor: 0x03007FE0As far as I know the other modes do not have default stack pointers.
r14 (LR): Link Register. Used primarily to store the address following a "bl" (branch and link) instruction (as used in function calls)
r15 (PC): The Program Counter. Because the ARM7tdmi uses a 3-stage pipeline, this register always contains an address which is 2 instructions ahead of the one currrently being executed. In 32-bit ARM state, it is 8 bytes ahead, while in 16-bit Thumb state it is 4 bytes ahead.
CPSR: The Current Program Status Register. This contains the status bits relevant to the CPU -31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 N Z C V R R R R R R R R R R R R R R R R R R R R I F T M M M M M0-4 (M) = Mode bits. These indicate the current processor mode: 10000 - User mode 10001 - FIQ mode 10010 - IRQ mode 10011 - Supervisor mode 10111 - Abort mode 11011 - Undefined mode 11111 - System mode5 (T) = Thumb state indicator. If set, the CPU is in Thumb state. Otherwise it operates in normal ARM state. Software should never attempt to modify this bit itself. 6 (F) = FIQ interrupt disable. Set this to disable FIQ interrupts. 7 (I) = IRQ interrupt disable. Set this to disable IRQ interrupts. On the GBA this is set by default whenever IRQ mode is entered. Why or how this is the case, I do not know. 8-27 (R) = Reserved 28 (V) = Overflow condition code 29 (C) = Carry/Borrow/Extend condition code 30 (Z) = Zero/Equal condition code 31 (N) = Negative/Less than condition code
The ARM7tdmi has six modes: user, system, IRQ, FIQ, SVC, Undef, and Abt. The default is user mode. Certain events
will trigger a mode switch. Some modes cause an alternate set of registers to be swapped in, effectively replacing
the current set of registers until the mode is exited.
User: This is the default mode.
System: This is intended to be a priveleged user mode for the operating system. As
far as I can tell it is otherwise the same as User mode. I am not sure if the GBA ever enters System mode during
BIOS calls.
IRQ: This mode is entered when an Interrupt Request is triggered. Any interrupt handler
on the GBA will be called in IRQ mode.
Banked registers: The ARM7tdmi has several sets of banked registers that get swapped in place of normal user mode registers when a priveleged mode is entered, to be swapped back out again once the mode is exited. In IRQ mode, r13_irq and r14_irq will be swapped in to replace r13 and r14. The current CPSR contents gets saved in the SPSR_irq register.
FIQ: This mode is entered when a Fast Interrupt Request is triggered. Since all of the hardware interrupts on the GBA generate IRQs, this mode goes unused by default, though it would be possible to switch to this mode manually using the "msr" instruction.
Banked registers: r8_fiq, r9_fiq, r10_fiq, r11_fiq, r12_fiq, r13_fiq, r14_fiq, and SPSR_fiq.
SVC: Supervisor mode. Entered when a SWI (software interrupt) call is executed. The GBA enters this state when calling the BIOS via SWI instructions.
Banked registers: r13_svc, r14_svc, SPSR_svc.
ABT: Abort mode. Entered after data or instruction prefetch abort.
Banked registers: r13_abt, r14_abt, SPSR_abt.
UND: Undefined mode. Entered when an undefined instruction is executed.
Banked registers: r13_und, r14_und, SPSR_und.
The ARM7tdmi has two possible states, either of which may be entered without fear of losing register contents
or current processor mode.
To enter Thumb State: In this state the CPU executes 16-bit, halfword-aligned
instructions. There are two ways it can be entered:
To Enter ARM State: This is the default state. It executes 32-bit, word-aligned instructions. When in Thumb state, the CPU can be switched back to ARM state by:
For more complete information on the ARM7tdmi, be sure to check out ARM's technical
reference manuals.
The following are the general areas of memory as seen by the CPU, and what they are used for.
System ROM:
Start: 0x00000000 End: 0x0003FFF Size: 16kb Port Size: 32 bit Wait State: 0
0x0 - 0x00003FFF contain the BIOS,
which is executable but not readable. Any attempt to read in the area from 0x0 to 0x1FFFFFFF will result in failure;
what you will see on a read is the current prefetched instruction (the instruction after the instruction used to
view the memory area), thus giving the appearance that this area of memory consists of a repeating byte pattern.
External Work RAM:
Start: 0x02000000 End: 0x0203FFFF Size: 256kb Port Size: 16 bit Mirrors: Every 0x40000 bytes from 0x02000000 to 0x02FFFFFF
This space is available for your game's data and code. If a multiboot cable is present on startup, the BIOS
automatically detects it and downloads binary code from the cable and places it in this area, and execution begins
with the instruction at address 0x02000000 (the default is 0x08000000). Though this is the largest area of RAM
available on the GBA, memory transfers to and from EWRAM are 16 bits wide and thus consume more cycles than necessary
for 32 bit accesses. Thus it is advised that 32 bit ARM code be placed in IWRAM
rather than EWRAM.
Internal Work RAM:
Start: 0x03000000 End: 0x03007FFF Size: 32kb Port Size: 32 bit Mirrors: Every 0x8000 bytes from 0x03000000 to 0x03FFFFFF
This space is also available for use. It is the fastest of all the GBA's RAM, being internally embedded in the
ARM7 CPU chip package and having a 32 bit bus. As the bus for ROM
and EWRAM is only 16 bits
wide, the greatest efficiency will be gained by placing 32 bit ARM code in IWRAM while leaving thumb code for EWRAM or ROM
memory.
IO Ram:
Start: 0x04000000 End: 0x040003FF (0x04010000) Size: 1Kb Port Size: Dual ported 32 bit Mirrors: The word at 0x04000800 (only!) is mirrored every 0x10000 bytes from 0x04000000 - 0x04FFFFFF.
This area contains a mirror of the ASIC (Application Specific Integrated Circuit) registers on the GBA. This
area of memory is used to control the graphics, sound, DMA, and other features. See memory-mapped
IO registers for details on the function of each register.
Palette RAM:
Start: 0x05000000 End: 0x050003FF Size: 1kb Port Size: 16 bit Mirrors: Every 0x400 bytes from 0x05000000 to 0x5FFFFFF
This area specifies the 16-bit
color values for the paletted modes. There are two areas of the palette: one for backgrounds (0x05000000) and
another for sprites (0x05000200). Each of these is either indexed as a single, 256-color palette, or as 16 individual
16-color palettes, depending on the settings of a particular sprite
or background.
VRAM:
Start: 0x06000000 End: 0x06017FFF Size: 96kb Port Size: 16 bit Mirrors: Bytes 0x06010000 - 0x06017FFF is mirrored from 0x06018000 - 0x0601FFFF. The entire region from 0x06000000 - 0x06020000 is in turn mirrored every 0x20000 bytes from 0x06000000 - 0x06FFFFFF.
The video RAM is used to store the frame buffer in bitmapped
modes, and the tile data and tile maps for tile-based "text"
and rotate/scale
modes.
OAM:
Start: 0x07000000 End: 0x070003FF Size: 1kb Port Size: 32 bit Mirrors: Every 0x400 bytes from 0x07000000 to 0x07FFFFFF
This is the Object Attribute Memory, and is used to control the GBA's sprites.
The following areas of memory are technically cart-dependent, but can generally be expected to behave as described.
GAME PAK ROM:
Start: 0x08000000 Size: The size of the cartridge (0 - 32 megabytes) Port Size: 16 bit Wait State: 0
The ROM in the game cartridge appears in this area. If a cartridge is present on startup, the instruction found
at location 0x08000000 is loaded into the program counter and execution begins from there. Note that the transfers
to and from ROM are all 16 bits wide.
GAME PAK ROM IMAGE 1:
Start: 0x0A000000 Size: The size of the cartridge (0 - 32 megabytes) Port Size: 16 bit Wait State: 1
This is a mirror of the ROM above. Used to allow multiple speed ROMs in a single game pak.
GAME PAK ROM IMAGE 2:
Start: 0x0C000000 Size: The size of the cartridge (0 - 32 megabytes) Port Size: 16 bit Wait State: 2
This is a mirror of the ROM above. Used to allow multiple speed ROMs in a single game pak.
CART RAM:
Start: 0x0E000000 (also seem to appear at 0x0F000000) Size: 0 - 64 kb Port Size: 8 bit
This is either SRAM or Flash ROM. Used primarily for saving game data. SRAM can be up to 64kb but is usually
32 kb. It has a battery backup so has the longest life (in terms of how many times it can be written to) of all
backup methods. Flash ROM is usually 64 kb. Its lifespan is determined by the number of rewrites that can be done
per sector (a 10,000 rewrite minimum is cited by some manufacturers).
EEPROM:
This is another kind of cart memory, but operates differently from SRAM or Flash ROM. Unfortunately, I don't know
the details of how it can be accessed by the programmer (mail
me if you have more information on it). It uses a serial connection to transmit data. The maximum size is 128
mb, but it can be any size, and is usually 4 kb or 64 kb. Like Flash ROM it has a limited life; some manufacturers
cite a minimum of 100,000 rewrites per sector.
There may be other regions of memory known as DEBUG ROM 1 and DEBUG ROM 2, though I really don't know whether these
are a part of commercial carts or if they are mapped to some part of the internal ROM, or if they're even available
on a standard GBA.
Note that EWRAM, IWRAM, VRAM, OAM, Palette RAM are all initialized to zero by the BIOS (i.e. you can expect them
to be zeroed at startup).
The GBA has a TFT color LCD that is 240 x 160 pixels in size and has a refresh rate of exactly 280,896 cpu cycles per frame, or around 59.73 hz. Most GBA programs will need to structure themselves around this refresh rate. Each refresh consists of a 160 scanline vertical draw (VDraw) period followed by a 68 scanline blank (VBlank) period. Furthermore, each of these scanlines consists of a 1004 cycle draw period (HDraw) followed by a 228 cycle blank period (HBlank). During the HDraw and VDraw periods the graphics hardware processes background and obj (sprite) data and draws it on the screen, while the HBlank and VBlank periods are left open so that program code can modify background and obj data without risk of creating graphical artifacts.
Exactly what the GBA draws on screen depends largely on the current video mode (also sometimes referred to as
the screen mode or graphics mode). The GBA has 6 such modes, some of which are bitmap-based
and some of which are tile-based.
The video mode is set by the bottom three bits of the hardware register known as REG_DISPCNT.
Background data is handled differently depending on what mode is enabled. Backgrounds can either be text
backgrounds (tile based), rotate-scale
backgrounds (tile based backgrounds that can be transformed), or bitmap
backgrounds. The starting address and size sprite graphics memory is also dependent on video mode. It starts
at 0x6010000 for tile modes and 0x6014000 for bitmapped
modes.
Enabling objs and one or more backgrounds in REG_DISPCNT
will cause the GBA to draw the specified backgrounds and objs in order of priority.
Mode 0:
In this mode, four text background layers can be shown. In this mode backgrounds 0 - 3 all count as "text"
backgrounds, and cannot be scaled or rotated. Check out the section on text
backgrounds for details on this.
Mode 1:
This mode is similar in most respects to Mode 0, the main difference being that only 3 backgrounds are accessible
-- 0, 1, and 2. Bgs 0 and 1 are text
backgrounds, while bg 2 is a rotation/scaling
background.
Mode 2:
Like modes 0 and 1, this uses tiled backgrounds. It uses backgrounds 2 and 3, both of which are rotate/scale
backgrounds.
Mode 3:
Standard 16-bit bitmapped (non-paletted) 240x160 mode. The map starts at 0x06000000 and is 0x12C00 bytes long.
See the Color Format table above
for the format of these bytes.
This allows the full color range to be displayed at once. Unfortunately, the frame buffer in this mode is too large
for page flipping to be possible. One option to get around this would be to copy a frame buffer from work RAM into
VRAM during the retrace, or (so I have heard) to use DMA3
with the start mode bits set to 11.
Mode 4:
8-Bit paletted bitmapped mode at 240x160. The bitmap starts at either 0x06000000 or 0x0600A000, depending on bit
4 of REG_DISPCNT. Swapping the
map and drawing in the one that isn't displayed allows for page flipping techniques to be used. The palette is
at 0x5000000, and contains 256 16-bit color
entries.
Mode 5:
This is another 16-bit bitmapped mode, but at a smaller resolution of 160x128. The display starts at the upper
left hand corner of the screen, but can be shifted using the rotation and scaling registers for BG2. The advantage
of using this mode is presumably that there are two frame buffers available, and this can be used to perform page
flipping effects which cannot be done in mode 3 due to the smaller memory requirements of mode 5. Bit 4 of REG_DISPCNT
sets the start of the frame buffer to 0x06000000 when bit 4 is zero, and 0x600A000 when bit 4 is one.
All colors (both paletted and bitmapped) are represented as a 16 bit value, using 5 bits for red, green, and blue, and ignoring bit 15. In the case of paletted memory, pixels in an image are represented as 8 bit or 4 bit indices into the palette RAM starting at 0x5000000 for backgrounds and 0x5000200 for sprites. Each palette is a table consisiting of 256 16-bit color entries. In the case of the bitmapped backgrounds in modes 3 and 4, pixels are represented as the 16-bit color values themselves.
F E D C B A 9 8 7 6 5 4 3 2 1 0 X B B B B B G G G G G R R R R R
0-4 (R) = Red 5-9 (G) = Green A-F (B) = Blue
Depending on the current video mode, three different types of backgrounds are available. They are
These are tile-based backgrounds that descend from the usage of tiles to display characters in text modes of
a PC or workstation. They are made up of 8x8 tiles, the bitmaps of which are stored at the tile data address. The
address of this data is set using registers REG_BG0CNT
- REG_BG3CNT. The HOFS and
VOFS registers can be used to scroll
around a larger area of up to 512x512 pixels (or 64 x 64 tiles).
In text backgrounds, the data for each pixel is stored as an 8 or 4 bit palette index. In 8-bit mode, the palette
is at 0x05000000 stores a 15-bit color value for each of the 256 palette entries. In 4-bit mode, the the map index
contains a 4-bit value indicating which of 16 16-color palettes to use for each tile. Each of these palettes is
32 bytes long and can be found at 0x05000000, 0x05000020, etc.
These backgrounds are also tile-based, and operate similarly to Text Backgrounds. However, these backgrounds may also be scaled or rotated. Additionally they may only use an 8-bit palette, and can vary in size from 128 to 1024 pixels across. The palette is at 0x5000000, and contains 256 16-bit color entries
These backgrounds vary depending on the video mode, but in all cases they rely on a single buffer upon which the image is drawn, either using an 8-bit palette or 16-bit color entries themsevles. Bitmap backgrounds are treated as BG2 for purposes of rotation, scaling, and blending. In the bitmap modes the frame buffer data extends into the obj tile data region, limiting it to the range from 0x6014000 - 0x6018000 (sprite indices 512 - 1024).
Text
Background Map Format:
The tile map, which stores the layout of the tiles on screen, begins at the tile map address found for a particular
background, detrmined by REG_BG0CNT -
REG_BG3CNT. It has a selectable size up to 512x512. The tile map contains a 16-bit entry for each tile, with
has the following format:
F E D C B A 9 8 7 6 5 4 3 2 1 0 L L L L V H T T T T T T T T T T
0-9 (T) = The tile number A (H) = If this bit is set, the tile is flipped horizontally left to right. B (V) = If this bit is set, the tile is flipped vertically upside down. C-F (L) = Palette number
For 256 x 256 and 256 x 512 backgrounds, the formula for calculating a map index is roughly,
mapEntry = tileMapAddress[(tileY * 32) + tileX]
For text mode sizes 512 x 256 and 512 x 512 backgrounds, however, the map is 64 tiles across, and these are stored in blocks of 32 * 32 tiles. This means that to calculate the map entry that would appear 33 tiles or more across the background, the following equation should be used:
mapEntry = tileMap[(tileY * 32) + (tileX - 32) + 32*32]
For entries 33 tiles or more down (in mode 11), use
mapEntry = tileMap[( (tileY-32) * 32) + tileX + 2*32*32];
And for entries 33 tiles or more down and 33 tiles or more across,
mapEntry = tileMap[( (tileY-32) * 32) + (tileX-32) + 3*32*32];
Rotational Background Map Format :
This is the same idea as the text
background map format, but you only have 8 bits for each entry. The format for the tile map entries is
7 6 5 4 3 2 1 0 T T T T T T T T
0-7 (T) = The tile number
Rotational backgrounds do not divide tile maps into blocks.
The GBA supports 128 simultaneous sprites. These can be up to 64x64 pixels in size. The OAM, which starts at 0x07000000,
has one entry for each of the 128 sprites. Intermixed with this data are the rotation/scaling attributes, of which
there are 32 sets of 4 16 bit values.
Each OAM entry is 8 bytes long and has the following format:
Bytes 1 and 2 (Attribute 0)
F E D C B A 9 8 7 6 5 4 3 2 1 0 S S A M T T D R J J J J J J J J
0-7 (J) = Y co-ordinate of the sprite (pixels). Note that for regular sprites, this is the y coordinate of the upper left corner. For rotate/scale sprites, this is the y coordinate of the sprite's center. center . Note on Coordinates: The values actually wrap around: to achieve a -1 y coordinate, use y = 255. 8 (R) = Rotation/Scaling on/off 9 (D) = 0 - sprite is single sized; 1 - sprite is virtually double sized; allowing sheared sprite pixels to overflow sprite the size (specified by bits 14 - 15 of OAM attribute 1). A 16x16 sized sprite is treated internaly as a 32x32 sprite. This specification comes in evidence when rotating a sprite at 45°, since the H/V size of the sprite becomes SQRT(16² + 16²) = SQRT(512) =~ 22.62 pixels. This will cause the sprite to appear clipped if this bit is set to 0. (Thanks to Kay for the description) A-B (T) = 00 - normal 01 - semi-transparent 10 - obj window 11 - illegal code Note that semi-transparent sprites appear as transparent even if REG_BLDMOD has the sprites bit turned off. Also note that sprites cannot be blended against one another. For more details, see REG_BLDMOD. C (M) = enables mosaic for this sprite. D (A) = 256 color if on, 16 color if off E-F (S) = See below
F E D C B A 9 8 7 6 5 4 3 2 1 0 S S V H X X X I I I I I I I I I (standard sprites) S S F F F F F I I I I I I I I I (rotation/scaling on)
0-8 (I) = X coordinate of the sprite (pixels). For regular sprites, this is the x coordinate of the upper left corner. For rotate/scale sprites, this is the x coordinate of the sprite's center. Note on coordinates: The values actually wrap around. To achieve a -1 x, use x = 511. C (H) = The flip horizinal bit D (V) = The flip vertical bit 9-D (F) = For rotation scaling sprites, the index into the rotation data to be used for that sprite. This index can be from 0 - 31. The rotation/scaling data is located in OAM attribute 3 (bytes 7 and 8). However, instead of the rotation and scaling data going with the corresponding sprite, it is separated accross four sequential sprites. This index can be thought of as referencing into an array of four-sprite blocks, 32 bytes each. E-F (S) = Size of the sprite. The top two bits of the size value are found in attribute 0 and the bottom two bits are in attribute 1. This forms a 4-bit value which sets the size of the sprite in the following way: 0000: 8 x 8 1000: 8 x 16 0001: 16 x 16 1001: 8 x 32 0010: 32 x 32 1010: 16 x 32 0011: 64 x 64 1011: 32 x 64 0100: 16 x 8 1100: Not used 0101: 32 x 8 1101: Not used 0110: 32 x 16 1110: Not used 0111: 64 x 32 1111: Not used
F E D C B A 9 8 7 6 5 4 3 2 1 0 L L L L P P T T T T T T T T T T
0-9 (T) = Tile number. This value indexes selects the bitmap of the tile to be displayed by indexing into the tile data area. Each index refernces 32 bytes, so the memory address of a tile is roughly 0x6010000 + T*32. (see Sprite Tile Data for details) A-B (P) = Priority. This controls the priority of the sprite. Note thate sprites take precedence over backgrounds of the same priority. See the description of priority under REG_BG0 - REG_BG3 for a more detailed explanation. C-F (L) = Palette number. If you use 16 color palettes, this tells you which pallette number to use.
 Instead of the rotation and scaling data going with the corresponding
sprite, it is separated accross four sequential sprites. This is indexed by bits 9 - 13 in attribute
1 (bytes 3 and 4). Note that these are all relative to the center of the sprite (background rotation/scaling
is relative to the upper left). Starting with sprite 0 and repeating every 4 sprites, they appear in the following
order:
Sprite 0, Attribute 3 - PA (DX):
Scales the sprite in the x direction by an amount equal to 1/(register value). Thus, a value of 1.0 results in the original image size, while a value of 2 is half as large, and a value of .5 is twice as large.
Sprite 1, Attribute 3 - PB (DMX):
Shears the x coordinates of the sprite over y. A value of 0 will result in no shearing, a value of 1.00 will make the image appear to be sheared left going down the screen, and a value of -1 will make the image appear sheared right going down the screen.
Sprite 2, Attribute 3 - PC (DY):
Shears the y coordinates of the sprite over x. A value of 0 will result in no shearing, a value of 1.00 will make the image appear to be sheared upwards to the right, and a value of -1 will make the image appear sheared downwards and to the right.
Sprite 3, Attribute 3 - PD (DMY):
Scales the image in the y direction by an amount equal to 1/(register value). Thus, a value of 1.0 results in the original image size, while a value of 2 is half as large, and a value of .5 is twice as large.
The basic form of the equations for rotating and scaling is as follows:
pa = x_scale * cos(angle);
pb = y_scale * sin(angle);
pc = x_scale * -sin(angle);
pd = y_scale * cos(angle);
The tile data area contains the actual bitmap for each tile. The sprites do not share tile data with the BG
layers as on the Gameboy Color. The sprite tile data starts at 0x06010000. All tiles are 8x8 pixels large. Sprites
use the second palette which begins
at 0x05000200. For 256 color sprites, there are 64 bytes per tile, one byte per pixel. This is an 8-bit value which
is an index into the 256 color palette. For 16-color sprites, attribute
2 (bytes 5 and 6) of the OAM data contains a 4 bit index into 16 16 color palettes, and sprites have 32 bytes
per tile, with 4 bits per pixel. Note that the tile index references 32 bytes at a time, so in the case of 256
color sprite tiles, you will want to set your tile number to reference ever other index (i.e. 0, 2, 4, 6, etc.).
Another thing to note is that in the bitmapped modes (3-5) the memory required to hold background data is larger
than 0x10000 bytes, forcing the GBA to cut away from available sprite tile data. Thus in these modes you may only
reference sprites tiles of indices 512 and up.
When the sprite is larger than 8x8 pixels, multiple tiles are glued together to make the sprite's width horizontally,
and then vertically. How this is done depends on whether character data is stored in 2d or 1d mode (determined
by bit 6 of DISPCNT).
1D Mapping:
In 1D mode, tiles are stored sequentially. If you were to set up a 32x32 16-color sprite, and set the tile number to 5, the sprite would be displayed as follows:--------------------- | 5 | 6 | 7 | 8 | | | | | | --------------------- | 9 | 10 | 11 | 12 | | | | | | --------------------- | 13 | 14 | 15 | 16 | | | | | | --------------------- | 17 | 18 | 19 | 20 | | | | | | ---------------------
2D Mapping:
Tiles on each row of the sprite are stored 32 slots in. Using the same 32x32 sprite above, with a tile number of 5, the sprite would be displayed as:--------------------- | 5 | 6 | 7 | 8 | | | | | | --------------------- | 37 | 38 | 39 | 40 | | | | | | --------------------- | 69 | 70 | 71 | 72 | | | | | | --------------------- | 101| 102| 103| 104| | | | | | ---------------------
Windowing is a method of dividing the screen into subsections known as (surprise) windows. The windows serve
as boundary areas to determine where various layers of the GBA will be shown and where they will be clipped. There
are two primary windows, win0 and win1, which can be enabled in REG_DISPCNT.
There is also the "obj" window, which can be thought of as another window which is defined by the visible
regions of the objs on screen. Finally there is the "outside" or "out" window - the area of
the screen not already occupied by any other winodw. The position and size of WIN0 and WIN1 are determined by REG_WIN0H, REG_WIN1H,
REG_WIN0V, and REG_WIN1V
(I/O offsets 0x40, 0x42, 0x44, 0x46). Exactly which characters and backgrounds appear within or without win0, win1,
and the obj window is determined by REG_WININ
and REG_WINOUT (0x48 and 0x4A).
Here are some things to keep in mind when using windows :
- WIN0 and WIN1 are drawn from the left and top boundary up to but not including the right and bottom boundaries.
- Everything in WIN0 appears "above" WIN1 (i.e. it has higher priority), and everything in windows 0 & 1 appears above the WINOUT and obj windows.
- If a bg or the obj's are turned off in dispcnt, they're off in all windows regardless of the settings in win_in and win_out.
- If only one window is on, WINOUT affects everything outside of it (if both windows are on, WINOUT affects everything outside both of them. IE, it affects (!WIN0)&&(!WIN1) ).
- If a window is on, but the effective display bits are all clear, the backdrop is displayed.
- If the window left coordinate is greater than the window right coordinate, the window will be drawn outside of this region (i.e. to the left and to the right) rather than in the area inbetween.
- Likewise, if the window top coordinate is greater than the window bottom coordinate, the window will be drawn to the top and the bottom.
- A completely inverted window is drawn in the area outside of the "+" shaped region defined by its boundaries.
Windows can be used in console games for a variety of different effects. Though the window registers define
a square region, differently shaped windows can be achieved by using hdma
or hblank interrupts to
change the parameters each scanline. Lantern lighting (when the hero has a lantern or flashlight that illuminates
a certain region of a cave) and x-ray vision (use of the window to cut away layers that are in front) are two common
effects created with windows. More are certainly possible.
Thanks again to gbcft for most of these notes and for his extensive testing on the nature of windowing.
Figuring out hardware interrupts was kind of painful. Everything below is what I have gleaned from reading ARM's docs, the list, the advice of other emulator and demo authors, and from various
other emulator's debug info. I hope it is of some use to you. Let me know if you find any errors or typos.
Key points:
- All hardware interrupt vectors lie in the BIOS. You cannot handle interrupts directly, you must go through the
BIOS. Thus, the instructions for exception handling in the ARM docs do not apply directly since we cannot handle
the exceptions directly.
- Interrupts are enabled by setting the flags in the REG_IE
and hardware registers like REG_DISPSTAT,
REG_KEYCNT, and REG_DMAXCNT.
The flag must be set in both REG_IE and the corresponding hardware register for it to work. When the interrupt
signal is sent, the appropriate flag is set in REG_IF.
The program code unsets this flag (by writing a 1 to that bit) in order to keep track of what interrupts have been
handled.
- When an interrupt occurs, the CPU does the following:
1. Switches state to IRQ mode, bank-swaps the current stack register and link register (thus preserving their old values), saves the CPSR in SPSR_irq, and sets bit 7 (interrupt disable) in the CPSR.
2. Saves the address of the next instruction in LR_irq compensating for Thumb/ARM depending on the mode you are in.
3. Switches to ARM state, executes code in BIOS at a hardware interrupt vector (which you, the programmer, never see)
- The BIOS code picks up at the hardware interrupt vector and does the following:
4. Pushes registers 0 - 3, 12, LR_irq (which cointains the address following the instruction when the interrupt occrued) onto the stack
5. Places the address for the next instruction (in the BIOS, not in your code) in LR
6. Loads the address found at 0x03007FFC
7. Branches to that address.
- The program code at that address is executed.
8. It is the responsiblity of the code at that address to return once finished,
using BX LR_irq
- The BIOS finishes up where your code leaves off:
9. It restores registers 0 - 3, 12, LR_irq
10. Branches to the intruction found in LR, using a SUBS PC, LR_irq, #4
- Upon receiving the SUBS PC, LR_irq, #4 instruction, the CPU
11. Copies the SPSR_irq back into the CPSR, restoring the status bits to their
state when the interrupt occurred, and bank swaps back in the stack register
and link register. The CPU will thus be placed in the correct state (ARM or Thumb)
it was in when the exception occurred.
So, the basic model for setting up interrupts is:
1. Place the address for your interrupt code at 0x03007FFC.
2. Turn on the interrupts you wish to use:
- REG_DISPSTAT, REG_TMXCNT,
REG_KEYCNT, or REG_DMAXCNT
tell the hardware which interrupts to send
- 0x04000200 (REG_IE) masks which interrupts
will actually be serviced (?)
- 0x04000208 (REG_IME) Turns all interrupts
on or off.
3. When the interrupt is reached, the code at the address at 0x3007FFC gets loaded into the CPU. To prevent unwanted
errors/behavior, the first thing this code should do is disable interrupts.
4. To determine what interrupt this is, check the flags in 0x04000202 (REG_IF).
Unset the flag by writing a 1 to that bit.
5. Once finished with the service routine, reenable interrupts and execute a BX LR (*Not* a SUBS PC, LR #4, which
is what the BIOS does). The BIOS will then take over and return your program to where execution left off.
Enable these interrupts using REG_DISPSTAT,
REG_TMXCNT, REG_KEYCNT,
or REG_DMAXCNT, then setting the
correct flags in REG_IE and REG_IME.
V-Blank: Occurs when the vcount
reaches 160, or 0xA0. (Enable in REG_DISPSTAT)
H-Blank: Occurs at the end of every raster line, from 0 - 228. H-blank interrupts DO occur during v-blank (unlike
hdma, which does not), so write your code accordingly. Thanks to gbcft for verifying this. (Enable in REG_DISPSTAT)
Serial: I am unsure about this; I presume it has to do with the link cable.
V-Count: Occurs when the vcount
reaches the number specified in REG_DISPSTAT.
Timer: These occur whenever one of the timer
registers is set to cause an interrupt whenever it overflows. Enable in REG_TMXCNT.
DMA: These occur after a DMA transfer, according to the flags in the DMA_CNT
registers and in REG_IE. Enable in
REG_DMAXCNT.
Key: Occurs when the user presses or releases the buttons specified in REG_KEYCNT.
Cassette: Occurs when the user yanks out or inserts the cartridge out while the GBA is still running. For a cartridge
interrupt to work properly the ISR must reside in RAM. It is possible to switch cartridges and have the routine
resume execution on a completely different ROM.
The BIOS calls are basically SWI instructions; the value passed into the instruction tells the CPU which interrupt
to execute.
The most significant portions of this section come from Martin Korth's very detailed description of the BIOS functions
in his no$gba documentation. Thanks also to Forgotten's call list
to his Visual Boy Advance FAQ.
Note that the BIOS SWI handler does not perform range checking, so calling SWI 43 - 255 (0x2B - 0xFF) will cause
a lock up.
0x00: SoftReset
Resets the GBA and runs the code at address 0x2000000 or 0x8000000 depending on the contents of 0x3007ffa (0 means 0x8000000 and anything else means 0x2000000).
0x01: RegisterRamReset
Performs a selective reset of memory and I/O registers.
Input: r0 = reset flags
0x02: Halt
Halts CPU execution until an interrupt occurs.
0x03: Stop
Stops the CPU and LCD until the enabled interrupt (keypad, cartridge or serial) occurs.
0x04: IntrWait
Waits for the given interrupt to happen.
Input: r0 = initial flag clear, r1 = interrupt to wait
0x05: VBlankIntrWait
Waits for vblank to occur. Waits based on interrupt rather than polling in order to save battery power.
Equivalent of calling IntrWait with r0=1 and r1=1.
0x06: Div
Input: r0 = numerator, r1 = denominator
Output: r0 = numerator/denominator
r1 = numerator % denominator;
r3 = abs (numerator/denominator)
0x07: DivArm
Input: r0 = denominator, r1 = numerator
Output: r0 = numerator/denominator
r1 = numerator % denominator;
r3 = abs (numerator/denominator)
Note: For compatibility with ARM's library only. Slightly slower than SWI 6.
0x08: Sqrt
Input: r0 = unsigned 32-bit number
Output: r0 = sqrt(number) (unsigned 32-bit integer)
0x09: ArcTan
Input: r0 = Tangent(angle) (16-bit; 1 bit sign, 1 bit integral, 14 bit decimal)
Output: r0 = "-PI/2<THETA/<PI/2" in a range of 0xC000h-0x4000.
Note: There is a problem in accuracy with "THETA<-PI/4, PI/4<THETA"
0x0A: ArcTan2
Note: I'm unsure about this one, since there is conflicting info about its purpose, and I have not tested it.
Version 1:
Calculates the arctangent of the given point.
Input: r0 = X (signed 16-bit), r1 = Y (signed 16-bit)
Output: r0=arctan
Version 2:
Calculates the arctangent after correction processing.
Input: r0 = Tangent(angle) (16-bit; 1 bit sign, 1 bit integral, 14 bit decimal)
Output: r0 = 0000h-FFFFh for 0<=THETA<2PI
0x0B: CPUSet
Performs a memory transfer.
Input: r0 = source address, r1 = dest address
r2 = Length and mode:
bit 24 = Fixed source address (0 - copy, 1 = set with word at r0)
bit 26 = 32 or 16 bit transfer
bits 15 - 0 = number of transfers
0x0C: CPUFastSet
Also performs a memory transfer, in 32-byte blocks, using LDMIA/STMIA instructions
Performs a memory transfer.
Input: r0 = source address, r1 = dest address
r2 = Length and mode:
bit 24 = Fixed source address (0 - copy, 1 = set with word at r0)
bits 15 - 0 = number of transfers
0x0D: BiosChecksum
Calculates the checksum of the whole BIOS by adding every 32-bit word from the BIOS.
Output: r0 = BIOS checksum
Note: this seems to only be present in the release version of the BIOS
0x0E: BgAffineSet
Calculates the affine parameters for bgs (rotation and scaling).
Input: r0 = source, r1 = dest, r2 = number of calculations
Where the data at the source is an array of r2 structures of the format:typdef struct tBGAffineSource { s32 x; //Original data's center X coordinate (8bit fractional portion) s32 y; //Original data's center Y coordinate (8bit fractional portion) s16 tX; //Display's center X coordinate s16 tY; //Display's center Y coordinate s16 sX; //Scaling ratio in X direction (8bit fractional portion) s16 sY; //Scaling ratio in Y direction (8bit fractional portion) u16 theta; //Angle of rotation (8bit fractional portion) Effective Range 0-FFFF } BGAffineSource;
And the return data (placed at the dest address) will be of the format:
typdef struct tBGAffineDest { s16 pa; //Difference in X coordinate along same line s16 pb; //Difference in X coordinate along next line s16 pc; //Difference in Y coordinate along same line s16 pd; //Difference in Y coordinate along next line s32 x; //Start X coordinate s32 y; //Start Y coordinate } BGAffineDest;
(from no$gba docs)
0x0F: ObjAffineSet
Calculates and sets the OBJ's affine parameters from the scaling ratio and angle of rotation.
The four affine parameters are set every offset bytes, starting from the dest pointer address.
If the offset value is 2, the parameters are stored contiguously. If the value is 8, they match the structure of OAM.
Input: r0 = source, r1 = dest, r2 = number of calculations, r3 = Offset in bytes for parameter addresses (2=contigiously, 8=OAM)
Where the data at the source address is of the format:typedef struct tObjAffineSource { s16 sX; //Scaling ratio in X direction (8bit fractional portion) s16 sY; //Scaling ratio in Y direction (8bit fractional portion) u16 theta; //Angle of rotation (8bit fractional portion) Effective Range 0-FFFF } ObjAffineSource;
And the data at the destination address is of the format:typedef struct tObjAffineDest { s16 pa; //Difference in X coordinate along same line s16 pb; //Difference in X coordinate along next line s16 pc; //Difference in Y coordinate along same line s16 pd; //Difference in Y coordinate along next line } ObjAffineDest;
0x10: BitUnPack
Unpacks bit packed data.
Input: r0 = source, r1 = dest, r2 = pointer to unpack parameters
Where the unpack parameters are of the format:typedef struct tBUP { u16 sourceLength; //Length of Source Data in bytes (0-0xFFFF) u8 sourceWidth; //Width of Source Units in bits (only 1,2,4,8 supported) u8 destWidth; //Width of Destination Units in bits (only 1,2,4,8,16,32 supported) u32 destOffset; //31-bit Data Offset (Bit 0-30), and Zero Data Flag (Bit 31) } BUP;
The Data Offset is always added to all non-zero source units.
If the Zero Data Flag was set, it is also added to zero units.
Data is written in 32-bit units, Destination can be Wram or Vram. The size of unpacked data must be a multiple of 4 bytes. The width of source units (plus the offset) should not exceed the destination width.
0x11: LZ77UnCompWRAM
Uncompresses LZSS data 8 bits at a time
Input: r0 = source address, r1 = dest address
0x12: LZ77UnCompVRAM
Uncompresses LZSS data 16 bits at a time
Input: r0 = source address, r1 = dest address
Note: The LZ77 decompressors actually decompress LZSS, not LZ77, which is slightly different. You will have to look on the web to find the algorithm as it is beyond the scope of this document. The following assumes a general famliarity with LZSS.
On the GBA, the ring buffer or "window" is of size 4096, the minumim compressed length is 3 and the maximum compressed length is 18. Looking into a compressed buffer you will find the size of the uncompressed memory in bytes 2, 3, and 4 (I'm not sure what the first byte does, but it seems to always be set to "01"), followed by the coded data. This is divided up into sections consisting of an 8 bit key followed by a corresponding eight items of varying size. The upper bits in the key correspond to the items with lower addresses and vice versa. For each bit set in the key, the corresponding item will be 16 bits; the top bits four being the number of bytes to output, minus 3, and the bottom sixteen bits being the offset behind the current window position from which to output. For each bit which is not set, the corresponding item is an uncompressed byte and gets sent to the output.
Thanks to Markus for providing me with some source that helped me figure out all of this.
0x13: HuffUnComp
Unpacks data compressed with Huffman and writes it 32-bits at a time.
Input: r0 = source address, r1 = dest address
Where the data at the source address is of the format:
Data Header (32bit)
Bit 0-3 Data size in bit units (normally 4 or 8)
Bit 4-7 Compressed type (must be 2 for Huffman)
Bit 8-31 24bit size of decompressed data in bytes
Tree Table
u8 tree table size/2-1
Each of the nodes below defined as:7 6 5 3 3 2 1 0 L R O O O O O O0 - 5 (O) = offset to next node -1 (2 byte units)
6 (R) = Right node end flag (if set, data is in next node)
7 (L) = Left node end flag
1 node Root node
2 nodes Left, and Right node
4 nodes LeftLeft, LeftRight, RightLeft, and RightRight node
- Compressed data
0x14: RLUnCompWRAM
Uncompresses RLE data 8 bits at a time
Input: r0 = source address, r1 = dest address
0x15: RLUnCompVRAM
Uncompresses RLE data 16 bits at a time (slower)
Input: r0 = source address, r1 = dest address
The data at the source address for both RLU functions is of the format:
Data header (32-bit)
Bit 0-3 Reserved
Bit 4-7 Compressed type (must be 3 for run-length)
Bit 8-31 Size of decompressed data
Repeat below. Each Flag Byte followed by one or more Data Bytes. Flag data (8bit)
Bit 0-6 Expanded Data Length (uncompressed N-1, compressed N-3)
Bit 7 Flag (0=uncompressed, 1=compressed)
Data Byte(s) - N uncompressed bytes, or 1 byte repeated N times
0x16: Diff8bitUnFilterWRAM
Unpacks data filtered with 8-bit difference and writes it 8-bits at a time.
Input: r0 = source, r1 = dest
0x17: Diff8bitUnFilterVRAM
Unpacks data filtered with 8-bit difference and writes it 16-bits at a time.
Input: r0 = source, r1 = dest
0x18: Diff16bitUnFilter
Unpacks data filtered with 16-bit difference and writes it 16-bits at a time.
Input: r0 = source, r1 = dest
In each UnFilter function the format of the dest is:
Data Header (32-bit)
Bit 0-3 Data size (must be 1 for Diff8bit, 2 for Diff16bit)
Bit 4-7 Type (must be 8 for DiffFiltered)
Bit 8-31 24bit size after decompression
Data Units (each 8bit or 16bit depending on used SWI function)
Data0 //original data
Data1-Data0 //difference data
Data2-Data1
Data3-Data2
0x19: SoundBiasChange
Sets the sound bias from 0 to 0x200 or from 0x200 to 0 depending on the value of R0.
Input: r0 = 0 to set it to 0, other values to set it to 0x200
0x1A: SoundDriverInit
Initializes the built in sound driver. Do not initialize more than once.
Input: r0 = SoundArea
Note: This has been abridged from the description in the no$gba documentation. I suggest checking there for a more thorough description.
The SoundArea Structure has the following format:typedef struct tSoundArea { u32 ident; //Flag the system checks to see if the work area has been //initialized/currently being accessed. vu8 DmaCount; //User access prohibited u8 reverb; //Variable for applying reverb effects to direct sound u16 d1; //User access prohibited void (*func)(); //User access prohibited int intp; //User access prohibited void* NoUse; //User access prohibited SoundChannel vchn[MAX]; //Array of Direct Sound channel structures. s8 pcmbuf[PCM_BF*2]; //?? } SoundArea; typedef struct tSoundChannel { u8 sf; //Channel status. When 0 sound it is stopped. To start sound, set other //parameters and then write 0x80h. Logical OR 0x40 for a key-off, or //write zero for a pause. The use of other bits is prohibited. u8 r1; //User access prohibited u8 rv; //Sound volume output to right side u8 lv; //Sound volume output to left side u8 at; //The attack value of the envelope. u8 de; //The decay value of the envelope. u8 su; //The sustain value of the envelope. u8 re; //The release value of the envelope. Key-off to enter this state. u8 r2[4]; //User access prohibited u32 fr; //The frequency of the produced sound. WaveData* wp; //Pointer to the sound's waveform data. u32 r3[6]; // User access prohibited u8 r4[4]; //User access prohibited } SoundChannel; typedef struct tWaveData { u16 type; //Indicates the data type. This is currently not used. u16 stat; //0 - non-looped 0x4000 - forward loop u32 freq; //Frequency. u32 loop; //Loop pointer (start of loop) u32 size; //Number of samples (end position) s8 data[]; //The actual waveform data. Takes (number of samples+1)bytes of 8bit //signed linear uncompressed data. The last byte is zero for a non-looped //waveform, and the same value as the loop pointer data for a looped waveform. } WaveData;
0x1B: SoundDriverMode
Sets the operation of the built in sound driver.
Input: r0 = operation mode31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 X X X X R R R R R R R R F F F F V V V V C C C C S R R R R R R R 0-6 (R) = Direct Sound Reverb value (0-127, default=0) (ignored if Bit7=0) 7 (S) = Direct Sound Reverb set (0=ignore, 1=apply reverb value) 8-11 (C) = Direct Sound Simultaneously-produced (1-12 channels, default 8) 12-15 (V) = Direct Sound Master volume (1-15, default 15) 16-19 (F) = Direct Sound Playback Frequency (1-12 = 5734,7884,10512,13379, 15768,18157,21024,26758,31536, 36314,40137,42048, def 4=13379 Hz) 20-23 (D) = Final number of D/A converter bits (8-11 = 9-6bits, def. 9=8bits)
0x1C: SoundDriverMain
Main function of the built in sound driver that is called by applications after SoundDriverVSync to render the sound. Does not have to be called at a precise 60hz interval, but must be called once during every 60hz period.
0x1D: SoundDriverVSync
Call this function at the very start of vblank (or, presumably, any other 60hz increment) to sync the BIOS sound driver.
0x1E: SoundChannelClear
0x1F: MIDIKey2Freq
Ox20: MusicPlayerOpen
0x21: MusicPlayerStart
0x22: MusicPlayerStop
0x23: MusicPlayerContinue
0x24: MusicPlayerFadeOut
0x25: MultiBoot
0x26: HardReset (Undocumented)
0x27: CustomHalt (Undocumented)
0x28: SoundDriverVSyncOff
Call this function in the event that the SoundDriverVSync function misses the 60hz interval (for example, when loading new data at the beginning of a stage).. It will keep the sound DMA from overflowing and playing noise.
0x29: SoundDriverVSyncOn
Call this after calling SoundDriverVSyncOff, to restore sound driver operation.
0x2A: GetJumpList (for sound?) (Undocumented)
?: FIQMasterEnable
The following section describes the function of each of the memory-mapped addresses in IO RAM. The register
naming scheme is based on a variant of the popular gba.h
by Eloist (specifically, that used by Uze in the examples on his Audio Advance site).
The notation for each entry is as follows:
R <- 'R' means "Read Only", 'W' means "Write Only" F E D C B A 9 8 7 6 5 4 3 2 1 0 <- These are the bits W V U S L K J I F D B A C M M M <- These letters are used in the key Entries marked with an 'X' usually serve no function, are unwriteable, and remain at 0.
0-2 (M) = The video mode. See video modes list above. <- The key for each bit field
Address: 0x4000000 - REG_DISPCNT (The display control register)
R F E D C B A 9 8 7 6 5 4 3 2 1 0 W V U S L K J I F D B A C M M M
0-2 (M) = The video mode. See video modes list above. 3 (C) = Game Boy Color mode. Read only - should stay at 0. 4 (A) = This bit controls the starting address of the bitmap in bitmapped modes and is used for page flipping. See the description of the specific video mode for details. 5 (B) = Force processing during hblank. Setting this causes the display controller to process data earlier and longer, beginning from the end of the previous scanline up to the end of the current one. This added processing time can help prevent flickering when there are too many sprites on a scanline. 6 (D) = Sets whether sprites stored in VRAM use 1 dimension or 2. 1 - 1d: tiles are are stored sequentially 0 - 2d: each row of tiles is stored 32 x 64 bytes in from the start of the previous row.
7 (F) = Force the display to go blank when set. This can be used to save power when the display isn't needed, or to blank the screen when it is being built up (such as in mode 3, which has only one framebuffer). On the SNES, transfers rates to VRAM were improved during a forced blank; it is logical to assume that this would also hold true on the GBA. 8 (I) = If set, enable display of BG0. 9 (J) = If set, enable display of BG1. A (K) = If set, enable display of BG2. B (L) = If set, enable display of BG3. C (S) = If set, enable display of OAM (sprites). D (U) = Enable Window 0 E (V) = Enable Window 1 F (W) = Enable Sprite Windows
Address: 0x4000004 - REG_DISPSTAT
R R R F E D C B A 9 8 7 6 5 4 3 2 1 0 T T T T T T T T X X Y H V Z G W
0 (W) = V Refresh status. This will be 0 during VDraw, and 1 during VBlank. VDraw lasts for 160 scanlines; VBlank follows after that and lasts 68 scanlines. Checking this is one alternative to checking REG_VCOUNT. 1 (G) = H Refresh status. This will be 0 during HDraw, and 1 during HBlank HDraw lasts for approximately 1004 cycles; HBlank follows, and lasts approximately 228 cycles, though the time and length of HBlank may in fact vary based on the number of sprites and on rotation/scaling/blending effects being performed on the current line. 2 (Z) = VCount Triggered Status. Gets set to 1 when a Y trigger interrupt occurs. 3 (V) = Enables LCD's VBlank IRQ. This interrupt goes off at the start of VBlank. 4 (H) = Enables LCD's HBlank IRQ. This interrupt goes off at the start of HBlank. 5 (Y) = Enable VCount trigger IRQ. Goes off when VCount line trigger is reached. 8-F (T) = Vcount line trigger. Set this to the VCount value you wish to trigger an interrupt.
Address: 0x4000006 - LCY / REG_VCOUNT (Read Only)
This location stores the current y location of the LCD hardware. It is incremented as the lines are drawn. The
160 lines of display are followed by 68 lines of Vblank period, before the whole thing starts again for the next
frame. Waiting for this register to reach 160 is one way to synchronize a program to 60Hz.
Address: 0x4000008 - REG_BG0CNT
Address: 0x400000A - REG_BG1CNT
Address: 0x400000C - REG_BG2CNT
Address: 0x400000E - REG_BG3CNT
These addresses set up the four background layers. The format is:
? F E D C B A 9 8 7 6 5 4 3 2 1 0 Z Z V M M M M M A C X X S S P P 0-1 (P) = Priority - 00 highest, 11 lowest Priorities are ordered as follows: "Front" 1. Sprite with priority 0 2. BG with priority 0 3. Sprite with priority 1 4. BG with priority 1 5. Sprite with priority 2 6. BG with priority 2 7. Sprite with priority 3 8. BG with priority 3 9. Backdrop "Back" When multiple backgrounds have the same priority, the order from front to back is: BG0, BG1, BG2, BG3. Sprites of the same priority are ordered similarly, with the first sprite in OAM appearing in front. 2-3 (S) = Starting address of character tile data Address = 0x6000000 + S * 0x4000 6 (C) = Mosiac effect - 1 on, 0 off 7 (A) = Color palette type - 1 - standard 256 color pallete 0 - each tile uses one of 16 different 16 color palettes (no effect on rotates/scale backgrounds, which are always 256 color) 8-C (M) = Starting address of character tile map Address = 0x6000000 + M * 0x800 D (V) = Screen Over. Used to determine whether rotational backgrounds get tiled repeatedly at the edges or are displayed as a single "tile" with the area outside transparent. This is forced to 0 (read only) for backgrounds 0 and 1 (only). E-F (Z) = Size of tile map For "text" backgrounds: 00 : 256x256 (32x32 tiles) 01 : 512x256 (64x32 tiles) 10 : 256x512 (32x64 tiles) 11 : 512x512 (64x64 tiles) For rotational backgrounds: 00 : 128x128 (16x16 tiles) 01 : 256x256 (32x32 tiles) 10 : 512x512 (64x64 tiles) 11 : 1024x1024 (128x128 tiles)
Address: 0x4000010 - REG_BG0HOFS Horizontal scroll co-ordinate for BG0 (Write Only)
Address: 0x4000012 - REG_BG0VOFS Vertical scroll co-ordinate for BG0 (Write Only)
Address: 0x4000014 - REG_BG1HOFS Horizontal scroll co-ordinate for BG1 (Write Only)
Address: 0x4000016 - REG_BG1VOFS Vertical scroll co-ordinate for BG1 (Write Only)
Address: 0x4000018 - REG_BG2HOFS Horizontal scroll co-ordinate for BG2 (Write Only)
Address: 0x400001A - REG_BG2VOFS Vertical scroll co-ordinate for BG2 (Write Only)
Address: 0x400001C - REG_BG3HOFS Horizontal scroll co-ordinate for BG3 (Write Only)
Address: 0x400001E - REG_BG3VOFS Vertical scroll co-ordinate for BG3 (Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X S S S S S S S S S S
0-9 (S) = Scroll value (pixels)
These registers are only effective for text
backgrounds; they set the pixel that is displayed in the top left hand corner of the GBA's display. In other
words, a value of -5, -5 puts the upper left hand corner of your background at x=5,y=5. All four BG planes wrap
when they reach their right or bottom edges.
These registers affect the translation, rotation, and scaling of tile-based rotate/scale backgrounds as well as the bitmapped backgrounds (which should be treated as BG2 for this purpose). The function of these registers is very hard to describe in words but easy to see the effects of on screen. I highly recommend checking out Stephen Stair's RSDemo - it lets you see the contents of the regs as you modify them as well as the effect they have on the background. Should also be somewhat useful for figuring out sprite rotation and scaling.
 Individual descriptions follow:
Address: 0x4000020 - REG_BG2PA (BG2 Read Source Pixel X Increment)(Write Only)
Address: 0x4000030 - REG_BG3PA (BG3 Read Source Pixel X Increment) (Write Only)
The effect of these registers is to scale the background (relative to the upper left corner) in the x direction
by an amount equal to 1/(register value).
Address: 0x4000022 - REG_BG2PB (BG2 Write Destination Pixel X Increment) (Write
Only)
Address: 0x4000032 - REG_BG3PB (BG3 Write Destination Pixel X Increment) (Write Only)
The effect of these registers is to shear the x coordinates of the background over y, relative to the upper left
corner. A value of 0 will result in no shearing, a value of 1.00 will make the background appear to be sheared
left as you go down the screen, and a value of -1 will make the background appear sheared right as you go down
the screen.
Address: 0x4000024 - REG_BG2PC (BG2 Read Source Pixel Y Increment) (Write Only)
Address: 0x4000034 - REG_BG3PC (BG3 Read Source Pixel Y Increment) (Write Only)
The effect of these registers is to shear the y coordinates of the background over x, relative to the upper left
corner. A value of 0 will result in no shearing, a value of 1.00 will make the background appear to be sheared
upwards to the right, and a value of -1 will make the background appear sheared downwards and to the right.
Address: 0x4000026 - REG_BG2PD (BG2 Write Destination Pixel Y Increment) (Write
Only)
Address: 0x4000036 - REG_BG3PD (BG3 Write Destination Pixel Y Increment) (Write Only)
The effect of these registers is to scale the background in the y direction (relative to the upper left corner)
by an amount equal to 1/(register value).
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 X X X X S I I I I I I I I I I I I I I I I I I I F F F F F F F F
0-7 (F) - Fraction 8-26 (I) - Integer 27 (S) - Sign bit
These registers define the location of the pixel that appears at 0,0. They are very similar to the background scrolling
registers, REG_HOFS and REG_VOFS,
which become disabled when a rotate/
scale background is in use.
Address: 0x4000040 - REG_WIN0H (Window
0 X Coordinates) (Write Only)
Address: 0x4000042 - REG_WIN1H (Window
1 X Coordinates)(Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0 L L L L L L L L R R R R R R R R
0-7 (R) = X coordinate for the rightmost side of the window 8-F (L) = X coordinate for the leftmost side of the window
Address: 0x4000044 - REG_WIN0V (Window
0 Y Coordinates) (Write Only)
Address: 0x4000046 - REG_WIN1V (Window
1 Y Coordinates)(Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0 T T T T T T T T B B B B B B B B
0-7 (B) = Y coordinate for the bottom of the window 8-F (T) = Y coordinate for the top of the window
Address: 0x4000048 - REG_WININ (Inside Window
Settings)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X T S R Q P O X X L K J I H G
0 (G) = BG0 in win0 1 (H) = BG1 in win0 2 (I) = BG2 in win0 3 (J) = BG3 in win0 4 (K) = Sprites in win0 5 (L) = Blends in win0 8 (O) = BG0 in win1 9 (P) = BG1 in win1 A (Q) = BG2 in win1 B (R) = BG3 in win1 C (S) = Sprites in win1 D (T) = Blends in win1
Address: 0x400004A - REG_WINOUT (Outside Window
and Sprite Window)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X T S R Q P O X X L K J I H G
0 (G) = BG0 outside 1 (H) = BG1 outside 2 (I) = BG2 outside 3 (J) = BG3 outside 4 (K) = Sprites outside 5 (L) = Blends outside 8 (O) = BG0 in sprite win 9 (P) = BG1 in sprite win A (Q) = BG2 in sprite win B (R) = BG3 in sprite win C (S) = Sprites in sprite win D (T) = Blends in sprite win
Address: 0x400004C - REG_MOSAIC (Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0 V V V V U U U U J J J J I I I I
0-3 (I) = BG X Size 4-7 (J) = BG Y Size 8-B (U) = Sprite X Size C-F (V) = Sprite Y Size
Use this register to control the size of the mosaic on backgrounds/sprites that have mosaic enabled..
Address: 0x4000050 - REG_BLDMOD
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X T S R Q P O M M L K J I H G
0 (G) = Blend BG0 (source) 1 (H) = Blend Bg1 (source) 2 (I) = Blend BG2 (source) 3 (J) = Blend BG3 (source) 4 (K) = Blend sprites (source) 5 (L) = Blend backdrop (source) 6-7 (M) = Blend Mode There are four different modes: 00: All effects off 01: alpha blend 10: lighten (fade to white) 11: darken (fade to black)
8 (O) = Blend BG0 (target) 9 (P) = Blend BG1 (target) A (Q) = Blend BG2 (target) B (R) = Blend BG3 (target) C (S) = Blend sprites (target) D (T) = Blend backdrop (target)
Use this register to determine the blending mode and which layer(s) you wish to perform blending on. In the case
of alpha blends (Mode 01), specify the layers that are "on top" using the source flags (bits 0 - 5) and
the layers that are on the bottom using the target flags (bits 8-13). The target layer must be below the source
layer in terms of its priority, or
the blend will not take effect. Other things to note about alpha blends:
- If there is more than one target layer, the blend will only occur for a target with lower priority in areas where it shows through targets of higher priority due to the transparent pixel being set
- Source layers will only blend with areas of a target layer that are visible beneath them. If another layer is blocking the way (even if it is another source layer), there will be no blend and the original source color will be drawn.
- As a result of these two conditions, it is never possible for any given pixel to be a blend of more than 2 layers. This eliminates the possiblity of using these registers to have 3 or more layers of translucent graphics showing through one another.
- A layer cannot blend with itself
- If an obj has semi-transparency enabled, it will blend normally (as if it were specified as a source layer)
- Unfortunately, it is not possible to alpha blend sprites against one another, no matter how your prioritize them. Alpha blended sprites that are "in front of" other sprites will blend with the other target layers while still occluding the sprites behind them (i.e. it will look like the portion of the non-blended sprite that is behind the blended one has disappeared), for a most unnatural effect.
Address: 0x4000052 - REG_COLEV (Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X B B B B B X X X A A A A A
0-4 (A) = Coefficient A, the source pixel (layer above) 8-C (B) = Coefficient B, the target pixel (layer below)
Use this in conjunction with REG_BLDCNT
to determine the amount of blending between layers. An unblended pixel of normal intensity is is considered to
have a coefficient of 16. Coefficient A and Coefficient B determine the ratio of each of the sources that will
get mixed into the final image. Thus, if A is 12 and B is 4, the resulting image will appear to be 12/16 the color
of A and 4/16 the color of B. Note that A and B can add up to be greater than 16 (for an additive or brightening
effect) or less than 16 (for a darkening effect).
Address: 0x4000054 - REG_COLEY (Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X X X X F F F F F
0-4 (F) = The lighten/darken value
This is the amount by which to lighten or darken the source layers (as specified in REG_BLDCNT)
.
The higher the value, the greater the fade. 16 is the peak fade value; values from 16 - 31 shade the layer with
either pure black (for a darken) or pure white (for a lighten).
Note: I've obtained this info (most of it verbatim) from Uze's BeLogic
unofficial GBA sound info site, which gives a much more thorough explanation as well as some sample source code
and demos. Thanks to Uze for providing such a great resource on GBA sound.
Address: 0x04000060 - REG_SOUND1CNT_L (Sound 1 Sweep control) (Unimplemented in CowBite)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X X T T T A S S S 0-2 (S) = Number of sweep shifts. These control the amount of change in frequency (either increase or decrease) at each change. The wave's new period is given by: T=T±T/(2n), where n is the sweep shift's value. 3 (A) = Sweep increase or decrease. When decrementing, if the frequency value gets smaller than zero, the previous value is retained. When incrementing, if the frequency gets greater than the maximum frequency (131Khz or 2048 for the register value) the sound stops. 0 - Addition (frequency increase) 1 - Subtraction (frequency decrease)
4-6 (T) = Sweep Time. This is the delay between sweep shifts. After each delay, the frequency increments or decrements. 000: Disable sweep function 001: Ts=1 / 128khz (7.8 ms) 010: Ts=2 / 128khz (15.6 ms) 011: Ts=3 / 128 khz (23.4 ms) 100: Ts=4 / 128 khz (31.3 ms) 101: Ts=5 / 128 khz (39.1 ms) 110: Ts=6 / 128 khz (46.9 ms) 111: Ts=7 / 128 khz (54.7 ms)
Sound channel 1 produces a square wave with envelope and frequency sweep functions. This register controls the
frequency sweep function. When the sweep function is not required, set the sweep time to zero and set the increase/decrease
bit to 1.
Address: 0x04000062 - REG_SOUND1CNT_H (Sound 1 Length, wave duty and envelope control)(Unimplemented
in CowBite)
W W W W W W F E D C B A 9 8 7 6 5 4 3 2 1 0 I I I I M T T T D D L L L L L L
0-5 (L) = Sound length. This is a 6 bit value obtained from the following formula: Sound length= (64-register value)*(1/256) seconds. After the sound length has been changed, the sound channel must be resetted via bit F of REG_SOUND1CNT_X (when using timed mode). 6-7 (D) = Wave duty cycle. This controls the percentage of the ON state of the square wave. 00 - 12.5% 01 - 25% 10 - 50% 11 - 75%
8-A (T) = Envelope step time. This is the delay between successive envelope increase or decrease. It is given by the following formula: Time=register value*(1/64) seconds. B (M) = Envelope mode. Controls if the envelope is to increase or decrease in volume over time. 0 - Envelope decreases 1 - Envelope increases
C-F (I) = Initial Envelope value. 1111 produces the maximum volume and 0000 mutes the sound. When sound 1 is playing, modifying the volume envelope bits has no effect until the sound is resetted.
 The minimum frequency is 64Hz and the maximum is 131Khz. Can be calculated from the following formula: F(hz)=4194304/(32*(2048-register value)). E (T) = Timed sound. When set to 0, sound 1 is played continuously regardless of the length data in REG_SOUND1CNT_H. When set to 1, sound is played for that specified length and after that, bit 0 of REG_SOUNDCNT_X is reset. F (R) = Sound reset. When set, sound resets and restarts at the specified frequency. When sound 1 is playing, modifying the volume envelope bits has no effect until the sound is resetted. Frequency and sound reset must be perfomed in a single write since both are write only. Frequency can always be changed without resetting the sound channel.
Address: 0x04000068 - REG_SOUND2CNT_L (Sound 2 Length, wave duty and envelope control)(Unimplemented
in CowBite)
W W W W W W F E D C B A 9 8 7 6 5 4 3 2 1 0 I I I I M T T T D D L L L L L L
0-5 (L) = Sound length. This is a 6 bit value obtained from the following formula: Sound length= (64-register value)*(1/256) seconds. After the sound length has been changed, the sound channel must be resetted via bit F of REG_SOUND1CNT_X (when using timed mode). 6-7 (D) = Wave duty cycle. This controls the percentage of the ON state of the square wave. 00 - 12.5% 01 - 25% 10 - 50% 11 - 75%
8-A (T) = Envelope step time. This is the delay between successive envelope increase or decrease. It is given by the following formula: Time=register value*(1/64) seconds. B (M) = Envelope mode. Controls if the envelope is to increase or decrease in volume over time. 0 - Envelope decreases 1 - Envelope increases
C-F (I) = Initial Envelope value. 1111 produces the maximum volume and 0000 mutes the sound. When sound 2 is playing, modifying the volume envelope bits has no effect until the sound is resetted.
 The minimum frequency is 64Hz and the maximum is 131Khz. Can be calculated from the following formula: F(hz)=4194304/(32*(2048-register value)). E (T) = Timed sound. When set to 0, sound 2 is played continuously regardless of the length data in REG_SOUND2CNT_L. When set to 1, sound is played for that specified length and after that, bit 1 of REG_SOUNDCNT_X is reset. F (R) = Sound reset. When set, sound resets and restarts at the specified frequency. When sound 2 is playing, modifying the volume envelope bits has no effect until the sound is resetted. Frequency and sound reset must be perfomed in a single write since both are write only. Frequency can always be changed without resetting the sound channel.
Address: 0x04000070 - REG_SOUND3CNT_L (Sound 3 Enable and wave ram bank control)(Unimplemented
in CowBite)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X N S M X X X X X
5 (M) = Bank Mode (0 - 2 32 sample banks, 1 - 1 64 sample bank) 6 (S) = Bank Select. Controls which bank is active for playing/reloading. If set to 0, samples are played from bank 0 and writing to the Wave Ram will store the data in Bank 1, and vice-versa. 7 (N) = Sound Channel 3 output enable. When this is set and bit 15 from REG_SOUND3CNT_X is set, the sound starts to play.
Sound channel 3 is a circuit that can produce an arbitrary wave pattern. Samples are 4 bit, 8 samples per word,
and are located in Wave Ram registers
from 0x400090 to 0x40009F. The Wave Ram is banked, providing the ability to play a 64 samples pattern or to select
between two 32 samples patterns (Bit 5). Sound channel 3 always produces some audio artifacts (distortion) when
sound is initialized. Fortunately, switching banks does not require re-initialisation during playback, thus allowing
for dynamic reloading of the Wave Ram without generating any distortion.
Both banks of Wave Ram are filled with zero upon initialization of the Gameboy, Bank 0 being selected. So writing
to bank 0 implies setting bit 6 to 1 before loading Wave Ram then set it back to 0 to play it.
Address: 0x04000072 - REG_SOUND3CNT_H (Sound 3 Sound length and output level control)(Unimplemented
in CowBite)
W W W W W W W W F E D C B A 9 8 7 6 5 4 3 2 1 0 R R R X X X X X L L L L L L L L
0-7 (L) = Sound length. The sound length is an 8 bit value obtained from the following formula: Register=Note length (in seconds)*256 Hence a 1 second maximum and a 3.9 millisecond minimum sound duration.  The minimum frequency is 64Hz and the maximum is 131Khz. Can be calculated from the following formula: F(hz)=4194304/(32*(2048-register value)). E (T) = Timed sound. When set to 0, sound 3 is played continuously regardless of the length data in REG_SOUND3CNT_H. When set to 1, sound is played for that specified length and after that, bit 2 of REG_SOUNDCNT_X is reset. F (R) = Sound reset. When set, sound resets and restarts at the specified frequency. Frequency and sound reset must be perfomed in a single write since both are write only. In continuous mode, frequency can be changed without resetting the sound channel.
Address: 0x04000078 - REG_SOUND4CNT_L (Sound 4 Length, output level and envelope
control)(Unimplemented in CowBite)
W W W W W W F E D C B A 9 8 7 6 5 4 3 2 1 0 I I I I M T T T X X L L L L L L
0-5 (L) = Sound length. This is a 6 bit value obtained from the following formula: Sound length= (64-register value)*(1/256) seconds. After the sound length has been changed, the sound channel must be resetted via bit F of REG_SOUND4CNT_H (when using timed mode). 8-A (T) = Envelope step time. This is the delay between successive envelope increase or decrease. It is given by the following formula: Time=register value*(1/64) seconds. B (M) = Envelope mode. Controls if the envelope is to increase or decrease in volume over time. 0 - Envelope decreases 1 - Envelope increases
D-F (I) = Initial Envelope value. 1111 produces the maximum volume and 0000 mutes the sound.
Address: 0x0400007C - REG_SOUND4CNT_H (Sound 4 Noise parameters, reset and loop control)(Unimplemented
in CowBite)
W F E D C B A 9 8 7 6 5 4 3 2 1 0 R T X X X X X X P P P P S C C C
0-2 (C) = Clock divider frequency. This divides the CPU frequency. Its output is then fed into the counter's pre-scaler (controlled by bits 4-7) which further devides the frequency. 000: f*2 f=4.194304 Mhz/8 001: f 010: f/2 011: f/3 100: f/4 101: f/5 110: f/6 111: f/7
3 (S) = Counter stages: 0=15 stages, 1=7 stages. This controls the period of the polynomial counter. It is given by (2^n)-1 where n is the number of stages. So for n=7, the pseudo-noise period lasts 63 input clocks. After that, the counter restarts the same count sequence. 4-7 (P) = Counter Pre-Stepper frequency: 0000: Q/2 0001: Q/2^2 0010: Q/2^3 0011: Q/2^4 .... 1101: Q/2^14 1110: Not used 1111: Not used Where Q is the clock divider's output frequency
E (T) = Timed sound. When set to 0, sound 4 is played continuously regardless of the length data in REG_SOUND4CNT_L. When set to 1, sound is played for that specified length and after that, bit 3 of REG_SOUNDCNT_X is reset. F (R) = Sound reset. When bit F is set to 1, Envelope is set to initial value, the LFSR count sequence is resetted and the sound restarts. In continuous mode, all parameters can be changed but the sound needs to be resetted when modifying the envelope initial volume or the clock divider for changes to take effects.
Channel 4 produces pseudo-noise generated by a polynomial counter. It is based on a 7/15 stages linear-feedback
shift register (LFSR). LFSR counts in a pseudo-random order where each state is generated once and only once during
the whole count sequence. The sound is produced by the least significant bit's output stage.
Address: 0x04000080 - REG_SOUNDCNT_L (Sound 1-4 Output level and Stereo control)(Unimplemented
in CowBite)
? F E D C B A 9 8 7 6 5 4 3 2 1 0 R Q P O N M L K J I I I H G G G
0-2 (G) = DMG Left Volume 3 (H) = Vin Left on/off (?) - According to BeLogic, Vin on/off allowed the original GameBoy paks to provide their own sound source. It is unkown whether they still work on a GBA. 4-6 (I) = DMG Right Volume 7 (J) = Vin Right on/off (?) 8 (K) = DMG Sound 1 to left output 9 (L) = DMG Sound 2 to left output A (M) = DMG Sound 3 to left output B (N) = DMG Sound 4 to left output C (O) = DMG Sound 1 to right output D (P) = DMG Sound 2 to right output E (Q) = DMG Sound 3 to right output F (R) = DMG Sound 4 to right output
This register controls only the DMG output amplifiers and have no effects on the individual sound channels' processing,
or Direct Sound channels' volume.
Address: 0x04000082 - REG_SOUNDCNT_H (Direct Sound control and Sound 1-4 output ratio)(Implemented
in CowBite)
W W F E D C B A 9 8 7 6 5 4 3 2 1 0 Q P O N M L K J X X X X I H G G
0-1 (G) = Output Sound Ratio for channels 1-4. 00 - 25% 01 - 50% 10 - 100% 11 - ?? 2 (H) = Direct sound A output ratio (0 - 50%, 1 - 100%) 3 (I) = Direct sound B output ratio (0 - 50%, 1 - 100%) 8 (J) = Direct Sound A to right output 9 (K) = Direct sound A to left output A (L) = Direct sound A Sampling rate timer (timer 0 or 1). Use this to set which timer contorls the playback frequency. B (M) = Direct sound A FIFO reset C (N) = Direct sound B to right output D (O) = Direct sound B to left output E (P) = Direct sound B Sampling rate timer (timer 0 or 1). Use this to set which timer controls the playback frequency. F (Q) = Direct sound B FIFO reset
This register is used in controlling Direct Sound on the GBA. Output ratios control the volume, in percentage,
that gets output to the speakers.
Address: 0x04000084 - REG_SOUNDCNT_X (Master sound enable and Sound 1-4 play status)(Partially
Implemented in CowBite)
R R R R F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X N X X X J I H G
0 (G) = DMG Sound 1 Status (Read only). 0 - Stopped, 1 - Playing 1 (H) = DMG Sound 2 Status (Read only). 0 - Stopped, 1 - Playing 2 (I) = DMG Sound 3 Status (Read only). 0 - Stopped, 1 - Playing 3 (J) = DMG Sound 4 Status (Read only). 0 - Stopped, 1 - Playing 7 (N) = All Sound circuit enable
This register is used to monitor the play status of sounds and to turn on or off all sound circuits. Turning the
sound circuits off saves battery power, allowing them to last up to 10% longer.
Address: 0x04000088 - REG_SOUNDBIAS (Sound bias and Amplitude resolution control)(Unimplemented
in CowBite)
F E D C B A 9 8 7 6 5 4 3 2 1 0 R R X X X X B B B B B B B B B X
1-9 (B) = PWM bias value, controlled by the BIOS. E-F (R) = Amplitude resolutions 00 - 9 bit at 32768 hz 01 - 8 bit at 65536 hz 10 - 7 bit at 131072 hz 11 - 6 bit at 262144 hz
The BIAS setting is used to offset the sound output and bring it back into a signed range. When the BIOS starts
up, it runs a timing loop where it slowly raises the BIAS voltage from 0 to 512. This setting should not be changed.
At best, the sound will become distorted. At worst the amplifier inside the GBA could be damaged.
When accessing bits F-E, a read-modify-write is required. The default value for bits F-E is 00. Most if not all
games use 01 for this setting.
Address: 0x04000090 - REG_WAVE_RAM0_L (Sound 3 samples 0-3)
Address: 0x04000092 - REG_WAVE_RAM0_H (Sound 3 samples 4-7)
Address: 0x04000094 - REG_WAVE_RAM1_L (Sound 3 samples 8-11)
Address: 0x04000096 - REG_WAVE_RAM1_H (Sound 3 samples 12-15)
Address: 0x04000098 - REG_WAVE_RAM2_L (Sound 3 samples 16-19)
Address: 0x0400009A - REG_WAVE_RAM2_H (Sound 3 samples 20-23)
Address: 0x0400009C - REG_WAVE_RAM3_L (Sound 3 samples 23-27)
Address: 0x0400009E - REG_WAVE_RAM3_H (Sound 3 samples 28-31)
These registers together contain four (4 bytes each) 4-bit wave RAM samples for Sound channel 3.
Address: 0x040000A0 - REG_FIFO_A_L (Direct Sound channel A samples 0-1)(Write Only)
Address: 0x040000A2 - REG_FIFO_A_H (Direct Sound channel A samples 2-3)(Write Only)
Address: 0x040000A4 - REG_FIFO_B_L (Direct Sound channel B samples 0-1)(Write Only)
Address: 0x040000A6 - REG_FIFO_B_H (Direct Sound channel B samples 2-3)(Write Only)
These are the locations of the Direct Sound 8-bit FIFO samples, from which Direct Sound pulls the music data to
be played on the speakers. Note that there are only 8 bytes total for all your samples. You repeatedly fill these
from a buffer of your own using DMA0
or DMA1, or by using timer interrupts.
To fill them using DMA, first set Timer
0 or Timer 1 to refresh at
the appropriate sample rate (for example, 16khz). Next, set the DMA
source address to a sound sample in memory, and the destination
address to one of these FIFO registers. Use REG_SOUNTCNT_H
to reset FIFO and tell Direct Sound to get its sampling rate from Timer 0 or Timer 1. Finally, set the DMA
control register to start on FIFO empty (start mode 11) and to repeat, then enable the timers. All of this
will cause the hardware to play sound samples in FIFO at the rate specified in your timer, and automatically refill
them using DMA.
To fill these using interrupts,
follow a similar process, but instead of using DMA, set the clock to interrupt on overflow. When using interrupts
instead of DMA, BeLogic recommends setting the timer
divider to 1024 and start the timer at 0xFFFF order to get a sampling rate of 16.384 khz. This apparently causes
less distortion than if you simply set the start time of the clock to 0xFFFF - (2^24/16000).
Note that reading from these registers can yield unpredictable results. It might be interesting to see just how
unpredictable...
 Note that it is 27-bit.
 Note that it is 28-bit.
 Note that it is 27-bit.
 Note that it is 28-bit.
Address: 0x40000B8 - REG_DMA0CNT_L (DMA0 Count Register)
Address: 0x40000C4 - REG_DMA1CNT_L (DMA1 Count Register)
Address: 0x40000D0 - REG_DMA2CNT_L (DMA2 Count Register)
Address: 0x40000DC - REG_DMA3CNT_L (DMA3 Count Register)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X L L L L L L L L L L L L L L
0-D (L) = Number of words or halfwords to copy
(Note: In some places you will see the DMA
control and DMA count registers depicted as a single 32-bit register called REG_DMAXCNT. I opted to treat them
as two 16-bit registers for sake of clarity.)
Address: 0x40000BA - REG_DMA0CNT_H (DMA0 Control Register)
Address: 0x40000C6 -REG_DMA1CNT_H (DMA1 Control Register)
Address: 0x40000D2 - REG_DMA2CNT_H (DMA2 Control Register)
Address: 0x40000DE - REG_DMA3CNT_H (DMA3 Control Register)
? F E D C B A 9 8 7 6 5 4 3 2 1 0 N I M M U S R A A B B X X X X X
(Note: In some places you will see the DMA control and DMA count registers depicted as a single 32-bit register called REG_DMAXCNT. I opted to treat them as two 16-bit registers for sake of clarity.) 5-6 (B) = Type of increment applied to destination address. If enabled, the address will be incremented/decremented by 2 or 4 bytes, depending on the selected size. When the DMA is activated, the contents of these registers are copied to internal counters in the DMA hardware, which then increments/decrements these registers during transfer, preserving the contents of the IORAM registers.* 00: Increment after each copy 01: Decrement after each copy 10: Leave unchanged 11: Increment without after each copy, reset to initial value at the end of transfer (or at the end of the current repetition) 7-8 (A) = Type of increment applied to source address: 00: Increment after each copy 01: Decrement after each copy 10: Leave unchanged 11: Illegal Note: I am somewhat uncertain about option "11" for both of these. Can anyone confirm? 9 (R) = Repeat. When in start modes 1 or 2, this bit causes the transfer to repeat for each interval. A (S) = Size. If set, copy 32-bit quantities (words) If clear, copy 16-bit quantities (half words) B (U) = Unknown. For DMA 0, 1, and 2, this bit is read only and set to 0. However, for DMA 3, it appears to be writeable. Thoughts, anyone? C-D (M) = Start Mode. 00: Transfer immediately 01: Transfer on vblank (i.e. vdma) 10: Transfer on hblank (i.e. hdma. Note that, unlike h-interrupts, hdma does NOT occur during vblank.) 11: The function of this varies based on the DMA channel. For DMA 1 or 2: Instructs the DMA to repeat on FIFO-empty requests. When this is set the size and count are ignored and a single 32 bit quantity is transferred on FIFO empty. For DMA 3: Apparently allows transfers to start at the beginning of a rendering line, copying data into a buffer as the line is being drawn on the screen. Useful for flicker-free transfers in mode 3, which has no backbuffer. E (I) = IRQ. Setting this bit causes the DMA to generate an interrupt when it is done with the data transfer. F (N) = Set this bit to enable DMA operation. Clear to end DMA operation.
This address controls a DMA transfer which allows large amounts of data to be transferred from one area of memory
to another. It is theoretically twice as fast as transfering by the CPU, which uses at least one cycle for a read
instruction and another for a write. DMA can also be used to clear memory to a constant value, if the source address
is not incremented with each copy. Fist, set the DMASAD
and DMADAD registers
to point to the addresses you want. Writing to DMACNT_H address with a '1' in the N field and a '00' in the M field
will start the transfer immediately.
DMA transfers may occur on an interrupt if the start mode bits are set for this. DMAs have a priority ranking with
3 at the lowest and 0 at the highest. For most cases, program code will be using DMA3 as it is lowest priority,
allowing it to be interrupted by more important DMA (see below).
Specific DMAs have the following properties:
DMA0: This DMA is the highester priority, but cannot be used to access cartridge memory
(addresses 0x8000000 and higher). It is suitable for time-critical operations such as transfering scale and rotate
data to the background scaling registers. Since it takes precedence over other DMAs, it will not be postponed or
interrupted (possibly causing undesirable results such as screen artifacts).
DMA1 and DMA2: These are the only DMA that can be used for
sound FIFO. If start mode "11" is set, the DMA will be triggered on FIFO empty. I believe that FIFO A
always sends its empty requests to DMA1 and that FIFO B sends its empty requests only to DMA2, though I don't have
any verification of this.
DMA3: This is is the lowest priority and thus often used as a "general purpose"
DMA. Using this DMA for your basic memory transfers ensures that sound FIFO DMA and other time-critical DMA are
not delayed, making audio or visual artifacts less likely.
* (Originally I had assumed a direct mapping between the source/destination registers and
the current transfer address, and thus this section of the doc distinguished between transfers which wrote-back
to the registers and those which did not. This appears to have been an incorrect assumption, and was brought to
light as I delved further into sound emulation)
The following table lists the cycle timings for various DMA transfers. The format of each entry is :
16 bit DMA / 32 bit DMA
Units are in cycles per item transfered. Thus, a rating of 4/8 indicates that the transfer takes 4 cycles for every 16 bits transferred with 16 bit DMA, or 8 cycles for every 32 bits transfered with 32 bit DMA.
Source Destination EWRAM IWRAM IO PAL RAM VRAM OAM ROM 0 WS 4/8 2/3 2/3 2/4 2/4 2/3 ROM 1 WS 5/10 3/5 3/5 3/6 3/6 3/5 ROM 2 WS 6/12 4/7 4/7 4/8 4/8 4/7 EWRAM 6/12 4/7 4/7 4/8 4/8 4/7 IWRAM 4/7 2/2 2/2 2/3 2/3 2/2 I/O 4/7 2/2 2/2 2/3 2/3 2/2 PAL RAM 4/8 2/2 2/3 2/4 2/4 2/2 VRAM 4/8 2/3 2/3 2/4 2/4 2/2 OAM 4/7 2/2 2/2 2/3 2/3 2/2
Note that it is not possible to DMA transfer from or to SRAM (Cart RAM) or BIOS, and (obviously) it is not possible
to transfer to ROM.
Thanks to Kay for supplying these transfer statistics!!

Note that these registers are R/W. The default is to start counting from 0x0000, but if a value is written to this
register, the timer will henceforth use that as a starting value. Thus the rate at which timers overflow and generate
interrupts (see REG_TMXCNT,
below) can be customized.
Timer 0 and Timer 1 are used to control the rate of Direct Sound FIFO. When using DMA
with start mode 11, they can automatically cause it to refill the FIFO. To set the rate of playback in hz, write
the value 0xFFFF - (2^24/Plaback Freq in hz) to the register. This sets the start value such that the timer will
overflow precisely when the next sound sample is needed, and cause the DMA to activate. When using interrupts,
set the start value of these to 0, but use REG_TMXCNT
to change the update frequency to 1024, thus causing an interrupt rate of 16.384khz.
Address: 0x4000102 - REG_TM0CNT (Timer 0 Control)
Address: 0x4000106 - REG_TM1CNT (Timer 1 Control)
Address: 0x400010A - REG_TM2CNT (Timer 2 Control)
Address: 0x400010E - REG_TM3CNT (Timer 3 Control)
* F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X E I X X X C F F
0-1 (F) = Frequency at which the timer updates. 00: Default frequency (full) - 16.78MHz (~17mlns ticks per second) 01: Every 64 clock pulses - ~262187.5KHz 10: Every 256 clock pulses - ~65546.875KHz 11: Every 1024 clock pulses - ~16386.71875KHz 2 (C) = Cascade (* Unused on TM0) - When this bit is set, the frequency of this timer is ignored. Instead the timer increments when the timer below it overflows. For example, if timer 1 is set to cascade, it will increment whenever timer 0's value goes from 0xFFFF to 0x0000. 6 (I) = Generate an interrupt on overflow 7 (E) = Enable the timer.
Using the link port and a link cable, the GBA can transmit serial data in one of five modes: Normal, Multilink,
JOY BUS, General-Purpose, and UART. The function of the serial communication registers changes significantly depending
on the mode. Thus each of these registers comes has several different discriptions associated with it, listed under
the associated mode.
Note: The serial comm information originates primarily from Martin Korth's no$gba
documentation, which is the most thorough explanation of GBA serial comm that I've read anywhere.
For 32-bit normal mode only. Contains 32-bit data. Outgoing data should be written to this register before starting the transfer. During transfer, transmitted bits are shifted-out (MSB first), and received bits are shifted-in simultaneously. Upon transfer completion, the register contains the received 32-bit value.

- SCD0 contains the data sent by the master (also called slave 0)
- SCD1 contains the data sent by the first slave (slave1)
- SCD2 contains the data sent by the second slave (slave2)
- SCD3 contains the data sent by the last slave (slave3)
These registers are automatically reset ot 0xFFFF on transfer start. After transfer, they contain the incoming
data from all linked GBAs (including data from the local machine).
Address: 0x4000128 - REG_SCCNT_L (Serial Communication channel control register)
Normal Mode
Multiplayer Mode
UART Mode
Normal Mode
R F E D C B A 9 8 7 6 5 4 3 2 1 0 X I M M X X X X S X X X N L C B
0 (B) = Shift Clock (SC) (0 - External, 1 - Internal) 1 (C) = Internal Shift Clock (0 - 256khz, 1 - 2 MHz) 2 (L) = SI State (opponents SO) (0 - Low, 1 - High/None) 3 (N) = SO during inactivity (0 - Low, 1 - High) 7 (S) = Start/Busy bit (0 - inactive/ready, 1 - start/active) C-D (M) = Comm Mode [8bit=00,32bit=01,Multiplayer=10,UART=11] E (I) = Interrupt on completion
The following is from Martin Korth's no$gba docs:
Recommended Communication Procedure for SLAVE unit (external clock)
- Initialize data which is to be sent to master (placed in REG_SCCNT_H
for 8-bit mode or REG_SCD0 for 32-bit
mode)
- Set Start bit (bit 7)
- Set SO to LOW to indicate that master may start now.
- Wait for IRQ (or for Start bit to become zero). (Check timeout here!)
- Set SO to HIGH to indicate that we are not ready.
- Process received data (received in REG_SCCNT_H
for 8-bit mode or REG_SCD0 for 32-bit
mode)
Recommended Communication Procedure for MASTER unit (internal clock)
- Initialize data which is to be sent to slave (placed in REG_SCCNT_H
for 8-bit mode or REG_SCD0 for 32-bit
mode)
- Wait for SI to become LOW (slave ready). (Check timeout here!)
- Set Start flag.
- Wait for IRQ (or for Start bit to become zero).
- Process received data (received in REG_SCCNT_H
for 8-bit mode or REG_SCD0 for 32-bit
mode)
Martin also notes that that when more than two GBAs are connected, data is rotated from the first to the last GBA
rather than just being swapped between the first and second in the chain. For a more detailed description, see
the help files included in no$gba.
Multi-Player Mode
* R R R R R F E D C B A 9 8 7 6 5 4 3 2 1 0 X I M M X X X X S E D D N L B B
0-1 (B) = Baud rate [00=9600,01=38400,10=57600,11=115200] 2 (L) = SI-Terminal (0 - Parent, 1- Child) 3 (N) = SD-Terminal (0 - Bad connection, 1 - All GBAs Ready) 4-5 (D) = ID of GBA [00=master,01=slave1,10=slave2,11=slave3] 6 (E) = Error (1 on error) 7 (S) = Start/Busy bit (1 triggers the start on the master, signifies busy on slaves) * Read only on slaves C-D (M) = Comm Mode [8bit=00,32bit=01,Multiplayer=10,UART=11] E (I) = Interrupt on completion
To transfer data in this mode, you must coordinate the actions of all the GBAs which are linked together. First
set the mode bits in REG_RCNT and in
this register. Each GBA slave must place the data they wish transfered in REG_SCCNT_H.
Then the Master/Slave 0 initiates the transfer by setting bit 7 of REG_SCCNT_L. This causes the hardware to transfer
the data. It will magically appear in the destination registers of each slave, according to the following:
REG_SCCNT_H from GBA with id 00
goes into REG_SCD0 on each GBA
REG_SCCNT_H from GBA with id 01
goes into REG_SCD1 on each GBA
REG_SCCNT_H from GBA with id 10
goes into REG_SCD2 on each GBA
REG_SCCNT_H from GBA with id 11
goes into REG_SCD3 on each GBA
Thus each GBA in the chain has a duplicate of the data.
ePAc has commented that the master is the GBA in the set that has the purple connector connected to its ext port.
So if you have a GBA that want to be a MBserver for a set of clients, then you need to put the cart in the one
with the purple connector. It is unclear to me how the other GBAs know what ID they are; perhaps this is also set
according to the link cable connector?
UART Mode
R R R F E D C B A 9 8 7 6 5 4 3 2 1 0 X I M M U T A F S E R S P C B B
0-1 (B) = Baud rate [00=9600,01=38400,10=57600,11=115200] 2 (C) = CTS Flag (0 - Send always, 1- Send only when SC = LOW) 3 (P) = Parity Control (0 - Even, 1 - Odd) 4 (S) = Send Data Flag (0 - Not full, 1 - Full) 5 (R) = Receive Data Flag (0 - Not empty, 1 - Empty) 6 (E) = Error (1 on error) 7 (L) = Data Length (0 - 7 bits, 1 - 8 bits) 8 (F) = FIFO Enable Flag 9 (A) = Parity Enable Flag 10 (T) = Send Enable Flag 11 (U) = Receieve Enable Flag C-D (M) = Comm Mode [8bit=00,32bit=01,Multiplayer=10,UART=11] E (I) = Interrupt (0 - Disable, 1 - IRQ when bits 4,5, or 6 become set)
To send data in UART mode:
The receiver outputs SD=LOW (which is input as SC=LOW at the remote side) when it is ready to receive data (that
is, when Receive Enable is set, and the Receive shift register (or receive FIFO) isn't full.
When CTS flag is set to always/blindly, then the sender transmits data immediately when Send Enable is set, otherwise
data is transmitted only when Send Enable is set and SC is LOW.
The error flag is set when a bad stop bit has been received (stop bit must be 0), when a parity error has occured
(if enabled), or when new data has been completely received while the receive data register (or receive FIFO) is
already full.
The error flag is automatically reset when reading from this register.
Init & Initback
The content of the FIFO is reset when FIFO is disabled in UART mode, thus, when entering UART mode initially set
FIFO=disabled.
The Send/Receive enable bits must be reset before switching from UART mode into another SIO mode!
JOY BUS and General-Purpose
This register is not used in these modes.
Address: 0x400012A - REG_SCCNT_H (Serial Communication Source Register)
As with the other serial registers, this info comes from the no$gba documentation.
Normal
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X S S S S S S S S
0-7 (S) = The 8-bit data to sent/received over the link cable.
For 8-bit normal mode only. Contains 8-bit data (only the lower 8bit are used). Outgoing data should be written
to this register before starting the transfer. During transfer, transmitted bits are shifted-out (MSB first), and
received bits are shifted-in simultaneously. Upon transfer completion, the register contains the received 8-bit
value.
Multiplayer
F E D C B A 9 8 7 6 5 4 3 2 1 0 S S S S S S S S S S S S S S S S
0-F (S) = The 16-bit data to be sent over the link cable.
UART
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X S S S S S S S S
0-7 (S) = The 8-bit data to sent/received over the link cable.
This is the send/receive shift register, or (when FIFO is used) the send/receive FIFO. The send/receive FIFO may store up to four 8-bit data units each. For example, while 1 unit is still being transferred from the send shift register, it is possible to deposit another 4 units in the send FIFO, which are then automatically moved to the send shift register one after each other.
Address: 0x4000130 - REG_KEY (The input register)(Read Only)
R R R R R R R R R R F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X J I D U L R S E B A
0 (A) = A button 1 (B) = B button 2 (E) = Select button 3 (S) = Start button 4 (R) = D-pad Right 5 (L) = D-pad Left 6 (U) = D-pad Up 7 (D) = D-pad Down 8 (I) = Right shoulder button 9 (J) = Left shoulder button
This register stores the state of the GBA's buttons. Each of the inputs is active low. This means that a '0' bit
indicates that the key is pressed, while a '1' bit indicates that the key is not pressed. In general a game which
samples these (rather than using interrupts) should do so at least once every refresh (60hz), or more in the case
of fast action fighting games (like Street Fighter).
Address: 0x4000132 - REG_P1CNT (Key Control Register - As yet unimplemented in CowBite)
F E D C B A 9 8 7 6 5 4 3 2 1 0 T K X X X X J I D U L R S E B A
0 (A) = A button 1 (B) = B button 2 (E) = Select button 3 (S) = Start button 4 (R) = D-pad Right 5 (L) = D-pad Left 6 (U) = D-pad Up 7 (D) = D-pad Down 8 (I) = Right shoulder button 9 (J) = Left shoulder button E (K) = generate interrupt on keypress F (T) = interrupt "type" 0: "OR" operation -- interrupt will be generated if _any_ of specified keys (bits 0-9) is pressed 1: "AND" operation, interrupt will be generated if _all_ specified keys are pressed at the same time.
Use this register to set which keypresses generate interrupts. The appropriate bits must also be set in REG_IE and REG_IME.
* * * * * * * * * F E D C B A 9 8 7 6 5 4 3 2 1 0 M M X X X X X I Q P O N M L K J 0 (J) = SC Data Bit (* GP Mode) 1 (K) = SD Data Bit (* GP Mode) 2 (L) = SI Data Bit (* GP Mode) 3 (M) = SO Data Bit (* GP Mode) 4 (N) = SC Direction (0 - Input, 1 - Output) (* GP Mode) 5 (O) = SD Direction (0 - Input, 1 - Output) (* GP Mode) 6 (P) = SI Direction (0 - Input, 1 - Output) (* GP Mode) 7 (Q) = SO Direction (0 - Input, 1 - Output) (* GP Mode) 8 (I) = Interrupt request enable. (* GP Mode) Interrupts can be requested when SI changes from HIGH to LOW, as General Purpose mode does not require a serial shift clock, this interrupt may be produced even when the GBA is in Stop (low power standby) state. E-F (M) = Mode selection 0 X - Normal, Multiplayer, UART modes 1 0 - General-Purpose Mode 1 1 - JOY BUS Mode * General Purpose Mode Only
Thanks to Martin Korth for all the details about this register, found in his no$gba
documentation.
The function of this register varies depending on the desired transfer mode. The mode bits should be initialized
before REG_SCCNT_L. In all modes
but General-Purpose mode, bits 0 - D go unused. In General-Purpose mode, this register serves as a 4bit bi-directional
parallel port, directly controlling the individual SI,SO,SC, and SD pins. Each can be separately declared as input
(with internal pull-up) or as output signal.
F E D C B A 9 8 7 6 5 4 3 2 1 0 M M X X X X X I X X X X X S C R 0 (R) = Device Reset Flag (Command 0xFF) 1 (C) = Receive Complete Flag (Command 0x14 or 0x15?) 2 (S) = Send Complete Flag (Command 0x14 or 0x15?) 8 (I) = IRQ when receive a Device Reset Command.
Thanks to Martin Korth for all the details about this register, found in his no$gba
documentation.
Bits 0 - 1 of this register work similarly to the bits in REG_IF;
write a "1" to them to reset them and "acknowledge" that the incoming data was processed.
Address: 0x4000150 - REG_JOYRE_L
Address: 0x4000152 - REG_JOYRE_H
Address: 0x4000154 - REG_JOYTR_L
Address: 0x4000156 - REG_JOYTR_H
These registers are used to send and recieve data in JOY BUS mode.
F E D C B A 9 8 7 6 5 4 3 2 1 0 M M X X X X X X X X G G S X R X 1 (R) = Receive Status Flag (0 - Remove GBA is/was recieving) 3 (S) = Send Status Flag (1 - Remot GBA is/was sending) 4-5 (G) = General use flag. Not assigned for any specific purpose.
Thanks to Martin Korth for all the details about this register, found in his no$gba
documentation.
Bit 1 of this register is automatically set when writing to REG_JOYTR,
and bit 3 is automatically reset when reading from REG_JOYRE.
Possible commands received in JOY BUS mode (not possible to issue commands):
Command FFh - Device Reset Receive FFh (Command) Send 00h (GBA Type number LSB (or MSB?)) Send 04h (GBA Type number MSB (or LSB?)) Send XXh (lower 8bits of SIOSTAT register) Command 00h - Type/Status Data Request Receive 00h (Command) Send 00h (GBA Type number LSB (or MSB?)) Send 04h (GBA Type number MSB (or LSB?)) Send XXh (lower 8bits of SIOSTAT register) |
Command 15h - GBA Data Write (to GBA) Receive 15h (Command) Receive XXh (Lower 8bits of JOY_RECV_L) Receive XXh (Upper 8bits of JOY_RECV_L) Receive XXh (Lower 8bits of JOY_RECV_H) Receive XXh (Upper 8bits of JOY_RECV_H) Send XXh (lower 8bits of SIOSTAT register) Command 14h - GBA Data Read (from GBA) Receive 14h (Command) Send XXh (Lower 8bits of JOY_TRANS_L) Send XXh (Upper 8bits of JOY_TRANS_L) Send XXh (Lower 8bits of JOY_TRANS_H) Send XXh (Upper 8bits of JOY_TRANS_H) Send XXh (lower 8bits of SIOSTAT register) |
Address: 0x4000200 - REG_IE (Interrupt Enable Register)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X T Y G F E D S L K J I C H V
0 (V) = VBlank Interrupt 1 (H) = HBlank Interrupt 2 (C) = VCount Interrupt 3 (I) = Timer 0 Interrupt 4 (J) = Timer 1 Interrupt 5 (K) = Timer 2 Interrupt 6 (L) = Timer 3 Interrupt 7 (S) = Serial Communication Interrupt 8 (D) = DMA0 Interrupt 9 (E) = DMA1 Interrupt A (F) = DMA2 Interrupt B (G) = DMA3 Interrupt C (Y) = Key Interrupt D (T) = Cassette Interrupt
Use this register to mask out which interrupts are enabled or disabled.
Address: 0x4000202 - REG_IF (Interrupt Flags Regster)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X T Y G F E D S L K J I C H V
0 (V) = VBlank Interrupt 1 (H) = HBlank Interrupt 2 (C) = VCount Interrupt 3 (I) = Timer 0 Interrupt 4 (J) = Timer 1 Interrupt 5 (K) = Timer 2 Interrupt 6 (L) = Timer 3 Interrupt 7 (S) = Serial Communication Interrupt 8 (D) = DMA0 Interrupt 9 (E) = DMA1 Interrupt A (F) = DMA2 Interrupt B (G) = DMA3 Interrupt C (Y) = Key Interrupt D (T) = Cassette Interrupt
This register will determine which interrupt is currently being serviced. When your interrupt service routine
get scalled, check these flags to determine what called it. In order to keep yourself from servicing the wrong
interrupt at a later time, you should reset the flags to 0 by writing a 1 to them.
Address: 0x4000204 - REG_WSCNT (Wait State Control)
R F E D C B A 9 8 7 6 5 4 3 2 1 0 G P X C C N M M L K K J I I S S
0-1 (S) = SRAM wait state 00: 4 cycles 01: 3 cycles 10: 2 cycles 11: 8 cycles 2-3 (I) = Bank 0x08000000 initial wait state 00: 4 cycles 01: 3 cycles 10: 2 cycles 11: 8 cycles 4 (J) = Bank 0x08000000 subsequent wait state 0: _2_ cycles 1: 1 cycle 5-6 (K) = Bank 0x0A000000 initial wait state 00: 4 cycles 01: 3 cycles 10: 2 cycles 11: 8 cycles 7 (L) = Bank 0x0A000000 subsequent wait state 0: _4_ cycles 1: 1 cycle 8-9 (M) = Bank 0x0C000000 initial wait state 00: 4 cycles 01: 3 cycles 10: 2 cycles 11: 8 cycles A (N) = Bank 0x0C000000 subsequent wait state 0: _8_ cycles 1: 1 cycle B-C (C) = Cart clock. Don't touch. 00: Terminal output clock fixed lo 01: 4 Mhz 10: 8 Mhz 11: 16 Mhz E (P) = Prefetch. When enabled, the GBA attempts to read opcodes from ROM when the CPU is not using the bus. The 8-word-by-16-bit prefetch buffer makes subsequent ROM reads faster (0 waits) in code that accesses both ROM and RAM. 0: Disable (and save battery power) 1: Enable F (G) = Game Pak type 0: AGB multiplexed bus 1: DMG/CGB bus
Use this register to control wait state settings and the prefetch buffer for ROM and SRAM. Thanks to Damian
Yerrick for contributing this info, and for pointing me to some relevant reading material.
Address: 0x4000208 - REG_IME (Interrupt Master Enable)
7 6 5 4 3 2 1 0 X X X X X X X M
0 (M) = Master interrupt enable. When off, all interrupts are disabled. This must be on for the interrupt bits in REG_IE to have any effect.
7 6 5 4 3 2 1 0 X X X X X X X F
0 (F) = First Boot Flag (0 = First, 1 = Further)
Thanks to Martin Korth for the details of this register. The following comes from his description in the no$gba documentation.
After initial reset, the GBA BIOS initializes the register to 0x1, and any further execution of the Reset vector
(0x00000000) will pass control to the Debug vector (0x0000001C) when sensing the register to be still set to 0x1.
Normally the debug handler rejects control unless it detects Debug flags in cartridge header, in that case it may
redirect to a cut-down boot procedure (bypassing Nintendo logo and boot delays).
Address: 0x4000301 - REG_HALTCNT_H (Low Power Mode Control - Unimplemented in CowBite)
7 6 5 4 3 2 1 0 M X X X X X X X
7 (M) = Power Down Mode (0 = Halt, 1 = Stop)
Thanks to Martin Korth for the details of this register. The following comes from his description in the no$gba documentation.
In Halt mode, the CPU is paused until an interrupt occurs, this should be used to reduce power-consumption during
periods when the CPU is waiting for interrupt events. In Stop mode, most of the hardware including sound and video
are paused, this very-low-power mode could be used much like a screensaver.
The current GBA BIOS addresses only the upper eight bits of this register (by writing 0x00 or 0x80 to address 0x04000301),
however, as the register isn't officially documented, some or all of the bits might have different meanings in
future GBA models. For best forwards compatibility, it'd generally be more recommended to use the BIOS Functions
SWI 2 (Halt) or SWI 3 (Stop) rather than writing to this register directly.
Address: 0x4000800 - REG_IMC_L (Internal Memory Control - Unimplemented in CowBite)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X X X X X X X M X L K J I 0 (I) = Purpose unkown. When set, locks the GBA or sets the top-left tile number to 0x82. 1 (J) = Unknown. 2 (K) = Unknown. 3 (L) = Unkown. 5 (M) = When unset this locks up the GBA or just disallows VRAM changes (but can be used simulteneously with bit 0). It is set by default.
This register is undocumented even for official developers. What little we know about this it comes separately
from Martin Korth's no$gba documentaion and gbcft's experimentations. gbcft comments that he did his testing a
while back and is unsure about his assessment of bits 0 and 5. Anybody who knows about it can feel free to email
me with more info.
This register (the whole 32-bit word, including REG_IMC_H) is mirrored at intervals of 0x10000 bytes in
IORAM (it is the only IORAM
register that is mirrored in in this way).
Address: 0x4000802 - REG_IMC_H (Internal Memory Control - Unimplemented in CowBite)
F E D C B A 9 8 7 6 5 4 3 2 1 0 X X X X W W W W X X X X X X X X 8 - B (W)= WRAM Wait state control. 1101 - 2 Waitstates (3/3/6 cycles 8/16/32bit accesses) 1110 - 1 Waitstate (2/2/4 cycles for 8/16/32bit acceses) Default setting appears to be 1101. A value of 1111 causes the system to lock up.
Thanks to Martin Korth for detailing the function of this registers in his no$gba documentation. Note that the benefits of this register are not guaranteed to work on all GBAs and may very well have undesirable results if tampered with! In other words, if you use this register at all, do so in your own private tests.
 I'm starting it off with . . .
These are registers that I don't know the function of. Gradually their numbers have dwindled down to almost nothing.While most aren't even readable, certain ones seem to be writeable. I have an idea of what some of them are based on the headers included with many open source demos, but as to their specific function, I have no idea. Let me know if you find out what purpose they serve, if any, and I will put your notes here (and of course give credit).
0x002: REG_DISPCNT_H - Writing to bit 0 will cause (horizontally) adjacent pairs of pixels to have their green component swapped. What good is this for? Anybody know? 0x04E: REG_MOSAIC_H - Unreadable (gobbledygook) 0x056 - 0x05E: Unreadable (gobbledygook) 0x066: REG_SOUND1CNT_X (high 16 bits) Unreadable (0x0000) 0x06A: REG_SOUND2CNT_L (high 16 bits) Unreadable (0x0000) 0x06E: REG_SOUND2CNT_H (high 16 bits) Unreadable (0x0000) 0x076: REG_SOUND3CNT_X (high 16 bits) Unreadable (0x0000) 0x07A: REG_SOUND4CNT_L (high 16 bits) Unreadable (0x0000) 0x07E: REG_SOUND4CNT_L (high 16 bits) Unreadable (0x0000) 0x086: REG_SOUNDCNT_X (high 16 bits) Unreadable (0x0000) 0x08A: REG_SOUNDBIAS (high 16 bits) Unreadable (0x0000) 0x08C: Unreadable (gobbledygook) 0x08E: Unreadable (gobbledygook) 0x0A8 - 0xAE: Unreadable (gobbledygook) 0x0E0 - 0x0FE: Unreadable (gobbledygook) 0x110 - 0x11E: Unreadable (gobbledygook) 0x12C: Unreadable (gobbledygook) 0x12E: Unreadable (gobbledygook) 0x136: REG_IR (high 16 bits) Unreadable (0x0000). Served as the Infrared register on prototypes. 0x138 - 13E: Unreadable (gobbledygook) 0x142: Unreadable (0x0000) 0x144-14E: Unreadable (gobbledygook) 0x15A: JOYSTAT_H - Unreadable (0x0000) 0x15C - 0x1FE: Unreadable (gobbledygook) 0x206: REG_WSCNT (high 16 bits) Unreadable (0x0000) 0x20A: REG_IME (high 16 bits) Unreadable (0x0000) 0x20C - 0x2FE: Unreadable (gobbledygook) 0x302: REG_PAUSE (high 16 bits) Unreadable (0x0000) 0x304 - 0x3FE: Unreadable (gobbledygook) 0x410: Martin Korth has observed that the BIOS writes 0xFF (8 bit) to this address on startup.
I have noted that some of these registers always read as a certain repeating gobbledygook value no matter what
is written to them (I take this to be of the same origin as the gobbledygook that comes from reading BIOS -- see
Jeff Frohwein's GBA FAQ), but some always read 0. For the most part these
seem to be the "high" 16 bits of registers we already know the function of (thanks gbcft for pointing
out what probably should have been obvious to me). Others are registers that probably do something, but I just
don't know what. They may read as something other than 0 if the conditions are right.
Possibilities:
The following are some suggested possiblities for what the unkown registers could be (thanks goes out to Kay for
this), based on what Nintendo has included in previous hardware:
SPR_TIME_OVER bit: sprite blit time out register (1 bit). This bit is set when sprite processing overloads during
HDraw
SPR_RANGE_OVER bit: displayed objects number (regardless of the size) becomes or is greater than maximum GFX ASIC
is able to process
xxxx_VER_NUMBER reg: regsiter containing the xxxx IC version number (usually bit 0 to 3 if made by Nintendo)
- Martin Korth notes that there also appears to be an undocumented register that is used to mask out cartridge
memory (except first 4KBytes of ROM) in Single Game Pak slave mode . ..
- Like all Nintendo hardware designs, the GBA may have one or more 8/16 bit in/out parallel data ports mapped at
the bottom of I/O addresses.
The following are links to other documents which should prove useful to GBA developers:
http://www.gbadev.org/ (A great resource for GBA developers)
Devrs.com GBA Site (Another great resource, maintained by Jeff Frohwein)
Jeff Frohwein's GBA Dev FAQ
The Pern Project (Tutorials for GBA development)
Mappy SDK (A document similar to this one but for Joat's
Mappy emulator)
ARM's Technical Reference Manuals (Docs that you should
have around if you want to understand the ARM processor)
The Audio Advance (A great site by Uze explaining the GBA's sound system)
Andrew May's site (Technical info on the GBA link
port)
CowBite (The emulator I've been writing off and on. Make sure you check it out and give
me feedback!)
no$gba (A good asm debugger/emulator for commercial developers
with VERY good documentation on the GBA hardware. Free version of no$gba is compatible with multiboot games.)
Mappy (A great emulator for asm debugging and graphical feedback on sprites, backgrounds, etc.)
Visual
Boy Advance (A very accurate emulator that is gdb compatible)
The following are individuals who contributed info or corrections to this document. Thanks guys!
Agent Q (Wrote the original spec, version 1.0)
Uze (All of the sound register info comes directly from his Audio Advance
site)
Martin Korth (Author no$gba of who has given me permission to consolidate
additional info from his emulator's informative help documents with this one, most particularly serial registers,
some BIOS functions, and undocumented registers.)
Forgotten (VBA Author. Many of the BIOS call descriptions come from his Visual
Boy Advance FAQ.
gbcft (LOTS of info on interrupts, windowing, memory mirrors, the "Unkown Registers" section; helped
me debug a lot of errors in the emulator, and offered many corrections, info, and suggestions).
Kay (Contributed memory port sizes and wait states, DMA cycle timings, info regarding the BIOS, and various
advice, testing, and expertise regarding the GBA and older console systems)
Damian Yerrick (Contributed the WSCOUNT register)
Markus (Actually I asked him for help with LZSS. Also, his gfx2gba tool has proven extremely helpful in
my non-CowBite projects.:)
ePac (Gave me links to serial info and did a nice writeup about it in the gbadev group)
Costis (A variety of new info/corrections)
Grauw (Info on forced blanking, hblank lenghths, and on the BIOS wait function.)
Max
Otaku
Ped (Pointed out errors in the memory ranges, DISPCNT bit 5, and a bad typo regarding rotates/scale backgrounds).
Yarpen (Almost all the information on the timer registers and the keyboard control register. Thanks!)
General Thanks
All those GBA demo authors. You rock!
Every other emu author
http://www.gbadev.org/
The gbadev list on yahoo
SimonB and all the others who run/moderate the above sites
Dovoto and the PERN Project
Jeff Frohwein and his Devrs.com site
Nocturn and his tutorials
Uze from BeLogic for all the great information on the GBA's sound!
Andrew May for his site on GBA serial data
Nintendo
If I've forgotten to list your name or an important resource in this section, let
me know.
This document and its author are in no way associated with, endorsed or supported
by
Nintendo. GBA and Game Boy Advance are registered trademarks of Nintendo.
The CowBite emulator itself is copyright 2002 Thomas Happ