CowBite Virtual Hardware Specifications

Unofficial documentation for the CowBite GBA emulator
by
Tom Happ

Thu Jul 18 23:25:19 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

Table of Contents

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


1. Introduction

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 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 (SorcererXIII@yahoo.com) 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

The Basics

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).


Programming 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.

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. However, I suggest the following resources as being invaluable to the beginner:

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.

HAM - Emanuel's HAM devkit is especially easy to install and can have you up and running in minutes.



2. CPU


This section is intended to be an overview only, detailing those aspects of the CPU which are important to understand when developing for the GBA in particular. A more thorough description of the ARM7tdmi CPU can be found in the technical reference manuals on ARM's website.

The CPU is a 16.78 MHz ARM7tdmi RISC processor. It is a 32-bit processor but can be switched to "Thumb" state, which allows it to handle a special subset of 16-bit instructions that map to 32-bit counterparts. Instructions follow a three-stage pipeline: fetch, decode, execute. As a result, the program counter always points two instructions ahead of the one currently being executed.


CPU Registers

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:   0x03007FE0

As 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 M
0-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 mode
5    (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

Processor Modes

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.

CPU State

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.


3. Memory

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).



4. Graphics Hardware Overview

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.

Video Modes

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 number of sprites available on screen is also dependent on the mode; modes with tile-based backgrounds support 128 sprites, while modes with bitmapped backgrounds will only support 64 sprites.

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 3 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 3 of REG_DISPCNT sets the start of the frame buffer to 0x06000000 when bit 3 is zero, and 0x600A000 when bit 3 is one.

Color Format:

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 0x50002000 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

5. Backgrounds

Depending on the current video mode, three different types of backgrounds are available. They are

Text Backgrounds:

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.

Scale/Rotate Backgrounds:

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

Bitmapped Backgrounds:

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).

Background Map Entry Format

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.



For specific details on the format of background data and map entries, check out the section on REG_BG0CNT - REG_BG3CNT (addresses 0x04000008 - 0x0400000E).

In all modes up to 128 sprites can be displayed as well as the 4 background layers. These use the second palette which is located at 0x05000200. See the OAM section for details on how to display sprites.

Both background tiles and sprites use palette entry 0 as the transparent color. Pixels in this color will not be drawn, and allow other background layers and sprites to show through.


6. OAM (sprites)


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 


Bytes 3 and 4 (Attribute 1)

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 3. 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


Bytes 5 and 6 (Attribute 2)

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. 


Bytes 7 and 8 (Attribute 3)

F E D C  B A 9 8  7 6 5 4  3 2 1 0
S I I I  I I I I  F F F F  F F F F
0-7 (F) = Fraction. 
8-E (I) = Integer
F = (S) = Sign bit


These bytes control sprite rotation and scaling. 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.

To Make a Sprite Rotate and Scale: (Taken from PERN Tutorial Day 3)

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);


Sprite Tile Data

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|
|    |    |    |    |
---------------------

7. Windowing

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.


8. Hardware Interrupts

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.


Types of Hardware Interrupts

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.


9. BIOS (Software Interrupts - partially implemented in CowBite)

The BIOS calls are basically SWI instructions; the value passed into the instruction tells the CPU which interrupt to execute. There is very little public domain information on the BIOS. Marat Fayzullin has a listing of the BIOS calls on his VGBA website, and Forgotten has added a list to his Visual Boy Advance FAQ. It is using these, in combination with observing the behavior of various demos in CowBite and other emulators that I was able to piece together what I have here.

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)

0x08: Sqrt

Input: r0 = number
Output: r0 = sqrt(number)

0x09: ArcTan

Input: r0 = angle (signed 16-bit)
Output: r0 = arctan(angle);

0x0A: ArcTan2

Calculates the arctangent of the given point.
Input: r0 = X (signed 16-bit), r1 = Y (signed 16-bit)
Output: r0=arctan


0x0B: CPUSet

- Performs a memory transfer.
Input: r0 = source address, r1 = dest address
r2 (guess) - formatted like DMA transfer
bit26 = 32 or 16 bit transfer
bits 15 - 0 = number of transfers

