Campho Advance Technical Documentation 0.1
June 13th, 2023
Shonumi aka D.S. Baxter


***************************************************
1. Introduction
***************************************************

The Campho Advance is a cartridge for the Game Boy Advance that allowed users to make video-based phonecalls. Released in Japan on July 30, 2004, it was sold in limited quanitites by Digital Act. The hardware features a built-in camera that points towards the user's face to capture a live video stream.


***************************************************
2. General Hardware Information
***************************************************

- Comes in an oversized red and black cartridge with a bulky top-end.
- Has a camera embedded in the upper center of the cartridge, captures video at ~5 FPS.
- Camera's native resolution is around 110,000 pixels.
- Has a RJ-11 phone jack on the side. Transmits and receives data over standard landlines.
- Has a microphone jack on the side for voice input.
- Requires constant external power to boot and has a port for an AGS-002 AC Adapter.
- Not compatible with any model of Nintendo DS; system will fail to boot.
- Contains some memory used to save contact information.
- Uses a unique method of mapping ROM data.
- Modem is capable of handling several AT commands.


***************************************************
3. I/O Registers
***************************************************

The Campho Advance uses a handful of I/O registers and address ranges mainly for reading ROM data via its unique mapper.

------------------------------------------------------------------------
Address Range			| I/O Name
------------------------------------------------------------------------
0x8000000 - 0x8007FFF		| ROM_DATA_1	(ROM Data Stream 1)
0x8008000 - 0x800FFFF		| ROM_DATA_2	(ROM Data Stream 2)
0x8010000 - 0x8013FFF		| ROM_STAT	(ROM Status)
0x8014000 - 0x801FFFF		| ROM_CNT	(ROM Control)
0x8020000 - 0x9FFFFFF		| ROM_DATA_1	(ROM Data Stream 1)
------------------------------------------------------------------------

These memory regions are also available from Wait State 1 (0xA000000). Currently unknown if they are available from Wait State 2 (0xC000000) as well. ROM_STAT and ROM_CNT are 16-bit registers.

ROM_DATA_1 and ROM_DATA_2 act as different, independent streams to read ROM. Data is pulled from ROM sequentially with each read to these regions, including code fetches requested by the CPU. As such, their internal read pointers automatically advance on their own. ROM_DATA_2 is special as it is primarily used to read the second portion of the bootstrap ROM (BS2) as well as handling input and output for Campho Advance commands. ROM_DATA_1 primarily reads the first part of the bootstrap ROM (BS1), reads the entirety of Program ROM, and reads pixel data captured by the camera.

ROM_STAT acts as a status flag of sorts indicating when certain data on Campho Advance is ready to be read. Used extensively to read Program ROM and prompting a read command for Graphics ROM.

ROM_CNT acts as an overall control register that determines what operations the Campho Advance will execute for reading or writing ROM data.

The rest of the data in the 32MB Wait State is dedicated to ROM_DATA_1 again.


***************************************************
4. ROM Data Sections
***************************************************

The Campho Advance has at least 3 different areas of ROM, each with their own method of access. They are also divided by what purpose they serve.

-----------------------------------------------------------
ROM Name		| Function
-----------------------------------------------------------
Bootstrap ROM		| Handles initial program loading
Program ROM		| Main code for the Campho Advance
Graphics ROM		| Bitmap graphics for menus
-----------------------------------------------------------

In terms of how the Campho Advance works, it first loads up bootstrap ROM in two parts. From there, the bootstrap runs and loads the entirety of Program ROM. Once that transfer completes, Program ROM takes over and runs until the GBA shuts down. Its job is to enter/exit menus, receive and send videocalls, and handle everything else the Campho Advance is capable of. It will periodically read large portions of Graphics ROM as needed depending on the menus it enters.


***************************************************
5. Data Format
***************************************************

Due to the way the Campho Advance was made (possibly as a result of some flaw in the way it handles addressing on the catridge data bus) some of the 16-bit values read from or written to the cartridge need to be adjusted in a very specific way. This documentation will refer to this process as "warping" and "unwarping". The former refers to reading 16-bit values from the Campho Advance and changing them to get the expected binary output. The latter refers to writing 16-bit values to the Campho Advance in a format it expects to receive. The math for warping and unwarping is specified below:

//UNWARP - (Read 16-bit value from Campho Advance)
OUTPUT_16 = ((INPUT_16 LSL 3) OR (INPUT_16 LSR 13))

//WARP - (Write 16-bit value to Campho Advance)
OUTPUT_16 = ((INPUT_16 LSL 13) OR (INPUT_16 LSR 3))

Generally speaking, warping and unwarping are used when dealing with commands, configuration data, contact data, Graphics ROM data, and camera input. This documentation will explain when each case applies. Many of the reads and writes to both ROM_CNT and ROM_STAT involve 2 values: 0x4015 and 0xA00A. These are the 16-bit warped values of 0x55 and 0xAA respectively. For simplicity, warped values are used in this documentation, as they represent the "raw" values the CPU deals with for the Campho Advance's I/O.

