Acknowledgements
+-
+
- Velipso, author of the Bootleg Carts article. +
The following are individuals who contributed info or corrections on the original CowBiteSpec document.
- Tom Happ @@ -198,7 +202,7 @@
- Uze (All of the sound register info comes directly from his Audio Advance site)
- Martin Korth (Author no$gba of who has given me permission to consolidate additional info from his emulator's informative help documents with this one, most particularly serial registers, some BIOS functions, and undocumented registers.)
- Forgotten (VBA Author. Many of the BIOS call descriptions come from his Visual Boy Advance FAQ. -
- gbcft (LOTS of info on interrupts, windowing, memory mirrors, the "Unkown Registers" section; helped me debug a lot of errors in the emulator, and offered many corrections, info, and suggestions). +
- gbcft (LOTS of info on interrupts, windowing, memory mirrors, the "Unkown Registers" section; helped me debug a lot of errors in the emulator, and offered many corrections, info, and suggestions).
- Kay (Contributed memory port sizes and wait states, DMA cycle timings, info regarding the BIOS, and various advice, testing, and expertise regarding the GBA and older console systems)
- Damian Yerrick (Contributed the WSCOUNT register)
- Markus (Actually I asked him for help with LZSS. Also, his gfx2gba tool has proven extremely helpful in my non-CowBite projects.:) diff --git a/audio/directsound.html b/audio/directsound.html index 52db101..e36f731 100644 --- a/audio/directsound.html +++ b/audio/directsound.html @@ -233,13 +233,13 @@
- Issues a "Program" command for each 16-bit value +
- Issues a "Program" command for each 16-bit value
- Writes the 16-bit value at the target address
- Waits in a loop until it reads the written value*
- Continues writing until all 16-bit values are written diff --git a/cpu.html b/cpu.html index 8261db1..086b3db 100644 --- a/cpu.html +++ b/cpu.html @@ -197,7 +197,7 @@
-
-
r14 (LR): Link Register. Used primarily to store the address following a "bl" (branch and link) instruction (as used in function calls)
+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.
@@ -256,7 +256,7 @@Processor Mod
-
-
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.
+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.
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.
+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
diff --git a/index.html b/index.html index 4e8c708..59e02e7 100644 --- a/index.html +++ b/index.html @@ -202,8 +202,8 @@The Basics
- 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.
Acknowledge
#include "gba.h"
+#include "gba.h"
//the sample. its a pcm wave file converted to an elf file with objcopyroda.exe (devrs.com/gba)
extern const u32 _binary_lo1234_pcm_start[];
//the interrupt handler from crt0.s
-void InterruptProcess(void) __attribute__((section(".iwram")));
+void InterruptProcess(void) __attribute__((section(".iwram")));
void InterruptProcess(void) {
//sample finished!,stop Direct sound
@@ -308,12 +308,12 @@ #include "gba.h"
+#include "gba.h"
//the sample. its an pcm wave file converted to an elf file with objcopyroda.exe (devrs.com/gba)
extern const u32 _binary_lo1234_pcm_start[];
//the interrupt handler from crt0.s
-void InterruptProcess(void) __attribute__((section(".iwram")));
+void InterruptProcess(void) __attribute__((section(".iwram")));
int iNextSample = 0;
int SampleSize = 36712;
diff --git a/audio/sound1.html b/audio/sound1.html
index 262c604..6252f09 100644
--- a/audio/sound1.html
+++ b/audio/sound1.html
@@ -192,7 +192,7 @@ gbadoc
Sound Channel 1
Sound channel 1 produces square waves with variable duty cycle, frequency sweep and envelope functions. It is often referred as a quadrangular wave pattern.
-Frequency sweeps allows "portamento"-like effects where the frequency raises or decreases during playback. The amount of increase or decrease in frequency (or sweep shifts) and the rate at which it occurs (sweep time) is controllable. Frequency sweeps are controlled by REG_SOUND1CNT_L
+Frequency sweeps allows "portamento"-like effects where the frequency raises or decreases during playback. The amount of increase or decrease in frequency (or sweep shifts) and the rate at which it occurs (sweep time) is controllable. Frequency sweeps are controlled by REG_SOUND1CNT_L
Sweep shifts are controlled by bits 0-2 and are calculated with the following formula:
\( T = T \pm \frac{T}{2^n} \) where T = Wave Period and n = Sweep Shifts
Sweep time (Ts) controls the delay between sweep shifts and is controlled by bits 4-6:
diff --git a/bios.html b/bios.html
index a39ecd2..0bce36e 100644
--- a/bios.html
+++ b/bios.html
@@ -280,7 +280,7 @@
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.
+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.
diff --git a/bootleg-carts/introduction.html b/bootleg-carts/introduction.html
index e308db0..bb0aaea 100644
--- a/bootleg-carts/introduction.html
+++ b/bootleg-carts/introduction.html
@@ -294,20 +294,20 @@
You can see that this information also exists in the FlashGBX source code, in the
config:
-"reset":[
+"reset":[
[ 0, 0xF0 ]
],
-"read_identifier":[
+"read_identifier":[
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ 0xAAA, 0x90 ]
],
-"read_cfi":[
+"read_cfi":[
[ 0xAA, 0x98 ]
],
...
-Notice that the "Auto-Select" row doesn't exactly match the "read_identifier"
information.
+Notice that the "Auto-Select" row doesn't exactly match the "read_identifier"
information.
Auto-Select starts with address 0xAAA
, data 0xAA
, but FlashGBX has address 0xAAA
, data
0xA9
-- this is because D0/D1 are swapped (10101010
-> 10101001
)! See the section
above.
@@ -315,11 +315,11 @@ erase the chip, it just resets any commands in progress.
// reset
*((u16 *)0x08000000) = 0xF0;
-__asm("nop");
+__asm("nop");
The forked goombacolor project from LesserKuma has example code, where you can see this
happen:
-#define _FLASH_WRITE(pa, pd) { *(((u16 *)AGB_ROM)+((pa)/2)) = pd; __asm("nop"); }
+#define _FLASH_WRITE(pa, pd) { *(((u16 *)AGB_ROM)+((pa)/2)) = pd; __asm("nop"); }
// reset
_FLASH_WRITE(0, 0xF0);
@@ -422,7 +422,7 @@ Erasing a S
_FLASH_WRITE(0x555, 0x56);
_FLASH_WRITE(sa, 0x30);
while (1) {
- __asm("nop");
+ __asm("nop");
if (*(((u16 *)AGB_ROM)+(sa/2)) == 0xFFFF) {
break;
}
@@ -447,7 +447,7 @@ Saving Data
_FLASH_WRITE(0xAAA, 0xA0);
_FLASH_WRITE(sa+i, (*(u8 *)(AGB_SRAM+i+1)) << 8 | (*(u8 *)(AGB_SRAM+i)));
while (1) {
- __asm("nop");
+ __asm("nop");
if (*(((u16 *)AGB_ROM)+((sa+i)/2)) == ((*(u8 *)(AGB_SRAM+i+1)) << 8 | (*(u8 *)(AGB_SRAM+i)))) {
break;
}
@@ -457,7 +457,7 @@ Saving Data
The code:
-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.
+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:
@@ -214,7 +214,7 @@ CPU Registers
As far as I know the other modes do not have default stack pointers.
#include "gba.h"
//the sample. its a pcm wave file converted to an elf file with objcopyroda.exe (devrs.com/gba)
extern const u32 _binary_lo1234_pcm_start[];
//the interrupt handler from crt0.s
-void InterruptProcess(void) __attribute__((section(".iwram")));
+void InterruptProcess(void) __attribute__((section(".iwram")));
void InterruptProcess(void) {
//sample finished!,stop Direct sound
@@ -308,12 +308,12 @@ #include "gba.h"
+#include "gba.h"
//the sample. its an pcm wave file converted to an elf file with objcopyroda.exe (devrs.com/gba)
extern const u32 _binary_lo1234_pcm_start[];
//the interrupt handler from crt0.s
-void InterruptProcess(void) __attribute__((section(".iwram")));
+void InterruptProcess(void) __attribute__((section(".iwram")));
int iNextSample = 0;
int SampleSize = 36712;
diff --git a/audio/sound1.html b/audio/sound1.html
index 262c604..6252f09 100644
--- a/audio/sound1.html
+++ b/audio/sound1.html
@@ -192,7 +192,7 @@ gbadoc
Sound Channel 1
Sound channel 1 produces square waves with variable duty cycle, frequency sweep and envelope functions. It is often referred as a quadrangular wave pattern.
-Frequency sweeps allows "portamento"-like effects where the frequency raises or decreases during playback. The amount of increase or decrease in frequency (or sweep shifts) and the rate at which it occurs (sweep time) is controllable. Frequency sweeps are controlled by REG_SOUND1CNT_L
+Frequency sweeps allows "portamento"-like effects where the frequency raises or decreases during playback. The amount of increase or decrease in frequency (or sweep shifts) and the rate at which it occurs (sweep time) is controllable. Frequency sweeps are controlled by REG_SOUND1CNT_L
Sweep shifts are controlled by bits 0-2 and are calculated with the following formula:
\( T = T \pm \frac{T}{2^n} \) where T = Wave Period and n = Sweep Shifts
Sweep time (Ts) controls the delay between sweep shifts and is controlled by bits 4-6:
diff --git a/bios.html b/bios.html
index a39ecd2..0bce36e 100644
--- a/bios.html
+++ b/bios.html
@@ -280,7 +280,7 @@
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.
+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.
diff --git a/bootleg-carts/introduction.html b/bootleg-carts/introduction.html
index e308db0..bb0aaea 100644
--- a/bootleg-carts/introduction.html
+++ b/bootleg-carts/introduction.html
@@ -294,20 +294,20 @@
You can see that this information also exists in the FlashGBX source code, in the
config:
-"reset":[
+"reset":[
[ 0, 0xF0 ]
],
-"read_identifier":[
+"read_identifier":[
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ 0xAAA, 0x90 ]
],
-"read_cfi":[
+"read_cfi":[
[ 0xAA, 0x98 ]
],
...
-Notice that the "Auto-Select" row doesn't exactly match the "read_identifier"
information.
+Notice that the "Auto-Select" row doesn't exactly match the "read_identifier"
information.
Auto-Select starts with address 0xAAA
, data 0xAA
, but FlashGBX has address 0xAAA
, data
0xA9
-- this is because D0/D1 are swapped (10101010
-> 10101001
)! See the section
above.
@@ -315,11 +315,11 @@ erase the chip, it just resets any commands in progress.
// reset
*((u16 *)0x08000000) = 0xF0;
-__asm("nop");
+__asm("nop");
The forked goombacolor project from LesserKuma has example code, where you can see this
happen:
-#define _FLASH_WRITE(pa, pd) { *(((u16 *)AGB_ROM)+((pa)/2)) = pd; __asm("nop"); }
+#define _FLASH_WRITE(pa, pd) { *(((u16 *)AGB_ROM)+((pa)/2)) = pd; __asm("nop"); }
// reset
_FLASH_WRITE(0, 0xF0);
@@ -422,7 +422,7 @@ Erasing a S
_FLASH_WRITE(0x555, 0x56);
_FLASH_WRITE(sa, 0x30);
while (1) {
- __asm("nop");
+ __asm("nop");
if (*(((u16 *)AGB_ROM)+(sa/2)) == 0xFFFF) {
break;
}
@@ -447,7 +447,7 @@ Saving Data
_FLASH_WRITE(0xAAA, 0xA0);
_FLASH_WRITE(sa+i, (*(u8 *)(AGB_SRAM+i+1)) << 8 | (*(u8 *)(AGB_SRAM+i)));
while (1) {
- __asm("nop");
+ __asm("nop");
if (*(((u16 *)AGB_ROM)+((sa+i)/2)) == ((*(u8 *)(AGB_SRAM+i+1)) << 8 | (*(u8 *)(AGB_SRAM+i)))) {
break;
}
@@ -457,7 +457,7 @@ Saving Data
The code:
-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.
+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:
@@ -214,7 +214,7 @@ CPU Registers
As far as I know the other modes do not have default stack pointers.
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 0x04000000 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.
+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 0x04000000 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).
diff --git a/intro.html b/intro.html index 4e8c708..59e02e7 100644 --- a/intro.html +++ b/intro.html @@ -202,8 +202,8 @@The Basics
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 0x04000000 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.
+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 0x04000000 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).
diff --git a/memory.html b/memory.html index 04dc481..5eafd48 100644 --- a/memory.html +++ b/memory.html @@ -248,7 +248,7 @@VRAM
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.
+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 diff --git a/print.html b/print.html index 9b9b7c8..704118d 100644 --- a/print.html +++ b/print.html @@ -203,8 +203,8 @@The Basics
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 0x04000000 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.
+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 0x04000000 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).
@@ -217,7 +217,7 @@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.
+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:
-
@@ -234,7 +234,7 @@
-
-
r14 (LR): Link Register. Used primarily to store the address following a "bl" (branch and link) instruction (as used in function calls)
+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.
@@ -276,7 +276,7 @@Processor Mod
CPU Registers
As far as I know the other modes do not have default stack pointers.
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.
+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.
VRAM
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.
+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 @@ -433,7 +433,7 @@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.
+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
@@ -643,7 +643,7 @@2D Mapping
---------------------
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.
+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:
@@ -652,7 +652,7 @@2D Mapping
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.
+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.
@@ -670,7 +670,7 @@2D Mapping
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.
+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.
@@ -848,7 +848,7 @@
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.
+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.
@@ -1002,13 +1002,13 @@
COLOR="#0099FF">C X X S S P P
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.
+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.
@@ -1002,13 +1002,13 @@