0x0C: CPUFastSet

- Also performs a memory transfer, in 32-bit blocks, presumably with some optimization (and limitations?). I believe the register parameters are set up the same as, or at least similar to, those for CPUSet.

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 sprites (rotation and scaling).
Input: r0 = source, r1 = dest, r2 = number of calculations, r3 = offset between calculations


0x0F: ObjAffineSet
0x10: BitUnPack

Unpacks bit packed data.
Input: r0 = source, r1 = dest, r2 = unpack parameters

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

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
Input: r0 = source address, r1 = dest address

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

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.
Input: r0 = SoundArea

0x1B: SoundDriverMode

Sets the operation of the built in sound driver.
Input: r0 = operation mode

0x1C: SoundDriverMain

Main function of the built in sound driver that is called by applications every VBLANK period to render the sound.

0x1D: SoundDriverVSync
0x1E: SoundChannelClear
0x1F: MIDIKey2Freq
Ox20: MusicPlayerOpen
0x21: MusicPlayerStart
0x22: MusicPlayerStop
0x23: MusicPlayerContinue
0x24: MusicPlayerFadeOut
0x25: MultiBoot
0x26: ??
0x27: ??
0x28: SoundDriverVSyncOff
0x29: SoundDriverVSyncOn

?: FIQMasterEnable



10. Memory-Mapped Hardware Registers

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




Addresses: 0x04000000 - 0x4000054 - Graphics Hardware Registers


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.



Addresses: 0x400008 - 0x400001E - Background Registers


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.




Addresses: 0x4000020 - 0x4000026 / 0x4000030 - 0x4000036 - Background Rotation/Scaling Registers (Write Only)

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.

F E D C  B A 9 8  7 6 5 4  3 2 1 0 
S I I I  I I I I  F F F F  F F F F 
0-7 (F) = Fraction 
8-E (I) = Integer 
F   (S) = Sign bit 

These registers apply only to Rotate/Scale backgrounds. 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).



Address: 0x4000028 - REG_BG2X (X Coordinate for BG2 Rotational Background)(Write Only)
Address: 0x4000038 - REG_BG3X (X Coordinate for BG3 Rotational Background)(Write Only)

Address: 0x400002C - REG_BG2Y (Y Coordinate for BG2 Rotational Background)(Write Only)
Address: 0x400003C - REG_BG3Y (Y Coordinate for BG3 Rotational Background)(Write Only)

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.



Addresses: 0x4000040 - 0x400004A - Windowing Registers


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 in win0 
5 (L) = Blends in win0 
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 



Addresses: 0x400004C - 0x4000054 - Effects Registers


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).




Addresses 0x040000060 - 0x0400000A6 (Sound Controls: Partially unimplemented in CowBite)

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.



Address: 0x04000064 - REG_SOUND1CNT_X (Sound 1 Frequency, reset and loop control)(Unimplemented in CowBite)

W          W W W  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 T X X  X F F F  F F F F  F F F F

0-A (F) = Sound frequency. 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.


Address: 0x0400006C- REG_SOUND2CNT_H (Sound 2 Frequency, reset and loop control)(Unimplemented in CowBite)

W          W W W  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 T X X  X F F F  F F F F  F F F F
0-A (F) = Sound frequency. 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.
          After the sound length has be changed, the sound channel must be
          resetted via bit F of REG_SOUND3CNT_X. 

D-F (R) = Output volume ratio:
          
          000 - Mute
          001 - 100%
          100 - 75%
          010 - 50%
          011 - 25%


Address: 0x04000074 - REG_SOUND3CNT_X (Sound 3 Frequency, reset and loop control)(Unimplemented in CowBite)

W          W W W  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 T X X  X F F F  F F F F  F F F F
0-A (F) = Sound frequency. 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...


Addresses: 0x40000B0, 0x40000BC, 0x40000C8, 0x40000D4 (DMA Source Registers)(Write Only)

Address: 0x40000B0 - REG_DMA0SAD (DMA0 Source Address)(Write Only)

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   X  A  A  A   A  A  A  A   A  A  A  A   A  A  A  A   A  A  A A  A A A A  A A A A