A 32-bit version of warping is used for Graphics ROM offsets. In that case, the input 32-bit value is broken into 2 separate 16-bit values and warping/unwarping is applied to each, then the result are joined together for a final 32-bit output.


***************************************************
6. Commands
***************************************************

The Campho Advance can issue a number of commands to control various bits of hardware outside memory management. Once again, all I/O registers use their Wait State 1 mirrors (0xA000000). Each command follows this general format:

------------------------------------------------------------------------
//All writes to ROM_DATA_2 are 16-bit
ROM_STAT = 0x4015

[ROM_DATA_2] = COMMAND_LO
[ROM_DATA_2] = COMMAND_HI

//The following are optional depending on parameters used
[ROM_DATA_2] = PARAMETER_01
[ROM_DATA_2] = PARAMETER_23
...

ROM_CNT = 0x4015
------------------------------------------------------------------------

Some commands return data for the Campho Advance to read after issuing the command, such as accessing Graphics ROM, configuration settings, and contact data. In these cases, the data can be read from ROM_DATA_2. The commands are 16-bit and warped. Their parameters are typically (but not always) warped as well. A list of all currently known commands is provided below:

------------------------------------------------------------------------
Unwarped	| Warped 	| Description
------------------------------------------------------------------------
0xBA01		| 0x3740	| Dial a phone number
0xBA02		| 0x5740	| Answer a phone call
0xBA04		| 0x9740	| Cancel a phone call (before connecting)
0xBA05		| 0xB740	| Starts input data from the camera (small 58x48 frame)
0xBA06		| 0xD740	| Starts input data from the camera (large 176x144 frame)
0xBA07		| 0xF740	| Halts input data from the camera
0xBA08		| 0x1741	| End a phone call
0xBA10		| 0x1742	| Set microphone volume
0xBA11		| 0x3742	| Set speaker volume
0xBA12		| 0x5742	| Set video brightness
0xBA13		| 0x7742	| Set video contrast
0xBA14		| 0x9742	| Set camera image flip
0xBA15		| 0xB742	| Read Graphics ROM data
0xBA21		| 0x3744	| Unknown (used when pulse dialing is enabled)
0xBBC1		| 0x3778	| Write full configuration settings or contact data
0xBBC5		| 0xB778	| Read full configuration settings or contact data
0xBBC6		| 0xD778	| Read the total number of contact data entries
0xBBC8		| 0x1779	| Erase contact data
0xCFFF		| 0xFF9F	| Finishes input frame from camera (and requests another?)
0xFF84		| 0x9FF0	| Sends an AT command to the modem
------------------------------------------------------------------------

For a full explanation of how each command works, see the following sections.

If a command expects to read data (typically from ROM_DATA_2), the Campho Advance has a slight delay before that information becomes accessible. After 0x4015 is written to ROM_CNT to finish the command sequence, ROM_STAT will eventually change to 0x4015 as well. When this happens, it signals to software that the data is ready for reading. The Campho Advance may return nonsense values if software tries to grab any data before ROM_STAT makes this switch. Software should also timeout if this I/O delay goes on for too long so as not to halt the entire program.


***************************************************
7. Bootstrap ROM
***************************************************

The bootstrap ROM is available for the CPU to read immediately once the GBA powers on (and provided the Campho Advance also has power supplied to it). This section of ROM is partitioned in two separate regions, named BS1 and BS2. They can be read at ROM_DATA_1 and ROM_DATA_2 respectively. BS1 contains a valid ROM header and the "Nintendo" logo necessary for the GBA's cartridge check, however, its format does not resemble those of most other cartridges.

Due to the way the Campho Advance returns data via an internal read pointer, both BS1 and BS2 have to specifically account for how the GBA BIOS reads ROM data. During to boot process, the BIOS reads various ROM addresses, and not all of them are necessarily in sequential order. For example, the first byte it reads is from 0x80000B4 (the cartridge Device Type). As a result the first value in BS1 is 0x80 (indicating a DACS cartridge, even though this is not the case for the Campho Advance). Altogether, the BIOS reads 281 bytes from ROM; the first 273 bytes of BS1 and the first 8 bytes of BS2 are tailored to give the GBA BIOS the expected output, such as the values for the "Nintendo" logo, game title, and 8-bit header checksum. After that, BS1 and BS2 contain the actual code to run once the BIOS hands over control.

Apparently, all internal read pointers can be reset in the Campho Advance if power is lost and then restored. The most stable way to do so is by booting the Campho Advance with the power cable attached, unplugging it, then reinserting the cable. Doing so allows homebrew software to freely read all of BS1 and BS2. Since running the BIOS advances both read pointers, the first 273 and 8 bytes of BS1/BS2 respectively are otherwise inaccessible without this power cycling method.