0-26 (A) = 27-bit source address

This is the source address for DMA channel 0 transfers. Note that it is 27-bit.

Address: 0x40000BC - REG_DMA1SAD (DMA1 Source Address)
Address: 0x40000C8 - REG_DMA2SAD (DMA2 Source Address)
Address: 0x40000D4 - REG_DMA3SAD (DMA3 Source Address)

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   A  A  A  A   A  A  A  A   A  A  A  A   A  A  A  A   A  A  A A  A A A A  A A A A

0-27 (A) = 28-bit source address

This is the source address for DMA channel 1, 2, or 3 transfers. Note that it is 28-bit.


Addresses: 0x40000B4, 0x40000C0, 0x40000CC, 0x40000D8 (DMA Destination Registers
) (Write Only)

Address: 0x40000B4 - REG_DMA0DAD (DMA0 Destination Address)
Address: 0x40000C0 - REG_DMA1DAD (DMA1 Destination Address)
Address: 0x40000CC - REG_DMA2DAD (DMA2 Destination Address)

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   X  A  A  A   A  A  A  A   A  A  A  A   A  A  A  A   A  A  A A  A A A A  A A A A

0-27 (A) = 27-bit destination address

This is the dest address for DMA channel 0, 1, and 2 transfers. Note that it is 27-bit.


Address: 0x40000D8 - REG_DMA3DAD (DMA3 Destination Address)(Write Only)

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   A  A  A  A   A  A  A  A   A  A  A  A   A  A  A  A   A  A  A A  A A A A  A A A A

0-27 (A) = 28-bit destination address

This is the dest address for DMA channel 3 transfers. Note that it is 28-bit.


Addresses: 0x40000B8, 0x40000C4, 0x40000D0, 0x40000DC (DMA Count Registers)
(Write Only)

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.)

Addresses: 0x40000BA, 0x40000C6, 0x40000D2, 0x40000DE (DMA Control Registers)

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)


DMA Transfer Ratings


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!!




Addresses: 0x4000100 - 0x400010E (Timer registers)

Address: 0x4000100 - REG_TM0D (Timer 0 Data)
Address: 0x4000104 - REG_TM1D (Timer 1 Data)
Address: 0x4000108 - REG_TM2D (Timer 2 Data)
Address: 0x400010C - REG_TM3D (Timer 3 Data)

F E D C  B A 9 8  7 6 5 4  3 2 1 0 
D D D D  D D D D  D D D D  D D D D
0-F (D) = Current count of the timer.


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.




Addresses 0x4000120 - 0x400012A - Serial Communication Registers) (Unimplemented in CowBite)

Note: All of the serial comm information originates from Andrew May's description of the GBA linker hardware, which in turn was compiled from various other sources on the web. My thanks to ePAc for discovering his site and putting the information into a format consistent with the rest of this spec. If anybody else has information to add to this, don't hesitate to mail me.

Address: 0x4000120 - REG_SCD0 (Master/Slave 0 destination reg) (Read Only)
Address: 0x4000122 - REG_SCD1 (Slave 1 destination reg) (Read Only)
Address: 0x4000124 - REG_SCD2 (Slave 2 destination reg) (Read Only)
Address: 0x4000126 - REG_SCD3
(Slave 3 destination reg) (Read Only)


R R R R  R R 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 
D D D D  D D D D  D D D D  D D D D
0-F (D) = The data received.

- 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)


Address: 0x4000128 - REG_SCCNT_L (Serial Communication channel control register)

                    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  L L B B
0-1 (B) = Baud rate [00=9600,01=38400,10=57600,11=115200]
2-3 (L) = SD(bit3) and SI(bit2) line direct access
4-5 (D) = ID of GBA [00=master,01=slave1,10=slave2,11=slave3]
6   (E) = Error (1 on error)
7   (S) = Start Transfer (1 triggers the start on the MASTER ONLY)
C-D (M) = Comm Mode [8bit=00,32bit=01,Multilink=10,UART=11]
E   (I) = Enable Comm Interupt


Using the link port and a link cable, the GBA can transmit serial data in one of four modes: 8 bit, 32 bit, Multilink, and UART. At the moment I only have info on the multilink mode. Mail me if you know more about the other modes.