Aside from that, no special proceedure is necessary to read BS1 or BS2. Simply reading ROM_DATA_1 or ROM_DATA_2 is enough. Without the data used for BIOS, BS1 measures in at 72 bytes. BS2 measures 122 bytes in total. The Campho Advance begins in BS1, pulling data via code fetches. BS1's purpose is to load executable code in RAM for BS2 and then jump. Since the Campho Advance's mapper always advances its internal read pointer (regardless of what the CPU's PC register is) the only way for the Campho Advance to run branching code is by copying it to RAM first. BS2's role is to load all of Program ROM into RAM and then jump to execute it.

Once all of the data for either BS1 or BS2 has been read, the Campho Advance will return garbage data.


***************************************************
8. Program ROM
***************************************************

Program ROM is the heart of the Campho Advance. It contains all of the code needed to operate the hardware. It measures exactly 65508 bytes, and the Campho Advance breaks that up into 16 separate 4094 byte banks (4 bytes metadata + 4090 bytes of ROM) along with final dummy bank at the end. BS2 is responsible for reading each block, copying each of them to the GBA's 256KB WRAM, and jumping to the start of Program ROM to begin execution. The following process is used to read the blocks:

------------------------------------------------------------------------
//Preps a block for reading
ROM_CNT = 0xA00A

CHECK_LOOP:

//Empty while loop, run indefinitely until condition is true
WHILE (ROM_STAT & 0xA00A) NOT EQUAL TO 0xA00A

//Read Block ID and Block Length from ROM Data Stream 1
ROM_STAT = 0xA00A
BLOCK_ID = READ 16 BITS FROM [ROM_DATA_1]
BLOCK_LEN = READ 16 BITS [ROM_DATA_1]

//Read data as long as Block ID is not 0xCD00
IF BLOCK_ID NOT EQUAL TO 0xCD00

        //Read data for the amount of bytes in the block
	//Store in 256KB WRAM
        WHILE BLOCK_LEN NOT EQUAL TO 0x00
                DATA_VAL = READ 16 BITS FROM [ROM_DATA_1] 
                [0x2000000 + INDEX] = DATA_VAL

                INDEX = INDEX + 2
                BLOCK_LEN = BLOCK_LEN - 2

        //Resets stuff to read next block
	//Yes, *2* subsequent writes ROM_DATA_1, probably to reset Block ID and Length
        [ROM_DATA_1] = 0x00
        [ROM_DATA_1] = 0x00

	//Preps a block for reading
        ROM_CNT = 0xA00A

        GOTO CHECK_LOOP
------------------------------------------------------------------------

First, ROM_CNT is set to 0xA00A, then the program must wait for ROM_STAT to read back the same value. Afterwards, writing 0xA00A to ROM_STAT will prompt the Campho Advance to begin reading the block. The first 32-bits (broken down into 2 16-bit values) of each block contains metadata about the block's ID and the total number bytes in the block. The block ID has a valid range of 0xCC00 to 0xCC0F. The next block ID after 0xCC0F is 0xCD00, which is a dummy zero-length block that signals the end of Program ROM. It is important to remember that any read from ROM_DATA_1 will grab Program ROM data sequentially, so the Campho Advance constantly accesses the address 0x8000000. After all data within a block has been read, the Campho Advance needs to be prepped to read the next one. This involves writing zeroes to ROM_DATA_1 twice and then setting ROM_CNT to 0xA00A once more.

None of the data read or written during this process is warped aside from values for ROM_CNT and ROM_STAT.


***************************************************
9. Graphics ROM
***************************************************

Graphics ROM contains various bitmap graphics for the Campho Advance's menus as well as other visual assets such as fonts. Program ROM handles all access to this data by issuing a command first, then reading the relevant data from ROM_DATA_2. All I/O registers use their Wait State 1 mirrors (0xA000000) for Graphics ROM. The proceedure is as follows:

------------------------------------------------------------------------
//All writes to ROM_DATA_2 are 16-bit
ROM_STAT = 0x4015

//Read Command
[ROM_DATA_2] = 0xB742

//Unknown Parameter, always 1 for reads
[ROM_DATA_2] = 0x0001

//32-bit bank
[ROM_DATA_2] = G_ROM_BANK_LO
[ROM_DATA_2] = G_ROM_BANK_HI

//32-bit offset
[ROM_DATA_2] = G_ROM_OFFSET_LO
[ROM_DATA_2] = G_ROM_OFFSET_HI

ROM_CNT = 0x4015
------------------------------------------------------------------------

G_ROM_BANK refers to the specific 32-bit internal address the Campho Advance assigns portions of Graphics ROM. It is broken down into 2 16-bit components (LO and HI) and written LSB first. G_ROM_BANK *is* warped using the 16-bit method (the upper 16-bits is unused). G_ROM_OFFSET refers to a 32-bit offset typically used when reading sections of Graphics ROM larger than 4000 bytes. G_ROM_OFFSET *is* warped using the 32-bit method described earlier.

As with other commands, the GBA's CPU needs to first wait for the I/O delay signal from ROM_STAT. Once that is done, the data can be read at ROM_DATA_2 in 16-bit units. Although Graphics ROM is normally read in 4000 bytes block at maximum, other smaller sizes are frequently read as well. The first two 16-bit reads will typically return an unknown parameter, possibly a Block ID or some kind of status, followed by the overall length of the block (written as a 32-bit warped value). Afterwards, the rest of the graphics data in that block is streamed. The graphics data itself are 16-bit RGB555 values used by the GBA's bitmap graphics mode that have been warped.

Before reading any blocks from Graphics ROM, however, the above command must first be used to set G_ROM_OFFSET to a value of 0xFFFFFFFF. This acts as some kind of reset mechanism. No data needs to be read, although ROM_STAT must still be checked to make sure Graphics ROM is ready for data transfers. Typically, the offset 0xFFFFFFFF contains no more than 16-bytes of metadata about Graphics ROM bank being read, with details such as its overall length.

When changing from one bank to another, data from the previous bank can still be read. For example, when switching to the offset 0xFFFFFFFF and reading more than 16-bytes, the Campho Advance will then respond with the next data from the old bank as if nothing had changed. Afterwards, when using a different offset for the new bank, new data will appear as expected. In effect, it takes a bit for the hardware to fully switch Graphics ROM banks, therefore it is important to check the length of data being read at this stage. This does not appear to be an issue if it is the first bank the Campho Advance is reading since boot.

There are a total of 314 different banks in Graphics ROM. Valid bank IDs range from 0 - 319 inclusive. However, some banks are either not addressable/non-existent (in the case of an I/O error) or have a length of zero bytes when trying to read them. The invalid banks are listed below:

------------------------------------------------------------------------
Bank ID	| Error Type
------------------------------------------------------------------------
0	| Zero Length
1	| I/O Error
2	| I/O Error
93	| Zero Length
315	| I/O Error
316	| I/O Error
------------------------------------------------------------------------

To check for these I/O errors, the Campho Advance's software runs a fairly tight loop for a few thousand iterations tring to verify that the I/O delay from ROM_STAT has ended. If ROM_STAT has not changed after a certain number of checks, it drops any attempts at reading that bank completely.


***************************************************
10. Camera Capture
***************************************************

The Campho Advance is capable of capturing video input and displaying those frames in real-time on the GBA. It allows the handheld to access 2 different framebuffers that contain the relevant pixel data. The large one measures at 176x144 pixels on the GBA's screen. The small one measures at 58x48. They have similar aspect ratios, so images from the smaller buffer should roughly look the same as the larger one, albeit with more pixelation. The Campho Advance updates its video framebuffer at approximately 5 FPS (or less depending on when the frame is actually ready). The video input can come from the user's Campho Advance or over a telephone network when receiving a videochat, therefore, network conditions may affect how quickly the hardware can fully process a frame. All I/O registers use their Wait State 1 mirrors (0xA000000) for reading camera pixel data.

Once a relevant command has been issued (see the above section), the Campho Advance will periodically alert the GBA when a new frame is available. Once ROM_STAT returns 0xA00A, a new frame can be read. A value of 0x4015 indicates no activity from the camera. Next, the GBA must read 32-bits of metadata from ROM_DATA_1. The first 16-bits designate Framebuffer Transfer Type (e.g. large frame or small frame) as well as the current "slice" of the framebuffer. The second 16-bits designate the Framebuffer Transfer Size in 32-bit units. The different Framebuffer Transfer Types are listed below:

------------------------------------------------------------------------
Type	| Description
------------------------------------------------------------------------
0xA90-	| Read a slice from the small (58x48) framebuffer
0xAA0-	| Read a slice from the large (176x144) framebuffer
0xCFFF	| Signals end of framebuffer reads (dummy data read here)
------------------------------------------------------------------------

Data for the small or large video capture framebuffers is not read all at once. Instead, data is read in shorter "slices". In the case of the small framebuffer, it is divided into 2 separate slices (58x35 and 58x13). For the large framebuffer, it is divided into 13 slices (176x12 each). The slices are drawn from top to bottom and each slice can be seen as an index that determines where it will get drawn on-screen. For example Slice 0 is drawn at the very top, while Slice 12 (on the large framebuffer) is drawn at the very bottom. The last 8-bits of the 16-bit Framebuffer Transfer Type are the slice number.

Both the Framebuffer Transfer Type and Framebuffer Transfer Size output by the Campho Advance are warped, as is the pixel data from the camera. After sending the Framebuffer Transfer Type and Framebuffer Transfer Size, the Campho Advance does the following to read slices:

------------------------------------------------------------------------
//Prep Campho Advance to read pixel data
ROM_STAT = 0xA00A

[ROM_DATA_1] = 0x0008
[ROM_DATA_1] = 0x0000

ROM_CNT = 0xA00A
DATA_INDEX = 0

//Grab pixel data at ROM_DATA_1
WHILE FRAME_TRANSFER_SIZE NOT EQUAL TO ZERO
	DATA_VAL = READ 16 BITS FROM [ROM_DATA_1]

	//Reformat (unwarp) data and store in WRAM (above 64KB used to execute Program ROM)
	DATA_VAL = ((DATA LSL 3) OR (INPUT_16 LSR 13))
	[0x2013000 + DATA_INDEX] = DATA_VAL

	DATA_INDEX = DATA_INDEX + 1
	FRAME_TRANSFER_SIZE = FRAME_TRANSFER_SIZE - 1
------------------------------------------------------------------------

The large framebuffer requires some special considerations for its slices. For whatever reason, its 13 slices slightly overlap. The chart below illustrates which slice draws which lines exactly:

-----------------------------------------------------------
Slice	| Lines Drawn
-----------------------------------------------------------
0	| 0   -  11
1	| 11  -  23
2	| 22  -  34
3	| 33  -  45
4	| 44  -  56
5	| 55  -  67
6	| 66  -  78
7	| 77  -  89
8	| 88  -  100
9	| 99  -  111
10	| 110 -  122
11	| 121 -  133
12	| 131 -  143
-----------------------------------------------------------

Note that the smaller framebuffer does not use anything like this at all. Although it uses 2 separate slices of 35 lines and 13 lines, they don't overlap. All pixels for both framebuffers (once reformatted) are 16-bit RGB555 values, meaning they can be plugged into the GBA's VRAM to draw a bitmap images. Once all pixel data for the camera has been pulled from each slice the Framebuffer Transfer Type changes to 0xCFFF. This signifies the end of readable camera input for a given frame. The Campho Advance then issues the 0xF9FF command to finish camera input and possibly request the next frame. It also writes 0x4015 to ROM_STAT before beginning the entire process all over again. When a new frame is ready, ROM_STAT will automatically read 0xA00A again.

Lastly, pressing L and R together causes the Campho Advance to rotate its entire screen 180 degrees. This can be done at any time outside of Modem Test Mode, although users can enter Modem Test Mode with a rotated screen. The controls flip accordingly as well, so pressing on the D-Pad acts allows users to navigate any menu naturally. This screen rotation allows users to physically rotate the GBA to better position the camera on their face. The actual camera output is not rotated, however, so users still have to change that via configuration settings. It should also be noted that the Campho Advance was designed with the GBA SP in mind, so users of the original GBA (AGB-001) will have to make such adjustments.


***************************************************
11. Configuration and Contact Data
***************************************************

The Campho Advance uses 24 bytes to save configuration data for several adjustable settings, such as brightness, contrast, and volume. The Campho Advance can read and write this entire block of memory all at once, or it can access each setting individually. Additionally, the Campho Advance can store contact data in the form of names and phone numbers using 28-byte entries. The following process is used to read either configuration or contact data; all I/O registers use their Wait State 1 mirrors (0xA000000):

------------------------------------------------------------------------
//All writes are 16-bit
ROM_STAT = 0x4015

//Read all settings/contact data command
[ROM_DATA_2] = 0xB778

//32-bit settings parameter -> 0x1FFE4000 or 0x----4000
[ROM_DATA_2] = DATA_TYPE_LO
[ROM_DATA_2] = DATA_TYPE_HI

ROM_CNT = 0x4015
------------------------------------------------------------------------

The DATA_TYPE value determines what data the Campho Advance will return. To read configuration data, use the value 0x1FFE4000. To read contact data, use the value 0x----4000. The upper 16-bits must be warped for contact data. Depending on this 16-bit value, different entires in the contact data list can be chosen, if multiple entries are present. The Campho Advance typically uses this to navigate up and down the list one entry at a time.

This 16-bit value, when unwarped, contains 2 separate 8-bit components that control what contact data is being looked up. The upper 8-bits is the index used for the contact data list. The lower 8-bits is the operating mode. This operating mode determines what happens to the index after the command is issued. There are 3 valid values:

------------------------------------------------------------------------
Operating Mode	| Effect
------------------------------------------------------------------------
0x00		| Contact Index = 8-bit MSB
0x01		| Contact Index = 8-bit MSB + 1
0xFF		| Contact Index = 8-bit MSB
------------------------------------------------------------------------

Setting the entire 16-bit value to 0xFFFF acts as a reset and forces the Contact Index back to zero.

Afterwards, 28 bytes can be read from ROM_DATA_2. Like Program ROM and Graphics ROM data, the first 32-bits are metadata entries the Campho Advance uses to determine the length to read. The subsequent 24 bytes are the actual settings configuration. To write the entire configuration, the following process is used:

------------------------------------------------------------------------
//All writes are 16-bit
ROM_STAT = 0x4015

//Write all settings/contact data command
[ROM_DATA_2] = 0x3778

//Write data length
[ROM_DATA_2] = 0x0003

//Write configuration data
[ROM_DATA_2] = CONFIG_OR_CONTACT_DATA_00
[ROM_DATA_2] = CONFIG_OR_CONTACT_DATA_01
...
[ROM_DATA_2] = CONFIG_OR_CONTACT_DATA_11

ROM_CNT = 0x4015
------------------------------------------------------------------------

The length of the config data is included, so a total of 26 bytes are written to ROM_DATA_2. Since the length never technically changes, it has a constant value of 0x0003. Note that the length is warped. The rest of the configuration data follows after that, written as 12 16-bit values.

The following process below outlines how to write to individual configuration settings:

------------------------------------------------------------------------
//All writes are 16-bit
ROM_STAT = 0x4015

//Write to settings ID to change a specific setting
[ROM_DATA_2] = SETTINGS_COMMAND

//Write configuration data
[ROM_DATA_2] = SETTINGS_DATA_LO
[ROM_DATA_2] = SETTINGS_DATA_HI

ROM_CNT = 0x4015
------------------------------------------------------------------------

Here, only 6 bytes are written: 16-bits for the settings commands and 32-bits for the actual data. The settings command determines which setting will change. This chart details the known IDs for their settings:

------------------------------------------------------------------------
Command	| Setting
------------------------------------------------------------------------
0x1742	| Microphone Volume
0x3742	| Speaker Volume
0x5742	| Video Brightness
0x7742	| Video Contrast
0x9742	| Camera Image Flip
------------------------------------------------------------------------

The upper half of settings data uses values of 0 - 100 in increments of 10, then that value is warped. The lower 16-bits are always 0x4000. Note that Camera Image Flip is an exception. It only writes 16-bits of data instead of 32-bits (so a total of 4 bytes are written to ROM_DATA_2 in the process shown above). Additionally, the 16-bits of data for Camera Image Flip is always 0x0000. The user's camera will invert vertically every time the command is called.

Once this settings data has been written to the Campho Advance's configuration, the current value can be read back from ROM_DATA_2. Note that the first 32-bits are metadata for the Campho Advance. Below is a layout of the Campho's 24-byte configuration data:

------------------------------------------------------------------------
Address		| Description
------------------------------------------------------------------------
0x00 - 0x01	| Data Type LSBs - Always 0xFFFF
0x02 - 0x03 	| Data Type MSBs - Always 0x1FFE
0x04 - 0x05	| Speaker Volume
0x06 - 0x07	| Microphone Volume
0x08 - 0x09	| Video Brightness
0x0A - 0x0B	| Video Contrast
0x0C - 0x0D	| Video Image Flip
0x0E - 0x0F	| Pulse or Tone Dialing
0x10 - 0x17	| Unknown
------------------------------------------------------------------------

Below is a layout of the Campho's 28-byte entries for contact data:

------------------------------------------------------------------------
Address		| Description
------------------------------------------------------------------------
0x00 - 0x01	| Metadata - Always 0x0831
0x02 - 0x03	| Data Length - Always 0x0003
0x04 - 0x05	| Contact Index
0x06 - 0x07	| Always 0xFFFF
0x08 - 0x11	| Contact Name (10 characters max)
0x12 - 0x1C	| Contact Phone Number (10 digits max)
------------------------------------------------------------------------

The Contact Index specifies which contact data is being written to. If there are multiple entries, for example, the user can edit and existing contact. The Contact Index is then used to decide which one will get written. The index starts counting from 0. The current maximum number of contacts is not yet known. The Contact Index is warped. Using a Contact Index of 0xFFFF has special meaning, as it will simply append new contact data at the furthest unoccupied index.

The Contact Name can be a mixture of katakana, Latin characters, and numbers. That format uses 8-bit values that match uppercase ASCII characters while using a custom character set for katakana. It has some similarities to JIS X 0201 with many modifications. The chart below shows the character maps for katakana:

------------------------------------------------------------------------------------------------------------------------------------
	| 00	01	02	03	04	05	06	07	08	09	0A	0B	0C	0D	0E	0F
------------------------------------------------------------------------------------------------------------------------------------
0xA0 	|	ア	イ	ウ	エ	オ	カ	キ	ク	ケ	コ	サ	シ	ス	セ	ソ	
0xB0	| タ	チ	ツ	テ	ト	ナ	ニ	ヌ	ネ	ノ	ハ	ヒ	フ	ヘ	ホ	マ
0xC0	| ミ	ム	メ	モ	ヤ	ユ	ヨ	ラ	リ	ル	レ	ロ	ワ	ヲ	ャ	ュ
0xD0	| ョ	ァ	ィ	ッ	ン	ゥ	ェ	ォ	ﾞ	ﾟ
------------------------------------------------------------------------------------------------------------------------------------

Note that 0xDA is used as the SPACE character instead the ASCII value 0x20. Characters are grouped into 16-bit pairs; the first character occupies the LSB and the next character occupies the MSB. That 16-bit value is then warped.

The contact's phone number uses the same encoding format as dialing phone numbers. See the next section (Dialing Phone Numbers) for more details.

Both the contact name and phone number are encoded as null terminated strings if their length is 9 characters or less. The Campho Advance seems to return garbage data after the null character for the rest of the contact name or phone number's length. For example, a contact name of "ALICE" would use 6 characters in total, and the remaining 4 would be whatever, usually leftovers from previous commands reading or writing contact data.

Contact data can be erased using the following command:

------------------------------------------------------------------------
//All writes are 16-bit
ROM_STAT = 0x4015

//Write erase command
[ROM_DATA_2] = 0x1779

[ROM_DATA_2] = 0x4000
[ROM_DATA_2] = CONTACT_INDEX

ROM_CNT = 0x4015
------------------------------------------------------------------------

Once again, the Contact Index dictates the exact entry in the contact data list to erase. This value is warped. The current number of contacts can be retrieved using the following command:

------------------------------------------------------------------------
//All writes are 16-bit
ROM_STAT = 0x4015

//Write contact list size command
[ROM_DATA_2] = 0xD778

[ROM_DATA_2] = 0x0000

ROM_CNT = 0x4015
------------------------------------------------------------------------

After waiting for the ROM_STAT I/O delay, 6 bytes of data will be available at ROM_DATA_2, in this format:

------------------------------------------------------------------------
Address		| Description
------------------------------------------------------------------------
0x00 - 0x01	| Metadata - Always 0x0832
0x02 - 0x03	| Data Length - Always 0x4000
0x04 - 0x05	| Contact List Size
------------------------------------------------------------------------

Note that both the Data Length and Contact List Size are warped values.


***************************************************
12. Telephony
***************************************************

As the Campho Advance is capable of video phone calls over landlines, it offers a few commands related to dialing phone numbers, answering phone calls, ending active phone calls, and initializing the camera for simultaneous input from the user and the Campho Advance being called. From the perspective of the GBA, the software does not deal with many low-level details of telephony. The Campho Advance provides an abstracted interface so the handheld can easily deal with this task.

For one Campho Advance to connect to another, one of the users must first dial a phone number via the following command. Unlike several other commands, this one takes parameters of variable lengths, as described below. All I/O registers use their Wait State 1 mirrors (0xA000000).

------------------------------------------------------------------------
//All writes to ROM_DATA_2 are 16-bit
ROM_STAT = 0x4015

[ROM_DATA_2] = 0x3740

[ROM_DATA_2] = NUMBER_OF_DIGITS
[ROM_DATA_2] = DIGITS_01_AND_02
[ROM_DATA_2] = DIGITS_03_AND_04
[ROM_DATA_2] = DIGITS_05_AND_06
[ROM_DATA_2] = DIGITS_07_AND_08
[ROM_DATA_2] = DIGITS_09_AND_10

ROM_CNT = 0x4015
------------------------------------------------------------------------

The Campho Advance can dial numbers of up to 10 digits. The longer the phone number, the more bytes need to be written as parameters. NUMBERS_OF_DIGITS is essentially the length of the phone number, using values of 1 - 10. This 16-bit value is then warped.

The actual digits for the phone number are stored as 16-bit values in pairs. The first digit occupies the LSB, while the second digit occupies the MSB. The Campho Advance uses ASCII encoding, however, the entire 16-bit value is warped.

Note that the "*" / "#" key appears to be just "." on the Campho Advance.

The Campho Advance software constantly checks for incoming data that signals the start of a phone call. At any given  moment, the software may be interrupted by this call, at which point the user is prompted to answer or reject it. If accepted, the connection is established and the call begins with audio and video transmissions. Checking the status of the telephone alerts the Campho Advance whenever any sort of change occurs and respond appropiately.

The process of reading the Modem Status is very similar to how the Campho Advance updates the camera. Typically, ROM_STAT will read 0x4015 when the cartridge receives no external input (either via the camera or the telephone). When new input data becomes available, ROM_STAT will change to 0xA00A. Afterwards, the GBA will read 32-bits from ROM_DATA_1. This value contains 2 16-bit components: a Transfer Type and the length of incoming data. For telephony, only one Transfer Type exists, 0xAB00. For updating the status of the telephone line, the Campho Advance receives an additional 32-bits of data via ROM_STAT, thus the length is always 4. All data read from ROM_DATA_1 at this time is warped.

The additional 32-bits of data is again 2 distinct 16-bit values, labeled here as Internal Phone Function and Modem Status. Internal Phone Function represents a value of 0 - 5 where that forces the Campho Advance to execute certain telephony-related commands, such as answering and ending calls. The below chart demonstrates the structure of the data sent to the Campho Advance:

------------------------------------------------------------------------
Address		| Description
------------------------------------------------------------------------
0x00 - 0x01	| Transfer Type. Always 0xAB00 (0x1560 when warped)
0x02 - 0x03	| Data Length. Always 0x0004 (0x8000 when warped)
0x04 - 0x05	| Internal Phone Function
0x06 - 0x07	| Modem Status 
------------------------------------------------------------------------

The Modem Status byte uses 6-bits to represent various changes in the modem during calls. Each bit seems to represent a distinct state for the Campho Advance. Currently the only definitely known function of these is Bit 5, which indicates that a call is incoming and has triggered the receiver's ringer. Based on string data and code from the ROM, the rest of the bits likely correspond to states for idle, dialing, ringing, connecting, and answering. The following needs hardware verification, but Modem Status may look like this:

------------------------------------------------------------------------
Bit	| Modem State
------------------------------------------------------------------------
0	| Idle
1	| Dialing
2	| Call Connecting
3	| Call Connected
4	| Answering
5	| Ringing
------------------------------------------------------------------------

To connect two Campho Advances, the caller initiates dialing and eventually starts ringing the receiver's end. The modem will transfer a Modem Status of 0x20, causing the receiver's software to switch to a screen with a ringing phone. Once the receiver accepts the incoming call, both the caller's and receiver's Modem Status should read 0x00 temporarily, with relevant value (0x05) stored in the Internal Phone Function. That value for the Internal Phone Function signals a connection being established and alerts the software to show the menu for an active call. The Internal Phone Function's values have the following effects:

------------------------------------------------------------------------
Value	| Function
------------------------------------------------------------------------
0	| Return to main menu (used when disconnecting)
1	| N/A
2	| N/A
3	| N/A
4	| Pauses all menus and animations 
5	| Display active call menu
------------------------------------------------------------------------

Note that the Internal Phone Function only affects how the Campho Advance's software switches between menus and contexts. It's a value returned by the modem, which the ROM's code processes accordingly. Theoretically, a value of 0x04 may be sent briefly by the modem before sending a value of 0x05, causing the Campho Advance to appear to pause shortly during the connection phase. This has not been tested on real hardware yet, however.

Once the caller and receiver are connected, the Campho Advance presumably activates each user's camera automatically. The Campho Advance will display the user's own camera input in the top-left smaller frame (58x48) while the other side's camera input will appear on the larger frame (176x144). The software will prep the Campho Advance to read pixel data by writing to ROM_STAT and ROM_DATA_1 (see the Camera Capture section above) and receive data for each frame in slices. While the user's own camera input should update at a constant 5FPS, the incoming data from the other side will be dependent on any latency from the landline. It appears the Campho Advance's hardware will transfer video data on its own during a call, so there is no need for software to handle that task.

To cancel an active call, either Campho Advance may select the large "X" from the menu to "kill" the connection. This triggers a command to end the call (0xBA08 unwarped, 0x1741 warped). Once the Campho Advance hardware terminates the connection, the modem will send data where both the Internal Phone Function and Modem Status fields are set to 0x00. As a result, the software will return to the main menu.

***************************************************
13. Modem Test Mode
***************************************************

The Campho Advance has a hidden debugger that allows users to directly send commands to the modem for testing purposes. To access it, the L, R, and B buttons must be simultaneously pressed on the same frame and held for a least one additional frame. Once successful, the software enters Modem Test Mode and displays a virtual keyboard, which can be used to enter AT commands. The D-Pad changes the cursor and selected key, the A button enters a key as input, the B button erases a character from input, the L button exits Modem Test Mode, and START initiates the AT command transfer. Any text-based output from the modem as a result of the command is also displayed on-screen. The Modem Test is not mentioned at all in the Campho Advance's manual.

To send the AT command, the Campho Advance software issues the 0xFF84 (0x9FF0 warped) command in the following format:

------------------------------------------------------------------------
//All writes are 16-bit
ROM_STAT = 0x4015

//Write AT send command
[ROM_DATA_2] = 0x9FF0

[ROM_DATA_2] = COMMAND_LENGTH
[ROM_DATA_2] = AT_CMD_01_AND_02
[ROM_DATA_2] = AT_CMD_02_AND_03
[ROM_DATA_2] = AT_CMD_04_AND_05
...

ROM_CNT = 0x4015
------------------------------------------------------------------------

The input will be variable in length depending on the AT command, which is an ASCII string (with no null termination) encoded in much the same fashion as names for contact data. That is to say, each ASCII character is grouped into 16-bit LSB-first pairs and then warped. COMMAND_LENGTH is the total of characters in the string, not the total number of bytes written to ROM_DATA_2.

Eventually, the modem will respond with data in much the same way it sends camera and telephony input. ROM_STAT will change to 0xA00A. Afterwards, the GBA will read 32-bits from ROM_DATA_1, which will contain 2 16-bit components: a Transfer Type and the length of incoming data. For AT command responses, the Transfer Type will be 0x41A0. The length here, however, does refer to the total number of bytes received from the modem. The response data is another ASCII string with the same encoding as previously described. Once the Campho Advance parses the string, it will be displayed.


***************************************************
14. System Compatibility
***************************************************

The Campho Advance is incompatible with any model from the Nintendo DS family. Attempting to boot the original DS or a DS Lite with the Campho Advance in Slot-2 while providing external power generally causes the system to halt with a blank white screen. The likely culprit is the novel way the Campho Advance streams ROM data, which conflicts with the DS firmware as it tries to read Slot-2 when turning on the system. Ultimately, the entire process on the DS differs significantly from the normal GBA BIOS startup routine, which the Campho Advance was heavily tailored around. 

In theory, however, the Campho Advance should work with the following Game Boy Advance models: AGB-001 (original GBA), AGS-001 (GBA SP), AGS-101 (GBA SP), OXY-001 (Game Boy Micro). According to official documentation, the Campho Advance is not compatible with the DOL-017 (Game Boy Player). It must be noted that the Campho Advance was developed and released before the DS launched, so Digital Act likely had no idea it would become incompatible when the next handheld generation came around. A similar situation happened with the Pocket Sonar when the Game Boy Color launched.