Multilink Mode
To transfer data in this mode, you must coordinate the actions of all the GBAs which are linked together. 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 and, as I understand, 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.

It is unclear to me how each GBA knows what ID it is; perhaps this value is automatically set when the link cable is attached? 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..

Note from me: I have a suspicion that some of these bits are write-only. Please let me know if you find out more.


Address: 0x400012A - REG_SCCNT_H (Serial Communication Source Register)

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 data to be sent over the link cable.




Addresses 0x4000130 - 0x4000132 - Keypad Input and Control Registers


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.




Address: 0x4000134 - REG_R

    R R  R R R                 R R    
F E D C  B A 9 8  7 6 5 4  3 2 1 0

This register appears to give direct access to the different lines of the link port. If you happen to have more information about which bit corresponds to which line, by all means mail me about it so I can update the doc.

Also, I used the name listed in Eloist's gba.h. I don't think it is very descriptive. If anyone has seen a better name for this register, let me know and I will change it. Otherwise I will probably change it to something like "REG_SCLINES" or "REG_SCPIN".




Addresses 0x4000200 - 0x4000208 - Interrupt Registers


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.  The GBA's 8-word-by-16-bit prefetch buffer makes
          subsequent ROM reads faster 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)

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 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.





Address: 0x4000300 - REG_PAUSE

? ? ? ?  ? ? ? ?  ? ? ? ?  ? ? ? ?
F E D C  B A 9 8  7 6 5 4  3 2 1 0 
P M X X  X X X X  X X X X  X X X X
F (M) = Mode
E (P) = Power down


I've written down the function of this as it appears in Mappy's SDK. However, I can't say how it works. Writing values to bits 14 and 15 seems to have no effect. This register shows up as 0x0001 when read. As always, send me mail if you have more info on this.




11. Miscellaneous/Weirdness

This is a new section devoted any interesting little tidbits that don't quite fit in anywhere else. I'm starting it off with . . .

Unknown Registers

These are registers that I don't know the function of. 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_R (high 16 bits) Unreadable (0x0000)
0x138 - 13E:   Unreadable (gobbledygook)

0x140:	       REG_HS_CTRL - Seems to have the following properties:
               R R R R  R 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

0x142:         Unreadable (0x0000)
0x144-14E:     Unreadable (gobbledygook)
0x150:         REG_JOYRE_L - Unreadable (0x0000)
0x152:         REG_JOYRE_H - Unreadable (0x0000)
0x154:         REG_JOYTR_L - Unreadable (0x0000)
0x156:         REG_JOYTR_H - Unreadable (0x0000)
0x158:         JOYSTAT_L - defaults to 0x8.  
               Seems to have the following properties: 
               R R R 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

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)
0x800:         Seems to have the following properties: 
			
               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) = When set, this sets the top-left tile number to 0x82
               1 (J) = Unknown.
               2 (K) = Unknown.
               3 (L) = Unkown.
               5 (M) = When unset this disallows VRAM changes (but can be used
                       simulteneously with bit 0).  It is set by default.

               What little we know about this register comes from gbcft's 
               experimentation a ways back, and he's not entirely sure about
               even this.  Anybody who knows about it can feel free to email
               me with more info. 

               This register (the whole 32 bit word) is also mirrored at
               intervals of 0x10000 bytes in IORAM (it is the only IORAM
               register that is mirrored in in this way).  

0x802:         Read only (reads as 0x0d00).

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)

- 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.

12. Links

The following are links to other documents which should prove useful to GBA developers:

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)
Mappy (A great emulator for developers)
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!)


13. Thanks


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)
gbcft (LOTS of info on interrupts, windowing, memory mirrors, the "Unkown Registers" section, as well as many corrections, info, and suggestions)
Damian Yerrick
(Contributed the WSCOUNT register)
Kay (Contributed memory port sizes and wait states, DMA cycle timings, and various advice, testing, and expertise regarding the GBA and older console systems)
Markus (Actually I asked him for help, and he kindly supplied me with what I needed to understand LZSS compression)
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
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