Hardware and Accessories

Overview

About Dan Docs

DMG and GBC

Barcode Boy

Barcode Taisen Bardigun Scanner

DMG-07 4-Player Adapter

Zok Zok Heroes Full Changer

GBC Infrared Communication

Gyogun Tanchiki: Pocket Sonar

Power Antenna + Bug Sensor

Turbo File GB

Sewing Machines

GBA

GBA Screen Stretch

Soul Doll Adapter

Battle Chip Gate

Multi Plust On System

Turbo File Advance

AGB-006

Virtureal Racing System

Magical Watch

Joy Carry Cartridge

Advance Movie Adapter

Music Recorder

Play-Yan

Glucoboy

Campho Advance

NDS

Ubisoft Thrustmaster Pedometer

HCV-1000

Magic Reader

Mobile Adapter GB

Hardware Documentation

Mobile Adapter GB

Game and Server Documentation

EX Monopoly

Game Boy Wars 3

Hello Kitty no Happy House

Mario Kart Advance

Mobile Trainer

Net de Get: Minigame @ 100

Zen Nihon GT Senshuken

About Dan Docs

For the longest time, a technical document called Pan Docs formed the basis of nearly all known documentation about the Nintendo Game Boy. To this day, Pan Docs (or an updated version such as the GBDev wiki) continues to be the go-to source of general Game Boy information. However, while Pan Docs covers the basics well enough, it does not touch upon more obscure Game Boy hardware. Dan Docs, on the other hand, aims to fill this gap. Dan Docs is basically everything else you wanted to know about the Game Boy, but no one dared to ask.

All of the data here either comes from my research for the GBE+ project or from others studying Game Boy hardware and software. Much of this information is copied+pasted from the text files I've made over the years. For ease of use and access, however, it's been converted to a single HTML document. As more items are reverse-engineered and studied, they will be added to Dan Docs as well as GBE+.

Consider all information within this document to be Public Domain. Copy and share as you please.

Credits

Billy - Mobile Adapter GB documentation

ClawGrip - Scans of all known Barcode Boy cards

EchelonPrime - Scans of all Card de Asobu cards + misc info

endrift - MBC6 documentation. Collaboration on Battle Chip Gate documentation (especially Progress Chip Gate) + testing + verification of results.

Háčky - Mobile Adapter GB documentation

mid-kid - Mobile Adapter GB documentation

pfero - Mobile Adapter GB documentation

Robert Abel (Tauwasser) - Net de Get translation help

Winter1760 - EX Monopoly and Mario Kart Advance documentation

Barcode Boy

General Hardware Information

Compatible Games

Barcode Boy to DMG Communication

Barcode Format

Card Dumping + Emulation

Barcode Errors

Barcodes

[Barcode Boy] : General Hardware Information

Appearing around 1992, the Barcode Boy is the earliest form of card-scanning on Nintendo's Game Boy line of handhelds, predating both the e-Reader and the Bardigun Taisen Reader by a number of years. Only a limited set of games made by Namcot were compatible with (or rather absolutely required) the Barcode Boy. All of the games and the Barcode Boy itself were only released in Japan.

[Barcode Boy] : Compatible Games

Only 5 Barcode Boy games are known to exist:

Barcode Boy titles come in two types: those that absolutely require the Barcode Boy for any gameplay at all (専用カートリッジ) and those that merely support the Barcode Boy as an accessory for additional content (対応カートリッジ). These games are differentiated with red and blue "B.B." logos respectively. Only Battle Space and Monster Maker: Barcode Saga fall into the first group.

[Barcode Boy] : Barcode Boy to DMG Communication

Each game will first try to detect if the Barcode Boy is plugged in and turned on. The Game Boy will send the bytes [0x10, 0x07, 0x10, 0x07] as part of a handshake. A properly functioning Barcode Boy will return the bytes [0xFF, 0xFF, 0x10, 0x07]. Barcode Boy games will still successfully detect the Barcode Boy scanner even if the first two bytes in the reply to the handshake aren't 0xFF, probably to simplify the game code. As a result, the first two bytes of the handshake are useless and ignored, but the last two bytes *MUST* be [0x10, 0x07]. If the Barcode Boy is plugged in but not turned on, it responds with 0x00 for the entire handshake, and the game produces an error message.

After detection passes, the Game Boy will sit and wait for a response. The Game Boy, unlike how it works with other SIO devices, takes on a passive role with the Barcode Boy by switching to an external clock. The Game Boy actually requires the Barcode Boy to take the initiative when scanning. Therefore, it is assumed that the Barcode Boy uses an internal clock and drives serial communications while scanning a barcode.

Nitty-gritty bits:

  1. The game logic pings the Barcode Boy with [0x10, 0x07, 0x10, 0x07]. The Barcode Boy is expected to reply; the first two bytes are not important (real hardware returns 0xFF), but the second two bytes must be [0x10, 0x07].
  2. Afterwards, the Game Boy waits for input using an external clock. What follows are two strings of numbers representing the barcode data. The "numbers" are represented as ASCII instead of hex.
  3. Both strings are 13-digits long and are the EAN-13 number corresponding to the barcode.
  4. Before sending each string, the Barcode Boy sends a 0x02 byte.
  5. After sending each string, the Barcode Boy sends a 0x03 byte.
  6. Altogether, the Barcode Boy transmits 30 bytes to the Game Boy.

Overall known communication protocol:

Standard communication flow:

[DMG]			[BCB]
Handshake	--->
		<---	Handshake

		<---	0x2
		<---	EAN-13
		<---	0x3

		<---	0x2
		<---	EAN-13
		<---	0x3

Since the Barcode Boy acts as master (after the handshake at least), the Game Boy never initiates a transfer during barcode transmission. When sending barcode data, the Barcode Boy doesn't seem to care what value the Game Boy writes to SB, although no Barcode Boy games write to SB at that time anyway. Ultimately unknown if the Barcode Boy accepts input beyond the handshake, but no evidence has been observed to suggest otherwise.

Once the Barcode Boy sends the handshake [0x10, 0x07] back to the Game Boy, the scanner returns 0xFF anytime the Game Boy tries to send additional data while the handheld is still on its own internal clock. After the Barcode Boy finishes sending back the barcode data to the Game Boy, it requires the handshake again. It appears the handshake can fail for unknown reasons (probably related to the hardware). For example, the Barcode Boy at times may send back [0x90, 0x07], which seems to indicate an error of some sort.

It should be noted that the barcode data itself is encapsulated by ASCII control codes, where 0x02 represents the Start of Text (STX) and 0x03 represents the End of Text (ETX).

[Barcode Boy] : Barcode Format

The two strings are the actual barcode data in numerical form. The barcode format itself is EAN-13, and a few games use JAN-13 specifically. Older JAN-13 barcodes start off with the flag code 49. Interestingly enough, the newer JAN-13 flag code is 45 and was introduced in 1992, the same year the Barcode Boy was released. Probably due to timing or convenience, the JAN-13 barcodes on the cards stuck to the older flag code. Some Barcode Boy barcodes are technically "coupons/vouchers" types, as they use the flag code 99 instead of 45 or 49. Family Jockey 2 and Famista 3 don't use JAN-13 specifically; instead they use random EAN-13 barcodes with varying flag codes.

Using scans of the barcode @ 600 DPI, the smallest bar width is approximately 7 pixels (give or take). With that information, it's possible to recreate the EAN-13 number with a sufficient image and barcode scanning software. It should be noted that the Barcode Boy appears to do away with the center guard, however, it maintains left and right guards.

[Barcode Boy] : Card Dumping + Emulation

Amazingly simple in comparison to something like Barcode Taisen Bardigun, chiefly because such a small amount of bytes need to be sent to the Game Boy. Basically, all you need to do is convert the barcode to EAN-13. Anything capable of reading standard barcodes found on most products should be sufficient to grab the numerical form of each card.

As far as emulation goes, simply convert the EAN-13 ASCII string to hex and transmit it accordingly.

[Barcode Boy] : Barcode Errors

Interestingly enough, a vast majority of the barcodes for Family Jockey 2 are completely incorrect. Only 3 out of the 8 barcodes actually generate horses with the stats listed on the cards. Barcodes A1, B1, and A4 work fine; the rest give stats that do not match up with the card's. Some, such as A2, even generate horses that are totally unfit for competition (A2 produces stats with 2s and 0s, and the max is supposed to be 9 in each category). It's not clear if this was a programming glitch or a mistake Namcot made when printing the cards, or some combination of the two. All other Barcode Boy games came packaged with cards that have no issues whatsoever.

[Barcode Boy] : Barcodes

Below are the full 13 digit barcodes for all known Barcode Boy cards along with any names, other identifying information found on the card, or important notes.

Battle Space

	* Berserker		バーサーカー
	* 4907981000301

	* Valkyrie		バルキリー
	* 4908052808369

	* Grizzly Bear		グリズリー
	* 4916911302309

	* Magic Soldier		マホウセンシ
	* 4902776809367

	* Knight		ナイト
	* 4905672306367

	* Wraith		レイス
	* 4912713004366

	* Shaman		シャーマン
	* 4913508504399

	* Thief			シーフ
	* 4918156001351

	* Sorcerer		ソーサラー
	* 4911826551347

	* Warrior		ウォリアー
	* 4909062206350

Family Jockey 2

	* A1
	* 5893713522816

	* A2			(Erroneous Barcode)
	* 2378649896765

	* A4
	* 9845554422318

	* B1
	* 1509843019075

	* B2			(Erroneous Barcode)
	* 4232978865152

	* B4			(Erroneous Barcode)
	* 3572821107673

	* C3			(Erroneous Barcode)
	* 7164625542390

	* C5			(Erroneous Barcode)
	* 6319537443513

Famista 3

	* Home-Run Batter	ホームランバッター
	* 8357933639923

	* Senior Batter		高打者バッター
	* 7814374127798

	* Swift Batter		駿打者バッター
	* 9880692151263

	* Pitcher		ピッチャー
	* 1414213562177

Kattobi Road

	* Truck			フォワールド
	* 4902105002063

	* Sedan			ガウディ
	* 4901121110004

	* Racecar		ナイト 2000
	* 4903301160625

	* Japanese Street Car	ミイラターボ
	* 4902888119101

	* 4x4 Jeep		リイスラックス
	* 4901780161157

	* F1-style racecar	ロクタスヨンート
	* 4987084410924

Monster Maker: Barcode Saga

	* Archer Lorian		弓使いロリエーン
	* 9998017308336

	* Archer Elysice	弓使いエリサイス
	* 9447410810323

	* Knight Lauren		騎士ローラン
	* 9052091324955

	* Dragon Knight Haagun	竜騎士ハーグン
	* 9322158686716

	* Warrior Diane		戦士ディアーネ
	* 9752412234900

	* Warrior Tamron	戦士タムローン
	* 9362462085911

Barcode Taisen Bardigun Scanner

General Hardware Information

Card Reader to GBC Communication

Barcode Format

Card Dumping

ROM Revision

Barcodes

[Barcode Taisen Bardigun] : General Hardware Information

Barcode Taisen Bardigun is a Japanese Game Boy game released December 11, 1998, made by TAM. It doesn't seem like a very interesting or noteworthy game in and of itself (yet another monster breeding/raising/fighting/collecting game). However, this game featured exclusive hardware, a card reader that scanned various barcodes

[Barcode Taisen Bardigun] : Card Reader to GBC Communication

Game Boy will initialize a transfer with an internal clock; much like every other Serial I/O device (GB Printer, GB Mobile Adapter), Game Boy sends initial data, then the reader responds. Transfer rate is 1KB/s, the slowest speed, so there is no difference between DMG and GBC transfers. To begin, the Game Boy constantly sends 0xFF to the reader. The game logic times out after a few seconds if no proper response is established.

To scan a card, hold it face down (barcode facing the ground and towards the reader), press the reader's button, and swipe. The scanner only seems to activate once the button is pushed (otherwise it'd waste battery if it were constantly on, or constantly on and trying to receieve commands from the Game Boy). Without pressing the button, the game logic times out the scanning process after a few seconds (about 9 seconds). If an error is detected during the scan process, the reader seems to acknowledge this pretty quickly.

Nitty-gritty bits

  1. When connected, the reader responds with 0x00 until it is prepared to send the barcode data.
  2. Afterwards, it begins processing barcode data. Data is represented serially. A bit reading "1" indicates that the card reader is detecting whitespace. A bit reading "0" indicates the card reader is detecting a black segment (black bar).
  3. The barcode sequence itself is nothing more than a continuous stream of zeroes and ones. That is to say, groups of ones and zeroes are always packed together, but the length of each group determines the length of any given bar.
  4. There doesn't appear to be a fixed number of bytes that the Game Boy seems to expect when scanning. Different scans seem to produce different amounts of data transferred to the Game Boy. This could be due to numerous reasons in the hardware (swipe speed, how clean the scanner is, some other variance within the scanner's light sensitivity). Overall, however, the most important thing seems to be the length and sequence of the bars encoded as groups of ones and zeroes.
  5. The Game Boy doesn't ever seem to send any interesting data, just 0xFF. No commands are sent. The Game Boy simply sends a byte and expects a result to come from the reader; the results are what matter and are interpreted later on.

[Barcode Taisen Bardigun] : Barcode Format

Because the incoming barcode data is not consistent byte-for-byte, the patterns are what matters most. To illustrate this idea, below are two sets of data extracted after scanning a card (using a hacked version of Barcode Taisen Bardigun and saving all SIO communications to Cart RAM).

SET_1		SET_2
00 00		00 03		
7F FE		FF F8
00 01		00 03
FF FF 		FF FF
FF FF		FF FF
FF C0		FF E0
00 3F		00 0F
FF 00		FF 80
00 00		00 00
07 FF		00 FF
00 00		FC 00
FF FF		03 FF
FF C0		FF FF
00 00		C0 00

Each set is actually a bitstream of 0s and 1s like so:

Set 1 [16:0] [14:1] [15:0] [43:1] ...
Set 2 [14:0] [15:1] [14:0] [45:1] ...

The patterns in the sets are roughly the same. They switch between 0s, 1s, and 0s (black, white, black) fairly quickly followed by a long segment of 1s (white) which is roughly the general pattern seen at the beginning/ends of the barcodes. Based on this information, the thinest bars are about 0.0133 inches (8 pixels when scanning at 600dpi). Some further calculations based on this information:

Bar Width (in pixels @ 600dpi) -> Estimated bit-count sent to Game Boy

8	->	~14-16
16	->	~27-29
24	->	~43-45

Every 8 pixels should be approximately 15 bits worth of data sent to the Game Boy, so:

Number of Pixels @ 600dpi * 1.875 = Approximate bit count

The physical barcode format on the actual cards is EAN-13.

[Barcode Taisen Bardigun] : Card Dumping

With the above guideline, it is possible to dump the cards by scanning them, then creating a binary file containing barcodes as alternating bitstreams of 0s and 1s. With this method, no homebrew techniques are needed, and only an image file is necessary to actually preserve the card.

The second method involves using a hacked version of the Barcode Taisen Bardigun ROM on a flashcart to save incoming Serial I/O data as a card is scanned. The binary can be pulled from a save file. Both binary files could be used an input to feed back to an emulator.

[Barcode Taisen Bardigun] : ROM Revision

Barcode Taisen Bardigun has two known ROMs, DMG-ABEJ-JPN and DMG-ABEJ-JPN-1. The later version polishes many rough edges found in the first release (e.g. including a text box when barcode scanning fails). Currently, both games appear to be largely the same besides these UI and UX enhancements. Barcode scanning is exactly the same in each.

[Barcode Taisen Bardigun] : Barcodes

Below is a chart with barcodes verified to work with the game. Each barcode will produce a single Bardigun when scanning to hatch an egg. The barcode can also be used to give Bardigun unique attacks when scanned before a battle begins. The names of each are listed in kana as well as Romanji or English when translatable.

------------------------------------------------------------------------------------------------
Barcode		| Bardigun :: Attack Name (English)	| Bardigun :: Attack Name (Japanese)
------------------------------------------------------------------------------------------------
4580245316402	| Chakanan :: High Hearing		| チャカナン :: ハイヒーリング
4900287167419	| Chibisshii :: Sword			| チビッシー :: ソード
4901330547479	| Chibisshii :: Eye Beam		| チビッシー :: めからベーム
4983164730678	| Chip :: Lullaby			| チップ :: こもりうた
4900753335663	| Noise :: Ikikaeeru			| ノイヅー :: イキカエール
4900363432103	| Nyaari :: Kaenhoushaki		| ニャーリー :: かえんほうしゃき
4900758340136	| Ralph :: Ikikaeeru			| ラルフ :: イキカエール
4902370501445	| Takora :: Fire Bolt			| タコラ :: ファイアーボルト
4900269429252	| Tamappi :: Nandemonaooru		| タマッピ :: ナンデモナオール
------------------------------------------------------------------------------------------------

DMG-07 4-Player Adapter

General Hardware Information

Compatible Games

Link Cable Protocol

Ping Phase

Transmission Phase

Restarting Ping Phase

[DMG-07] : General Hardware Information

The DMG-07 is an accessory that allows 4 Game Boys to connect for multiplayer. In the West, it first appeared with the game F-1 Race as bundle in 1990. Only a few other games took advantage of the DMG-07 (namely Wave Race and Faceball 2000, Yoshi's Cookie) and it did not see widespread support at all.

[DMG-07] : Compatible Games

F1 Pole Position is the localization of the Japanese game Nakajima Satoru F-1 Hero GB '92: The Graded Driver. Both versions support the DMG-07. The prequel, Nakajima Satoru F-1 Hero GB World Championship '91, was however a Japanese exclusive.

Several games are claimed to be compatible but actual support for the DMG-07 remains dubious at best for those titles. Gauntlet II advertises 4-player action via the Link Cable, but this may simply refer to 2-player mode with each Game Boy controlling 2 characters (and switching among friends when appropiate).

Micro Machines 1 claims to support the DMG-07 in its instruction manual, but it does not appear to work; it may have been a planned but unfinished feature. Although the game initially tries to handle the DMG-07 Ping Phase, the acknowledgement signal is malformed. Based on hardware tests the game does not properly follow the DMG-07 protocol. If a DMG-07 is plugged in while booting the game, the software may ignore all input from Player 1 if the title screen runs for a few seconds. Unplugging the DMG-07 restores input from Player 1. The main game can be accessed by pressing buttons quickly on the title screen, however, various glitches occur with the DMG-07 plugged in. Most immediately return to the title screen after choosing a race course.

Micro Machines 2 has no indication of 4-player support outside of other versions, such as the PC edition.

[DMG-07] : Link Cable Protocol

The DMG-07 protocol can be divided into 2 sections, the "ping" phase, and the "transmission" phase. The initial ping phase involves sending packets back and forth between connected Game Boys probing for their current connection status. Afterwards, the DMG-07 enters into transmission mode where the Game Boys exchange data across the network.

A very important thing to note is that all Game Boys transfer data across the DMG-07 via an external clock source. Apparently, the clock source is provided by the DMG-07 itself. Trying to send data via an internal clock results in garbage data.

[DMG-07] : Ping Phase

When a "master" Game Boy (Player 1) is first connected to the DMG-07, setting Bit 7 of 0xFF02 to 1 and setting Bit 0 of 0xFF02 to 0 causes the accessory to send out "ping" packets periodically. All connected Game Boys will receive 4 bytes as part of the ping packet, at a rate of about 2048 bits-per-second, or about 256 bytes-per-second. Essentially, the ping seems to run 1/4 as fast as the clock used for normal serial transfers on the DMG (1KB/s). The ping data looks like this:

0xFE		ID Byte
0x??		STAT1
0x??		STAT2
0x??		STAT3

3 "STAT" bytes are sent indicating the current connection status of the other Game Boys. Each byte is usually the same, however, sometimes the status can change mid-way through a ping, typically on STAT2 or STAT3. Each STAT byte looks like such:

Bit 0-2: 	Player ID
Bit 4:		Player 1 Connected
Bit 5:		Player 2 Connected
Bit 6:		Player 3 Connected
Bit 7:		Player 4 Connected

The Player ID is simply a value of 1-4. Its value is determined by whichever port a Game Boy is connected to. As more Game Boys connect, the upper bits of the STAT bytes are turned on.

When talking about Game Boys and the "connection", this refers to a Game Boy properly responding to STAT1 and STAT2 bytes when receiving a ping packet from the DMG-07. In this way, the Game Boy broadcasts across the Link Cable network that it is an active participant in communications. It also acts as a sort of acknowledgement signal, where software can drop a Game Boy if the DMG-07 detects an improper response during a ping, or a Game Boy simply quits the network. The proper response is to send 0x88 *after* receiving the ID Byte and STAT1, in which case the upper-half of STAT1, STAT2, and STAT3 are updated to show that a Game Boy is "connected". If for whatever reason, the acknowledgement codes are not sent, the above bits are unset.

Some examples of ping packets are shown below:

0xFE 0x01 0x01 0x01	->	Ping packet received by Player 1 with no other Game Boys connected
0xFE 0x11 0x11 0x11	->	Ping packet received by Player 1 when Player 1 has connected
0xFE 0x31 0x31 0x31	->	Ping packet received by Player 1 when Players 1 & 2 have connected
0xFE 0x71 0x71 0x71	->	Ping packet received by Player 1 when Players 1, 2, & 3 have connected
0xFE 0x62 0x62 0x62	->	Ping packet received by Player 2 when Players 2 & 3 are connected (but not Player 1)

It's possible to have situations where some players are connected but others are not; the gaps don't matter. For example, Player 1 and Player 4 can be connected, while Player 2 and Player 3 can be disconnected (or non-existant, same thing); most games do not care so long as Player 1 is active, as that Game Boy acts as master and orchestrates the multiplayer session from a software point of view. Because of the way the DMG-07 hardcodes player IDs based on which port a Game Boy is physically connected to, in the above situation Player 4 wouldn't suddenly become Player 2 in a game like F-1 Race.

During the ping phase, the master Game Boy is capable of setting up two parameters that will be used during the transmission phase. The clock rate for the transmission phase can be adjusted, as well as the packet size each Game Boy will use. The master Game Boy needs to respond with one byte for STAT2 and STAT3 respectively. The chart below illustrates how a master Game Boy should respond to all bytes in a ping packet:

----------------------------
DMG-07		Game Boy
----------------------------
0xFE	<-->	(ACK1) = 0x88
STAT1	<-->	(ACK2) = 0x88	
STAT2	<-->	(RATE) = Link Cable Speed 
STAT3	<-->	(SIZE) = Packet Size

The new clock rate is only applied when entering the transmission phase; the ping phase runs at a constant 2048 bits-per-second. The formula for the new clock rate is as follows:

DMG-07 Bits-Per-Second --> 4194304 / ((6 * RATE) + 512)

The lowest setting (RATE = 0) runs the DMG-07 at the normal speed DMGs usually transfer data (1KB/s), while setting it to 0xFF runs its close to the slowest speed (2042 bits-per-second).

SIZE sets the length of packets exchanged between all Game Boys. Nothing fancy, just the number of bytes in each packet. It probably shouldn't be set to zero.

[DMG-07] : Transmission Phase

When the master Game Boy (Player 1) is ready, it should send 4 bytes (0xAA 0xAA 0xAA 0xAA). Some games only send 3 bytes however (0xAA 0xAA 0xAA and 0x00). This alerts the DMG-07 to start the transmission phase. The RATE and SIZE parameters are applied at this point. The protocol is simple: Each Game Boy sends a packet to the DMG-07 simultaneously, then the DMG-07 outputs each packet to all connected Game Boys. All data is buffered, so there is a 4 packet delay after each Game Boy submits their data (the delay is still 4 packets long even if some Game Boys are not connected). For example, say the packet size is 4 bytes; the flow of data would look like this when sending:

--------------------------------------------------------------------------------------------
P1 send		P2 send		P3 send		P4 send		Transfer count
--------------------------------------------------------------------------------------------
P1_byte_1	P2_byte_1	P3_byte_1	P4_byte_1	0
P1_byte_2	P2_byte_2	P3_byte_2	P4_byte_2	1
P1_byte_3	P2_byte_3	P3_byte_3	P4_byte_3	2
P1_byte_4	P2_byte_4	P3_byte_4	P4_byte_4	3

0		0		0		0		4 (Typically supposed to be zero, but DMG-07 ignores anything here)
0		0		0		0		5
0		0		0		0		6
0		0		0		0		7

0		0		0		0		8
0		0		0		0		9
0		0		0		0		10
0		0		0		0		11

0		0		0		0		12
0		0		0		0		13
0		0		0		0		14
0		0		0		0		15

And when receiving, the flow of data would look like this:

--------------------------------------------------------------------------------------------
P1 recv		P2 recv		P3 recv		P4 recv		Transfer count
--------------------------------------------------------------------------------------------
P1_byte_1	P1_byte_1	P1_byte_1	P1_byte_1	16
P1_byte_2	P1_byte_2	P1_byte_2	P1_byte_2	17
P1_byte_3	P1_byte_3	P1_byte_3	P1_byte_3	18
P1_byte_4	P1_byte_4	P1_byte_4	P1_byte_4	19

P2_byte_1	P2_byte_1	P2_byte_1	P2_byte_1	20
P2_byte_2	P2_byte_2	P2_byte_2	P2_byte_2	21
P2_byte_3	P2_byte_3	P2_byte_3	P2_byte_3	22
P2_byte_4	P2_byte_4	P2_byte_4	P2_byte_4	23

P3_byte_1	P3_byte_1	P3_byte_1	P3_byte_1	24
P3_byte_2	P3_byte_2	P3_byte_2	P3_byte_2	25
P3_byte_3	P3_byte_3	P3_byte_3	P3_byte_3	26
P3_byte_4	P3_byte_4	P3_byte_4	P3_byte_4	27

P4_byte_1	P4_byte_1	P4_byte_1	P4_byte_1	28
P4_byte_2	P4_byte_2	P4_byte_2	P4_byte_2	29
P4_byte_3	P4_byte_3	P4_byte_3	P4_byte_3	30
P4_byte_4	P4_byte_4	P4_byte_4	P4_byte_4	31

Again, due to buffering, data output to the DMG-07 is actually delayed by several transfers according to the size of the packets. All connected Game Boys should send their data into the buffer during the first few transfers. Here, the packet size is 4 bytes, so each Game Boy should submit their data during the first 4 transfers. The other 12 transfers don't care what the Game Boys send; it won't enter into the buffer. The next 16 transfers return the packets each Game Boy previously sent (if no Game Boy exists for player, that slot is filled with zeroes).

With the buffering system, Game Boys would normally be reading data from previous packets during transfers 0-15, in addition to sending new packets. Likewise, during transfers 16-19 each Game Boy is sending new packets. In effect, while receiving old data, Game Boys are supposed to pump new data into the network.

When the DMG-07 enters the transmission phase, the buffer is initially filled with garbage data that is based on output the master Game Boy had sent during the ping phase. At this time, it is recommended to ignore the earliest packets received, however, it is safe to start putting new, relevant data into the buffer.

[DMG-07] : Restarting Ping Phase

It's possible to restart the ping phase while operating in the transmission phase. To do so, the master Game Boy should send 4 or more bytes (0xFF 0xFF 0xFF 0xFF). Again, some games send less (0xFF 0xFF 0xFF and 0x00). It's possible only 1 or 2 0xFF bytes need to be sent, but this has not been extensively investigated yet. At any rate, the bytes alert the DMG-07 that the ping phase should begin again. Most games use this to end the multiplayer session and return to the title screen. For example, in F-1 Race, the game automatically jumps back to the title screen after all races have been completed, while Wave Race has a menu to continue playing or end the session. In either case, the games send 0xFF bytes and the DMG-07 sends ping packets after a brief delay. During this delay, the transmission protocol is still working as intended until the switch happens.

Zok Zok Heroes Full Changer

General Hardware Information

Operation

IR Communication

Capturing IR Data

Emulation

Cosmic Characters

[Full Changer] : General Hardware Information

Zok Zok Heroes was a GBC JRPG released on August 4, 2000, made by Media Factory when they still produced video games. It used a special accessory called the "Full Changer", a device that looks like a toy, but acts as an IR transmitter. It sent signals to the GBC once players moved it through the air to "draw" certain patterns. Once the GBC gets the IR light pulses, it allows players to transform into different "Bright Heroes" to do battle against evil bad guys. It never sold outside of Japan. After a specific point early in the game, it becomes impossible to progress further in emulators without cheat codes/hacks or by properly emulating the Full Changer.

[Full Changer] : Operation

  1. Grab the Full Changer firmly, holding it by the strap
  2. Press and release the top button. It should beep and the 3 lights should flash for approximately 5 seconds.
  3. During those 5 seconds, move the Full Changer to draw the pattern of a "Cosmic Character" e.g. for "Z" start left, move right, stop, move downward and leftward, stop, move right, stop.
  4. Make sure the Full Changer is always held upright while drawing.
  5. For each successful movement, the Full Changer will activate another light and beep. Once all three at lit, it beeps a little tune and the data is ready to be sent to the GBC.
  6. Put the bottom of the Full Changer on top of the GBC, making sure to cover the IR port. The Full Changer has a little plastic guide to make sure everything fits and faces the right direction.

[Full Changer] : IR Communication

The Full Changer sends a total of 18 IR pulses (ON then OFF periods) when transmitting data. The length of these pulses varies and determines what values the Full Changer is trying to send. Zok Zok Heroes runs in a couple of loops while the pulse takes place. Each iteration, it increments a counter to get an idea of the overall "delay" it takes for the IR light to turn on then turn off. That counter is then placed in WRAM as a single byte (anything greater than 0xFF causes a timeout) and verified later. In this way, Zok Zok Heroes can view data from the Full Changer as a series of bytes rather than light pulses. These 18 bytes do not have especially strict values, rather they are expected to fall within a certain range to indicate long or short pulses.

[Full Changer] : Capturing IR Data

Below is psuedo-code representing how Zok Zok Heroes grabs the 18 bytes:

==================================
LABEL CHECK_ON_LOOP:
==================================

	//Use an 8-bit CPU register as a Time-Out Counter, initially set to 0xFF, exit if it hits zero
	TIMEOUT_COUNTER--
	
	IF(TIMEOUT_COUNTER == 0)
	{
		RETURN
	}

	//Load A from 16-bit immediate address for RP register
	A = [0xFF56]

	//Wait for IR light to come on (Bit 1 of 0xFF46 goes to zero)
	IF(A AND 0x1)
	{
		GOTO CHECK_ON_LOOP
	}

	//Use another 8-bit CPU register to act as a counter for total number of bytes processed from Full Changer
	TOTAL_BYTES = 0x12

	//Set a 16-bit CPU register pair as the destination address (0xD005+) to write IR data
	DEST_ADDR = 0xD005

==================================
LABEL GRAB_IR_BYTES:
==================================

	//Wait for IR light to go off (Bit 1 of 0xFF46 goes to one)
	//Set an 8-bit CPU register to act as an IR pulse length counter, initialized to 0x00
	PULSE_LENGTH = 0x00

	CALL WAIT_FOR_OFF
	CALL WAIT_FOR_ON

	//Save pulse length results to 0xD005 - 0xD017
	[DEST_ADDR] = PULSE_LENGTH

	DEST_ADDR++
	TOTAL_BYTES--

	IF(TOTAL_BYTES != 0)
	{
		GOTO GRAB_IR_BYTES
	}
	
	...

	//IR handling code ends here

==================================
FUNCTION WAIT_FOR_OFF:
==================================

	PULSE_LENGTH++
	
	IF(PULSE_LENGTH == 0)
	{
		RETURN
	}

	//Load A from 16-bit immediate address for RP register
	A = [0xFF56]

	//Wait for IR light to come on (Bit 1 of 0xFF46 goes to one)
	IF((A AND 0x1) == 0x00)
	{
		GOTO WAIT_FOR_OFF
	}

	RETURN

==================================
FUNCTION WAIT_FOR_ON:
==================================

	PULSE_LENGTH++
	
	IF(PULSE_LENGTH == 0)
	{
		RETURN
	}

	//Load A from 16-bit immediate address for RP register
	A = [0xFF56]

	//Wait for IR light to come on (Bit 1 of 0xFF46 goes to zero)
	IF(A AND 0x1)
	{
		GOTO WAIT_FOR_ON
	}

	RETURN

Once all 18 bytes have been stored in WRAM, it's possible to read them and save them using a ROM hack. Alternatively, homebrew software can use code with the same timing to accurately capture IR data from the Full Changer.

[Full Changer] : Emulation

The Full Changer can be successfully emulated by setting Bit 1 of RP register (located at 0xFF56) to 0 or 1 at the appropiate times. To do so requires accurate timing and knowing the amount of cycles it takes to generate the delays represented by those 18 bytes in WRAM. When activating the Full Changer, GBE+ always fires the 1st "ON" IR signal at a specific time to get consistent timings:

TIMEOUT_COUNTER--
	
IF(TIMEOUT_COUNTER == 0)
{
	RETURN
}

A = [0xFF56]

<---- After the CPU reads 0xFF56 and the user activates the Full Changer, IR light is turned on here
<---- This happens after the actual read instruction is executed, so the loop runs once more

IF(A AND 0x1)
{
	GOTO CHECK_ON_LOOP
}

Afterwards, the timings for ON and OFF pulses can be calculated as such (ALL TIMING IS IN DOUBLE SPEED):

1st ON pulse length			74 + (20 * (LENGTH-2))

Every other ON pulse length		78 + (20 * (LENGTH-2))

OFF pulse length			38 + (20 * (LENGTH-2))

The LENGTH is number of times the 8-bit CPU register is incremented in the WAIT_FOR_OFF or WAIT_FOR_ON functions. The sum of two LENGTHs from one ON pulse and one OFF pulse must be equal to the delay data in WRAM. For example, say the delay data contains 0x20. This means that the TOTAL amount of times the 8-bit register was incremented is 0x20. In a perfect world, the Full Changer would probably turn on the IR light so that this 8-bit register is incremented 0x10 times, then turn off the IR light so that D is incremented again 0x10 times. In reality, however, the length of the ON/OFF pulses could run a bit longer or shorter. As far as Zok Zok Heroes is concerned, the total amount of time the IR light is ON then OFF is what matters, so the ON/OFF pulse timings ultimately have to add up

The current database GBE+ uses recreates ON/OFF pulses that generally run for the same amount of cycles. However, based on hardware tests, the ON pulses have variable lengths, while the OFF pulses are typically constant. Again, Zok Zok Heroes won't care, as long as the total time of the ON/OFF pulses meets whatever value it expects.

[Full Changer] : Cosmic Characters

There are a total of 70 "Cosmic Characters" available in Zok Zok Heroes, and by extension, there are 70 unique transformations. This Cosmic Character is simply an 8-bit ID generated from the ON and OFF pulses from the Full Changer. Using the delays stored in the 18 WRAM bytes, the game software uses the following logic to determine an ID.

The first pulse is checked to ensure that it has a delay greater than 0x20, signaling a long pulse, otherwise processing for the Cosmic Character does not continue. Afterwards, the next 16 pulses are examined to build two separate 8-bit values. These values are constructed LSB. A short pulse (any value from 0x00 to 0x13) translates into a "0", and a long pulse (any value from 0x14 to 0x20) translates into a "1". The 1st 8-bit value built from these pulses is used for a checksum of a sort, and the 2nd 8-bit value is complemented to form an ID. IDs range from 0x01 to 0x46 and correspond to the 70 Cosmic Characters. Note that while the 18th IR pulse is required by the software, it isn't used for the ID or checksum.

Checksum Calculation:
Pulse Byte 1 + Pulse Byte 2 = 0xFF

Cosmic Character ID Calculation:
~Pulse Byte 2 = Cosmic Character ID

Pulse Byte 1 Calculation (using an arbitrary ID of one's choosing):
Pulse Byte 1 = 0xFF - (~Cosmic Character ID)

Pulse Byte 2 Calculation (using an arbitrary ID of one's choosing):
Pulse Byte 2 = ~Cosmic Character ID

------------------------------------------------------------------------------------------------------------
ID	| Cosmic Character Movements (S* = Short Move)	| Translated Name	| (Character) Japanese Name
------------------------------------------------------------------------------------------------------------
01 	| Up, Down, Up					| Alkaline Powered	| (あ) アルカリパワード
02 	| Right, Left, Right				| In Water 		| (い) イン ウォーター
03 	| Down, Up, Down				| Ultra Runner		| (う) ウルトランナー
04 	| Left, Right, Left 				| Aero Power		| (え) エアロ パワー
05 	| Down+Left, Right, Left			| Ochaapa		| (お) オチャッパ
06 	| Up, Right, Down				| Kaizer Edge		| (か) カイザーエッジ
07 	| Right, Down, Left				| King Batter		| (き) キングバッター
08 	| Down, Left, Up				| Crash Car		| (く) クラッシッカー
09 	| Left, Up, Right				| Cellphone Tiger	| (け) ケイタイがー
10 	| Down+Left, Up, Right				| Cup Ace		| (こ) コップエース
11 	| Up, Left, Down				| Sakanard		| (さ) サカナード
12 	| Right, Up, Left				| Thin Delta		| (し) シンデルター
13 	| Down, Right, Up				| Skateboard Rider	| (す) スケボーライダー
14 	| Left, Down, Right				| Celery Star		| (せ) セロリスター
15 	| Down+Left, S* Down, Right			| Cleaning Killer	| (そ) ソウジキラー
16 	| S* Up, Right, S* Up				| Takoyaki Kid		| (た) タコアキッド
17 	| S* Right, Down, S* Right			| Chinkoman		| (ち) チンコーマン
18 	| S* Down, Left, S* Down			| Tsukai Stater		| (つ) ツカイステイター
19 	| S* Left, Up, S* Left				| Teppangar		| (て) テッパンガー
20 	| S* Down+Left, Up, S* Left			| Tongararin		| (と) トンガラリン
21 	| S* Up, Right, Left				| Nagashiman		| (な) ナガシマン
22 	| S* Right, Down, Up				| Ninja			| (に) ニンジャーノン
23 	| S* Down, Left, Right				| Plushy-chan		| (ぬ) ぬいぬいちゃん
24 	| S* Left, Up, Down				| Screw Razor		| (ね) ネジレイザー
25 	| S* Down+Left, Up, Down			| Nobel Brain		| (の) ノーベルブレイン
26 	| S* Up, Left, S* Up				| Hard Hammer		| (は) ハードハンマー
27 	| S* Right, Up, S* Right			| Heat Man		| (ひ) ヒートマン
28 	| S* Down, Right, S* Down			| Flame Gourmet		| (ふ) フレイムグルメ
29 	| S* Left, Down, S* Left			| Hercules Army		| (へ) ヘラクレスアーミー
30 	| S* Down+Left, S* Down, S* Left		| Hot Card		| (ほ) ホットカード
31 	| S* Up, Left, Right				| Mr. Muscle		| (ま) マッスルさん
32 	| S* Right, Up, Down				| Mist Water		| (み) ミストウォーター
33 	| S* Down, Right, Left				| Mushimushi Man	| (む) ムシムシマン
34 	| S* Left, Down, Up				| Megaaten		| (め) メガーテン
35 	| Down+Left, Down, Up				| Mobile Robot X	| (も) モビルロボX
36 	| Up, Down, Left				| Yaki Bird		| (や) ヤキバード	 
37 	| Down, Up, Right				| Utron			| (ゆ) ユートロン
38 	| Down+Left, Right, Down			| Yo-Yo Mask		| (よ) ヨーヨーマスク
39 	| Up, Down, Right				| Radial Road		| (ら) ラジアルロード
40 	| Right, Left, Down				| Remote-Control Man	| (り) リモコンマン
41 	| Down, Up, Left				| Ruby Hook		| (る) ルビーフック
42 	| Left, Right, Up				| Retro Sounder		| (れ) レトロサウンダー
43 	| Down+Left, Right, S* Up			| Rocket Bastard	| (ろ) ロケットやろう 
44 	| Up, Down, Up+Left				| Wild Sword		| (わ) ワイルドソード
45 	| Up, Down+Right, S* Left			| Guts Lago		| (が) ガッツラゴー
46 	| Right, Down+Left, S* Up			| Giniun		| (ぎ) ギーニウン
47 	| Down, Up+Left, S* Right			| Great Fire		| (ぐ) グレートファイヤー
48 	| Left, Up+Right, S* Down			| Gamemark		| (げ) ゲーマルク
49 	| Down+Left, Up+Right, S* Down			| Gorilla Killa		| (ご) ゴウリキラー
50 	| Up, Down+Right, S* Right			| The Climber		| (ざ) ザ・クライマー
51 	| Right, Up+Left, S* Down			| G Shark		| (じ) Gシャーク
52 	| Down, Up+Right, S* Left			| Zoom Laser		| (ず) ズームレーザー
53 	| Left, Down+right, S* Up			| Zenmai		| (ぜ) ゼンマイン
54 	| S* Down+Left, S* Down+Right, S* Up		| Elephant Shower	| (ぞ) ゾウシャワー
55 	| Up, Down+Right, Up				| Diamond Mall		| (だ) ダイヤモール
56 	| Right, Down+Left, Right			| Digronyan		| (ぢ) ヂグロニャン
57 	| Down, Up+Left, Down				| Ziza One		| (づ) ヅィザーワン
58 	| Left, Up+Right, Left				| Danger Red		| (で) デンジャレッド
59 	| Down+Left, Up+Right, Left			| Dohatsuten		| (ど) ドハツテン
60 	| Up, Down+Left, Up				| Balloon		| (ば) バルバルーン
61 	| Right, Up+Left, Right				| Videoja		| (び) ビデオージャ
62 	| Down, Up+Right, Down				| Boo Boo		| (ぶ) ブーブーウー
63 	| Left, Down+Right, Left			| Belt Jain		| (べ) ベルトジャイン
64 	| S* Down+Left, Down+Right, Left		| Boat Ron		| (ぼ) ボートロン
65 	| Up, Down+Left, Up+Left			| Perfect Sun		| (ぱ) パーフェクトサン
66 	| Right, Up+Left, Up+Right			| Pinspawn		| (ぴ) ピンスポーン
67 	| Down, Up+Right, Down+Right			| Press Arm		| (ぷ) プレスアーム
68 	| Left, Down+Right, Down+Left			| Pegasus Boy		| (ぺ) ペガサスボーイ
69 	| S* Down+Left, S* Down+Right, S* Down+Left	| Pop Thunder		| (ぽ) ポップサンダー
70 	| Right, Down+Left, Down+Right			| Ndjamenas		| (ん) ンジャメナス

GBC Infrared Communication

General Hardware Information

Compatible Games

Communication Types

Communication Protocol

RP Register

Signal Fade

Obscure Behavior

Pokemon Pikachu 2

Pocket Sakura

[GBC Infrared] : General Hardware Information

The Game Boy Color came with an infrared port on the very top of the handheld. Previously, where IR communications had to be done with special cartridges (like the HuC-1 variants), the Game Boy itself now had the hardware built-in. Contrary to many misconceptions, this feature was used in a number of games and accessories. The IR port essentially sends out signals and is also capable of receiving them, allowing for fast, wireless, line-of-sight transmission.

[GBC Infrared] : Compatible Games

This list represents all the games that have been verified to use the IR port. While exhaustive, this list is probably not complete. There are likely more Japanese exclusives that need to be added. It's dubious whether or not Animorphs actually is a "Ubi Key" game. The back boxart doesn't have the "IR Compatible" logo, and the manual makes no mention of IR communication.

The North American version of Disney's Aladdin claims to have infrared support on the box, supposedly for Ubi Key functionality, however, no such option is accessible in the game. Additionally, European variants omit the GBC IR logo from their boxes. It's possible that games like Animorphs, Aladdin had its IR features stripped.

It should be noted that at least one game that uses the HuC-3 MBC, Pocket Family GB 2, is not in fact a "GB KISS" game. Instead, it uses the GBC's built-in IR hardware. A similar phenomenon can be seen with the Japanese release of Pokemon TCG (which used the HuC-1) versus releases for any other region (which use the GBC's native IR). Pocket Family GB 2 abandons the IR diodes on the HuC-3 PCB. At this point in time, Hudson may have finally decided to abandon GB KISS and the HuC-1 and HuC-3's IR features as they were redundant, especially for games designed to run exclusively on the GBC.

[GBC Infrared] : Communication Types

While a number of games may use similar formats for their IR communications, there is no "standard" protocol that all games use. IR communication is entirely determined by the game's code, hence it can vary wildly depending on needs. However, all communications fall into one of several general categories as described below:

[GBC Infrared] : Communication Protocol

Again, there is no set or established infrared protocol that games must follow. Many games vary in their approach. For example, the 2nd Generation Pokemon games use the GBC's hardware timers, while others have hardcoded values that count cycles to check timing. The simplest form is a barebones communication protocol, i.e. something like a binary Morse code where a "0" is a long ON-OFF pulse and "1" is a short ON-OFF pulse or vice versa. Properly done, data could have been short, compact, and easily converted into bytes in RAM. Sakura Taisen GB seems to follow this model in its communications with the Pocket Sakura. Not all games do this, however, and appear to be doing who knows what, opting instead for customized and specialized communications unique to each title. To illustrate this idea, it would be possible to use a table of given lengths of IR ON-OFF pulses so that individual bytes could be sent all at once instead of in a binary, bit-by-bit manner. A number of games try to send a few pulses when pressing input like the A button and wait for another GBC to echo that in response, but after the handshake, most of the IR pulses are impossible to understand without disassembling the code.

One thing to note is that 4 games in particular do share somewhat similar IR protocols, at least in regards to the initial handshake between 2 GBCs. They are Pokemon TCG 1 & 2 and Bombermax Red & Blue, all from the "2-Player Init" category above. Typically, IR capable GBC games will continually wait for an IR signal on both sides, i.e. the "1-Player Init" category. When one player presses certain input, that GBC takes the initiative and sends out a few IR pulses. That is to say, for most IR games, it only takes *just one* player to start the entire process.

The handshake for the 4 games previously mentioned, however, requires *both* players to input at almost the same time. One has to be slightly faster or slower than the other. Each side continually sends a few IR pulses, then reads the sensor to see if anything was received. If so, the GBCs begin to sync. The idea is that one side should be sending while the other is checking, and then the handshake completes. This is why one side needs to be faster or slower to input; if they are sending IR signals at the same time, they don't see anything when reading the sensor. As a result, both GBCs cannot input at exactly the same time. Practically speaking, this is unlikely to happen under normal circumstances, since most humans can't synchronize their actions down to a handful of microseconds, so the handshake will normally succeed.

The following is just theory. This handshake is possibly an artifact of the HuC-1. Consider that the Japanese version of Pokemon TCG 1 used the HuC-1 for its IR communications, and the developers may have borrowed the "best practices" used by other HuC-1/"GB KISS" games. When bringing Pokemon TCG 1 overseas, the IR handling code was likely minimally adapted to use the GBC's IR port, with the underlying protocol remaining unchanged in most regards. Pokemon TCG 2 ditched the HuC-1 in favor of the GBC IR port, so the IR code from non-Japanese versions of Pokemon TCG 1 was copy+pasted. The Bomberman games were made by Hudson Soft, literally the same people who created the HuC-1 in the first place. They too probably used the same protocol that had worked forever in their "GB KISS" games, so they used the same handshake method as before, just on the GBC IR port now. More research into the HuC-1 itself and the games needs to be done to confirm any of this.

[GBC Infrared] : RP Register

On the GBC, the MMIO register located at 0xFF56 controls infrared communication. Simply known as "RP" (Radiation Port? Reception Port? Red Port???), it is responsible for sending and receiving IR signals. Below is a diagram of the 8-bit register:

Bit 0:		Turn IR light ON (1) or OFF (0)					(R/W)
Bit 1:		IR signal (0 = Receiving signal) (1 = Normal/No signal)		(R)
Bits 2-5:	Unused
Bits 6-7:	Signal Read Enable (0 = Disable) (3 = Enable)			(R/W)

Turning on the IR light is as simple as writing to Bit 0 of RP. Reading is a bit more complicated. Bits 6 and 7 must both be set (0xC0), to read Bit 1, otherwise Bit 1 returns 1, acting as if no signal is detected, except in edge cases detailed below in "Obscure Behavior". With signal reading enabled, Bit 1 will determine the status of any incoming IR signals. Like other Game Boy MMIO registers, unused bits read high (set to 1).

[GBC Infrared] : Signal Fade

The IR sensor in the GBC adapts to the current level of IR light. That is to say, if the GBC receives a sustained IR signal beyond a certain amount of time, eventually the sensor treats this as a new "normal" level of IR light, and Bit 1 of RP goes back to 1. This is called the signal "fade" because it may appear as if the signal disappears.

Signal fade time is dependent on length and has an inverse relationship with the distance between a GBC and the IR light. The closer a GBC is to the IR source, the longer the fade time. The farther away a GBC is to the IR source, the shorter the fade time. One possible explanation for everything is that the IR signal is weaker on the receiving end, so the signal is prone to get "lost" to surrounding noise. The GBC IR sensor is probably good at sending IR signals (evidenced by the Mission Impossible cheat to turn a GBC into a TV remote) but not so good at picking up signals (evidenced by Chee Chai Aliens plastic add-on to enhance IR reception).

At about 3.0 to 3.5 inches (7.62 to 8.89cm) signal fade time appears to be around 3ms. Optimal distance seems to be 2.5 to 4.0 inches (6.35 to 10.16cm) to maintain a fade time close to 3ms and avoid potential miscommunication. One oddity of note is that putting two GBCs very close together (physically touching) produced unusually short fade times, far shorter than 3ms. There may be some sort of interference at that range.

[GBC Infrared] : Obscure Behavior

The RP register has one very strange quirk. Disabling Bits 6 and 7 and then subsequently re-enabling them causes Bit 1 to go to zero under certain conditions. In other words, the IR sensor will act as if it is detecting a signal if reading the signal is disabled then enabled. It seems this behavior happens in the presence of any light; covering up the sensor during the read signal disable/enable causes the sensor to act normally. It's possible that the sensor resets itself (to its lowest level of detection???) and immediately detects any infrared sources, even from ambient/environmental light. The presence of any noise may temporarily trick the sensor into "seeing" IR light. By abusing this behavior, the GBC has some rudimentary ability to gauge the type of nearby lighting:

--------------------------------------------------------------------------------------------
Result of 1st RP Write (0x00)	Result of 2nd RP Write (0xC0)	Type of Lighting	
--------------------------------------------------------------------------------------------
Bit 1 = 1			Bit 1 = 1			Dark
Bit 1 = 0			Bit 1 = 1			Ambient
Bit 1 = 0 (sometimes 1)		Bit 1 = 0			Bright

Writing 0x00 to RP, followed by 0xC0 will trigger these results listed above. One very important thing to note is that when enabling Bits 6 and 7 (writing 0xC0), it does take some time for the sensor to register legitimate IR light coming into the sensor. I.e. if you want to use this method to detect what kind of light a GBC is looking at, the software needs to loop for a bit until Bit 1 of RP changes. Generally a few hundred cycles in double-speed mode will suffice. If Bit 1 of RP remains 1 after the loop, it's safe to assume the lighting is either ambient or dark. This delay doesn't seem to happen when Bits 6 and 7 are never disabled (which is what most official GBC software does). Games typically write either 0xC0 or 0xC1 to RP, with a small handful setting it to 0x00 initially when setting up other MMIO registers (Pokemon G/S/C does this).

The downside to this method is that when detecting a bright IR source, the sensor quickly adjusts to this new level, and the next attempt at writing 0x00 followed by 0xC0 to RP will result in readings of dark or ambient (typically dark though). Essentially the bright result only appears briefly when transitioning from lower levels of light, then it "disappears" thanks to the short time it takes for IR signal fade. Designing a game mechanic (darkness and light) around this quirk is still possible, although it would require careful thought and planning to properly work around the observed limitations.

One suggested method: once the Bright setting is detected, switch to writing only 0xC0 to RP so that the IR sensor works normally. If IR light stops being detected, switch to alternating 0x00 and 0xC0 writes as described above to determine Dark or Ambient settings. Whether it's practical or not to do this in a game remains theoretical at this point.

[GBC Infrared] : Pokemon Pikachu 2

The Pokemon Pikachu 2 (PP2) is a virtual pet device similar in concept to Tamagotchis. The PP2 is the successor to the original Pokemon Pikachu with a number of notable changes, largely the new color screen and the ability to communicate with Pokemon Gold, Silver, and Crystal via IR signals. These signals are used for the Mystery Gift functionality. Unlike normal Mystery Gifts between two GBCs, which produce random items, the PP2 gives out consistent items based on the number of "watts" transferred. The "watts" are the PP2's form of currency generated by the unit's pedometer (via walking, or more commonly, just shaking). Players either give Pikachu watts to make it happy, or send them to another PP2, or use them to Mystery Gift with Pokemon G/S/C.

In addition to giving out predictable items via Mystery Gift, the PP2 can also Mystery Gift without time limits. Normally, when two GBCs Mystery Gift 5 times in Pokemon G/S/C, players have to wait until the following day to try again. No such restriction applies when a GBC communicates with the PP2. The two can Mystery Gift endlessly, as long as the PP2 has watts to transfer. Below is a table of watts and the items they generate:

0 - 99 Watts		Eon Mail
100 - 199 Watts		Berry
200 - 299 Watts		Bitter Berry
300 - 399 Watts		Great Ball
400 - 499 Watts		Max Repel
500 - 599 Watts		Ether
600 - 699 Watts		Miracle Berry
700 - 799 Watts		Gold Berry
800 - 899 Watts		Elixir
900 - 998 Watts		Revive
999 Watts		Rare Candy

Current analysis of the IR communications between a GBC and a PP2 indicates that the PP2 interacts with Pokemon Crystal differently in comparison to Pokemon Gold and Silver. Each transfer appears to be 2007 ON-OFF transitions long.

[GBC Infrared] : Pocket Sakura

The Pocket Sakura is another virtual pet device similar to the Pokemon Pikachu 2. Design-wise, it is a copy+paste version of the PP2, except it's pink. Interestingly enough, the Pocket Sakura was made by Media Factory, the same people behind Zok Zok Heroes and the Full Changer device. The Pocket Sakura uses a pedometer to make Sakura travel to various locations and meet other Sakura Taisen-based characters. When resting at a location, the pedometer turns steps into "points" (10 steps = 1 point), which can then be sent to a GBC running Sakura Taisen GB or another Pocket Sakura.

Each transfer appears to be 1607 ON-OFF transitions long.

Gyogun Tanchiki: Pocket Sonar

General Hardware Information

MBC1S

Sonar Format

Fish Finder

Game Boy Incompatibilities

Further Research

[Pocket Sonar] : General Hardware Information

Gyogun Tanchiki: Pocket Sonar (shortened to just Pocket Sonar) was a combination "game" and accessory released by Bandai on July 24, 1998 exclusively in Japan. The cart and attached sonar device act as a fish finder, capable of probing water depths of up to 20 meters. It was the first video-game based sonar hardware, but not the last (Bandai released the WonderSwan Handy Sonar the following year). Apparently, Bandai worked with Honda Electronics for this product.

[Pocket Sonar] : MBC1S

The MBC1S is a specialized variant of the standard MBC1. The key difference here is that the ability to control sonar hardware was added. Aside from that, the MBC1S appears largely identical to the MBC1 from a high-level view. Below are the MBC registers:

0x0000 - 0x1FFF (W)	:	Unknown. Not used in the Pocket Sonar. Pocket Sonar has no cart RAM.

0x2000 - 0x3FFF (W)	:	ROM Bank Number. Same as MBC1.

0x4000 - 0x5FFF	(W)	:	Sonar Pulse. Apparently activates the sonar when writing "1", turns it off when writing "0". Must be in "sonar mode"

0x6000 - 0x7FFF	(W)	:	Sonar Mode Enable/Disable. Activates "sonar mode" when writing "1". Pocket Sonar never seems to write "0" here though.

0xA000		(R)	:	Sonar Data. Data comes in byte-by-byte and the software uses that information to build an image of what's in the water.

The Pocket Sonar doesn't have cartridge-based RAM, so it repurposes most MBC1 registers dealing with RAM to instead handle sonar.

[Pocket Sonar] : Sonar Format

The Pocket Sonar displays a 160x96 image on screen based on sonar data. This "frame" is constantly updated, albeit quite slowly. The next frame slides in from the right to replace the old one. Each frame is generated using the responses that come from reading 0xA000. The byte held in this register determines what color the software should draw on-screen, and the colors ultimately represent either open water or soil, sediment, rocks, and other solid flooring. The Pocket Sonar interprets two different "sets" of colors, one for before solid flooring is detected, and one for after. With Shade 0 being the lightest DMG pixel color and Shade 3 being the darkest DMG pixel color, the following values held in 0xA000 determine the corresponding colors:

---------------------------------------------------------
VAL = 0xA000 AND 0x7 : Before solid flooring detected (0xA000 reads 0x00)
---------------------------------------------------------
1		SHADE 3		Solid object or debris (the top-most exterior)
2, 3		SHADE 2		Solid object or debris (inner layers)
4, 5, 6, 7	SHADE 0		Open water

---------------------------------------------------------
VAL = 0xA000 AND 0x7 : After solid flooring detected (0xA000 reads 0x00)
---------------------------------------------------------
0, 1, 2, 3	SHADE 3		Solid floor (the top-most exterior)
4, 5, 6, 7	SHADE 1		Solid floor (inner layers)

Solid floor detections appears to happen after the Pocket Sonar returns a single 0x00 byte for each section of the frame. Every frame is internally divided into 1x96 strips by the software. Depending on the depth the Pocket Sonar is trying to probe (e.g. 2m, 5m, 10m, etc), the device reads 0xA000 more frequently.

---------------------------------------------------------
Depth		1x96 Reads		Total Frame Reads
---------------------------------------------------------
2 meters	188			30080
5 meters	196			31360
10 meters	198			31680
15 meters	199.4			31904
20 meters	199			31840
30 meters	200			32000

The first 96 reads correspond directly to a 1x96 strip that's part of the larger 160x96 frame. That is to say, 1 read = 1 pixel drawn on-screen (after the waterline). The additional reads from 0xA000 are not drawn unless the magnification feature is used. With magnification, instead of displaying the sonar image from the waterline to the probing depth (e.g. 0-2m, 0-5m, 0-10m), the Pocket Sonar will start drawing at halfway to the probing depth (e.g. 1-2m, 2.5-5m, 5-10m). It effectively drops viewport of the sonar image, and in doing so displays some of the other reads beyond the first 96. Consequently, using the magnification feature changes the above chart to this:

-----------------------------------------------------------------
Depth			1x96 Reads		Total Frame Reads
-----------------------------------------------------------------
1.0 - 2.0 meters	176			28160
2.5 - 5.0 meters	192			30720
5.0 - 10.0 meters	196			31360
7.5 - 15.0 meters	198			31680
10.0 - 20.0 meters	198			31680
20.0 - 30.0 meters	199			31840

The Pocket Sonar represents the waterline as all black and forcibly draws a certain number of pixels for it depending on the depth the device is checking. The waterline is not applicable when using magnification. Apparently the Pocket Sonar internally divides the 160x96 frame into a 80x96 "sub-frame". It isn't clear what the purpose of this is, but it appears to be some sort of mid-frame reset if necessary, perhaps if garbage values are detected (e.g. sonar data that doesn't realistically make sense?)

To collect the above sonar data, the MBC1S must first send out a sonar pulse by writing "1" then "0" to the memory regions 0x4000 - 0x5FFF. Afterwards, 0xA000 will hold a single byte representing part of the sonar image. The process of reading back the sonar image appears to take some time, however. It doesn't seem to be immediate, as the Pocket Sonar's software reads 0xA000 across several screen refreshes. Below are charts detailing the number of 0xA000 reads per-screen refresh on the Game Boy LCD:

-------------------------------------------------------------
2 Meters	Magnification OFF	Magnification ON
-------------------------------------------------------------
Refresh_0	188 reads		176 reads
Refresh_1	0 reads			0 reads
Refresh_2	0 reads			0 reads
Refresh_3	0 reads			0 reads
Refresh_4	0 reads			0 reads
Refresh_5	0 reads			0 reads
Refresh_6	0 reads			0 reads
Refresh_7	0 reads			0 reads

-------------------------------------------------------------
5 Meters	Magnification OFF	Magnification ON
-------------------------------------------------------------
Refresh_0	153 or 154 reads	192 reads
Refresh_1	42 or 43 reads		0 reads		
Refresh_2	0 reads			0 reads
Refresh_3	0 reads			0 reads
Refresh_4	0 reads			0 reads
Refresh_5	0 reads			0 reads
Refresh_6	0 reads			0 reads
Refresh_7	0 reads			0 reads
Refresh_8	0 reads

-------------------------------------------------------------
10 Meters	Magnification OFF	Magnification ON
-------------------------------------------------------------
Refresh_0	76 reads		135 or 137 reads
Refresh_1	121 reads		59 or 61 reads
Refresh_2	1 read			0 reads
Refresh_3	0 reads			0 reads
Refresh_4	0 reads			0 reads
Refresh_5	0 reads			0 reads
Refresh_6	0 reads			0 reads
Refresh_7	0 reads			0 reads
Refresh_8	0 reads			0 reads
Refresh_9	0 reads

-------------------------------------------------------------
15 Meters	Magnification OFF	Magnification ON
-------------------------------------------------------------
Refresh_0	50 reads		90 or 92 reads
Refresh_1	81 reads		106 or 108 reads
Refresh_2	68 reads		0 reads
Refresh_3	0 reads			0 reads
Refresh_4	0 reads			0 reads
Refresh_5	0 reads			0 reads
Refresh_6	0 reads			0 reads
Refresh_7	0 reads			0 reads
Refresh_8	0 reads			0 reads
Refresh_9	0 reads

-------------------------------------------------------------
20 Meters	Magnification OFF	Magnification ON
-------------------------------------------------------------
Refresh_0	37 reads		68 or 69 reads
Refresh_1	60 reads		109 reads
Refresh_2	59 or 60 reads		20 or 21 reads
Refresh_3	42 or 43 reads		0 reads
Refresh_4	0 reads			0 reads
Refresh_5	0 reads			0 reads
Refresh_6	0 reads			0 reads
Refresh_7	0 reads			0 reads
Refresh_8	0 reads			0 reads
Refresh_9	0 reads			0 reads
Refresh_10	0 reads

-------------------------------------------------------------
30 Meters	Magnification OFF	Magnification ON
-------------------------------------------------------------
Refresh_0	24 reads		45 or 46 reads
Refresh_1	40 reads		73 reads
Refresh_2	41 reads		73 reads
Refresh_3	40 reads		7 or 8 reads
Refresh_4	40 reads		0 reads
Refresh_5	15 reads		0 reads
Refresh_6	0 reads			0 reads
Refresh_7	0 reads			0 reads
Refresh_8	0 reads			0 reads
Refresh_8	0 reads			0 reads
Refresh_10	0 reads			0 reads
Refresh_11	0 reads
Refresh_12	0 reads

The values above should be considered approximate. When changing between different depths, the above numbers get slightly messed up for a short time (usually just for 1 sonar pulse) before they normalize. During the transition, the totals still add up (e.g. 10m still reads 0xA000 198 times per 1x96 segment of the frame, with magnification off), however, the spacing between reads shifts a bit. Trying to change 30m to the next depth (pressing A on the depth change menu item) sometimes causes an elongated pause between sonar pulses (31 LCD refreshes, so more than 1/2 a second) but since 30m is the max, the Pocket Sonar keeps reading 0xA000 at 200 times per 1x96 frame segment. The numbers briefly fluctuate across screen refreshes until returning to the chart above.

[Pocket Sonar] : Fish Finder

The usefulness of the Pocket Sonar, aside from bathymetry, is largely its fish finding capabilities. The Pocket Sonar has a toggable option for displaying any fish it believes it has detected. The fish are represented by simple 8x8 graphics. Strangely enough, the fish are aligned to a slightly different grid than the 160x96 sonar image. If using the 160x96 sonar image divided into 8x8 cells as a reference, the fish are drawn over this image with a Y offset of -1. This "fish grid" also determines when the Pocket Sonar software thinks it has located a fish.

Fish tiles are always aligned on the X-axis by 8 pixels of the "fish grid", so they are always locked into columns, however, they seem to shift freely on the Y-axis. Obviously, fish are only detected in open water; once solid flooring (and not just debris or other objects) has been detected, no fish appear below the floor. As such, fish detection only happens when using the first "set" of colors for drawing the frame. To detect fish, an 8x8 section of the "fish grid" needs to have only 1 value of 0x00 or 0x01 within the first column. If not, the Pocket Sonar will treat it as a miscellaneous object. Even if the second column (or every other one) has multiple 0x00 or 0x01 values, the Pocket Sonar only cares about first column. The first occurence of a 0x00 or 0x01 value in the first column of any 8x8 cell on the "fish grid" appears to determine where the fish tile is aligned vertically.

Oddly enough, several options change the X offset of the "fish grid". Enabling or disabling the option for displaying fish seems to reposition the "fish grid" according to whatever 1x96 segment of the frame is rendered. Additionally, toggling magnifcation or the "auto" (オート) mode resets the "fish grid".

[Pocket Sonar] : Game Boy Incompatibilities

For some reason, Game Boy Color and Game Boy Advance units do not work with the Pocket Sonar. These handhelds seem to return 0x00 when reading 0xA000 for the sonar. When the sonar is turned on, this results in a pure black screen. When the sonar is turned off, some other value (probably 0xFF) is read, resulting in a pure white screen. DMG and MGB Game Boys have no apparent trouble properly reading sonar data from 0xA000 though.

[Pocket Sonar] : Further Research

There are a couple of discrepancies that require further clarification. The Pocket Sonar displays a brief "demo" mode if players wait around the title screen. It shows an example sonar image scrolling across the screen, however it uses 3 shades to represent the ground (SHADE 3, SHADE 2, and SHADE 1 in that order). It doesn't seem possible to recreate this type of image when actually using the Pocket Sonar, as the ground only uses 2 shades (SHADE 3 and SHADE 1). Additionally, on the box and in the manual, all pictures of the Pocket Sonar in action only show these 2 shades. Extensive testing using various values for the sonar image data at 0xA000 could not reproduce the "demo" mode either. While the "demo" mode may be impossible on real hardware, as actual tests in real bodies of water have not reproduced it.

Additionally, while the Pocket Sonar clearly states it can probe a depth of 20m, the software has settings for 30m. Furthermore, there is photographic evidence of at least one individual successfully using the 30m option. It isn't clear if the Pocket Sonar is capable of handling 30m without issue or if it can do 30m with some degree of inaccuracy. Again, real world testing would have to be done to determine the exact nature of the 30m setting.

GBA Screen Stretch

GBA hardware has the ability to stretch the final image drawn on-screen when running DMG or GBC games. On applicable hardware (e.g. not the Micro, original NDS, or NDS Lite models), the L and R triggers toggle this feature on and off respectively. The default mode is to display the DMG/GBC image in the middle of the GBA screen with black borders. The dimensions are as follows:

Top and bottom borders (240x8 pixels, or 30x1 tiles)
Left and right borders (40x160 pixels, or 5x20 tiles)
DMG/GBC screen (160x144 pixels, or 20x18 tiles)

Technically, the original DMG/GBC screen has an offset of (40, 8). Once the player toggles stretching, the above dimensions change:

Top and bottom borders (240x8 pixels, or 30x1 tiles)
Left and right borders (Not Applicable)
DMG/GBC screen (240x144 pixels, or 30x18 tiles)

The DMG/GBC screen completely stretches to the left and right ends of the screen. No vertical stretching occurs; the black bars still exist at the top and the bottom. Horizontal stretching follows a simple formula. For every 2 pixels from the original 160x144 image, a third pixel is generated by blending them together. This third pixel is then placed between the two original pixels. For example, imagine Pixel A and Pixel B represent original pixels from the 160x144 image. Pixel C is the result of blending the two of them. The GBA will produce A-C-B when stretching DMG and GBC games.

This method of stretching acts on the present 160x144 image generated by the DMG/GBC game, that is to say, scrolling the background, window, or OBJs can produce minor inconsistencies depending on where a tile is rendered to the screen. Generally, these inconsistencies affect the blending seen around edges. For example, in the first level of Super Mario Land, the trunks of the trees in the background are only 1 pixel wide. When stretching, the blended edge will switch from the left to the right depending on its current position due to scrolling. However, these inconsistencies are barely visible under the best circumstances, and almost impossible to detect during actual gameplay.

The blending comes straight from the GBA's affine transformations. That is to say, after the final DMG/GBC screen is rendered, the GBA controls all output via BG2. Even in the GBA's DMG/GBC backward compatibility mode, GBA video hardware is still being used to display graphics. Currently, the exact formula for determining colors remains unknown, however, something as simple as averaging Pixel A and Pixel B gives quick, adequately believable results. One thing that is known about the blending: if A and B are the same color, they will not produce a different color.

Power Antenna + Bug Sensor

General Hardware Information

Game Boy Color Operation

Game Boy Advance Operation

Misc. Notes

[Power Antenna + Bug Sensor] : General Hardware Information

The Power Antenna are accessories bundled with the Keitai Denjuu Telefang Telefang games for the Game Boy Color and Game Boy Advance. An identical accessory, called the Bug Sensor, was also bundled with the Network Adventure Bugsite games on the GBC. Although the first versions of Gachasta! Dino Device did not come with any peripherals, they were nonetheless compatible with both the Power Antenna and Bug Sensor. Primarily cosmetic, these devices were essentially LEDs that were programmed to light up depending on certain events in the games.

* The 2nd version of the Power Antenna, the one that came with Telefang 2, is physically only compatible with the GBA's link port. However, it can be used with the GBC games.

[Power Antenna + Bug Sensor] : Game Boy Color Operation

To communicate with the Power Antenna + Bug Sensor, the GBC must run on an internal clock. A single byte is then transmitted via serial communications. The chart below describe what input will affect the LED:

-----------------------------------------------------
Value Sent		| LED Result	
-----------------------------------------------------
0x00			| Turns LED off
Bit 0 == 1		| Turns LED on (Strong Light)
Bit 0 == 0		| Turns LED on (Weak Light)
-----------------------------------------------------

"Strong Light" refers to the LED turning on and sustaining its brightest output; it will not turn off until a value of 0x00 is sent. "Weak Light" refers to the LED turning on temporarily and rapidly fading on its own. Weak Light is very dim (not noticable under certain lighting conditions) and is extremely short-lived. This mode does not appear to be used by the games. Instead, only Strong Light is turned on. Weak Light can be emitted constantly and indefinitely if multiple and repeated serial transfers occur. Sending such a transfer around 60Hz is enough to get weak light turned on for as long as desired.

It is possible to cause flickering by turning the LED on and off at given intervals. For Strong Light, this involves alternate transfers of 0x00 and some other value with Bit 0 set high. For Weak Light, simply send a value with Bit 0 set low and increase the gaps between transmission (e.g. delay transmission by 2 frames or 3 frames).

When the Power Antenna + Bug Sensor are emitting any kind of light, the device returns 0xF3 to the GBC. This is true even after Weak Light has fully faded. When no light is being emitted, the device returns 0xF2.

[Power Antenna + Bug Sensor] : Game Boy Advance Operation

Communications with the Power Antenna + Bug Sensor are a bit different when operating in GBA mode (i.e. running GBA software, not using a GBA to run GBC software). The GBA must use NORMAL_8BIT or NORMAL_32BIT mode; either one is fine. The following values of SIOCNT will affect the LED:

-----------------------------------------------------
Value Written		| LED Result	
-----------------------------------------------------
0x0080			| Turns LED off
0x0089			| Turns LED on (Strong Light)
0x0081			| Turns LED on (Weak Light)
-----------------------------------------------------

To turn off the LED, simply set Bit 3 of SIOCNT low and start a serial transfer. It does not matter whether an internal or external clock is set. For Strong and Weak Light, the 8-bit or 32-bit data sent is ignored. Instead, high or low values of Bit 3 of SIOCNT respectively dictate whether Strong or Weak Light is produced.

In NORMAL_8BIT mode, Strong and Weak Light return an 8-bit value of 0xFF instead of 0xF3 as on the GBC. In NORMAL_32BIT mode, the returned 32-bit value is 0x00.

[Power Antenna + Bug Sensor] : Misc. Notes

Since all Power Antenna + Bug Sensors rely on the presence or absence of a single bit, it is possible for other software to inadvertedly turn it on. For example, the GBA BIOS performs a few NORMAL_32BIT transfers on an internal clock, therefore turning on the LED for the duration of the boot logo (and indefinitely if the game does not change SIOCNT). Even software written specifically for these devices may turn them on at odd moments. Telefang triggers the LED on when attempting to use multiplayer via the Link Cable, although in this case, there is a reasonable expectation that the Power Antenna would be unplugged first.

Turbo File GB

General Hardware Information

Compatible Games

Communication Protocol

Commands

File Structure

Memory Card

Unused Space

[Turbo File GB] : General Hardware Information

Developed by ASCII Corporation and released in March of 2000, the Turbo File GB is an external storage device designed to hold large amounts of save data. Having already made several similar devices for the Famicom and Super Famicom, the company brought a new unit over to the Game Boy Color. Only select games specifically programmed to take advantage of the Turbo File GB were compatible. The accessory made use of memory cards as well, a first for the Game Boy.

[Turbo File GB] : Compatible Games

Only 2 games were officially compatible with the Turbo File GB, both RPG Maker titles. Despite the Turbo File GB technically being compatible with older Game Boys, the only compatible software was all GBC-exclusive.

It should also be noted that these games are RPG "Tskuru" as in the Japanese verb "To Make". A number of resources mistakenly translate this as "School" perhaps given the katakana used on the boxart, title screens, and other media.

[Turbo File GB] : Communication Protocol

The GBC communicates with the Turbo File on an external clock. It starts off with a sync signal, waiting for the Turbo File to begin. Once the first sync signal has been acknowledged, a packet is transferred from the GBC to the Turbo File, followed by a second sync signal. The packet consists of the following parts:

-------------------------------------------------
Packet Format
-------------------------------------------------
Sync Signal 1		| 1 Byte (0x6C)
Packet Body		| Length varies
Checksum		| 1 Byte
Sync Signal 2		| 2 Bytes (0xF1, 0x7E)
-------------------------------------------------

For the first sync signal, the GBC sets 0xFF01 to 0x6C and waits until the Turbo File sends 0xC6. After the packet body and checksum have been transferred, a second sync signal is sent. For this signal the GBC sets 0xFF01 to 0xF1, then 0x7E. The Turbo File should send 0xE7 and 0xA5 respectively.

The packet body consists of the following parts:

-------------------------------------------------
Packet Body Format
-------------------------------------------------
Magic Byte		| 1 Byte (0x5A)
Command			| 1 Byte
Parameters		| Length varies
-------------------------------------------------

Not every command has parameters, therefore, that section of the packet is not always present.

The checksum is calculated as such: 0x100 - (Sum of Packet Body Bytes)

After the entire packet has been sent, the GBC will wait with the value 0xF2 for several transfers, the length of which depends on the given command. During that time, the Turbo File responds with the appropiate data. This data is formatted as a packet as well, however, it does not use sync signals.

The basic flow of commands goes something like this:

1. Command 0x10			Get status (called often in-between other commands)
2. Command 0x20			Begin session
3. Command 0x23 or 0x22		Switch bank for read/write mode
4. Command 0x40 or 0x30		Read/write 64 bytes from/to memory
5. ...				Repeat 3 and 4 as needed
6. Command 0x24			End session

[Turbo File GB] : Commands

Command 0x10 - Get Status

Parameters: None

Response Data: 9 bytes detailing the status of the Turbo File GB.

Returns various bits of information about the Turbo File GB. Called frequently before and after many other commands. The response packet for this command follows this format:

-------------------------------------------------
Command 0x10 Response Packet Bytes
-------------------------------------------------
0x00 - Command		| 0x10
0x01 - Unknown		| 0x00
0x02 - Device Status	| See below
0x03 - Card Status	| 0x01 = No memory card, 0x05 = Card present
0x04 - Current Bank MSB	| 0x00 through 0x01
0x05 - Current Bank LSB	| 0x00 through 0x7F
0x06 - Unknown		| 0x00
0x07 - Unknown		| 0x00
0x08 - Checksum		| 0x100 - 0xA5 - (Sum of Bytes 0 through 7)
-------------------------------------------------

The device status byte uses the following bits to represent several states:

-------------------------------------------------
Device Status Bits
-------------------------------------------------
Bit 0			| Device Ready = 1
Bit 1			| Unknown
Bit 3			| Initialized ???
Bit 7			| Read-Only Physical Switch On/Off
-------------------------------------------------

Command 0x20 - Begin Session

Parameters: 1 byte of unknown significance

Response Data: 4 byte echo packet

Appears to be called before reading or writing operations take place. The response packet for this command is an echo of the previous packet from the GBC.

-------------------------------------------------
Command 0x20 Response Packet Bytes
-------------------------------------------------
Byte 0x00		| 0x20
Byte 0x01		| 0x00
Byte 0x02		| Device Status
Byte 0x03		| Checksum = 0x100 - 0xA5 - (Sum of Bytes 0 through 2)
-------------------------------------------------

Command 0x22 - Set Write Bank

Parameters: 2 bytes forming an 8-bit bank number (MSB first)

Response Data: 4 byte echo packet

This command sets the bank for write operations. The 1st parameter is Bit 7 and the 2nd parameter is Bit 0-6. This command also sets Bit 3 of the Device Status flag for all future Get Status commands. The response packet for this command is an echo of the previous packet from the GBC.

-------------------------------------------------
Command 0x22 Response Packet Bytes
-------------------------------------------------
Byte 0x00		| 0x22
Byte 0x01		| 0x00
Byte 0x02		| Device Status (Bit 3 set)
Byte 0x03		| Checksum = 0x100 - 0xA5 - (Sum of Bytes 0 through 2)
-------------------------------------------------

Command 0x23 - Set Read Bank

Parameters: 2 bytes forming an 8-bit bank number (MSB first)

Response Data: 4 byte echo packet

This command sets the bank for read operations. The 1st parameter is Bit 7 and the 2nd parameter is Bit 0-6. This command also sets Bit 3 of the Device Status flag for all future Get Status commands. The response packet for this command is an echo of the previous packet from the GBC.

-------------------------------------------------
Command 0x23 Response Packet Bytes
-------------------------------------------------
Byte 0x00		| 0x23
Byte 0x01		| 0x00
Byte 0x02		| Device Status (Bit 3 set)
Byte 0x03		| Checksum = 0x100 - 0xA5 - (Sum of Bytes 0 through 2)
-------------------------------------------------

Command 0x24 - End Session

Parameters: None

Response Data: 4 byte echo packet

This command is called after the game has finished reading or writing all necessary data. The response packet is like all of the echo packets for other commands, however, it technically isn't a copy of the original packet (which is only 2 bytes: a command and a checksum).

-------------------------------------------------
Command 0x24 Response Packet Bytes
-------------------------------------------------
Byte 0x00		| 0x24
Byte 0x01		| 0x00
Byte 0x02		| Device Status
Byte 0x03		| Checksum = 0x100 - 0xA5 - 0x24
-------------------------------------------------

Command 0x30 - Write Data

Parameters: 2 bytes forming a 13-bit offset (MSB first) and 64 bytes of data to write

Response Data: 4 byte echo packet

The two parameters are the 13-bit offset where to write data. The 1st parameter is Bit 8-12 and the 2nd parameter is Bit 0-7. Data will be written to the bank specified by Command 0x22. Only 64 bytes can be written at a time. The response packet for this command is an echo of the previous packet from the GBC.

-------------------------------------------------
Command 0x30 Response Packet Bytes
-------------------------------------------------
Byte 0x00		| 0x30
Byte 0x01		| 0x00
Byte 0x02		| Device Status
Byte 0x03		| Checksum = 0x100 - 0xA5 - (Sum of Bytes 0 through 2)
-------------------------------------------------

Command 0x40 - Read Data

Parameters: 2 bytes forming a 13-bit offset (MSB first)

Response Data: 69 bytes for a data packet

The two parameters are the 13-bit offset to read data from. The 1st parameter is Bit 8-12 and the 2nd parameter is Bit 0-7. Data will be read from the bank specified by Command 0x23. Only 64 bytes can be read at a time. The response packet follows this format:

-------------------------------------------------
Command 0x40 Response Packet Bytes
-------------------------------------------------
Byte 0x00		| 0x40
Byte 0x01		| 0x00
Byte 0x02		| Device Status
Byte 0x03 - 0x42	| Data
Byte 0x43		| Checksum = 0x100 - 0xA5 - (Sum of Bytes 0x00 through 0x42)
-------------------------------------------------

Even though the Turbo File GB uses flash memory, these commands do not correspond to ones generally used by other devices. The Turbo File GB may be using an additional microprocessor (an M38034M4 by Mitsubishi) to handle and translate the GBC's packets into valid flash commands.

Although the flash memory inside the Turbo File GB supports block erase commands, the Turbo File GB has not been verified to process such a command from the Game Boy. Whereas the Turbo File Advance uses the 0x34 command to erase blocks, no GBC games make use of such a command, nor have limited hardware tests succeeded in executing that command. If the Turbo File GB's microprocessor does translate input from the Game Boy, it may not have been programmed to handle command 0x34 at all.

[Turbo File GB] : File Structure

Bank 0x7F (for internal storage) and Bank 0xFF (for memory card storage) contain the file headers for each file. These identify the name of the file and how many blocks it occupies. With this information, games can know where each file is within the lower banks and correctly access them. Each header occupies 64 bytes. The format is described below:

-------------------------------------------------
File Header
-------------------------------------------------
Byte 0x00		| 0x5A
Byte 0x01 - 0x04	| Game ID
Byte 0x05 - 0x10	| ASCII String for filename (12 characters max)
Byte 0x11 - 0x15 	| Should all be 0x20
Byte 0x16		| Current block ranging from 0 to (Total - 1)
Byte 0x17		| Total number of blocks for save
Byte 0x18 - 0x3F	| Should all be 0x00	
-------------------------------------------------

Each 8KB block a file occupies is given its own header, hence the need for a byte detailing the current block. The smallest file saved by games is 4 blocks, thus it has 4 separate headers. Since the very last 32KB on both internal storage and the memory card are reserved for these file headers, the maximum number of available blocks on either will be 120 (displayed as 119 in compatible games), enough for 30 different files.

Bytes 0x01 through 0x04 act as IDs. They are the same bytes found in the game's ROM header, specifically right after the ASCII-encoded title (bytes 0x13F through 0x142). Interestingly enough, these header bytes are supposed to be the new manufacturer code Nintendo specified for GBC games. As both RPG Tsukuru GB and Uchuu Nin Tanaka Tarou De RPG Tsukuru GB2 can save to the Turbo File GB, using an ID prevents incompatibilities when trying to load a file. Each game ignores reading files from the other, however, both can freely erase any file on the device.

[Turbo File GB] : Memory Card

The Turbo File GB's memory cards can be accessed by setting Bit 0 of the 1st parameter byte for commands 0x22 and 0x23. The memory cards effectively act as expanded storage, and thus the parameters from commands 0x22 and 0x23 form an 8-bit bank number. Banks 0x00 through 0x7F represent data stored internally on the Turbo File. Banks 0x80 through 0xFF represent data stored on the memory card.

To detect whether a memory card is present, games must check Bit 2 of Byte 3 of the 0x10 command. If that is set, a memory card has been inserted, otherwise, nothing has been slotted in.

[Turbo File GB] : Unused Space

While the last block of internal storage or the memory card is reserved for file headers, a number of blocks before that are deemed off-limits by game software. This empty space acts as a buffer against any errant writes, with the idea being the last 8 blocks should not be touched for anything but file header access. Thus the maximum usable space on the Turbo File GB should be 120 blocks, as advertized on the product's box.

Unfortunately, due to a programming error in RPG Tsukuru GB and Uchuu Nin Tanaka Tarou De RPG Tsukuru GB2, an additional 4 blocks are rendered inaccessible. Instead of having 1 block for file headers and 7 blocks as padding, they use 1 block for file headers and 8 blocks as padding. This results in 119 blocks as the maximum usable space. After filling up 116 blocks (for 29 saves), only 3 blocks remain, which is too small for one last save. This off-by-one counting error does not exist in Derby Stallion Advance or RPG Tsukuru Advance when using the Turbo File Advance.

Sewing Machines

General Hardware Information

Compatible Software

Transmission Protocol

Packet Format

Stitching Logic - Regular Stitching

Stitching Logic - Embroidery

Sewing Machine Status

[Sewing Machines] : General Hardware Information

In 2000, 3 different sewing machines were released that featured connectivity with the Nintendo Game Boy. The Jaguar JN-100 and later the Jaguar JN-2000 were released in Japan, while the Singer IZEK-1500 was released in the US later. Jaguar JN-100 models were also released in Europe. Each machine comes with a built-in Link Cable that allows a Game Boy running specialty software to send various stitching commands. With this, the Game Boy dictates sewing for patterns, buttonholes, and embroidery. Aside from their novelty, these devices mark one of the first attempts at pushing affordable programmable sewing machines to average consumers.

Singer IZEK-1500

Jaguar JN-100

Jaguar JN-2000

[Sewing Machines] : Compatible Software

System Compatibility

[#] = DMG and GBC compatible

[*] = GBC only

Sewing Machine Compatibility

[-] = Not compatible

[x] = Compatible

[!] = Compatible ONLY with an embroidery arm

[#] Sewing Machine Operation Software

[#] Raku x Raku Mishin

[*] Raku x Raku Moji

[*] Raku x Raku Cut Shuu

[*] Jaguar Mishin Sashi Senyou Soft: Mario Family

[*] Kanji Shishuu

[*] Kirby Family

A majority of the software was released exclusively to take advantage of the EM-2000 embroidery arm. Sewing Machine Operation Software and Raku x Raku Mishin are functionally identical, save for some cosmetic differences and offering Latin character stitching instead of kana. Otherwise, an IZEK-1500 can use the Japanese version of the software without issue and vice versa. The IZEK-1500 and the JN-100 cannot use Moji, Cut Shuu, Kanji Shishuu, Mario Family, or Kirby Family as they have no slot to accept an embroidery arm. The JN-2000 is the ONLY sewing machine that can do embroidery. The general functionality of each piece of software is detailed below:

Sewing Machine Operation Software

Raku x Raku Mishin

Raku x Raku Moji

Raku x Raku Cut Shuu

Jaguar Mishin Sashi Senyou Soft: Mario Family

Kanji Shishuu

Kirby Family

Kanji Shishuu and Kirby Family were never commercially released, thus out of the 7 known compatible titles, only 5 were sold to the public. Kanji Shishuu is very similar to Moji except it has a vastly larger pool of available kanji. Kirby Family is very similar to Cut Shuu and Mario Family, with embroidery patterns that appear largely inspired by Kirby 64.

[Sewing Machines] : Transmission Protocol

All communication between the sewing machines and the Game Boy happens via the attached Link Cable. The Game Boy and the sewing machine, however, alternate between which side uses an internal clock or an external clock. The general pattern is 2 external transfers followed by 1 internal transfer. On the first external transfer, the Game Boy sends a value of 0x00. Presumably before such a transfer can complete (literally a few CPU instuctions later), the Game Boy sends another external transfer, this time with actual data for the sewing machine. This transfer does finish, however, the clock rate provided by the sewing machine is currently unknown. On this transfer, the sewing machine sends back a single byte reporting its status. Finally the last transfer is sent by the Game Boy via an internal clock. The Game Boy sends 0x00 and the sewing machine responds with 0xFF.

-------------------------------------------------
Transfer Flow
-------------------------------------------------
External Transfer 1		| Short "dummy" transfer with 0x00. Quickly cancelled by next transfer
External Transfer 2		| Payload data sent to sewing machine. Machine status may be returned
Internal Transfer 1		| Send 0x00, receive 0xFF. Signals end of transfer for 1 byte
-------------------------------------------------

When transferring a pattern to the sewing machine, the first few bytes of payload data are as follows: [0x80, 0x80, 0x80, 0x86]. This acts as a start signal, after which the Game Boy starts trasmitting packets. After all packets for a pattern have been sent to the machine, the Game Boy sends 0x80 endlessly until the next pattern is submitted. During that time, it's possible for the Game Boy to check the current status of machine.

[Sewing Machines] : Packet Format

For regular stitching and embroidery, data is transferred to each sewing machine in 128-byte packets containing stitch coordinate data. The format is described below:

-------------------------------------------------
Packet Format
-------------------------------------------------
Header				| 1st packet = 8 or 9 bytes, Other packets = 0 Bytes
Real Coordinate Data		| 1st packet = 118 bytes, Other packets = 126 Bytes
Checksum			| 2 Bytes
-------------------------------------------------

Headers only appear on the first packet sent to the machine when defining what to sew. Until the operating software finishes that definition, subsequent packets are headerless. Regular stitching and embroidery use two different headers. Each format is as follows:

-------------------------------------------------
Packet Header Bytes - Regular Stitching
-------------------------------------------------
0x00 - New Packet Control Code	| 0xB9
0x01 - Checksum Seed LSB	| 0x00 - 0xFF
0x02 - Checksum Seed MSB	| 0x00 - 0xFF
0x03 - N/A			| 0x00
0x04 - Virtual X Coordinate	| 0x00 - 0x20
0x05 - N/A			| 0x00
0x06 - Virtual Y Coordinate	| 0x00 - 0x20
0x07 - N/A			| 0x00
-------------------------------------------------


-------------------------------------------------
Packet Header Bytes - Embroidery
-------------------------------------------------
0x00 - New Packet Control Code	| 0xB9
0x01 - Checksum Seed LSB	| 0x00 - 0xFF
0x02 - Checksum Seed MSB	| 0x00 - 0xFF
0x03 - N/A			| 0x00
0x04 - N/A			| 0x00
0x05 - X Offset LSB		| 0x00 - 0xFF
0x06 - X Offset MSB		| 0x00 - 0xFF
0x07 - Y Offset LSB		| 0x00 - 0xFF
0x08 - Y Offset MSB		| 0x00 - 0xFF
-------------------------------------------------

The checksum is a 16-bit sum of all the previous packet bytes, including the header. The header appears to contain seeds as a means to influence the checksum.

For regular stitching, the header contains two bytes that determine starting coordinates for stitching. The machines treat these as virtual coordinates that determine how to move towards the first pair of real coordinates where stitching actually begins. When repeating a pattern, the virtual coordinate data is ignored, and instead the machines begin processing at the start of real coordinate data.

For embroidery, the header contains two 16-bit values that determine the initial offset where the machine will begin the pattern. The effective stitching area for embroidery ranges from 0xFED0 to 0xFFFF horizontally and from 0xFFFF to 0xFE30 vertically:

0xFFFF = Right boundary
0xFED0 = Left boundary

0xFFFF = Top boundary
0xFE30 = Bottom boundary

Real coordinate data always comes in XY pairs. The values represent how far left/right or up/down the machine needs to shift the material when sewing. The format differs between regular stitching and embroidery. Both formats are as follows:

-------------------------------------------------
Real Coordinate Data - Regular Stitching
-------------------------------------------------
X Coordinate			| 0x00 - 0x1F
Y Coordinate			| 0x00 - 0x20
-------------------------------------------------


-------------------------------------------------
Real Coordinate Data - Embroidery
-------------------------------------------------
X Coordinate			| 0x00 - 0x10 and 0x40 - 0x50
Y Coordinate			| 0x00 - 0x10 and 0x40 - 0x50
-------------------------------------------------

Each format's data has its own meaning and needs to be interpreted separately; the logic for both are described later in the sections below. Real coordinate data contains a few bytes in between these pairs that signal what type of data the sewing machine can next expect from the Game Boy. These control codes are as follows:

-------------------------------------------------
Packet Control Codes
-------------------------------------------------
0xC1	| 1st byte after header. Signals start of a path.
0xC2	| 1st byte after header. Signals start of a path.
0xC3	| 1st byte after header. Signals start of a path.
0xC4	| 1st byte after header. Signals start of a path.
0xC7	| Signals a path end after next 4 bytes.
0xB9	| Signals start of a new packet.
0xBA	| Signals end of session (no more data, no more packets). Generally appears right before the checksum.
0xBB	| Signals end of one packet in a multi-packet session. Appears right before the checksum
0xBC	| Signals Real Coordinate Data has ended. The rest of the packet data is zero-filled.
0xBE	| Signals start of Shift Coordinate Data for moving EM-2000 to new positions.
0xBD	| Signals end of Shift Coordinate Data for moving EM-2000 to new positions.
0xBF	| Signals end of session (no more data, no more packets). Generally appears right before the checksum.
0xE7	| Signals a path end after next 4 bytes.
0xF7	| Signals a path end after next 4 bytes.
-------------------------------------------------

A typical single-session packet might look like this:

------------------------
Header
0xC1
X Data
Y Data
...
0xBC
Zero-filled
0xBF
Checksum
------------------------

A typical multi-session might look like this:

------------------------
Header
0xC1
X Data
Y Data
...
0xBB
Checksum



0xB9
X Data
Y Data
...
0xBC
Zero-filled
0xBF
Checksum
------------------------

[Sewing Machines] : Stitching Logic - Regular Stitching

X coordinates range from 0x00 (farthest point left) to 0x1F (farthest point right). Whenever the X coordinate changes, the machine will adjust the needle accordindly. Y coordinates are more complicated however, with regards to shifting up or down. The below chart details what values will shift the actual fabric (not the needle) vertically and how far:

-------------------------------------------------
0x00				Shift Down 1.25mm
0x01				Shift Down 1.1875mm
0x02				Shift Down 1.125mm
0x03				Shift Down 1.0625mm
0x04				Shift Down 1.0mm
0x05				Shift Down 0.9375mm
0x06				Shift Down 0.875mm
0x07				Shift Down 0.8125mm
0x08				Shift Down 0.75mm
0x09				Shift Down 0.6875mm
0x0A				Shift Down 0.625mm
0x0B				Shift Down 0.5625mm
0x0C				Shift Down 0.5mm
0x0D				Shift Down 0.4375mm
0x0E				Shift Down 0.375mm
0x0F				Shift Down 0.3125mm
0x10				Shift Down 0.25mm
0x11				Shift Down 0.1875mm
0x12				Shift Down 0.125mm
0x13				Shift Down 0.0625mm
0x14				No Change
0x15				Shift Up 0.0625mm
0x16				Shift Up 0.125mm
0x17				Shift Up 0.1875mm
0x18				Shift Up 0.25mm
0x19				Shift Up 0.3125mm
0x1A				Shift Up 0.375mm
0x1B				Shift Up 0.4375mm
0x1C				Shift Up 0.5mm
0x1D				Shift Up 0.5625mm
0x1E				Shift Up 0.625mm
0x1F				Shift Up 0.6875mm
0x20				Shift Up 0.75mm
-------------------------------------------------

Ultimately, the sewing machines can program stitching to move vertically in 0.0625mm increments and horizontally in 0.25mm increments. Horizontal movement is limited to a set "window", e.g. setting multiple X coordinates to 0x1F keeps the stitching at farthest point right. Vertical movement is unlimited, as the machines will move the fabric up or down like a feed.

While the X and Y coordinates come in pair, it is important to note how each affects the movement of the needle and fabric. The below example demonstrates how X and Y coordinates actually dictate movement, assuming there are only 4 sets of Real Coordinate data.

----------------------------------------------------------------------------------------------------------------------------------------------------
Data	| Location				| X movement			| Y movement
----------------------------------------------------------------------------------------------------------------------------------------------------
X0, Y0	| Virtual Coordinates from header	| Start at X0, move to X1	| IF Y1 >= 0x1A THEN Move fabric by Y1, ELSE Move fabric by Y0
X1, Y1	| 1st set of Real Coordinates in packet	| Move needle from X1 to X2	| Move fabric by Y1
X2, Y2	| 2nd set of Real Coordinates in packet	| Move needle from X2 to X3	| Move fabric by Y2
X3, Y3	| 3rd set of Real Coordinates in packet | Move needle from X3 to X4	| Move fabric by Y3
X4, Y4	| 4th set of Real Coordinates in packet	| Move needle from X4 to X1	| Move fabric by Y4
----------------------------------------------------------------------------------------------------------------------------------------------------
If the control codes 0xC7, 0xE7, or 0xF7 are not sent in one of the packets, the pattern continually loops as such:
----------------------------------------------------------------------------------------------------------------------------------------------------
X1, Y1	| 1st set of Real Coordinates in packet	| Move needle from X1 to X2	| Move fabric by Y1
X2, Y2	| 2nd set of Real Coordinates in packet	| Move needle from X2 to X3	| Move fabric by Y2
X3, Y3	| 3rd set of Real Coordinates in packet | Move needle from X3 to X4	| Move fabric by Y3
X4, Y4	| 4th set of Real Coordinates in packet	| Move needle from X4 to X1	| Move fabric by Y4
----------------------------------------------------------------------------------------------------------------------------------------------------

Ideally, repeating patterns would have the same data for the Virtual Coordinates and the very last Real Coordinate pair. When the pattern begins looping, the Virtual Coordinates are ignored.

[Sewing Machines] : Stitching Logic - Embroidery

X and Y coordinates use Bit 6 to determine whether the embroidery arm must move in a positive or negative direction, after which the machine will stitch once. The distance of each movement can be calculated as such:

IF X COORDINATE AND 0x40
	THEN X -= (X COORDINATE - 0x40)
ELSE
	X += X COORDINATE


IF Y COORDINATE AND 0x40
	THEN Y -= (Y COORDINATE - 0x40)
ELSE
	Y += Y COORDINATE

At certain point during embroidery, the embroidery arm must shift to a different area. The designs themselves are broken into multiple parts that are stitched continuously. When a new section that is not continuous with the current one must be stitched, the machine receives Shift Coordinate Data that dictate where to move next. This data always begins with the control code 0xBE and ends with the control code 0xBD. Typically, the path also ends (control code 0xE7 or 0xC7) right before the Shift Coordinate Data is sent. Shift Coordinate Data has the following format:

-------------------------------------------------
Shift Coordinate Data
-------------------------------------------------
0xBE				| Data Start
X Shift LSB			| 0x00 - 0xFF
X Shift MSB			| 0x00 - 0xFF
Y Shift LSB			| 0x00 - 0xFF
Y Shift MSB			| 0x00 - 0xFF
0xFF				| Signals additional 16-bit XY shifts if applicable
...				|
Additional XY shifts		|
...				|
0xBD				| Data End
-------------------------------------------------

The distance shifted horizontally or vertically comes in 16-bit XY pairs. Note that these These values are very different from 16-bit offsets found in the header. While the 16-bit XY pair in the header represents an absolute position, the Shift Coordinate Data operates on relative positioning. That is to say, the embroidery arm will shift up/down/left/right from the last position that was previously stitched. The 16-bit XY pairs for Shift Coordinate Data are calculated as such:

IF X SHIFT >= 0xFF00
	THEN X -= (0x10000 - X SHIFT)
ELSE
	X += (X SHIFT & 0xFF)


IF Y SHIFT >= 0xFF00
	THEN Y += (0x10000 - Y SHIFT)
ELSE
	Y -= (Y SHIFT & 0xFF)

Multiple, additional shifts can be made. In that case, after each 16-bit XY pair, a 0xFF byte must follow along with the next 16-bit XY pair. The final XY pair, however, is simply terminated by the 0xBD control code.

Note that sometimes the software sends shifts that result in no movement. These appear to be dummy shifts, perhaps for the sake of consistency when everything was programmed. These dummy shifts are often the last shifts to be made (and at times the only ones made).

[Sewing Machines] : Sewing Machine Status

The sewing machines report their status whenever the Game Boy sends the value 0x80 via external transfer. This byte describes various aspect of the machine during operation.

-------------------------------------------------
Status Byte
-------------------------------------------------
Bit 0 - Large Embroidery Hoop	| Used for EM-2000. If set, Bit 2 must also be set.
Bit 1 - EM-2000 Attached	| 0 = Not attached, 1 = Attached,
Bit 2 - Small Embroidery Hoop	| Must be set to use EM-2000 at all. If Bit 0 not set, defaults to small embroidery hoop.
Bit 3 - N/A			| 
Bit 4 - N/A			|
Bit 5 - "SW" Button		| Used for EM-2000. Alerts software to advance to next segment of embroidery.
Bit 6 - Foot Pedal		| 0 = Foot pedal is up, 1 = Foot pedal is pressed down.
Bit 7 - Pause Operation		| Alerts software when sewing operations are immediately paused.
-------------------------------------------------

Soul Doll Adapter

General Hardware Information

Communication Protocol - Start Signal

Communication Protocol - Read Operations

Communication Protocol - Write Operations

Soul Doll Data Format

Soul Doll Data Stats

Soul Doll Data Obfuscation

[Soul Doll Adapter] : General Hardware Information

The Soul Doll Adapter is a GBA accessory for the Legendz franchise, designed to allow data from plastic figurines to transfer over the games. The hardware came bundled with special editions of Legendz: Yomigaeru Shiren no Shima (released July 29th, 2004) and its sequel, Legendz: Sign of Necrom (released February 17th, 2005). The figurines, called "Soul Dollz" contain powerful monsters that players can use in battle. The Soul Dollz are "reborn" in the games, and from there they can level up and transfer that data back to the figurine.

*Ones made after Yomigaeru Shiren no Shima was released may not be "recognized" in that game. If the data sent to the adapter is correct but the Soul Doll is not in the game's internal database, it is categorized as "unknown".

[Soul Doll Adapter] : Communication Protocol - Start Signal

The GBA and the Soul Doll Adapter communicate via the serial port using General Purpose Mode. The protocol is essentially bit-banging. For most of the protocol, the GBA sets both SC and SI high. To begin any communications with the Soul Doll Adapter, the GBA writes to following "device start signal" to RCNT:

Device Start Signal:
--------------------
0x8020
0x8025
--------------------

The device start signal basically takes the Soul Doll Adapter out of standby-mode. The Soul Doll Adapter then accepts read or write commands to the EEPROM controller inside the Soul Dollz. When sending any commands or performing write operations, the start signal is always identified with Bit 7 of RCNT set to 0. When receiving data from commands through read operations, the start signal is always identified with Bit 7 of RCNT set to 1. For example, the least significant byte of RCNT may be the following for the start signals:

Start signal when issuing commands or performing writes:
--------------------
0x25 0x27 0x27 0x25
--------------------

Start signal when receiving data through read operations:
--------------------
0xA5 0xA7 0xA7 0xA5
--------------------

These signals determine when one command ends and another begins or when data is read or written.

[Soul Doll Adapter] : Communication Protocol - Read Operations

The 24LC08 allows for random access at any given address. To do so, the EEPROM controller must receive the following 3 pieces of information:

  1. Start Signal + Slave Address + Dummy Write Command
  2. Start Signal + Word Address
  3. Start Signal + Slave Address + Read Command

The slave address is 1 byte, with the Bits 4-7 being the device identifier (in the case of the 24LC08, this is 0b1010). Bits 1-3 are the device address. They effectively form the two MSBs of the final address (Bit 3 is ignored on the 24LC08, only use Bits 1-2). Bit 0 is the command; 0 = Write and 1 = Read.

The GBA uses 4 transfers per bits, with Bit 3 of RCNT determining whether the value is a "0" or a "1". A typical slave address sent via the GBA might look like this:

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bit 7               | Bit 6               | Bit 5               | Bit 4               | Bit 3               | Bit 2               | Bit 1               | Bit 0
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Device ID - 0b1010                                                                    | Ignored             | 2 MSB of final address                    | EEPROM command     
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0xAD 0xAF 0xAF 0xAD | 0xA5 0xA7 0xA7 0xA5 | 0xAD 0xAF 0xAF 0xAD | 0xA5 0xA7 0xA7 0xA5 | 0xA5 0xA7 0xA7 0xA5 | 0xAD 0xAF 0xAF 0xAD | 0xAD 0xAF 0xAF 0xAD | 0xA5 0xA7 0xA7 0xA5
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Data is received MSB first. The 1st and 4th transfers for each bit are probably irrelevant, however, the 2nd and 3rd transfers contain the actual data for the bit. So:

0xAD 0xAF 0xAF 0xAD = Bit 3 is HIGH = 1
0xA5 0xA7 0xA7 0xA5 = Bit 3 is LOW = 0

The first slave address sent is basically ignored, as if the write command. This, however, prompts the 24LC08 to expect a word address next. The word address is the same format; 4 transfers per bit, with the 2nd and 3rd Bit 3 values determining whether it's a "0" or a "1". The word address forms the lower 8 bits of the final address to read from.

After the word address is sent, a final slave address is sent along with Bit 0 being set to 1 to indicate a read command. This final slave address forms the real two MSBs of the final address. Once this slave address and the read command are sent, EEPROM can be read from by sending a start signal followed by 32 transfers. The EEPROM controller doesn't seem to care what is sent during reading, so long as it's not another start signal. Once a full byte has been read, the internal pointer for the EEPROM address is incremented, and another read can be done simply by sending another start signal followed by 32 more transfers. The data format for reading looks something like this:

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bit 7               | Bit 6               | Bit 5               | Bit 4               | Bit 3               | Bit 2               | Bit 1               | Bit 0
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0x2D 0x2F 0x2F 0x2D | 0x25 0x27 0x27 0x25 | 0x2D 0x2F 0x2F 0x2D | 0x25 0x27 0x27 0x25 | 0x2D 0x2F 0x2F 0x2D | 0x25 0x27 0x27 0x25 | 0x2D 0x2F 0x2F 0x2D | 0x25 0x27 0x27 0x25
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Again, 2nd and 3rd transfers use Bit 3 to determine a "0" or a "1". The above example would be 0b10101010 or 0xAA. Once another command is detected, reading stops. One important thing to note, after sending the final slave address, the very first start signal still looks something like:

--------------------
0x25 0x27 0x27 0x25
--------------------

But after the 1st byte has been read, the start signal shifts to something like:

--------------------
0xA5 0xA7 0xA7 0xA5
--------------------

It isn't until another command is issued that the start signals swap. Generally, both Isle of Trial and Sign of Nekrom tend to read EEPROM in chunks of 128 bytes of 256 bytes. If the internal pointer for the EEPROM address is incremented past 0x3FF, it rolls over to 0x000. Apparently, when this happens, another device start signal must be issued.

[Soul Doll Adapter] : Communication Protocol - Write Operations

Writing shares many of the same conventions as reading. The EEPROM controller needs 2 pieces of information:

  1. Start Signal + Slave Address + Write Command
  2. Start Signal + Word Address

It's exactly like reading, except no secondary slave address is issued, therefore what would normally be the dummy write command is actually acknowledged. Additionally, there is no need to shift to a different start signal; only [0x25 0x27 0x27 0x25] is used. Once the slave address, write command, and word address are sent, data is written using a start signal plus 32 transfers for the byte. Once again, the format of the byte looks something like this:

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bit 7               | Bit 6               | Bit 5               | Bit 4               | Bit 3               | Bit 2               | Bit 1               | Bit 0
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0xAD 0xAF 0xAF 0xAD | 0xA5 0xA7 0xA7 0xA5 | 0xAD 0xAF 0xAF 0xAD | 0xA5 0xA7 0xA7 0xA5 | 0xAD 0xAF 0xAF 0xAD | 0xA5 0xA7 0xA7 0xA5 | 0xAD 0xAF 0xAF 0xAD | 0xA5 0xA7 0xA7 0xA5
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Again, 2nd and 3rd transfers use Bit 3 to determine a "0" or a "1". The above example would be 0b10101010 or 0xAA. Unlike reads, which can continue on updating the internal EEPROM address, writes are done in 16-byte pages. Up to 16-bytes can be written sequentially; anymore and the writes loop around. E.g. if writing to 0x100 a page write has a range of 0x100 to 0x10F. Attempting to write a 17th byte will overwrite 0x100 instead of 0x110. In order to write 0x110 to 0x11F, another write slave address, write command, and word address need to be sent to the 24LC08.

[Soul Doll Adapter] : Soul Doll Data Format

Most of the 1KB data contained on the 24LC08 appears to be related to the Talispod or Talisdam accessories, e.g. such data as the Legend's preferred humidity and tempurature, and their stats. For the games, however, only bytes 0x300 - 0x3FF are relevant. This area of memory specifies the nickname, the owner's name, and various other flags related to auto-training mode and attached items. Most importantly, these bytes determine what kind of Legend is generated from the Soul Doll.

The layout of this memory varies depending on which Legendz game is being played. Data for Legendz: Yomigaeru Shiren no Shima and Legendz: Sign of Necrom change the location of the fields. While Sign of Necrom can recognize the format of Yomigaeru Shiren no Shima, data from Sign of Nekrom is incompatible with Yomigaeru Shiren no Shima.

For Yomigaeru Shiren no Shima, EEPROM data is arranged as follows:

-----------------------------------------------------------
Address		| Data Description
-----------------------------------------------------------
0x302		| Legend ID
0x398 - 0x39C	| Owner Name
0x3A1 - 0x3B0	| Message
0x3B1 - 0x3B9	| Legend Name
0x3D4		| Legend Level
0x3D5 - 0x3DE	| Legend Stats
0x3EE		| Auto Adventure Flag
0x3F0		| Attached Item Flag
0x3F1 - 0x3F2	| Attached Item Type & Quantity
0x3FE - 0x3FF	| Checksum
-----------------------------------------------------------

For Sign of Nekrom, EEPROM data is arranged as follows:

-----------------------------------------------------------
Address		| Data Description
-----------------------------------------------------------
0x302		| Legend ID
0x390 - 0x394	| Owner Name
0x3A1 - 0x3B0	| Message
0x399 - 0x3A0	| Legend Name
0x3BD		| Legend Level
0x3BE - 0x3C7	| Legend Stats
0x3CC		| Auto Adventure Flag
0x3CE - 0x3CF	| Attached Item Type & Quantity
0x3FC		| Attached Item Flag
0x3FE - 0x3FF	| Checksum
-----------------------------------------------------------

Byte 0x302 acts as the Legend ID. Depending on the value of this, the games will produce a different Legend. Their values are listed below:

0x01 = Windragon (A)?			0x21 = Command Windragon Break Armed		0x43 = Minotauros
0x03 = Windragon (B)?			0x22 = Command Blazedragon Volk Armed		0x44 = Oberon
0x04 = Mermaid				0x23 = Chimaera					0x45 = Lich
0x05 = Werewolf				0x24 = Triton					0x48 = Colonel Windragon Tornado Soul		
0x06 = Will 'o' Wisp			0x25 = Gargoyle					0x49 = Pheonix
0x07 = Tornado Kingdragon		0x26 = Cloud Giant				0x4A = Behemoth
0x08 = Blaze Dragon (A)?		0x27 = Command Windragon			0x4B = Jabberwock
0x09 = Goblin				0x28 = Command Blazedragon			0x4C = Leviathan
0x0A = Yeti				0x2B = Spiritual Windragon			0x4D = Fenrir
0x0B = Hell Hound			0x2C = Hexadragon				0x4E = Colonel Blazedragon Volcano Soul
0x0C = Volcano Kingdragon		0x2D = Windragon Berserker Mode (Growing)?	0x4F = Sphinx
0x0D = Windragon Berserker Mode		0x2E = Blazedradon Berserker Mode (Growing)?	0x50 = Cyclops
0x0E = Blazedragon Berserker Mode	0x31 = Devour Crocodile (Dandy)			0x54 = Syclla
0x0F = Fire Giant			0x32 = Harpy					0x55 = Titan
0x10 = Undine				0x33 = Cait Sith				0x56 = Echidna
0x11 = Peryton				0x34 = Command Blazedragon Volk Armed		0x59 = Ranshiin (B)?
0x12 = Troll				0x35 = Devour Crocodile				0x5A = Chibi Shiron (Manga Version)?
0x13 = Command Windragon		0x36 = Vampire					0x5B = Blazedragon (B)?
0x14 = Manticore			0x37 = Spiritual Kingdragon			0x5C = Windragon (Manga Version)
0x15 = Carbuncle			0x38 = Ogre					0x5D = Griffin
0x16 = Command Blazedragon		0x39 = Spriggan					0x5E = Bigfoot
0x17 = Dwarf				0x3A = Command Windragon Break Armed		0x5F = Tiamat
0x18 = Skeleton				0x3B = Bicorn					0x66 = Wyvern
0x19 = Earthquake Kingdragon		0x3C = Centaur					0x67 = Storm Kingdragon
0x1A = Storm Kingdragon			0x3D = Nekrom Kingdragon			0x68 = Carbuncle
0x1B = Wyvern				0x3E = Golem					0x6D = Giant Crab
0x1E = Ranshiin (A)?			0x3F = Ifrit					0x71 = Hydra
0x1F = Ranshiin (B)?			0x41 = Gorgon					0x72 = Iron Golem
0x20 = Chibi Shiron			0x42 = Kraken					0x73 = Valkyrie
											0x74 = Cerberus

Several IDs appear to be mapped to the same Legend. This may be explained by the fact that some Soul Dollz were released in A, B, and sometimes C variants. The plastic figurine is different, but the GBA games generate the same sprite and default name for the Soul Doll. All of the potential duplicates are marked with "?" in the list above. Although there are 103 Soul Dollz, the list remains incomplete. The gaps between entries do not generate valid Legendz, which suggests other bytes in EEPROM are also responsible for the ID.

1 byte represents the so called "Training Bonus" granted to a Legend when it is reborn. This adds a certain amount of points to its various base stats, such as HP, Strength, Defense, etc. The larger the value of this byte, the greater the stat boost will be. It has a limited range of valid values (1 = Minimum, 6 = Maximum).

2 bytes represent the quantity and type of attached items for a Soul Doll. A Legend can temporarily hold onto items from the player's inventory. Only 1 type of item can be given to a Legend at a time, but its quanitity can vary (1 = Minimum, 9 = Maximum).

5 bytes are used to store the owner's name. During the Soul Doll Initialization process, the player's name is registered to the Soul Doll. The games use this to lock the Soul Doll to a particular player. If the owner name written to EEPROM doesn't match the current one from the game's save file, EEPROM must be erased and the Soul Doll reset in order to use it. Each byte in EEPROM represents one character. The exact string format is currently unknown.

16 bytes are used to store a brief message inside the Soul Doll. This message can be checked during the Reborn process on a Soul Doll that was previously initialized for a given player. Each byte in EEPROM represents one character. The exact string format is unknown.

8 bytes are used to store the Legend's name. Each byte in EEPROM represents one character. The exact string format is currently unknown.

1 byte represents the level of the Legend. Its value ranges from 1 to 99.

10 bytes represent the various stats about the player's Legend inside the Soul Doll (HP, Strength, Defense, Magic Power, Magic Defense, and Speed). The size of each value varies in terms of bits, and the same value is usually spread over multiple bytes. See the next section for more information.

1 byte represents the Auto Adventure flag. When the Legend goes on an Auto Adventure, this byte is set to a non-zero value, otherwise it is set to 0x00. For Yomigaeru Shiren no Shima, this flag is always 0x01 when set. For Sign of Nekrom, it varies depending on the type of Auto Adventure, acting as a sort of ID.

Bytes 0x3FE through 0x3FF are a 16-bit checksum the data 0x380 through 0x3FD. The checksum is computed by adding up every byte within that range. If the checksum is incorrect, both Legendz games will treat the entire Soul Doll data as invalid, which will require it to be reinitialized. After calculating the initial checksum, it must be XOR'ed with a separate 16-bit value. Yomigaeru Shiren no Shima uses 0x4832, while Sign of Nekrom uses 0x4C32. Sign of Nekrom can detect both types of checksums and uses this to determine which game last modified EEPROM data.

[Soul Doll Adapter] : Soul Doll Data Stats

Use the following psuedocode to obtain the values for each attribute of the Soul Doll's Legend. Assume that ADDRESS the specified the EEPROM address 0x3D5 (for Yomigaeru Shiren no Shima) or 0x3BE (for Sign of Nekrom).

-----------------------------------------------------------
HP
-----------------------------------------------------------
VAL1 = READ 16 BITS FROM (ADDRESS)
VAL2 = READ 08 BITS FROM (ADDRESS + 2)
HP = (VAL_1 >> 6) | ((VAL & 0x0F) << 10)


-----------------------------------------------------------
STRENGTH
-----------------------------------------------------------
VAL1 = READ 16 BITS FROM (ADDRESS + 2)
STRENGTH = ((VAL1 << 18) >> 22)


-----------------------------------------------------------
DEFENSE
-----------------------------------------------------------
VAL1 = READ 16 BITS FROM (ADDRESS + 6)
DEFENSE = ((VAL1 << 20) >> 22)


-----------------------------------------------------------
MAGIC POWER
-----------------------------------------------------------
VAL1 = READ 32 BITS FROM (ADDRESS + 2)
MAGIC POWER = ((VAL1 << 8) >> 22)


-----------------------------------------------------------
MAGIC DEFENSE
-----------------------------------------------------------
VAL1 = READ 32 BITS FROM (ADDRESS + 6)
MAGIC DEFENSE = ((VAL1 << 10) >> 22)


-----------------------------------------------------------
SPEED
-----------------------------------------------------------
VAL1 = READ 08 BITS FROM (ADDRESS + 6)
VAL2 = READ 08 BITS FROM (ADDRESS + 5)
SPEED = ((VAL1 & 0x03) << 8) | VAL2

[Soul Doll Adapter] : Soul Doll Data Obfuscation

The EEPROM data is obfuscated with a repeating 32-bit key. This makes the data somewhat inaccessible unless parsed first. The 32-bit key is 0xA8262CDB as an LSB first value. Each 32-bit value from EEPROM is simply XOR'ed by the key. Another way to unscramble EEPROM is demonstrated by the following psuedocode:

ARRAY = 0xDB, 0x2C, 0x26, 0xA8
UNSCRAMBLED VALUE = EEPROM BYTE XOR ARRAY[EEPROM ADDRESS AND 0x03]

This obfuscation only occurs on bytes 0x380 through 0x3FF. The checksum is calculated and XOR'ed by its own 16-bit value before XOR'ing this 128-byte region with the above mentioned 32-bit value.

Battle Chip Gate

General Hardware Information

Compatible Games

Protocol

Multiplayer Setup

Starting with Mega Man Battle Network 4, Capcom along with Takara introduced GBA accessories known as Battle Chip Gates. These devices allowed players to insert physical Battle Chips into a slot, which in turn executed attacks or activated special moves during combat. Effectively, these Battle Chip Gates simulated the act of being a real "Net Navi operator" as depicted in the games and anime. Three hardware revisions exist for each numbered Battle Network game released after 2003 (4, 5, 6). Among those revisions are several variants that differ only in color and design. Each revision additionally uses its own collection of Battle Chips.

[Battle Chip Gate] : General Hardware Information

[Battle Chip Gate] : Compatible Games

Battle Chip Gate

Mega Man Battle Network 4:				Enables Operation Battles + using real chips in that same mode
Mega Man Zero 3						Unlocks Guardian minigames based on chip ID
Rockman EXE 4.5: Real Operation				Enables using real chips in ever battle

Progress Chip Gate

Mega Man Battle Network 5				Enables Navi Change and Operation Battles + using real chips in that same mode

Beast Link Gate

Rockman EXE 6						Enables infinite BeastOut, Link Navi System, and using real chips in any battle

4.5 Real Operation was never released outside of Japan. Supposedly these accessories were deemed unpopular in the west, therefore English versions of Battle Network 6 had features relating to the Beast Link Gate disabled or removed. The bulk of content, such as BeastOut and loading Battle Chips during fights still works. The English version, however, merely alters the detection code so that it fails to recognize the Beast Link Gate even when properly plugged in.

For Mega Man Zero 3, chips with odd IDs unlock the Phantom minigame, while chips with even IDs unlock the Harpuia minigame. The RedSun chip (#304) unlocks the Fefnir minigame, while the BlueMoon chip (#309) unlocks the Leviathan minigame.

[Battle Chip Gate] : Protocol

Each Battle Chip Gate uses mostly the same protocol with only very slight changes. They are largely the same hardware in different shells and different physical arrangements. From a software point of view, however, they behave nearly identically.

The Battle Chip Gates communicate via the GBA's Multi16 mode with a baud rate of 115200bps. The GBA acts as the parent, and the device is Child 1. The Chip Gates begin in a sort of "stand-by" mode where they continually respond with their "Gate ID". This ID is the only thing the Chip Gates send until the GBA transmits a start signal. The Gate IDs are as follows:

Battle Chip Gate		0xFFC6
Progress Chip Gate		0xFFC7
Beast Link Gate			0xFFC4

The English release of Battle Network 6 checks for a Gate ID of 0xFF00 instead of 0xFFC4, thus causing the rest of the detection code to fail and preventing players from using the Beast Link Gate via normal means.

The start signal looks something like this sequence of transmissions:

  1. 0x0000
  2. 0xA---
  3. 0xA---
  4. 0xA---
  5. 0x8FFF
  6. 0xA---
  7. 0x0000

Typically, the 0xA--- values will be 0xA380 (used for Mega Man Zero 3), 0xA3D0 (used for 4.5 Real Operations), or 0xA6C0 (used for Battle Network 6). The purpose and function or lower 12-bits are unknown, but they may arbitrary, or simply any value OR'ed with 0x280. At any rate, the games use them as a means to keep track of the protocol by examining the last value sent (which would be stored in the halfword at 0x4000120).

On the transmission of the 6th value for the above start signal, the protocol is already switching over to the next phase, a repeating series of 9 transfers that contains the Battle Chip ID. The 9-stage transfer session looks something like this:

  1. Chip Gate ID (e.g. 0xFFC6)
  2. 0xFFFF
  3. 0xFFFF
  4. 0x--00
  5. 0xFF--
  6. Battle Chip ID
  7. 0x0000
  8. 0x0000
  9. 0x0000

The 4th and 5th transfer contains seeds that increment and decrement respectively on each transfer. The two seeds together add up to 255, however, it appears all compatible game software simply ignore this data. 6th transfer is the Battle Chip ID as determined by the DIP switch. A value of zero indicates no chip is inserted, while a non-zero value indicates a chip is currently slotted. This 9-stage transfer loops endlessly until the GBA sends another start signal. Once any 0xA--- value of the start signal is received, the Battle Chip Gate responds with its Gate ID (just like in stand-by mode) until the start signal terminates. Afterwards, the 9-stage transfers begin once again.

Mega Man Battle Network 6 sends an indeterminate number of transfers via Normal32 mode before the first start signal, and oddly enough before the any first battle after loading a save. The Battle Chip Gates simply return zero for these transfers.

It appears that some of the bytes set high (such as transfers 2, 3, and 5) occasionally do hold other values ranging from 0x00, 0x80, or 0xC0, however the conditions under which this occurs remains unknown. Needless to say, on the software side those changes are irrelevant.

[Battle Chip Gate] : Multiplayer Setup

It's possible to link together 2 GBAs, each with their own Battle Chip Gate, for multiplayer battles in all of the compatible Battle Network games. The model for this multiplayer appears to work as follows:

Player 1			Parent
Player 1 Battle Chip Gate	Child 1
Player 2			Child 2
Player 2 Battle Chip Gate	Child 3

With this setup, Player 1 and Player 2 can technically ignore any output the opponent's Battle Chip Gate and focus on their own, despite essentially being able to see exactly what's happening on the other side. It also indicates that the Battle Chip Gates are capable of operating as Child 1 or Child 3.

Multi Plust On System

General Hardware Information

Compatible Games

Communication Protocol

Pluster IDs

[Multi Plust On System] : General Hardware Information

The Multi Plust On System (MPOS) is an accessory for the Bouken Yuuki Pluster World franchise from Takara. Designed as a "toys-to-life" device, it allows plastic figurines to transfer characters known as "Plusters" into the games. Bouken Yuuki Pluster World: Densetsu no Plust Gate and the EX version are RPGs, while Bouken Yuuki Pluster World: Pluston GP is a racing game. All 3 were released in 2003 and came with special sets featuring the the MPOS and a bundled Pluster figurine.

[Multi Plust On System] : Compatible Games

All 3 games are more or less unplayable without the MPOS. A few minigames can be played in Densetsu no Plust Gate EX, but in both that game and the regular Densetsu no Plust Gate, starting the main RPG requires the MPOS be attached with a Pluster Figure inserted. In Pluston GP, many of the menus can be navigated, but beginning a race also requires the accessory and an inserted figurine.

[Multi Plust On System] : Communication Protocol

Communication between the MPOS and the GBA is very simple. The role of the MPOS is to provide a single 16-bit number. Depending on which spokes the plastic model uses to put on the MPOS' array of pressure pads, a different number is sent to the GBA. The number effectively acts as an ID for the Pluster figurine. Using General Purpose Mode, both sides send a total of 37 transfers. At the beginning, of a session, the games will set all lines (SC, SD, SI, SO) as output with the RCNT value 0x80F0. Afterwards the 37 transfers keep looping indefinitely. The first 4 transfer appear to act as a start signal. The start signal is the following:

----------------------------------------------
RCNT		|SC	| SD	| SI	| SO 
----------------------------------------------
0x80BD		| 1	| 0	| 1	| 1
0x80B5		| 1	| 0	| 1	| 0
0x80BF		| 1	| 1	| 1	| 1
0x80BF		| 1	| 1	| 1	| 1

Although the games' code ignores the results of the start signal, the MPOS returns these values:

----------------------------------------------
RCNT		|SC	| SD	| SI	| SO 
----------------------------------------------
0x80B9		| 1	| 0	| 0	| 1
0x80B1		| 1	| 0	| 0	| 0
0x80BB		| 1	| 1	| 0	| 1
0x80BB		| 1	| 1	| 0	| 1

The next 33 transfers are used for the 16-bit ID, 1 bit for every 2 transfers. The last transfer appears to dangle. This may simply be necessary to complete the transfer of the ID and begin the process over again. The GBA sends the following over and over again until it sends another start signal:

----------------------------------------------
RCNT		|SC	| SD	| SI	| SO 
----------------------------------------------
0x80BE		| 0	| 1	| 1	| 1
0x80BC		| 0	| 0	| 1	| 1

In response, the MPOS toggles SI every odd transfer (when receiving 0x80BE from the GBA) to send the the bit. For example, for the Pluster Wyburst (PF002), it produces the ID 0x16A0. The values sent back to the GBA look like this:

------------------------------------------------------
RCNT		|SC	| SD	| SI	| SO 	| Bit
------------------------------------------------------
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BE		| 0	| 1	| 1	| 1	| 1
0x80BC		| 0	| 0	| 1	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BE		| 0	| 1	| 1	| 1	| 1
0x80BC		| 0	| 0	| 1	| 1	|
0x80BE		| 0	| 1	| 1	| 1	| 1
0x80BC		| 0	| 0	| 1	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BE		| 0	| 1	| 1	| 1	| 1
0x80BC		| 0	| 0	| 1	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BE		| 0	| 1	| 1	| 1	| 1
0x80BC		| 0	| 0	| 1	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BA		| 0	| 1	| 0	| 1	| 0
0x80B8		| 0	| 0	| 0	| 1	|
0x80BA		| 0	| 1	| 0	| 1	|

The ID is received serially, MSB first. Essentially, a "1" bit is transferred whenever both SD and SI go high, and a "0" bit is transferred whenever SD is high, but SI is low.

[Multi Plust On System] : Pluster IDs

Currently, there are 22 identified Pluster figurines along with some 16-bit IDs that will generate that character in the games. There are multiple variants of figurines, therefore Plusters have multiple valid IDs, since the configuration of their spokes is different. The electronic toys may treat them differently, yet the GBA games do not.

IMPORTANT: Most of these IDs were generated artificially by testing them against the games. Entries marked with a "!" represent actual IDs directly captured from a MPOS. The artificially generated ones are, however, sufficient for the purposes of emulation or using homebrew on a second GBA to fake a connected MPOS.

PF001 :: Beetma
	! 0x1780
	* 0x16C0
	* 0x1682
	* 0x1642

PF002 :: Wyburst
	! 0x16A0
	* 0x1660
	* 0x1622

PF003 :: Gabrian
	* 0x1650
	* 0x1630

PF004 :: Molly
	* 0x16D8
	* 0x16B2
	* 0x1672

PF005 :: Hania
	* 0x1688
	* 0x1648
	* 0x1628

PF006 :: Zagarian
	* 0x1614

PF007 :: Tan Q
	* 0x16D4

PF008 :: Warrion
	* 0x16F0
	* 0x1612

PF009 :: Doryuun
	* 0x16B8
	* 0x1678

PF010 :: Fezard
	* 0x16D2
	* 0x1618

PF011 :: Mashanta
	* 0x1684		
	* 0x1644
	* 0x1624

PF012 :: Gingardo
	* 0x16B4		
	* 0x1674

PF013 :: Torastorm
	* 0x16CC

PF014 :: Gongoragon
	* 0x16AC

PF015 :: Mighty V
	* 0x169C

PF016 :: Dorastorm
	* 0x16FC

PF-EX001 :: Beetma EX
	! 0x1666

PF-EX002 :: Varouze
	* 0x1636

PF-EX003 :: Gigajoule
	* 0x164E

PF-EX004 :: Badnick
	* 0x161E

PF-EX005 :: Poseihorn
	* 0x167E

PF-EX006 :: Tera
	* 0x1621

When the MPOS is connected to the GBA but has no Pluster figurine inserted, the device returns the ID 0x1400.

Turbo File Advance

General Hardware Information

Compatible Games

Communication Protocol

Commands

File Structure

[Turbo File Advance] : General Hardware Information

Developed by Sammy Corporation and released in April of 2002, the Turbo File Advance is an external storage device designed to hold large amounts of save data. Following in the footsteps of ASCII Corporarions Turbo File GB, the Turbo File Advance came out two years later, with the key difference between the two being support for GBA software. Only select games specifically programmed to take advantage of the Turbo File Advance were compatible. The accessory made use of memory cards as well, one of only two instances where this happened on the Game Boy.

The Turbo File Advance is pretty much an exact copy of the Turbo File GB. The PCB even still has "TURBO FILE GB" printed on it, and one microprocessor still says "ASCII".

[Turbo File Advance] : Compatible Games

Although the manual explicitly claims that the previous Turbo File GB games are not compatible, it is actually unknown if that is the case. In theory, the Link Cable on the Turbo File Advance would be capable of handling 3.3v instead of the 5v used on the Turbo File GB, which would be one source of incompatibility. Whether or not the Turbo File Advance would function when using the GBA's backward compatibility or if the Turbo File Advance itself was just a marketing ploy to sell more hardware remains uncertain.

[Turbo File Advance] : Communication Protocol

The Turbo File Advance has exactly the same protocol as the Turbo File GB. The GBA communicates over an external clock in 8-bit Normal mode, mirroring how a GBC would generally work with the device. The sync signal, packet format, banking, use of memory cards, and commands have not been changed in the Turbo File Advance. Reference existing Turbo File GB documentation for further information.

[Turbo File Advance] : Commands

Only one new command is used by the Turbo File Advance (and only one game, Derby Stallion, executes it). The other commands are the exact same as the previous Turbo File GB commands.

Command 0x34 - Block Write

Parameters: 2 bytes forming a 13-bit offset (MSB first) and 1 byte with value to fill block with

Response Data: 4 byte echo packet

The two parameters are the 13-bit offset to read data from. The 1st parameter is Bit 8-12 and the 2nd parameter is Bit 0-7. The 3rd parameter is the value to write into the next 64 bytes of the block. The response packet is like all of the echo packets for other commands, however, it technically isn't a copy of the original packet.

-------------------------------------------------
Command 0x34 Response Packet Bytes
-------------------------------------------------
Byte 0x00		| 0x34
Byte 0x01		| 0x00
Byte 0x02		| Device Status
Byte 0x43		| Checksum = 0x100 - 0xA5 - (Sum of Bytes 0x00 through 0x02)
-------------------------------------------------

[Turbo File Advance] : File Structure

The banking in the Turbo File Advance is the same as the Turbo File GB. Bank 0x7F (for internal storage) and Bank 0xFF (for memory card storage) contain the file headers for each file; these headers identify the name of the file and how many blocks it occupies. The format is described below:

-------------------------------------------------
File Header
-------------------------------------------------
Byte 0x00		| 0x5A
Byte 0x01 - 0x04	| Game ID
Byte 0x05 - 0x13	| ASCII String for filename (16 characters max)
Byte 0x14 - 0x15 	| Should all be 0x20
Byte 0x16		| Current block ranging from 0 to (Total - 1)
Byte 0x17		| Total number of blocks for save
Byte 0x18 - 0x3F	| Should all be 0xFF	
-------------------------------------------------

Games generally write in 8 blocks (meaning 15 saves total for internal storage or the memory card). However, Derby Stallion can write 1 or 7 blocks of data. Even so, without expanding the memory capacity from the Turbo File GB, the Turbo File Advance generally ends up holding fewer saves.

Bytes 0x01 through 0x04 act as IDs. They are the same bytes found in the game's ROM header, specifically the ASCII-encoded "Game Code" (bytes 0xAC through 0xAF). Once again, the use of IDs prevents incompatibilities between games when reading data.

AGB-006

General Hardware Information

Device Detection

IR Operation

Comparison to GBC IR

Zoid Commands

Prototype IR Port

[AGB-006] : General Hardware Information

The AGB-006 is an accessory released in conjunction with Cyber Drive Zoids: Kiju no Senshi Hyuu on July 18, 2003. It serves as an infrared adapter, coming as a bundle with each game. Using IR signals, players can turn their GBAs into remote controls to pilot three toy model Zoids. Although the GBA removed the GBC's IR port, the AGB-006 officially restored that functionality as an add-on. Unfortunately Cyber Drive Zoids was the only game to take adavantage of the AGB-006.

[AGB-006] : Device Detection

The AGB-006 can be detected in software by generating an interrupt request in General Purpose mode whenever sending an OFF/ON pulse. When no AGB-006 is plugged in, no interrupts are triggered, so checking Bit 7 of the Interrupt Request Flags is sufficient to verify whether or not the adapter is present. At a minimum, two writes are necessary. The first sets the SO line LOW (turning the IR signal off). The second sets the SO line HIGH (turning the IR signal on) and enables interrupts. The following RCNT values are sent by Cyber Drive Zoids to trigger an interrupt request:

0x80B2		//Turn IR light off
0x81BA		//Turn IR light on and enable Serial I/O interrupts

For this example, after the interrupt is generated, RCNT should hold the value 0x2004 at that time.

[AGB-006] : IR Operation

The following values of RCNT can be used for various IR-related functions:

----------------------------------------
Value		| Usage
----------------------------------------
0x80BA		| Turns IR signal on
0x80B2		| Turns IR signal off
0x8190		| Receive IR signal

For turning the IR signal on, set the SO line HIGH. For turning the IR light off, set the SO line LOW.

For receiving IR signals, set SI's direction as input. An interrupt will be requested once the signal arrives. This interrupt is only generated when the IR sensor begins detecting light when it previously detected none. Essentially it comes when transitioning from a "no light" to "light" state. There doesn't appear to be a way to get an interrupt once the signal goes off. It should be noted that Cyberdrive Zoids, the only officially supported game for the AGB-006, is not programmed to receive IR signals. This feature was thus never used in commercial software.

Both sending and receiving signals can trigger an interrupt if Bit 8 of RCNT is set. For receiving IR signals, interrupts are the most effective method of detecting an incoming signal, as simply waiting for RCNT to change its read value is unreliable (unlike the device detection phase). Writing the value 0x8190 to RCNT, for example, instantly changes its read value to 0x8196, even when no AGB-006 is connected. For this reason, interrupts are all but required for properly receiving IR signals. Requesting interrupts while sending IR signals is optional but of limited use.

When receiving an IR signal, software should in theory measure the delay until the next IR signal to get the total ON/OFF pulse duration. Once RCNT is set, IR interrupts are continuously generated whenever a new IR signal is detected, as long as Bit 7 of the Interrupt Request Flags is cleared after each pulse. The so-called "signal fade" present in GBC IR hardware is not evident in the AGB-006, so the accessory will not automatically stop receiving an IR signal after a set amount of time. Software should set a cut-off threshold for pulse durations to decide when one side has stopped sending, especially as the AGB-006 does not have any apparent feedback to manually check.

[AGB-006] : Comparison to GBC IR

The biggest difference between the AGB-006 and the GBC's native IR hardware are interrupts. While prototype GBAs originally were designed to have IR ports with their own associated interrupts, the AGB-006 repurposes the existing serial interrupt. Interrupts potentially simplify the task of detecting IR light. Depending on the communication protocol, however, actually servicing an interrupt may be too slow for rapid data transfer. In such cases, a tight loop that merely continuously reads the Interrupt Request Flags may be more effecient. The AGB-006's interrupts excel in convenience over the GBC when detecting the next IR signal, as they eliminate the need to check any OFF status of the IR signal. The only thing a program needs to do is maintain a maximum allowed duration for pulses to see when communications should stop (something GBC software does anyway to check for errors mid-transmission).

Physically speaking, the AGB-006 has a far wider range of reception. It is capable of receiving signals at a maximum distance roughly between 1.7 and 1.8 meters. Furthermore, it can receive signals approximately within 150 degrees horizontally, and approximately 165 degrees vertically (IR light is only undetectable from very extreme angles beneath the unit). This stands in contrast to the GBC, which mostly needs line-of-sight to communicate via IR, or even detect IR sources.

Finally, while the GBC IR hardware is receptive to incandescent light sources, the AGB-006 largely ignores them.

[AGB-006] : Zoid Commands

Officially, the AGB-006 is exclusively used to control motorized minature models from the Zoids franchise. This communication is always one-way, with the GBA blasting IR signals repeatedly once a button is pressed. The protocol is fairly simple. A number of IR pulses (total ON and OFF time) are sent with only a few specific lengths. Their exact timing seems to vary and may not be entirely consistent, so relative duration must be used. The ON phase of the pulse accounts for a very miniscule amount time, while the OFF phase accounts for the majority of the delay.

Mini Pulse		Smallest pulse. Very short and very numerous
Short Pulse		Roughly 16x the length of a Mini Pulse
Medium Pulse		Roughly 40x the length of a Mini Pulse
Long Pulse		The longest pulse. Easily around 6000x the length of a Mini Pulse

Mini Pulses appear to last anywhere from 18.1us to 20us. There are dozens of them in between every other type of pulse, and they seem to act as a sort of "keep-alive" for IR transmission. Below are the specific transfers used to manipulate the Zoids. There are two separate "channels" for ID1 and ID2. The goal was to have two players compete against each other, so two distinct versions of each command exist to avoid interference.

When omitting Mini Pulses, each IR command is 12 Short or Medium Pulses followed by 1 Long Pulse. The order of Short and Medium Pulses determines the exact command, while the Long Pulse functions as a stop signal. Each command can be converted into binary by treating a Medium Pulse as "1", and a Short Pulse as a "0". Commands can then be parsed by examining every 4-bit segment. Below describes how each segment affects the command. Note that the values use the first pulse as the MSB and the last pulse as the LSB.

-----------------------------------------------------------
Bits 8-11 - Channel + Action Category
-----------------------------------------------------------
0x8		Perform "Main Actions" for ID1
0x9		Perform "Misc. Actions" for ID1
0xA		Perform "Main Actions" for ID2
0xB		Perform "Misc. Actions" for ID2
-----------------------------------------------------------

Bits 8-11 determine which channel the command belongs to, as well as the overall category of action the CDZ model should perform. Main Actions describe things such as moving forward/backward, firing the cannon, and turning. Misc. Actions describe a variety of things such as syncing/initializing the GBA and CDZ model, roaring, and retreating. It is also used for some actions during the "boost" mode. A number of these actions are not listed in the game's manual.

-----------------------------------------------------------
Bits 4-7 - Motion Type
-----------------------------------------------------------

For Main Actions

0x2		Boost Backward
0x3		Boost Backward
0x4		Backward Speed 2
0x6		Backward Speed 1
0x8		Backward Speed 0
0xA		Forward Speed 0
0xC		Forward Speed 1
0xE		Forward Speed 2

For Misc. Actions

0x0		Boost Forward
0x1		Boost Forward + Fire (optionally)
0x3		Sync Signal/Hidden Moves
0x5		Hidden Moves
-----------------------------------------------------------

The Cyber Drive Zoids game can use the save data from the single-player mode to enhance the actions performed by the CDZ model, chiefly in regards to speed, HP, and the ability to boost. Once sufficient progress is made in the single-player mode, the CDZ model can shift gears up and down to alter speed. The regular IR controller that comes packaged by default with CDZ models does not offer these advantages. The sync signal is used on startup to activate the CDZ model for a match.

-----------------------------------------------------------
Bits 0-3 - Action Type
-----------------------------------------------------------

For Main Actions

0x0		Walk OR Fire if Motion Type == 1 or 3
0x1		Walk OR Fire if Motion Type == 1 or 3
0x2		Jump (typically for Boost Mode)
0x3		Jump (typically for Boost Mode)
0x4		Jump
0x5		Jump
0x6		Jump
0x7		Jump
0x8		Jump
0x9		Jump
0xA		Fire
0xB		Fire
0xC		Fire
0xD		Fire

For Misc. Actions

0x0		If Motion Type == 1 -> Fire
0x1		If Motion Type == 1 -> Fire

0x2		If Motion Type == 0 -> Jump 
		If Motion Type == 3 -> Sync ID1, Boost Level 0 
		If Motion Type == 5 -> Intimidate


0x3		If Motion Type == 0 -> Jump
		If Motion Type == 3 -> Sync ID2, Boost Level 0
		If Motion Type == 5 -> Intimidate		

0x4		If Motion Type == 3 -> Sync ID1, Boost Level 1 
		If Motion Type == 5 -> Swing Hips	


0x5		If Motion Type == 3 -> Sync ID2, Boost Level 1 
		If Motion Type == 5 -> Swing Hips

0xA		War Cry
0xB		War Cry
0xE		Escape
0xF		Escape
-----------------------------------------------------------

For Main Actions, if the Motion Type is not one of the above specified values (e.g. a 0), and the Action Type is jumping or firing, then the Zoid will move not forward or backward. Instead, it will remain stationary while performing that action. In this same manner, it's possible to simultaneously combine jumping or firing with moving by properly setting the Motion Type. Walking should always specify one of the listed Motion Types, however.

The CDZ model has a boost mode where the toy is temporarily invulnerable to damage and shifts into the highest gear. This mode lasts for 10 seconds. The sync signals specify how many boosts are available per match for that CDZ model. The boost mode commands are spread across Main Actions and Misc. Operations such as firing and jumping are often conditional, requiring the Motion Type to be Boost Forward or Boost Backward.

[AGB-006] : Prototype IR Port

Cyber Drive Zoids appears to frequently read from the memory location 0x4000136 which was supposed to have been the MMIO register for the IR port on prototype GBAs. The AGB-006 does not cause the 16-bit value of that location to change at all, however, and all reads do in fact return zero. The purpose of that bit of code is currently unclear. It may be a remnant of earlier code long made before the AGB-006 was fully realized.

Virtureal Racing System

General Hardware Information

Carrera Racing

VRS Protocol

LED Indicator

Multiplayer Protocol

[Virtureal Racing System] : General Hardware Information

The Virtureal Racing System, also known as the VRS, is a specialized Carrera GO!!! connection track designed to communicate with GBAs. It was introduced exclusively in European markets in 2003. Described as a "motor driver", it replaces the standard connection section for 1:43 Carrera GO!!! tracks and allows players digital control of their slot cars via the GBA. The VRS is used in conjunction with the game Carrera Power Slide, which provides the interface through the Carrera Racing mode.

[Virtureal Racing System] : Carrera Racing

The VRS lets 2 GBAs connect to the motor driver to move slot cars along the track and/or to monitor conditions of the race such as number of laps, total race duration, damage, and fuel level. Power Slide uses a dedicated software mode called "Carrera Racing" for this purpose. The first GBA acts as master and requires a Power Slide cart. The second downloads data from the first via MultiBoot. Power Slide offers several modes of "Real Racing" play through Carrera Racing:

Stop Watch is the only mode that does not use the GBA to control a slot car. Instead, the GBA is used to record lap times, and The Carrera GO!!! hand controls must be used instead. For all other modes, the GBA controls the slot car, even if hand controls are plugged in. Also note that only the first GBA is required for Carrera Racing. The second racer may use an additional GBA or (if such a GBA is absent) hand controls. If hand controls are used for the second racer, however, Power Slide only recognizes the first racer for the above 2-player modes.

When using a second GBA, the first GBA running Power Slide will send data and code via MultiBoot. Once downloaded, the second GBA will feature an near-exact copy of the Carrera Racing interface, except without the ability to select the "Real Racing" modes or set any options (this is the role of the first GBA).

[Virtureal Racing System] : VRS Protocol

All communication with the VRS uses the GBA's Multi16 mode with a baud rate of 115200bps. The first GBA acts as the Parent, while the second GBA acts as the Child 2. Even though the VRS has only two Link Cables, the entire setup behaves as if an additional GBA is connected as Child 1. This extra connection reports the status for each racer. The entire multiplayer model works as follows

Racer 1 Input		 	Parent
Race Status			Child 1
Racer 2 Input			Child 2
Unused				Child 3

Each GBA writes to their own input, which in turn controls the speed of the slot car. The VRS is responsible for updating the racers' status which simply consists of counting laps. Because of the nature of Multi16 mode, the first GBA must continually transfer data, even if that racer is not actively sending input to their slot car, otherwise input from the second GBA would not reach the VRS. The format for input and status are described below:

-------------------------------------------------
Input
-------------------------------------------------
Speed Level 0 - Lane 1			| 0xFFC0
Speed Level 1 - Lane 1			| 0xFF41
Speed Level 2 - Lane 1			| 0xFF42
Speed Level 3 - Lane 1			| 0xFFC3
Speed Level 4 - Lane 1			| 0xFF44
Speed Level 5 - Lane 1			| 0xFFC5
Speed Level 6 - Lane 1			| 0xFFC6
Speed Level 7 - Lane 1			| 0xFF47
Speed Level 8 - Lane 1			| 0xFF48
Speed Level 9 - Lane 1			| 0xFFC9
Speed Level 10 - Lane 1			| 0xFFCA
Speed Level 11 - Lane 1			| 0xFF4B
Speed Level 12 - Lane 1			| 0xFFCC
Speed Level 13 - Lane 1			| 0xFF4D
Speed Level 14 - Lane 1			| 0xFF4E
Speed Level 15 - Lane 1			| 0xFFCF
-------------------------------------------------
Speed Level 0 - Lane 2			| 0xFF50
Speed Level 1 - Lane 2			| 0xFFD1
Speed Level 2 - Lane 2			| 0xFFD2
Speed Level 3 - Lane 2			| 0xFF53
Speed Level 4 - Lane 2			| 0xFFD4
Speed Level 5 - Lane 2			| 0xFF55
Speed Level 6 - Lane 2			| 0xFF56
Speed Level 7 - Lane 2			| 0xFFD7
Speed Level 8 - Lane 2			| 0xFFD8
Speed Level 9 - Lane 2			| 0xFF59
Speed Level 10 - Lane 2			| 0xFF5A
Speed Level 11 - Lane 2			| 0xFFDB
Speed Level 12 - Lane 2			| 0xFF5C
Speed Level 13 - Lane 2			| 0xFFDD
Speed Level 14 - Lane 2			| 0xFFDE
Speed Level 15 - Lane 2			| 0xFF5F
-------------------------------------------------

Slot car speeds span 16 different levels. The higher the level, the faster the car moves. The lower the level, the slower the car moves. Normally, the maximum is Level 7, however turbo boosts temporarily allow cars to reach the upper levels. Technically, any speed less than or equal to Level 3 results in the slot car not moving at all. This is used when enabling fuel levels during races. In that scenario, Power Slide keeps track of how long it has been sending commands to move the slot car and constantly decreases a virtual amount of fuel. When the software sees that there is no more virtual fuel, it forcibly limits the slot car by setting the speed to Level 3. The racer must then perform a pit stop via the software to recover virtual fuel and continue running the track.

Similar to the virtual fuel, slot cars on the VRS can simulate damage from crashes or collisions. This is entirely a feature of Power Slide's software. When damage is enabled for a race, a "crash" is registered whenever a slot car stops moving for a certain period of time. In the event of a crash, a racer would normally stop input on their GBA and move around to put the slot car back on the track. If a racer takes too much damage, the software limits the speed to Level 3. Racers must then perform a pit stop to repair the car. Unfortunately, the software registers any and all stops (outside of pit stops) as damage, even if no crash physically occurred. The VRS itself has no method to detect when a slot car has left the track, so this software solution based on human behavior works as an approximation.

Either GBA may use Lane 1 or Lane 2; this is not hardwired. Depending on the input received, the VRS will control the slot car for that lane.

-------------------------------------------------
Status
-------------------------------------------------
Current Lap Count - Lane 1	| Bits 0 - 2
Current Lap Count - Lane 2	| Bits 3 - 6
Not used - Set Low		| Bit  7
Not used - Set High		| Bits 8 - 15
-------------------------------------------------

The lap count is merely a 3-bit value of 0 through 7. Every time a slot car moves through one of the physical switches built into the VRS' two lanes, Bits 0 - 2 or Bits 3 - 6 increment. Once these either of these 3 bits overflow, they begin again at zero. Power Slide constantly monitors these value for any changes, at which point it updates the time for a finished lap. By comparing lap times and the total number of laps completed, the software can determine which racer is in first place as well.

When the VRS and GBAs are connected, Child 1 Multi16 data reads 0xFFFF when the power is off. When the power is on, Child 1 returns the status in the form 0xFF--, where Bit 7 must be low. These values can be used by software to determine whether the VRS is attached and whether or not it is active. If Child 2 Multi16 data reads 0xFFFF, this normally indicates that there is no second GBA attached.

[Virtureal Racing System] : LED Indicator

The LED built into the VRS generally signals whether or not the unit has any external power. However, while the first GBA transmits MultiBoot data to the second GBA prior to racing, the light will temporarily turn off. It will stay off until the MultiBoot process is complete, at which point it comes back on again. The LED appears to shut off whenever a large series of transfers occurs, followed by a pause (presumably of 1/16 seconds or greater), followed by another large series of transfers. Power Slide likely achieves this when calling the MultiBoot Software Interrupt, as that function in the GBA BIOS does contain a brief delay before sending more transfers. Afterwards, the LED will remain off for approximately 54 seconds. Power Slide finishes all MultiBoot transfers by that time. There does not appear to be a way to shut the LED off via software again until the power button is released.

Even when the VRS has no external power, or when external power is provided but the power button is released, serial input/output can cause the LED to come on at a lower brightness. Any time the GBA sets SO as LOW the LED goes dark, while any time the GBA sets SO as HIGH the LED lights up. If both GBAs set their SO values as HIGH, this causes the LED to become slightly brighter than when only one GBA sets SO as HIGH. When the power button is pressed down, the LED reaches its brightest level constantly, and all such traces of serial input/output activity are no longer observable.

[Virtureal Racing System] : Multiplayer Protocol

When using the Carrera Racing interface, any time first GBA sends a value not listed in the VRS protocol, the second GBA running the MultiBoot program is expected to eventually echo what was sent. The first GBA sends specific values in groups of three. If it receives an echo, it knows that the MultiBoot program is running and will enable 2-player functionality in the various racing modes. If no second GBA with the MultiBoot program is detected, Power Slide restricts Carrera Racing to 1-player. Even though a second racer can join in without a GBA by using the standard hand controls, Power Slide will not recognize them via software.

If the first GBA is powered off or reset, the MultiBoot program running on the second GBA does not need to be downloaded again. As long as the second GBA continues running, it will successfully echo any bytes to establish contact.

Magical Watch

General Hardware Information

Communication Protocol - Overview

Communication Protocol - Start Signal

Communication Protocol - Data & Command Upload

Communication Protocol - Data Download

Communication Protocol - Stop Signal

[Magical Watch] : General Hardware Information

The Magical Watch is a digital watch bundled with the GBA game Wagamama☆Fairy: Mirumo de Pon! Hachinin no Toki no Yousei. It was released on December 11, 2003 by Konami. This device allowed users to play various minigames and activities on the watch itself through the use of its LCD screen and buttons. A Link Cable port lets players transfer data to the game and unlock special items.

[Magical Watch] : Communication Protocol - Overview

The GBA sets its serial port to General Purpose mode to send or receive data with the Magical Watch. Its protocol consists of four distinct phases as listed below:

Because the Magical Watch uses unknown components, a chip-on-board design encapsulated by a glob top, timing information for most transfers is also documented below. These are rough approximations based on how Mirumo de Pon! Hachinin no Toki no Yousei's code communicates with the Magical Watch.

[Magical Watch] : Communication Protocol - Start Signal

The Start Signal involves writing 2 specific values to the RCNT register over a set number of iterations. The value 0x80B0 is written 100 times; following that, the value 0x8000 is written 100 times as well. Mirumo de Pon! Hachinin no Toki no Yousei enters into a fairly small loop and cycles through these writes relatively quickly.

When sending a Start Signal, the transition between these two values may alert the Magical Watch that the GBA is ready to begin communications. It may not be necessary to perform exactly 100 writes of each value, but rather the Magical Watch may simply need sufficient time to detect when the SC, SD, and SO lines switch from HIGH to LOW. The 0x80B0 and 0x8000 writes both last ~0.77ms. Between the end of the Start Signal and the beginning of the Command Upload, there is a ~15.87ms gap before the GBA resumes communication.

Before Mirumo de Pon! Hachinin no Toki no Yousei issues a Start Signal, it temporarily switches to the serial port to UART mode for ~0.77ms. This, however, is not necessary to begin communicating with the Magical Watch. At the end of the Start Signal, before transitioning to the Command Upload phase, the game also temporarily switches to Normal 8-bit mode, however this too is likely irrelevant to properly link with the Magical Watch. In either case, no data is transferred when the game enters UART or Normal 8-bit mode.

Ultimately the Start Signal looks something like this:

-----------------------------------------------------------
Description			| Duration in ms 
-----------------------------------------------------------
UART Switch			| 0.77ms
General Purpose: RCNT = 0x80B0	| 0.77ms
General Purpose: RCNT = 0x8000	| 0.77ms
-----------------------------------------------------------

[Magical Watch] : Communication Protocol - Data & Command Upload

The GBA sends 80 bytes serially to the Magical Watch. The first portion stores a copy of the "Fairy Picturebook" data that the user has unlocked in the main game. The second portion instructs the device to return data that is later used to generate in-game items. During this phase, the GBA sets the direction of SC and SD as Output. SC is constantly set HIGH, and SD changes to represent the current bit being sent. Essentially, the GBA will write 0x8033 to RCNT to transmit a value of "1" and 0x8031 to transmit a value of "0". Bytes are sent MSB first.

Before sending any bytes, a brief sync signal must be issued. After the first byte is sent, additional syncs must be sent in between each subsequent byte. After the last byte, the GBA sends a final sync signal. Typical transmissions look like this:

-----------------------------------------------------------
Value	| Delay in ms 	| Description
-----------------------------------------------------------
0x8031	| N/A		| Initial Command Sync 
0x8033	| 0.65ms	| Sets SD LOW, HIGH, LOW, HIGH, LOW
0x8031	| 6.50ms	|
0x8033	| 1.30ms	|
0x8031	| 0.65ms	|
-----------------------------------------------------------
xxxx	| 0.65ms	| Bit 7 of Byte to Send
xxxx	| 0.65ms	| Bit 6 of Byte to Send
xxxx	| 0.65ms	| Bit 5 of Byte to Send
xxxx	| 0.65ms	| Bit 4 of Byte to Send
xxxx	| 0.65ms	| Bit 3 of Byte to Send
xxxx	| 0.65ms	| Bit 2 of Byte to Send
xxxx	| 0.65ms	| Bit 1 of Byte to Send
xxxx	| 0.65ms	| Bit 0 of Byte to Send
-----------------------------------------------------------
0x8031	| 0.65ms	| Recurring Sync
0x8033	| 1.30ms	| Sets SD LOW, HIGH, LOW
0x8031	| 0.65ms	|
-----------------------------------------------------------
xxxx	| 0.65ms	| Bit 7 of Next Byte to Send
xxxx	| 0.65ms	| Bit 6 of Next Byte to Send
xxxx	| 0.65ms	| Bit 5 of Next Byte to Send
xxxx	| 0.65ms	| Bit 4 of Next Byte to Send
xxxx	| 0.65ms	| Bit 3 of Next Byte to Send
xxxx	| 0.65ms	| Bit 2 of Next Byte to Send
xxxx	| 0.65ms	| Bit 1 of Next Byte to Send
xxxx	| 0.65ms	| Bit 0 of Next Byte to Send
-----------------------------------------------------------
... Repeat Recurring Sync ...
-----------------------------------------------------------
... Send Next Byte ...
-----------------------------------------------------------
0x8033	| 0.65ms	| Final Command Sync
0x8033	| 0.65ms	|
0x8033	| 0.65ms	|
0x8033	| 0.65ms	|
0x8031	| 0.65ms	|
0x8033	| 0.65ms	|
0x8033	| 0.65ms	|
0x8031	| 0.65ms	|
0x8031	| 0.65ms	|
-----------------------------------------------------------

The first 8 bytes sent to the Magical Watch represent any entries in the "Fairy Picturebook" obtained by the player. These are gained by interacting with various characters throughout the game, and some are granted automatically as part of the story's progression. Each entry occupies a single bit, with "0" meaning the player has not met that character, and "1" meaning they have. There are a total of 60 entries, so only 7.5 bytes are actually used. The data here corresponds 1:1 to the player's "Fairy Picturebook" when reading the bytes LSB first from Byte 0 to Byte 7.

The other 72 bytes appear to be commands that tell the Magical Watch to retrieve data for several special items. There are evidently 6 commands issued during this time, each consisting of 12 bytes. The exact significance of each individual byte or command is currently unknown.

-----------------------------------------------------------
Commands 0 - 5
-----------------------------------------------------------
0x58 0x40 0x88 0x48 0x70 0x40 0x50 0x00 0x00 0x01 0x00 0x01
0x58 0x40 0x88 0x48 0x70 0x40 0x50 0x00 0x19 0x06 0x19 0x06
0x58 0x40 0x88 0x48 0x70 0x40 0x50 0x00 0x19 0x06 0x19 0x06
0x58 0x40 0x88 0x48 0x70 0x40 0x50 0x00 0x19 0x06 0x19 0x06
0x58 0x40 0x88 0x48 0x70 0x40 0x50 0x00 0x19 0x06 0x19 0x06
0x58 0x40 0x88 0x48 0x70 0x40 0x50 0x00 0x19 0x06 0x19 0x06
-----------------------------------------------------------

[Magical Watch] : Communication Protocol - Data Transfer

After sending the commands mentioned above, the GBA will receive a total of 9 bytes from the Magical Watch. Mirumo de Pon! Hachinin no Toki no Yousei waits ~1.95ms after the Final Sync has completed. From there, bytes can be read serially, MSB first. The SI line is used to indicate the individual bits as well as a Stop Bit. The game follows this convention when reading the RCNT register for each byte:

-----------------------------------------------------------
Read #	| Delay in ms 	| Description
-----------------------------------------------------------
Read 0	| 1.95ms	| Stop Bit
Read 1	| 1.95ms	| Receive Bit 7
Read 2	| 1.95ms	| Receive Bit 6
Read 3	| 1.95ms	| Receive Bit 5
Read 4	| 1.95ms	| Receive Bit 4
Read 5	| 1.95ms	| Receive Bit 3
Read 6	| 1.95ms	| Receive Bit 2
Read 7	| 1.95ms	| Receive Bit 1
Read 8	| 1.95ms	| Receive Bit 0
-----------------------------------------------------------

The received bytes can then be converted into the following in-game items depending on their values.

-----------------------------------------------------------
Byte 0		| Small Drop of Time (0 - 99)
Byte 1		| Large Drop of Time (0 - 99)
Byte 2		| Lucky Jewel (0 - 99)
Byte 3		| Add 15 seconds
Byte 4		| Add 1 hour + 4 minutes
Byte 5		| Add 2 hours + 30 Minutes
Byte 6		| Screw of Time (0 - 99)
Byte 7		| N/A
Byte 8		| 8-bit checksum
-----------------------------------------------------------

For Bytes 0, 1, 2, and 6, the game only permits players to have 99 items. Even if the Magical Watch sends values above 0x63, the game will only recognize 99 as the absolute maximum.

When transferring Time to the game, Bytes 3, 4, and 5 are used as a total sum. The absolute maximum value the game recognizes is 2 hours and 30 minutes. Byte 3 is used to add individual minutes, essentially by dividing its raw binary value by 4 (e.g. 0x8 = add 2 minutes). Byte 4 adds 1 hour and 4 minutes multiplied by its raw binary value (e.g. 0x2 = add 2 hours and 8 minutes). Byte 5 is used to set Time to its maximum value with any non-zero value.

The checksum is simply the sum of Bytes 0 - 7. Mirumo de Pon! Hachinin no Toki no Yousei validates this upon receiving all 9 bytes from the Magical Watch.

After all 9 bytes have been read, a sync signal is sent from the GBA:

-----------------------------------------------------------
Value	| Delay in ms 	| Description
-----------------------------------------------------------
0x8031	| 1.95ms	| Data Transfer Sync
0x8031	| 6.50ms	|
0x8033	| 0.65ms	|
0x8031	| 0.65ms	|
0x8031	| 0.65ms	|
0x8033	| 0.65ms	|
0x8031	| 0.65ms	|
0x8033	| 0.65ms	|
0x8031	| 0.65ms	|
0x8033	| 0.65ms	|
0x8031	| 0.65ms	|
0x8033	| 0.65ms	|
0x8031	| 0.65ms	|
-----------------------------------------------------------

[Magical Watch] : Communication Protocol - Stop Signal

Once the Data Transfer is complete, a brief delay (slightly greater than 5ms) occurs before sending the Stop Signal. Like the Start Signal, Mirumo de Pon! Hachinin no Toki no Yousei switches the serial port into UART mode for ~0.77ms. Afterwards, it re-enters General Purpose Mode for ~0.77ms, writing the value 0x8031 to RCNT 100 times. Again, it switches to UART mode for ~0.77ms. Just like the Start Signal, no data is actually transferred when the game switches to UART mode. Finally, it re-enters General Purpose mode, writing the value 0x80B0 to RCNT 100 times, and then writing the value 0x8000 to RCNT 100 times, with each duration lasting ~0.77ms.

Ultimately, the Stop Signal looks something like this:

-----------------------------------------------------------
Description			| Duration in ms 
-----------------------------------------------------------
UART Switch			| 0.77ms
General Purpose: RCNT = 0x8031	| 0.77ms
UART Switch			| 0.77ms
General Purpose: RCNT = 0x80B0	| 0.77ms
General Purpose: RCNT = 0x8000	| 0.77ms
-----------------------------------------------------------

Joy Carry Cartridge

General Hardware Information

GameCube Communication

ROM Mapping

Flash Commands

Status Register

[Joy Carry Cartridge] : General Hardware Information

The Joy Carry Cartridge is a special Game Boy Advance cartridge that came bundled with the GameCube title Hikaru no Go 3. Released in Japan on March 20, 2003, it allowed players to rewrite most of the contents on the cartridge, working as an officially licensed flashcart of sorts. The underlying hardware is referred to as Nintendo's Debugging and Communication System, also known as DACS, and it was the only recorded instance where this technology was sold to the public. Joy Carry was the name of the GBA-to-GameCube functionality in Japan, often associated with temporary download. The Joy Carry Cartridge aimed to make large amounts of transferred data persistent.

[Joy Carry Cartridge] : GameCube Communication

Hikaru no Go 3 gives players the choice of sending two specific pieces of software to the Game Boy Advance. The first Igo Mondaishuu (囲碁問題集) consists of 200 individual Go-based challenges. Igo Mondaishuu is divided into 4 separate sections of 50 problems. Only 1 section at a time may be downloaded to the Joy Carry Cartridge. As players solve each Go question, their progress is saved with the results ("O" = Passed, "-" = Attempted, "X" = Failed). The second software Keitai Magnet Goban (携帯マグネット碁盤) is intended to act as a virtual, portable Go board. It lets players link up with other GBAs for 1v1 or 2v2 Go matches. It saves the results of recent matches along with various statistics. The software will also display the player's name, rank, win/loss counts, and their ID generated by Hikaru no Go 3 on GameCube.

When transferring data from the GameCube to the GBA, the handheld must be booted with the Joy Carry Cartridge inserted. Players must hold down both the START and SELECT buttons to force the BIOS to enter MultiBoot mode and wait for data via JoyBus communications. Initially, a small program is loaded to manage downloading data from the GameCube and overwriting the previous contents of the Joy Carry Cartridge. This program helpfully displays a progress bar, as does the GameCube's screen. Due to the amount of data sent and the time it takes to issue flash commands, the process takes several minutes. Once finished, the GBA may be turned off or reset and the Joy Carry Cartridge will boot its newly written software.

[Joy Carry Cartridge] : ROM Mapping

The data stored on the Joy Carry Cartridge's flash memory is mapped to the last 1MB of the GBA's ROM address space, from 0x9F00000 to 0x9FFFFFF. In order to properly start the game, however, an 8KB boot sector is mapped from 0x9FFC000 to 0x8000000. The ~31MB gap inbetween these two sections should read as zero. This unique mapping prevents most commercial games from simply being copied onto the Joy Carry Cartridge and treating it like a normal flashcart, as portions of code would need to be adapted to handle having data in the upper region of ROM address space. Additionally, the limited size of the Joy Carry Cartridge further complicates matters.

The last 8KB section of the Joy Carry Cartridge, located at 0x9FFE000 can be used to ID the cartridge. This data is not known to be rewritable, making it a reliable method of determining whether or not hardware is a Joy Carry Cartridge or not. Thanks to this, however, the full capacity of the Joy Carry Cartridge is only around 1016KB.

[Joy Carry Cartridge] : Flash Commands

The Joy Carry Cartridge accepts standard flash commands for manipulating data. The following commands have been verified to work on the LH28F800BLE:

-----------------------------------------------------------
Command Byte 	| Description
-----------------------------------------------------------
0x10		| Write Data
0x20		| Block Erase
0x40		| Write Data
0x60		| Set Block-lock Bit / Clear Block-lock bit
0x50		| Clear Status Register
0x70		| Read Status Register
0x90		| Read Flash ID Codes / Enter ID Mode
0xF0		| Terminate ID Mode
0xFF		| Read Data / Reset
-----------------------------------------------------------

Operations appear to work based on 8KB sectors or blocks. Depending on the address where certain commands are issued (such as the Set Block-lock Bit command or Block Erase command), it will have an effect on that specific block only. Note that these commands are all sent to mirrored addresses, specifically Wait State 2 (0xC000000 - 0xDFFFFFF).

Reading the Flash ID codes involves the following process. Take note which reads/writes are 16-bit and 32-bit:

-----------------------------------------------------------
WRITE-16 0x00AA to 0xDFE0AAA
WRITE-16 0x0055 to 0xDFE0554
WRITE-16 0x0090 to 0xDFE0AAA		//Enter ID Mode
WRITE-16 0x00F0 to 0xDFE0000		//Terminate ID Mode

WRITE-16 0x0055 to 0xDFE0554
WRITE-16 0x00AA to 0xDFE0AAA
WRITE-16 0x00E0 to 0xDFE0554		//???

WRITE-16 0x0055 to 0xDFE0554
WRITE-16 0x00AA to 0xDFE0AAA
WRITE-16 0x00E0 to 0xDFE0554		//???

READ-32 FROM 0xDF00000			//Read 16-bit Manufacture code + 16-bit Lock Bit data
WRITE-16 0x00FF to 0xDFE0AAA		//Reset, also exits ID Mode
-----------------------------------------------------------

Other commands don't appear to rely on writing to the 0x----554 addresses. Instead, they're issued as follows:

-----------------------------------------------------------
WRITE-16 COMMAND to 0xDFE0AAA
or
WRITE-16 COMMAND to 0xDF-----		//Issue command for specific 8KB block

...then for any parameters...

WRITE-16 PARAMETER to 0xDFE0AAA
or
WRITE-16 PARAMETER to 0xDF-----		//Issues command parameters for specific 8KB block
-----------------------------------------------------------

The above information is the bare minimum necesary for operating the Joy Carry Cartridge via the Game Boy Advance or GameCube. For more detailed information beyond the scope of this document, refer to other similar Sharp flash components with available datasheets such as the LH28F800BJE.

[Joy Carry Cartridge] : Status Register

The Status Register monitors the state of the flash controller. It works on a per-block level, typically reporting on the write or protection status of that block. While the LH28F800BLE should more or less resemble similar controllers, only the following status bits have been verified:

-----------------------------------------------------------
Bit		| Function
-----------------------------------------------------------
0		|
1		| Device Protection Status, 0 = Unlocked, 1 = Locked
2		|
3		|
4		|
5		|
6		|
7		| Write Status, 0 = Busy, 1 = Ready
-----------------------------------------------------------

When reading from any 0x----AAA address, it appears to return the Status Register for that block (e.g. if the program needs to determine if a specific block's Lock Bit is set). Otherwise, reading any other address will return data from flash memory or zeroes if the area is outside the mapped 1MB ROM.

It should be noted that the software often issues an unknown parameter (0x77) to the Set Lock Bit command. It is not well understood what this does exactly or how it affects the Status Register.

Also regarding the Status Register, both Igo Mondaishuu and Keitai Magnet Goban check it to assess whether the flash controller responds in a timely fashion. On boot, the software are particularly concerned with the Write Status and will abort initial flash operations such as verifying save data. Failing this part will not stop the programs from attempting to write data to flash memory later on, however. For the rest of flash operations, the programs generally examine whether a block is locked or unlocked. If a block is locked, they will abort writing any new save data.

Advance Movie Adapter

General Hardware Information

Cartridge Mapping

Adapter I/O Registers

AM_BLK_STAT

Commands

Command Usage

Read Pointer

File System And Hierarchy

00.AM3

Error Handling

List of AM3 Cards and Products

[Advance Movie Adapter] : General Hardware Information

The Advance Movie Adapter is a specialized Game Boy Advance cartridge capable of reading SmartMedia cards. Released on November 20, 2003, the adapter and its software were designed for audio/video playback. SmartMedia cards with prewritten data could be inserted, and the internal firmware would read, decrypt, decode, and finally play the media.

[Advance Movie Adapter] : Cartridge Mapping

Unlike many other GBA cartridges, the Advance Movie Adapter has an unusual method of mapping cartridge data. Only 2KB are addressable at any given time. The lower 1KB (0x8000000 - 0x80003FF) contains data pulled from either the firmware or the SmartMedia card. The upper 1KB (0x8000400 - 0x80007FF) contains memory-mapped I/O registers used to control what data is accessible from the lower half. Data is "swapped" or "banked" dynamically into the lower 1KB in a manner similar to the old memory bank controllers found in DMG/GBC cartridges.

These 2KB sections of data and I/O registers are mirrored endlessly across the 32MB of addresses the GBA reserves for the cartridge. Within the 1KB region reserved for the adapter's I/O registers, the registers are mirrored every 64 bytes.

[Advance Movie Adapter] : Adapter I/O Registers

The vast majority of the Advance Movie Adapter's function is to read data from the SmartMedia card. As such, it dedicates a number of memory-mapped I/O registers to control this process. Although the registers are mirrored across many different addresses, the firmware uses only one specific mirror. For simplicity, only those addresses are noted in this document.

----------------------------------------------------------------------------------------------------------------------
Data Block Control
----------------------------------------------------------------------------------------------------------------------
AM_BLK_ADDR	(R/w)	0x08010400 	32-bit		Address where data block will be copied
AM_BLK_SIZE	(R/W)	0x08010408	32-bit		Size of block to copy to AM_BLK_ADDR
AM_BLK_STAT	(R/W)	0x08010420 	16-bit		Controls block operations / Reports operation status
----------------------------------------------------------------------------------------------------------------------

AM_BLK_ADDR determines where any data (from either the firmware or the SmartMedia card) will be mapped to. This is always 0x8000000 as far as the firmware is concerned.

AM_BLK_SIZE determines the size of data to read from the firmware. As the Advance Movie Adapter only maps in a maximum of 1KB for data blocks, this value is never greater than 0x400 as far as the firmware is concerned. Note that setting the size of data for SmartMedia card reads is a separate register.

AM_BLK_STAT controls the majority of operations on the Advance Movie Adapter. By writing to the register and setting certain bits, it starts the mapping process, switches between firmware and SmartMedia card, and makes the 128-bit DES key readable. It also reserves several bits that report on the status of current operations. See the next section for further details.

----------------------------------------------------------------------------------------------------------------------
SmartMedia Control
----------------------------------------------------------------------------------------------------------------------
AM_SMC_OFFS	(R/W)	0x08010404	32-bit		Move data read pointer by signed offset
AM_SMC_SIZE	(R/W)	0x0801040A	16-bit		Size of data block to copy from SmartMedia card
AM_SMC_FILE	(R/W)	0x0801040C	16-bit		Sets current file to read from the FAT on the SmartMedia card
AM_SMC_EOF	(R)	0x0801040E	16-bit		Remaining bytes from current read pointer to End-Of-File
----------------------------------------------------------------------------------------------------------------------

AM_SMC_OFFS adjusts the current read pointer by a signed (2's complement) 32-bit integer, making it possible to shift it forwards or backwards. This is used when a select portion of data or data at a specific location must be read. The read pointer does have some quirks, as detailed in a following section.

AM_SMC_SIZE determines the size of data to read from the SmartMedia card. As the Advance Movie Adapter only maps in a maximum of 1KB for data blocks, this value is never greater than 0x400 as far as the firmware is concerned. Note that setting the size of data for firmware reads is a separate register.

AM_SMC_FILE selects the current file to begin reading data from. Below in further section, a thorough explanation of the AM3 file hierarchy is provided.

AM_SMC_EOF returns the remaining bytes from the current read pointer until the current End-Of-File is reached. This value normally reports the same 16-bit value as AM_SMC_SIZE when at least that many bytes remain between the read pointer and EOF. If the read pointer advances after mapping in new data, and the distance between the read pointer and the EOF is less than AM_SMC_SIZE, AM_SMC_EOF will report the smaller value. Note that AM_SMC_EOF can also change when simply switching to a new file (by writing to AM_SMC_FILE) that is smaller than AM_SMC_SIZE.

----------------------------------------------------------------------------------------------------------------------
Misc
----------------------------------------------------------------------------------------------------------------------
AM_FILE_SIZE	(R)	0x08010410	32-bit		Current file size according to FAT
AM_SMID		(R)	0x08010410	128-bit		16-byte SmartMedia ID used for copy-protection
----------------------------------------------------------------------------------------------------------------------

AM_FILE_SIZE returns the current file size as determined by the FAT of the SmartMedia card. Note that this register overlaps with AM_SMID. To switch, the CPU must write the value 0x05 to AM_BLK_STAT.

AM_SMID returns the 128-bit (16-byte) SmartMedia ID (SMID) that the firmware verifies for copy-protection purposes. This ID is unique to every SmartMedia cards and is embedded in a region not normally accessible by standard card readers. When no SmartMedia card is inserted in the adapter, these bytes return zero. Note that this register partially overlaps with AM_FILE_SIZE. To switch, the CPU must write the value 0x03 to AM_BLK_STAT.

To properly access any of the I/O registers, the PHI terminal output should be set to 16.78MHz. On that note, the amount of cycles spent in various waitstates does not appear to affect the overall operation of the adapter. However, slower access, if significant, could potentially degrade the firmware's video playback functions. The firmware should handle a small amount slower access without issue. For example, on the DS Lite, there is a brief pause during the initial setup (before the AM3 logo appears) with a small loading icon. This screen is not shown on an original Game Boy Advance due to apparent timing differences.

[Advance Movie Adapter] : AM_BLK_STAT

This I/O register is heavily used by the adapter and is central to its operation. It acts as a way for the CPU to send commands to the adapter as well as determine the status of firmware or SmartMedia card mapping. Its various bits work as follows:

-----------------------------------------------------------
Bit 0		(R/W)		Execute Operation
Bit 1-2		(R/W)		Operation Type
Bit 3		(R/W)		Internal Operation/External Operation
...
Bit 8		(R)		EOF Reached/Passed Flag
...
Bit 14		(R)		I/O Registers Ready Flag
-----------------------------------------------------------

Whenever AM_BLK_STAT is written, firmware waits indefinitely to validate that the register holds the new value. Every command issued to the adapter must set Bit 0 to "1" to take effect. Afterwards, it waits until Bit 0 returns to "0" to signal the end of the operation. After every operation, the lower 8-bits of AM_BLK_STAT will always read as zero, however, depending on the current status of the adapter, the upper read-only 8-bits may be set.

Operation Type describes 4 fundamental operations available:

-----------------------------------------------------------
Value		| Operation Description
-----------------------------------------------------------
0		| Read Block
1		| Write I/O Register
2		| Set File Size Mode
3		| Set SMID Mode
-----------------------------------------------------------

The most common operation is "Read Block" which simply copies a data block of a set size from either firmware or the SmartMedia card.

Writing to an I/O register is exactly that. AM_BLK_STAT needs to signal to the adapter that the CPU will update one of its I/O registers.

Set File Size Mode and Set SMID Mode refer to the values held in AM_FILE_SIZE and AM_SMID. Since these registers have overlapping addresses, AM_BLK_STAT controls which mode the adapter will use, and which values to return when reading these memory locations. Once the SMID is read, there is usually no need to return to this mode.

These operations can be further divided as being "internal" or "external". The first deals with data that resides on the Advance Movie Adapter itself, such as reading firmware or writing to I/O registers. The second deals with data residing on the SmartMedia card, such as the files themselves, file sizes, and SMID. A value of "1" chooses internal operations, while a value of "0" chooses external operations. In practice, however, only a few limited values are ever written to AM_BLK_STAT. These can then be seen as single-byte "commands".

-----------------------------------------------------------
Command		| Description
-----------------------------------------------------------
0x01		| Read SmartMedia Card Data Block
0x03		| Set SMID Mode
0x05		| Set File Size Mode & Update File Size
0x09		| Read Firmware Data Block
0x0B		| Write I/O Register
-----------------------------------------------------------

When performing any of these commands, it is recommended to disable interrupts. Any non-zero writes to AM_BLK_STAT will trigger a GamePak IRQ once the value of AM_BLK_STAT is updated. Servicing other interrupts may delay the progam from determining when exactly an operation has finished when AM_BLK_STAT's Bit 0 reads zero. For AM3 cards, this timing is critical to deliver smooth audio and video playback, so interrupts are disabled frequently in the firmware while it waits in several tight loops.

[Advance Movie Adapter] : Commands

Command 0x01 - Read SmartMedia Card Data Block

Data Source: File Specified By AM_SMC_FILE + Current Read Pointer + AM_SMC_OFFS

Data Destination: AM_BLK_ADDR

Data Size: AM_SMC_SIZE

This command reads a fixed amount of bytes as specified by AM_SMC_SIZE from the current file. The exact position within the file is the current read pointer plus the offsets specified by AM_SMC_OFFS. For further information on this command's various behaviors, see the next section regarding the read pointer.

Command 0x03 - Set SMID Mode

After issuing this command, the 16 bytes beginning at AM_SMID (0x08010410 - 0x0801041F) will return the 128-bit SmartMedia ID whenever read.

Command 0x05 - Set File Size Mode

After issuing this command, the 4 bytes at AM_FILE_SIZE (0x08010410 - 0x08010413) will return the current file size. These values are pulled from the File Allocation Table written to the SmartMedia card. Most importantly, when switching to a new file by writing to AM_SMC_FILE, this commands updates the current file size the CPU will read. When a new file is chosen, AM_SMC_FILE does not update automatically. That is to say, the old value will be read unless the Set File Size Mode command is called.

Command 0x09 - Read Firmware Data Block

Data Source: Current Read Pointer

Data Destination: AM_BLK_ADDR

Data Size: AM_BLK_SIZE

This command reads a fixed amount of bytes as specified by AM_BLK_SIZE from the Advance Movie Adapter's firmware. Unlike reading from SmartMedia cards, there are no offsets. Instead, only the read pointer is used. For further information on this command's various behaviors, see the next section regarding the read pointer.

Command 0x0B - Write I/O Register

Before writing to any of the Advance Movie Adapter's I/O registers, the CPU must send this command. Once the adapter is ready for the CPU to write to its I/O registers, Bit 14 of AM_BLK_STAT will change to "1" and then back to "0". After both Bit 14 and Bit 0 are clear, the CPU can then write to a given I/O register. The firmware issues this command every time it writes to an I/O register, even if it needs to write to multiple registers.

[Advance Movie Adapter] : Command Usage

Below are psuedo-code samples explaining how to use the adapter's various commands.

-----------------------------------------------------------
Writing to Adapter I/O Registers:
-----------------------------------------------------------
WRITE_IO(AM_IO_REG, VALUE):
	IME = 0
	[AM_BLK_STAT] = 0x0B

	WHILE [AM_BLK_STAT] NOT EQUAL TO 0x0B
		READ [AM_BLK_STAT] AGAIN
	
	WHILE [AM_BLK_STAT].BIT14 EQUALS 0
		READ [AM_BLK_STAT] AGAIN

	[AM_IO_REG] = VALUE

	WHILE [AM_BLK_STAT].BIT0 EQUALS 1
		READ [AM_BLK_STAT] AGAIN

	IME = 1


-----------------------------------------------------------
Read Firmware
-----------------------------------------------------------
WRITE_IO(AM_BLK_ADDR, 0x8000000)
WRITE_IO(AM_BLK_SIZE, 0x400)

IME = 0

WHILE [AM_BLK_STAT].BIT8 EQUALS ZERO
	[AM_BLK_STAT] = 0x09

	WHILE [AM_BLK_STAT] NOT EQUAL TO 0x09
		READ [AM_BLK_STAT] AGAIN

	COPY DATA @ 0x8000000 TO RAM - 0x400 BYTES TOTAL
	INCREMENT RAM POINTER BY 0x400

IME = 1


-----------------------------------------------------------
Read SmartMedia Card
-----------------------------------------------------------
WRITE_IO(AM_BLK_ADDR, 0x8000000)	//Only if this has not been done before
WRITE_IO(AM_BLK_SIZE, 0x400)		//Only if this has not been done before

WRITE_IO(AM_SMC_OFFS, 0x8000000)
WRITE_IO(AM_SMC_SIZE, 0x400)
WRITE_IO(AM_SMC_FILE, INDEX_GOES_HERE)

IME = 0

WHILE [AM_BLK_STAT].BIT8 EQUALS ZERO
	[AM_BLK_STAT] = 0x01

	WHILE [AM_BLK_STAT] != 0x01
		READ [AM_BLK_STAT] AGAIN

	COPY DATA @ 0x8000000 TO RAM - COPY NUMBER OF BYTES IN AM_SMC_EOF
	INCREMENT RAM POINTER BY NUMBER OF BYTES IN AM_SMC_EOF

IME = 1


-----------------------------------------------------------
Read Current File Size
-----------------------------------------------------------
[AM_BLK_STAT] = 0x05
	
WHILE [AM_BLK_STAT] NOT EQUAL TO 0x05
	READ [AM_BLK_STAT] AGAIN

CURRENT_FILE_SIZE = [AM_FILE_SIZE]


-----------------------------------------------------------
Read SMID in 32-bit Chunks
-----------------------------------------------------------
[AM_BLK_STAT] = 0x03
	
WHILE [AM_BLK_STAT] NOT EQUAL TO 0x03
	READ [AM_BLK_STAT] AGAIN

SMID_0 = [AM_SMID + 0x00]			//Read 0x08010410 - 0x08010413
SMID_1 = [AM_SMID + 0x04]			//Read 0x08010414 - 0x08010417
SMID_2 = [AM_SMID + 0x08]			//Read 0x08010418 - 0x0801041B
SMID_3 = [AM_SMID + 0x0C]			//Read 0x0801041C - 0x0801041F

[Advance Movie Adapter] : Read Pointer

The read pointer is an internal and inaccessible value that indicates where within firmware or the SmartMedia card the adapter should begin reading data. As a result, it is the CPU's job to manage and track the read pointer based on the commands it issues and the I/O registers it writes. The read pointer will automatically advance whenever the 0x01 or 0x09 commands are sent. The amount incremented depends on the value held in AM_BLK_SIZE for firmware and AM_SMC_SIZE for the SmartMedia card. There are several specific edge cases that need to be accounted for.

Read Pointer Value On Boot

When turning on the Game Boy Advance, the first 1KB of firmware (the bootloader) is loaded into the address space at 0x8000000 - 0x80003FF. As such, it has already advanced by 0x400 bytes by the time the CPU begins executing instructions from that area of memory.

Reading More Than 11KB of Firmware

If the CPU should try to read more 11KB of firmware, the read pointer essentially resets itself as zero. Reading a 12th 1KB data block will simply read the 1st 1KB data block (e.g. the bootloader. Note that when reading the 11th 1KB data block of firmware, Bit 8 of AM_BLK_STAT will be set to "1" to indicate that all the data for the firmware has been read, treating the firmware as if it were another file.

Reading Data Past EOF

If the read pointer advances past a given file's EOF position, the read pointer will reset itself as zero. The next 0x01 command sent by the CPU will read data at the beginning of the file. Bit 8 of AM_BLK_STAT will be set to "1" to indicate that all the data for the file has been read.

Setting the Read Pointer Before The File

If the read pointer is adjusted with a negative offset that would technically put it before the start of the current file, the read pointer is forcibly reset to zero. Additionally, the value of AM_SMC_EOF returns zero, likely indicating an error. These two outcomes are true even when the read pointer wraps due to reading data past the EOF. That is to say, there is no wrapping of the read pointer at all when trying to move backwards.

[Advance Movie Adapter] : File System And Hierarchy

AM3's SmartMedia cards utilize the FAT12 filesystem. The adapter itself is responsible for parsing information from File Allocation Table to determine where the audio, video, and data files are located within the card. This brief overview outlines the basics of navigating through the raw bytes of a SmartMedia image.

Master Boot Record (MBR):

Located in the first 512 bytes. Holds data on how partitions are arranged on the medium. Most importantly, it points to the Volume Boot Record through the Logical Block Address (LBA) of the partitions first sector. AM3 files are stored on the first partition with Bytes Per Sector at a size of 512 bytes. Therefore the LBA can be calculated as:

Volume Boot Record Logical Block Address = (32-bit value of bytes 0x1C6 - 0x1C9) * 512

Volume Boot Record (VBR):

Also known as the Volume ID and the start of the FAT filesystem. It contains crucial information such as Bytes Per Sector, Sectors Per Cluster, Reserved Sector Count, Number of File Allocation Tables, Maximum Number of Root Directory Entries, and Sectors Per File Allocation Table. The VBR consists of 32-byte entries with these various fields. This information is used to calculate the logical addresses of the First Fat, the Root Directory, and Data Region.

First FAT Logical Block Address = VBR Logical Address + (Reserved Sector Count * Bytes Per Sector)
Root Directory Logical Block Address = First FAT Logical Address + ((Number of File Allocation Tables * Sectors Per File Allocation Table) * Bytes Per Sector)
Data Region Logical Block Address = Root Directory Logical Address + (Maximum Number of Root Directory Entries * 32)

Data Region:

Represents the actual data stored on the medium. At the start of this a single directory with various AM3 related files. Typically the files are ordered in the following manner

01.AM3
02.AM3
03.AM3
...
11.AM3
INFO.AM3
00.AM3

The first set of numbered AM3 files are for audio/video playback. INFO.AM3 contains more metadata that explains which files are mapped to a given index when writing to AM_SMC_FILE. 00.AM3 contains encrypted data. It must be decrypted internally, then certain data from that file is checked against the card's SMID. The firmware fails to boot if the data from 00.AM3 and the SMID are different.

INFO.AM3 is particularly relevant for the Advance Movie Adapter. It consists of large table offset 512 bytes from the start of the file. Each 32-byte entry merely lists a file name. The first file listed is mapped to index "0" for AM_SMC_FILE; the second file listed in mapped to index "1" for AM_SMC_FILE, so on and so forth. The order that the card's files appear at the start of the Data Region thus does not reflect how the adapter ultimately arranges them internally. Files not listed in INFO.AM3 are inaccessible to the Advance Movie Adapter.

For any invalid index written to AM_SMC_FILE, the adapter will treat it as if the index points to the last file in the list. For example, if there are only a total of 11 files, writing 12 to AM_SMC_FILE will point to the 11th file. The exception to this is when the value 0xFFFF is written to AM_SMC_FILE, in which case it points to the 1st file. Under normal circumstances, the firmware only ever does the first case, typically as a shortcut to read INFO.AM3, which is generally the last file on the card. If an error occurs that interferes with the boot process, the firmware does write 0xFFFF to AM_SMC_FILE before it aborts.

The table entries in the Data Region has fields for File Attributes, Creation Date/Time, Modification Data/Time, but most of all the File Cluster and File Size. The last two bits of data describe the logical address of the file and how many bytes total the file occupies. These values are calculated automatically by the adapter and only used internally when it reads data. As far as the CPU is concerned, it only needs to feed the appropiate index to AM_SMC_FILE. The Logical Block Address of the file is thus:

Data Region Logical Address + ((File Cluster - 2) * Sectors Per Cluster * Bytes Per Sector)

It is important to note that as AM3 SmartMedia cards use FAT filesystems, they are still vulnerable to file fragmentation. Evidently, some cards were fragmented even when users first purchased them. However, as far as the Advance Movie Adapter is concerned, data can be extracted normally in continuous 1KB segments regardless of fragmentation. The adapter automatically pieces files together as a whole, so the firmware reads them without jumping across clusters.

[Advance Movie Adapter] : 00.AM3

This acts as a "lock file", a small encrypted portion of the SmartMedia card that determines whether or not the SMID is valid. The rest of the data on the SmartMedia card is apparently unencrypted. That is to say, between two separate copies of the same anime/TV show episode, the 00.AM3 file should be the only difference between them. For example, with multiple copies of Detective Conan Episode 1, the data for all files except 00.AM3 will match. When the firmware decrypts 00.AM3, a portion of the file contains its own 128-bit ID. This internal ID is compared again the external one from AM_SMID. In order to play any videos, both IDs must match.

As the firmware internally calculates what the correct ID should be, at multiple points it's possible to intercept the expected value. This can be done by simply pausing the firmware's execution through a debugger and reading select RAM locations. As long as a fake, non-zero ID is provided when reading AM_SMID, the firmware generates its own for comparison.

Although this "security" is easily defeated, at the time, it was only meant to deter casual, physical piracy, as SmartMedia card readers and writers were once common. The SmartMedia's 128-bit ID is permanently set at the time of manufacture, so even commercially available blank cards would have a different ID, meaning the AM3 files could not blindly be copied over. Digital solutions, however, such as emulators, are not bound by these constraints.

The ID can be legitimately extracted by any GBA ROM dumper or other homebrew by simply trying to read the Advance Movie Adapter as if it were a normal game cartridge. As long as an AM3 SmartMedia card is inserted, the ID will appear at the bytes 0x08010410 through 0x0801041F.

[Advance Movie Adapter] : Error Handling

The Advance Movie Adapter behaves slightly differently when the SmartMedia card cannot be read. While the first 1KB section of the firmware is loaded normally for the initial bootloader, trying to read subsequent 1KB blocks of the firmware returns a repeating 5KB section of code dedicated to error handling. This 5KB section is distinct from the regular firmware 11KB that deals with decoding and playing audio/video files. It can only be accessed when a SmartMedia card related issue occurs. Examples include a missing/improperly inserted card, an unsupported SmartMedia card type, or a damaged SmartMedia card. The error handling code helpfully displays an on-screen message in Japanese and English (with a typo) in such an event.

Additionally, when the adapter needs to handle SmartMedia card errors, Bit 8 of AM_BLK_STAT no longer serves as an EOF flag. The GBA can read an indefinite amount of repeating 1KB blocks from firmware (the 5KB section) without ever changing the status of Bit 8. Lastly, AM_SMID will return zeroes for each of its 16-bytes. These two conditions can be used for software to manually check whether or not a SmartMedia card is inside the adapter.

[Advance Movie Adapter] : List of AM3 Cards and Products

-----------------------------------------------------------
Individual Cards with Video
-----------------------------------------------------------
am3-00002		Detective Conan Episode 2: 社長令嬢誘拐事件
am3-00003		Detective Conan Episode 3: アイドル密室殺人事件
am3-00004		Detective Conan Episode 4: 大都会暗号マップ事件
am3-00007		Time Bokan Episode 1: 「発進!タイムボカンだペッチャ」
am3-00008		Time Bokan Episode 2: 「ギリシャのズッコケ戦争だペッチャ」
am3-00009		Time Bokan Episode 3: 「恐怖の魔女狩りだペッチャ」
am3-00010		Time Bokan Episode 4: 「へんてこ西遊記だペッチャ」
am3-00012		Detective Conan Episode 5: 新幹線大爆破事件
am3-00013		Detective Conan Episode 6: バレンタイン殺人事件
am3-00014		Detective Conan Episode 7: 月いちプレゼント脅迫事件
am3-00015		Time Bokan Episode 5: 「原始人はやさしいだペッチャ」
am3-00016		Time Bokan Episode 6: 「海賊はオウムが好きだペッチャ」
am3-00017		Time Bokan Episode 7: 「合図はひらけゴマだペッチャ」
am3-00018		Detective Conan Episode 8: 美術館オーナー殺人事件
am3-00019		Detective Conan Episode 9: 天下一夜祭殺人事件
am3-00020		Detective Conan Episode 10: プロサッカー選手脅迫事件
am3-00025		Rerere no Tensai Bakabon Vol. 1
am3-00026		Rerere no Tensai Bakabon Vol. 2
am3-00027		Detective Conan Episode 12: 歩美ちゃん誘拐殺人事件
am3-00028		Detective Conan Episode 13: 奇妙な人捜し殺人事件
am3-00029		Detective Conan Episode 14: 謎のメッセージ殺人事件
am3-00030		Detective Conan Episode 11: ピアノソナタ『月光』殺人事件
am3-00033		Pokemon Movie: 劇場版ポケットモンスター ピカチュウのなつやすみ
am3-00035		Pokemon TV Anime Episode 1
am3-00046		Pokemon TV Anime Episode 2
am3-00047		Pokemon TV Anime Episode 3
am3-00067		Pokemon Movie: 劇場版ポケットモンスター ミュウツーの逆襲 完全版
am3-00069		Pokemon Movie: 劇場版ポケットモンスター ピカチュウたんけんたい
am3-00085		Pokemon Movie: 劇場版ポケットモンスター ピチューとピカチュウ
am3-00104		Pokemon Movie: 劇場版ポケットモンスター 幻のポケモン ルギア爆誕
am3-00131		Pokemon Movie: 劇場版ポケットモンスター 結晶塔の帝王 エンテイ
am3-00137		Bakusho Mondai no Bakuten: パラパラまんが
am3-00144		Crayon Shin-chan Movie: ブリブリ王国の秘宝
am3-00167		Pokemon Movie: 劇場版ポケットモンスターセレビィ~時を超えた遭遇~


-----------------------------------------------------------
Individual Cards with Video + Adapter Bundle
-----------------------------------------------------------
am3-00001		Detective Conan Episode 1: ジェットコースター殺人事件
am3-00006		Time Bokan Episode 1: 「発進!タイムボカンだペッチャ」
am3-00024		Rerere no Tensai Bakabon Vol. 1
am3-00031		Pokemon Movie: 劇場版ポケットモンスター ピカチュウのなつやすみ
am3-00034		Pokemon TV Anime Episode 1
am3-00065		Pokemon Original Animation: オリジナルアニメーション ピカチュウのふゆやすみ
am3-00068		Pokemon Movie: 劇場版ポケットモンスター ピカチュウたんけんたい
am3-00084		Pokemon Movie: 劇場版ポケットモンスター ピチューとピカチュウ
am3-00090		Akubi-chan: Episode 1 (???)
am3-00111		Ocha-ken: ちょこっとものがたり vol.1収録


-----------------------------------------------------------
Blank Gashapon Cards
-----------------------------------------------------------
am3-00049		Pikachu Gashapon Card
am3-00052		Bulbasaur Gashapon Card
am3-00054		Charmander Gashapon Card
am3-00056		Squirtle Gashapon Card
am3-00080		Mew Gashapon Card
am3-00082		Lucario Gashapon Card
am3-00083		Munchlax Gashapon Card
am3-00086		Akubi-chan Gashapon Card #1
am3-00088		Akubi-chan Gashapon Card #2
am3-00089		Akubi-chan Gashapon Card #3
am3-00112		Ocha-ken Gashapon Card
am3-00116		Time Bokan Gashapon Card
am3-00130		Kyorge Gashapon Card
am3-00139		Bakusho Mondai no Bakuten Gashapon Card
am3-00146		Crayon Shin-chan Gashapon Card #1
am3-00147		Crayon Shin-chan Gashapon Card #2
am3-00148		Crayon Shin-chan Gashapon Card #3
am3-00166		Manaphy Gashapon Card


------------------------------------------------------------
Blank Gashapon Cards + Adapter Bundle
------------------------------------------------------------
am3-00049		Pikachu Gashapon Card
am3-00081		Lucario Gashapon Card
am3-00087		Akubi-chan Gashapon Card #1

Music Recorder

General Hardware Information

I/O Registers

Command Overview

Command Usage

Index Overview & Usage

Recording File Formats

CompactFlash File & Directory Structure

[Music Recorder] : General Hardware Information

The Game Boy Advance Music Recorder is a cartridge for the Game Boy Advance capable of playing MP3s, recording audio, and performing karaoke. Designed and developed by Kemco, it was released on November 15, 2002 in Japan. A year later, Radica Games became the distributor for the product in North America and released it as the Game Boy Advance Jukebox. It marked the first time an officially licensed product could playback media of the user's choosing on the Game Boy.

[Music Recorder] : I/O Registers

All registers for the Music Recorder/Jukebox are 8-bit. They are located in the 0xB------ address range.

-----------------------------------------------------------
Address		| Register Name
-----------------------------------------------------------
0xB000000	| UNKNOWN
0xB020000	| UNKNOWN
0xB080000	| ZMP_INDEX_HI
0xB0A0000	| ZMP_INDEX_LO
0xB0C0000	| ZMP_DATA_HI
0xB0E0000	| ZMP_DATA_LO
0xB100000	| UNKNOWN
0xB120000	| ZMP_STATUS_RESET

ZMP_INDEX_HI and ZMP_INDEX_LO are used to set the current index. Each index points to specific data from the hardware, such as the current output volume, users settings, battery level, and the time remaining for recording or music playback. Each index is 16-bit and ZMP_INDEX_HI and ZMP_INDEX_LO form two 8-bits components of that value. ZMP_INDEX_HI contains the upper 8-bits and ZMP_INDEX_LO contains the lower 8-bits.

ZMP_DATA_HI and ZMP_DATA_LO are used to read data from or write data to the selected index. Data inside each index is also 16-bit, therefore ZMP_DATA_HI accesses the upper 8-bits and ZMP_DATA_LO accesses the lower 8-bits.

ZMP_STATUS_RESET forcibly resets the current value of cartridge's reported status. To do so, ZMP_STATUS_RESET must first be set to 0x00. After brief delay (approximately 16ms is sufficient) ZMP_STATUS_RESET must then be set to 0x01. The cartridge's status will then reset to zero after a period of about 500ms. The status is reported by the Device Status index. The upper-half of the index appears to represent the current audio playback state while lower half represent the current command issued to the cartridge.

Registers 0xB000000, 0xB020000, and 0xB100000 appear to be used by the software under certain circumstances, however, their purpose is currently unknown.

[Music Recorder] : Command Overview

The major functions of the Music Recorder/Jukebox are controlled from the software by sending a series of commands. Complex tasks such as reading the CompactFlash memory card or even deciding when to decode MP3 files are largely abstracted away from the CPU by a simple, high-level interface. To issue a command, software must follow the proceedure listed below:

  1. Write the value 0x0000 to the index 0x0081, then delay about 16ms.
  2. Write the command to the index 0x0080.
  3. Write the value 0x0000 to ZMP_STATUS_RESET, delay about 16ms, then write the value 0x0001 to ZMP_STATUS_RESET.

After writing to ZMP_STATUS_RESET, the Device Status index will then return either 0x100 in most cases, or 0x8000 when performing certain audio operations.

Each command is 8-bits in length and occupy the lower half of the Device Status index. Their values serve as enumerations to various audio and memory related functions. The software has been observed using the below commands:

-----------------------------------------------------------
Command		| Description
-----------------------------------------------------------
0x00		| Unknown
0x01		| Unknown
0x02		| Format CompactFlash Card
0x08		| Select Music Files
0x09		| Record Music Files
0x0A		| Select Voice Memo Files
0x0B		| Record Voice Memo Files
0x0C		| Select Karaoke Files
0x0D		| Record Karaoke Files
0x0E		| Unknown
0x10		| Unknown
0x11		| Commit Title/Artist Changes
0x13		| Play Selected Audio File/Record New Audio File 	
0x14		| Reset Currently Selected Audio File
0x15		| Move Forward 1 Audio File
0x16		| Move Backward 1 Audio File
0x19		| Delete Current Audio File
0x20		| Stop Playing/Recording Audio File

[Music Recorder] : Command Usage

For all commands dealing with audio input/output (0x109, 0x10B, 0x10D, 0x113), refer to the section below for dealing with the actual data transfers.

Command 0x00 - Unknown

This is the first command that the software for the Music Recorder/Jukebox issues. The software also sends this command after finishing recording Music Files, indicating that it might reset or initialize functions related to the Line-In jack.

Command 0x01 - Unknown

This is the second command that the software for the Music Recorder/Jukebox issues, indicating that it is possibly used to initialize the hardware.

Command 0x02 - Format CompactFlash Card

This command will format the CompactFlash card inserted into the Music Recorder/Jukebox. Presumably, it also creates several directories used to separate music files into different categories. It also creates the AGB.INFO file in the root directory, which contains a list of all MP3 files detected by the hardware.

Once this command has been sent, the index 0x101 is used to measure the progress of the formatting process. The 16-bit value in that index represent progress in 1 / 32768 units. That is to say, 0% is 0x0000, 25% is 0x2000, 50% is 0x4000, 75% is 0x6000, and 100% is 0x8000. Various percentages can be created using any value in between 0x0000 through 0x8000. For example, ~14.22% would be 0x1234.

The software only displays whole integers, ignoring any decimals results. Surprisingly, it can measure 0% through 199%.

Command 0x08 - Select Music Files

This command is used to read information about MP3 music files or any music recordings via Line-In stored on the CompactFlash card. It is also used to select the Music/Line-In Recordings category when playing files. The command largely affects the output of indices 0x00A1 - 0x00A6 and 0x00B0 - 0x00CF for data relating to the music's filename, formal title, and artist.

Command 0x09 - Record Music

This command prepares the Music Recorder/Jukebox to record audio data from the Line-In jack. After sending this command, the software waits for the CompactFlash Status index to change to the value 0x1010 to indicate the hardware is ready. Input data from the jack is then stored as a sequentially numbered .GB3 file. The user can optionally turn on a "Silence Detection" feature that splits incoming audio data into seperate files when a period of silence appears in the stream, automatically breaking up songs from CDs or cassette players for example.

Command 0x0A - Select Voice Memo Files

This command is used to read information about Voice Memo files recorded via the built-in microphone and stored on the CompactFlash card. It is also used to select the Voice Memo category when playing files. The command largely affects the output of indices 0x00A1 - 0x00A6 for data relating to the memo's filename.

Command 0x0B - Record Voice Memo Files

This command prepares the Music Recorder/Jukebox's to record audio data from the microphone. Input data from the microphone is then stored in sequentially numbered .WAV files.

Command 0x0C - Select Karaoke Files

This command is used to read information about Karaoke Files stored on the CompactFlash card and created by playing audio from the Music Files and recording over them with the microphone. The command largely affects the output of indices 0x00A1 - 0x00A6 for data relating to the memo's filename.

Command 0x0D - Record Karaoke Files

This command prepares the Music Recorder/Jukebox to record audio data from the microphone on top of the unit and by mixing audio samples from one of the Music Files. When recording Karaoke Files, the user is prompted to first select an existing Music File.

Command 0x0E - Unknown

This command always follows the 0x01 command. The Music Recorder/Jukebox's software appears to only issue this command at the very beginning when initializing hardware.

Command 0x10 - Unknown

This command always follows a command related to file access (0x08, 0x0A, 0x0C, 0x14, 0x15, 0x16, and 0x19), indicating that it might serve as a means to update the current list of files for a given category. For commands that select a given category (0x08, 0x0A, and 0x0C), the software for the Music Recorder/Jukebox issues this command twice in a row.

Command 0x11 - Commit Title/Artist Changes

For .GB3 files recorded via the Line-In jack, the Music Recorder/Jukebox software allows users to manually input the song's full name as well as the artist. Up to 30 characters can be used for either the title or artist fields. The software writes the data to the relevant indices at 0xB0 - 0xCF and sends this command to save the data.

Command 0x13 - Play Selected Audio File/Record New Audio File

This command either plays a selected audio file or starts recording a new file, depending on which commands were previously issued. All 3 categories of audio - Music, Voice Memo, and Karaoke - use this command to actually output audio. For recording, the commands 0x09, 0x0B, and 0x0D merely prep the hardware for recording a new file, while this command actually instructs the hardware to start grabbing input audio samples. Most importantly, this command affects the value of the CompactFlash Status index, depending on which category of audio has been selected and whether the mode is playing or recording:

-----------------------------------------------------------
Mode			| CompactFlash Status
-----------------------------------------------------------
Music Play		| 0x1001
Music Record		| 0x1012
Voice Memo Play 	| 0x1101
Voice Memo Record	| 0x1112
Karaoke Play		| 0x1201
Karaoke Record		| 0x1211
-----------------------------------------------------------

When the song is finished playing, or when there is no space left on the CompactFlash card, the CompactFlash Status index stops matching those above values.

Command 0x14 - Reset Currently Selected Audio File

This command appears to reset any information regarding the currently selected file. The Music Recorder/Jukebox issues this command on boot and again every time the user exits the "PLAY" or "REC" menus for a given category of audio.

Command 0x15 - Move Forward 1 Audio File

Select the next audio file for playback. If the current file is the last file for a given audio category, the audio file at the beginning of the list is selected instead.

Command 0x16 - Move Backward 1 Audio File

Selects the previous audio file for playback. If the current file is the first file for a given audio category, the audio file at the end of the list is selected instead.

Command 0x17 - Move Audio File 1 Slot Forward

This command changes the order of audio files when playing them from the Music category. It will take the currently selected song and move it up one slot, effectively allowing the user to make a customized playlist. For example, if the selected song is #1 in the playlist, this command will move it into slot #2. The previous song that was in slot #2 will also move to slot #1. If the selected song occupies the last slot in the playlist, the Music Recorder/Jukebox's interface prevents the user from executing this command.

Command 0x18 - Move Audio File 1 Slot Backward

This command changes the order of audio files when playing them from the Music category. It will take the currently selected song and move it down one slot, effectively allowing the user to make a customized playlist. For example, if the selected song is #2 in the playlist, this command will move it into slot #1. The previous song that was in slot #1 will also move to slot #2. If the selected song occupies the first slot in the playlist, the Music Recorder/Jukebox's interface prevents the user from executing this command.

Command 0x19 - Delete Current Audio File

Erases all data for the current audio file from the CompactFlash card.

Command 0x20 - Stop Playing/Recording Audio File

Halts all audio input/output for a given audio file.

[Music Recorder] : Index Overview & Usage

Each index is mapped to different hardware data, giving the CPU access to information regarding music playback or recording. Below is a list of known indices and their roles:

-----------------------------------------------------------
Index	| R/W	| Description
-----------------------------------------------------------
0x0080	| W	| Write Device Status
0x0081	| R	| Read Device Status
0x0082	| R	| CompactFlash Status
0x0084	| R	| Remaining Playback Time (Minutes)
0x0085	| R	| Remaining Playback Time (Seconds)
0x0086	| R	| Remaining Recording Time (Minutes)
0x0087	| R	| Remaining Recording Time (Seconds)
0x0088	| R/W	| Music Output Volume (0x3F = Min, 0x00 = Max)
0x008A	| R/W	| Voice Output Volume (0x3F = Min, 0x00 = Max)
0x008C	| R/W	| Equalizer Settings
0x008B	| R	| Recording Volume (0xFFEE = Min, 0x0004 = Max)
0x008F	| R/W	| Voice Cancellation Settings
0x009A	| R/W	| Spectrum Analyzer Update Status
0x009B	| R/W	| GBA Speaker Volume db (0xFFEC = Min, 0x0013 = Max)
0x009C	| R	| CompactFlash Detection Flag
0x009D	| R	| Battery Level (Min = 0x02, Max = 0x00)
0x00A0	| R	| Current File Track Number
0x00AD	| R	| Current Number of Music Files Detected
0x00AE	| R	| Current Number of Voice Memo Files Detected
0x00AF	| R	| Current Number of Karaoke Files Detected
0x0100	| R	| Audio Index Length
0x0101	| R	| CompactFlash Format Progress / CompactFlash Access Progress???
0x0102	| R	| Current Karaoke File Number for Recording (Hundreds Value)
0x0103	| R	| Current Karaoke File Number for Recording (Tens and Ones Values)
0x01C8	| R/W	| General Configuration Settings
0x01C9	| R/W	| Line-In and Microphone Input Levels

Index 0x0080 - Write Device Status

Allows the CPU to overwrite the cartridge's 16-bit STATUS value. When STATUS is set to certain values, it acts as a command.

Index 0x0081 - Read Device Status

Returns the CPU to read the cartridge's 16-bit STATUS value. Primarily used to see if the cartridge is ready to perform certain operations after issuing a command.

Index 0x0082 - CompactFlash Status

Returns the current state of the CompactFlash card. When recording music, it should read 0x1010.

Index 0x0084 - Remaining Playback Time (Minutes)

Returns the remaining minutes left when playing a music file or recording. Has a range of 0 - 99. The cartridge's hardware will automatically update the value during playback.

Index 0x0085 - Remaining Playback Time (Seconds)

Returns the remaining seconds left when playing a music file or recording. Has a range of 0 - 59. The cartridge's hardware will automatically update the value during playback.

Index 0x0086 - Remaining Recording Time (Minutes)

Returns the remaining minutes left when making any recording. Has a range of 0 - 99. The value is dependent on remaining free space of the CompactFlash card and the audio quality chosen for recording. The cartridge's hardware will automatically update the value during a recording session.

Index 0x0087 - Remaining Recording Time (Seconds)

Returns the remaining seconds left when making any recording. Has a range of 0 - 59. The value is dependent on remaining free space of the CompactFlash card and the audio quality chosen for recording. The cartridge's hardware will automatically update the value during a recording session.

Index 0x0088 - Music Output Volume

Specifies the output volume for Music and Karaoke Files through either the GBA's speakers or the cartridge's built-in headphone jack. Has a range of 0x3F - 0x00, for minimum to maximum volume. Operates separately from the Voice Output Volume index.

Index 0x008A - Voice Output Volume

Specifies the output volume for Voice Memo Files through either the GBA's speakers or the cartridge's built-in headphone jack. Has a range of 0x3F - 0x00, minimum to maximum volume. Operates separately from the Music Output Volume index, however an apparent software glitch seems to overwrite this index with the other volume index when switching audio categories.

Index 0x008C - Equalizer Settings

Specifies the type of equalizer to apply for music playback. Accepts values of 0 - 4 to select the following equalizers respectively: None, Jazz, Pop, Classical, Rock.

Index 0x008B - Recording Volume

Returns the current volume of input audio from the a recording (via Line-In or the microphone).

Index 0x008F - Voice Cancellation Settings

Toggles voice cancellation during audio playback. 0 = OFF, 1 = ON.

Index 0x009A - Spectrum Analyzer Update Status

Represents when the spectrum analyzer for Music Files needs to be updated. When this value is zero, the spectrum analyzer is disabled. For any non-zero values, the spectrum analyzer is enabled. When enabled, this index will increase in to indicate the spectrum analyzer needs to be redrawn. The update only happens when the current value of the index is greater than the previously recorded value. If this index overflows 16-bits and reads zero or if the value is frozen, the software will not update the spectrum analyzer.

As it is limited to 16-bit values, the spectrum analyzer can only be updated a certain amount of times before it overflows. The software appears to check this index a maximum of 45 times per-second during playback, so the Music Record/Jukebox can play songs up about 18:30 long without issue.

Index 0x009B - GBA Speaker Volume db

Adjusts the output volume from the GBA speakers in the range of -20 to +19 db. The index itself goes from 0xFFEC as the minimum to 0x0013 as the maximum.

Index 0x009C - CompactFlash Detection Flag

Determines whether a CompactFlash card has been inserted into the cartridge. Any non-zero value indicates the card cannot be detected.

Index 0x009D - Battery Level

Returns the current level of the AA battery inside the cartridge. Has 3 levels total with the values 0x02 representing 1 bar, 0x01 representing 2 bars, and 0x00 representing 3 bars.

Index 0x00A0 - Current File Track Number

Returns the current file track number. This is determined by how the cartridge arranges files, not by any metadata from the file itself. For Music, Voice Memos, and Karaoke files, this value is used for playback purposes. For Music and Voice Memos, this value is also used during recording. When recording Karaoke files, however, indices 0x0102 and 0x0103 are used instead.

Index 0x00AC - Current Number of Music Files Detected

Returns the current number of Music Files detected on the CompactFlash card.

Index 0x00AE - Current Number of Voice Memo Files Detected

Returns the current number of Voice Memo Files detected on the CompactFlash card.

Index 0x00AF - Current Number of Karaoke Files Detected

Returns the current number of Karaoke Files detected on the CompactFlash card.

Index 0x0100 - Audio Index Length

Determines how many indices to read from 0x102 and beyond for audio input/output data.

Index 0x0101 - CompactFlash Format Progress / CompactFlash Access Progress

Appears to indicate the progress of certain tasks involving the CompactFlash card. For formatting the card, this index represents the overall progress of that process from 0% to 100% using the range 0x0000 through 0x8000. For playing and recording audio data, it seems to determine when certain chunks are finished using a range of 0x0000 through 0x4000.

Index 0x0102 - Current Karaoke File Number for Recording (Hundreds Value)

Returns 8-bits representing the current file number (in hundreds) for recording Karaoke files. It has an unusual offset not seen in the 0x00A0 index. It can be calculated as the following:

INDEX = (((CURRENT_FILE / 100) + 0xA6) AND 0xFF)

Index 0x0103 - Current Karaoke File Number for Recording (Tens and Ones Values)

Returns 8-bits representing the current file number (in tens and ones) for recording Karaoke files. It has an unusual offset not seen in the 0x00A0 index. It can be calculated as the following:

INDEX = (((CURRENT_FILE modulo 100) + 0xA8) AND 0xFF)

Index 0x01C8 - General Configuration Settings

Stores various flags that represent user-changeable settings such as the software's wallpaper, whether to use the Game Boy's speakers vs. headphones, and MP3 recording quality. The bits and the values they affect are listed below:

-----------------------------------------------------------
Bits		| Description
-----------------------------------------------------------
Bits 2-3	| Spectrum Analyzer Type (0 = Analyzer #1, 1 = Analyzer #2, 2 = Analyzer #3)
Bits 4-5	| Wallpaper Type (0 = Wallpaper #1, 1 = Wallpaper #2, 2 = Wallpaper #3)
Bit 8		| GBA Speaker Flag (0 = Use Headphones, 1 = Use GBA Speaker)
Bit 9		| MP3 Recording Silence Detection Flag (0 = Off, 1 = On)
Bits 10-11	| MP3 Recording Quality (0 = 128Kbps, 1 = 96Kbps, 2 = 64Kbps)
Bit 14		| Voice Silence Detection Flag (0 = Off, 1 = On)
Bit 15		| Auto Replay Flag (0 = Off, 1 = On)

Index 0x01C9 - Line-In and Microphone Input Levels

Used to calibrate volumes when recording via Line-In or the microphone. The Music Recorder/Jukebox uses an 8-bit value for this calibration. The high byte is used for microphone sensitivity while the low byte is used for Line-In volumes.

Some indices have a widespread range and serve as string data or audio input/output

-----------------------------------------------------------
Index Range	| R/W	| Description
-----------------------------------------------------------
0x0090 - 0x0098	| R	| Spectrum Analyzer Level For Bars 1 - 9 (0x00 = Min, 0x13 = Max)
0x00A1 - 0x00A6	| R/W	| "8.3" DOS-style short name for music file
0x00B0 - 0x00BE	| R/W	| 30 character song title
0x00BF - 0x00CD	| R/W	| 30 character artist name
0x0102+		| R/W	| Audio in/out data for recording/playing

For the string data at 0x00A1 through 0x00CD, the string is terminated by a null character (value 0x00). The strings for the Jukebox use ASCII.

When reading input/output audio data, the software accesses indices starting at 0x0102 and ends at the length specified by index 0x100. For example, if the Audio Index Length is 0x0004, the CPU reads indices 0x0102 through 0x0105 inclusive. Note that the 0x0102 and 0x0103 are also used for other purposes. Depending on the context, it may represent audio sample data or a Karaoke file number.

[Music Recorder] : Recording File Formats

The Music Recorder/Jukebox uses 2 different file formats for recording. For Voice Memos and Karaoke, the device encodes audio via IMA ADPCM into a WAV file. This format uses a 11025Hz sample rate, 16-bits per sample, and just one channel.

For Music recorded via the Line-In jack, an MP3 file is generated. Depending on the user's settings, it will have a bit-rate of 128Kbps, 96Kbps, or 64Kbps. It uses ID3v1 to store metadata at the very last 128 bytes of the file. Instead of regular MP3 files, the Music Recorder/Jukebox produces "GB3" files. However, these GB3 files appear to be normal MP3s without a header. This design prevents music from being recorded and copied to a PC and may have been intended to deter piracy.

[Music Recorder] : CompactFlash File & Directory Structure

The CompactFlash card used by the Music Recorder/Jukebox contains a FAT-12 filesystem. The hardware is capable of formatting the card as necessary without the need of a PC or any other kind of media writing device. By default, it has a volume label that reads "AGB-MP3 ". 4 folders and 1 file in the root directory are created after a formatting the card:

-----------------------------------------------------------
Name		| Description
-----------------------------------------------------------
ADPCM		| Folder - Holds all Voice Memo recordings
GB3		| Folder - Holds all Music recordings
MP3		| Folder - Holds all user MP3s for playback
SONG		| Folder - Holds all Karaoke recordings
INFO.AGB	| File - Contains filenames for content in the above folders

Despite its name, INFO.AGB contains no executable code intended to run on the GBA. Instead, simply has a list of all the files present for each category of audio. Additionally, it links MP3 and GB3 files to a given Karaoke recording. INFO.AGB is always 15KB exactly and is divided into the following 4 sections:

-----------------------------------------------------------
Offset 		| Description
-----------------------------------------------------------
0x0000		| MP3 + GB3 Folder File List
0x1800		| ADPCM Folder File List
0x2400		| Song Folder File List
0x3000		| Karaoke Link Data

For sections listing filenames, MP3 files use "8.3" DOS-style short names in ASCII. WAV and GB3 files (named sequentially e.g. 0001.WAV or 0002.WAV) use an even shorter "4.3" style in ASCII. Data is stored as strings with no terminating character or padding. The strings are formatted such that they use 16-bit pairs of characters that need to be read LSB first. Do note that the MP3 and GB3 files are listed together rather than separately.

The Karaoke Link Data essentially points to the relevant MP3 or GB3 file that acted as the source of a Karaoke recording. The files here are ordered sequentially according to how the Music Recorder/Jukebox displays Karaoke files for playback. That is to say, the first file listed in INFO.AGB corresponds to the first file viewed from the Karaoke -> Play menu. This seems necessary for the Jukebox as it allows the software to pull up the 30 character song title and artist fields from the MP3 and GB3 files even though it plays the WAV Karaoke recording (which has no such metadata). If the Karaoke Link Data is corrupted or missing, the Music Recorder/Jukebox refuses to play any Karaoke recordings.

The Music Recorder/Jukebox automatically updates INFO.AGB during various operations, such as deleting files. After a reformat, the Music Recorder/Jukebox inserts a blank INFO.AGB in the root directory.

Play-Yan

General Hardware Information

Hardware Registers and I/O

Reading and Writing Firmware

Reading SD Card Data

Play-Yan Commands

Game Pak IRQs

Reading Video Frames and Video Thumbnails

Garage Games

Key File

[Play-Yan] : General Hardware Information

On February 21, 2005, Nintendo released their very own video/music player for the Game Boy Advance in the form of a unique cartridge. It was branded the Play-Yan and was designated the product code AGS-006. Sold exclusively in Japan, it handled MP3 audio files as well and MPEG-4 video files. The hardware had a dedicated SD card slot so users could access their own media.

On September 13, 2005, Nintendo released an updated version called the Play-Yan Micro. It was largely the same as the original Play-Yan, however, it was updated with native support for the MP4 video container, a different interface, and it removed support for the 13 minigames. The Play-Yan Micro was otherwise unchanged.

[Play-Yan] : Hardware Registers and I/O

The Play-Yan has a large number of addresses mapped to cartridge ROM that control firmware access, issue playback commands, and retrieve information such as filenames, thumbnails, and other metadata.

----------------------------------------------------------------------------------------------------------------------
Hardware Registers	| R/W	| Address	| Size		| Description
----------------------------------------------------------------------------------------------------------------------
PY_INIT_DATA		| (R)	| 0x9000000	| 8-bit		| Appears to be some kind of data stream.
PY_STAT			| (R)	| 0x9000006	| 8-bit		| Play-Yan Status Register.
UNKNOWN REGISTER 00	| (w)	| 0xB000000 	| 16-bit	| Unknown. Play-Yan mostly writes zero to this register.
UNKNOWN REGISTER 02	| (R/W)	| 0xB000002	| 16-bit	| Unknown. Play-Yan mostly writes zero to this register.
PY_DATA_ADDR		| (R/W)	| 0xB000004	| 16-bit	| Address used to access Play-Yan data.
PY_DATA_MODE		| (R/W)	| 0xB000006	| 16-bit	| Determines data access mode (e.g. firmware read or firmware write).
PY_DATA_PARAM		| (R/W)	| 0xB000010	| 16-bit	| Appears to be some kind of parameter for data access.
PY_FIRM_STAT		| (R/W)	| 0xB000012	| 16-bit	| Play-Yan Firmware Status Register.
----------------------------------------------------------------------------------------------------------------------

PY_INIT_DATA is read a number of times during the initial boot sequence. It appears to be a data stream of unknown purpose.

PY_STAT acts as the overall status register for the Play-Yan. Its primary purpose appears to be checking whether or not firmware is available accessible. Before uploading any portion of firmware during the initial boot sequence, the Play-Yan checks Bit 7 of PY_STAT, which acts as a busy flag for firmware operations. If Bit 7 is set LOW, the firmware is busy, otherwise if Bit 7 is set HIGH, firmware is ready for more data.

PY_DATA_ADDR determines the address used for data operations for Play-Yan related data. It is used in conjunction with the I/O regions listed below as well as PY_DATA_MODE. Depending on the value of PY_DATA_ADDR, different contexts are used to retrieve data from these regions, e.g. it distinguishes between writing commands for the Play-Yan to execute or writing firmware data. The address is actually 32-bits. The Play-Yan must write to PY_DATA_ADDR twice, with the lower 16-bit first, and the upper 16-bit second.

PY_DATA_MODE determines what kind of data read or write the Play-Yan will perform. Used in conjection with the IO regions listed below as well as PY_DATA_ADDR.

PY_DATA_PARAM appears to be a parameter passed along to the Play-Yan that affects data access. Currently unknown exactly how it functions.

PY_FIRM_STAT appears to be another type of firmware status register. Before reading any portion of firmware, the Play-Yan checks this to make sure Bit 4 is set.

Several regions of memory on the Play-Yan are dedicated to unique purposes. Some of them overlap, and their function often depends on whether data is being written or read. The Play-Yan typically uses these for accessing large amounts of information, such as pixels representing video data, firmware, or commands.

----------------------------------------------------------------------------------------------------------------------
I/O Regions		| I/O Direction	| Description
----------------------------------------------------------------------------------------------------------------------
0xB000100 - 0xB0002FF	| Input		| Play-Yan Command
0xB000100 - 0xB0002FF	| Input		| Firmware In
0xB000300 - 0xB00031F	| Output	| Game Pak IRQ Data
0xB000300 - 0xB0004FF	| Output	| Play-Yan SD Card and Internal Data
0xB000500 - 0xB0006FF	| Output	| Play-Yan Thumbnail and Video Data
----------------------------------------------------------------------------------------------------------------------

[Play-Yan] : Reading and Writing Firmware

To write to the Play-Yan's firmware, the following steps are performed:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x0A
PY_DATA_MODE = 0x68
PY_DATA_ADDR = LOW 16 BITS OF ADDRESS
PY_DATA_ADDR = HIGH 16 BITS OF ADDRESS
UNKNOWN REGISTER 02 = 0x00

WAIT FOR BIT 7 OF PY_STAT TO READ HIGH
WRITE DATA INTO 0xB000300 THROUGH 0xB0004FF
-----------------------------------------------------------------------

The address to write the firmware is internal to the Play-Yan. This is evidently any address from 0x00000 - 0xEFFFF. Only 512 bytes can be written at a time, so writing the entire firmware to the Play-Yan requires multiple iterations of the above steps.

The Play-Yan provides its own default firmware in its ROM and uploads this accordingly on every boot. This method ensures that the firmware is never corrupted by a bad update. A similar method is used for the WiiSpeak accessory on the Wii. The Play-Yan can update to a newer firmware if such a file is included on the SD card. For the original Play-Yan, the software looks for the file "playan.fup". Nintendo did release at least one firmware update as well, allowing the original Play-Yan to run MP4 files, something the later Play-Yan Micro version could do out-of-the-box.

To read from the Play-Yan's firmware, the following steps are performed:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = LOW 16 BITS OF ADDRESS
PY_DATA_ADDR = HIGH 16 BITS OF ADDRESS
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
READ DATA FROM 0xB000300 THROUGH 0xB0004FF
-----------------------------------------------------------------------

It's possible to read sequential blocks of firmware without repeating all of the above steps. The Play-Yan's ROM, for example, reads a total of 0xA00 bytes at a time. After each 0x200 bytes, only PY_FIRM_STAT needs to be checked before reading the next block. Once a total of 0xA00 bytes have been read, however, all the steps mentioned above are repeated before reading sequentially yet again.

[Play-Yan] : Reading SD Card Data

The Play-Yan is capable of reading select data from the SD Card. After the software issues a command, the Play-Yan will respond with different kinds of data, for example, a list of all files in a given directory. This means that while the Play-Yan's software does not have direct access to the card, it has a vastly simpler interface to retrieve information. The memory region used overlaps with where firmware is read from, however, the process for accessing is somewhat different. The following steps are performed:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = 0x00
PY_DATA_ADDR = 0x00
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
PY_DATA_PARAM = 0x08
READ DATA FROM 0xB000300 THROUGH 0xB0004FF
-----------------------------------------------------------------------

As with reading firmware, sequential 512-byte blocks can be read at a time. This is once again achieved by checking PY_FIRM_STAT. An additional step, setting PY_DATA_PARAM to 0x08, however, is necessary. The Play-Yan's software does not update the address when sequentially reading SD card data. Typically, the Play-Yan reads around 0x6800 bytes worth of data at a time and later copying that to RAM. Such a large amount of data allows it to process long lists of filenames, video frames, or vast amounts of metadata, depending on the expected response to a command.

[Play-Yan] : Play-Yan Commands

A number of commands may be issued to the Play-Yan. These allow the software to access many of the cartridge's advanced functions surrounding multimedia playback and file handling. Rather than manually processing things, the Play-Yan hands things over to its hardware and firmware through an interface. There are two methods of sending commands on the Play-Yan: serial and non-serial. These determine whether the data is written to a single, fixed 16-bit address or across a range of I/O addresses, respectively.

Each command typically consists of 12 bytes written to the 0xB000000 - 0xB00001F address range for serial commands and the 0xB000100 - 0xB00011F address range for non-serial commands. Some commands may contain additional parameter data beyond this, and not every command follows the same pattern of using 32-bit parameters. In general, however, the structure of a command is as follows:

-----------------------------------------------------------------------
Address			| Data
-----------------------------------------------------------------------
0xB000x00 - 0xB000x03	| Command 
0xB000x04 - 0xB000x07	| Parameter 1
0xB000x08 - 0xB000x0B	| Parameter 2
0xB000x0C ...		| Parameter 3
-----------------------------------------------------------------------

Data for most commands is usually broken into 32-bit chunks, sent LSB first. Essentially, the Play-Yan just sends a command along with 2 parameters, both of which are optional. Below is a list of known or observed commands along with their parameters:

----------------------------------------------------------------------------------------------------------------------------------------------
Command					| Parameter 1							| Parameter 2
----------------------------------------------------------------------------------------------------------------------------------------------
0x200 - Get Filesystem Information	| File Type							| N/A
0x201 - Change Current Directory	| Directory Name						| N/A
0x300 - Adjust Video Brightness		| Brightness level, Min = 0x101, Max = 0x2C0, 0x40 increments	| N/A
0x400 - Unknown				| N/A								| N/A
0x500 - Grab Video Thumbnail Data*	| Width of thumbnail (60 pixels)				| Height of thumbnail (40 pixels)
0x600 - Grab ID3 Data*			| Music Filename						| N/A
0x700 - Play Video/Grab Video Frame*	| Width of video (240 pixels)					| Height of video (160 pixels)
0x701 - Stop Video Playback		| N/A								| N/A
0x800 - Play Music File*		| Music Filename						| N/A
0x801 - Stop Music Playback		| N/A								| N/A
0x902 - Pause Music/Video Playback	| N/A								| N/A
0x903 - Unknown				| N/A								| N/A
0x904 - Resume Music/Video Playback	| N/A								| N/A
0x905 - Seek Forwards/Backwards		| Seek Speed							| N/A
0x906 - Unknown				| N/A								| N/A
0xB00 - Adjust Volume			| Volume level, Min = 0x00, Max = 0x38				| N/A
0xD00 - Adjust Bass Boost		| Bass boost level, Min = 0x00, Max = 0x0F			| N/A
0xD01 - Enable/Disable Bass Boost	| ON = 0x800F, OFF = 0x8F0F					| N/A
0x2000 - Play Sound Effect		| N/A								| N/A
0x3000 - Check For Key File*		| Key File Name							| N/A
0x3001 - Read Key File Data		| N/A								| N/A
0x3003 - Close Key File			| N/A								| N/A
0x8000 - Get SD Cartridge Status	| N/A								| N/A
0x10000 - Enter Sleep Mode		| N/A								| N/A
0x800000 - Unknown			| N/A								| N/A
----------------------------------------------------------------------------------------------------------------------------------------------

*These commands send non-standard amounts of data for their parameters. See the end of this section for further details on each. additional data beyond a second parameter. Overall, it sends a total of 0x218 bytes, the latter portion of which has an unknown purpose.

The Play-Yan Micro exclusively uses serial commands and uses the following proceedure to issue them:

-----------------------------------------------------------------------
PY_DATA_MODE = 0x28
PY_DATA_ADDR = 0xF020
PY_DATA_ADDR = 0x000F
UNKNOWN REGISTER 02 = 0x00

WAIT FOR BIT 7 OF PY_STAT TO READ HIGH
WRITE 16-BIT DATA INTO 0xB000000
REPEAT 16-BIT WRITES INTO 0xB000000 AS NEEDED FOR COMMAND LENGTH
PY_DATA_PARAM = 0x0C
PY_DATA_PARAM = 0x08
-----------------------------------------------------------------------

The original Play-Yan exclusively uses non-serial commands and uses the following proceedure to issue them:

-----------------------------------------------------------------------
PY_DATA_MODE = 0x68
PY_DATA_ADDR = 0xF020
PY_DATA_ADDR = 0x000F
UNKNOWN REGISTER 02 = 0x00

WAIT FOR BIT 7 OF PY_STAT TO READ HIGH
WRITE DATA INTO 0xB000100 THROUGH 0xB00010B
PY_DATA_PARAM = 0x0C
PY_DATA_PARAM = 0x08
-----------------------------------------------------------------------

Note that the data address specified by PY_DATA_ADDR is 0xFF020. Some commands will trigger a Game Pak IRQ when the Play-Yan responds. See the section below for more details.

The 0x201 Change Current Directory command uses Parameter 1 as a null-terminated string representing the target folder the Play-Yan will move into. The string has no fixed length, thus making this an irregular command. The Play-Yan appears to send additional unknown data after the string.

The 0x500 Grab Video Thumbnail Data command sends additional data via Parameter 3. Some of these bytes are a null-terminated string representing the filename of a specific video to generate thumbnail data. This string begins at 0xB000114. Altogether, 0x218 bytes are sent. Since this amount exceeds the 0xB0002FF boundary for parameter input, the last 0x18 bytes are written at the beginning of the section, starting over at 0xB000100.

The 0x600 Grab ID3 Data command uses Parameter 1 as a null-terminated string representing the target file to lookup metadata. The string has no fixed length, thus making this an irregular command. The Play-Yan appears to send additional unknown data after the string.

The 0x700 Play Video command uses Parameter 3 as a null-terminated string representing the filename of a specific video file to play. Like music, the Play-Yan software internally monitors which video the user has highlighted and passes the filename's string to the hardware. This string likewise has no fixed length. The Play-Yan appears to send additional unknown data after the string.

The 0x800 Play Music File command uses Parameter 1 as a null-terminated string representing the filename of specific music file to play. The Play-Yan software internally keeps track of which song the user has currently highlighted, and it passes the filename's string to the hardware. The string has no fixed length, thus making this an irregular command. The Play-Yan appears to send additional unknown data after the string.

The 0x905 Seek Forwards/Backwards command uses Parameter 1 to indicate the direction to fast forward or rewind audio/video. It operates differently depending on which media is being played. For audio, it represents a new value for the Track Bar Position used for the 0x800 command. To go forward, the Play-Yan's software takes the current value and increments it, then passes it along to the 0x905 command. For video, only two values are used for Parameter 1: 0x01 to go forward and 0xFFFFFFFF to go backwards.

The 0x3000 Check For Key File command uses Parameter 1 as a null-terminated string representing the filename of the "key file", which is a .ini text file containing various settings such as what theme to use, video brightness, and audio volume. This command, as well as all other 0x300x commands, is exclusive to the Play-Yan Micro. The string should have a fixed length, as the software is hardcoded to use "play_yanmicro.ini", however, it can technically be any length.

[Play-Yan] : Game Pak IRQs

The Play-Yan's hardware produces a variety of Game Pak IRQs when the software sends certain commands. Not every command will generate an IRQ, however, the ones that do are pivotal to operating the Play-Yan. For example, during the initial boot process, the Play-Yan's software waits indefinitely until several commands to respond with IRQs, without which the software essentially locks up. Each Game Pak IRQ returns data that can be read at 0xB000300 - 0xB00031F. Some commands may cause multiple IRQs to be generated as well, where the return data is simply 0x80000100 or 0x80001000 to signify the end of certain internal operations within the Play-Yan. Use the following process to read the Game Pak IRQ data:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = 0xF000
PY_DATA_ADDR = 0x000F
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
PY_DATA_PARAM = 0x08
READ DATA FROM 0xB000300 THROUGH 0xB00031F
-----------------------------------------------------------------------

A list of commands and their known IRQs and the IRQ data is shown below:

-----------------------------------------------------------------------
Command 0x200 - Get Filesystem Information - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000200
Bytes 0x04 - 0x07	| 0x01 or 0x02
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

This command prompts the Play-Yan to start reading the filesystem on the SD card. It allows the software to grab a list of available files or folders for music, or video files. The Play-Yan will scan for any files and folders it can find. Afterwards, the software can read the data through the SD Card Data interface described in the section above. The data contains the total number of files and folders within the directory along with 268-byte entries of metadata for each item found. The format of the list returned via SD Card Data is as follows:

-----------------------------------------------------------------------
Bytes 0x0000 - 0x0003	| Unused (zeroes)
Bytes 0x0004 - 0x0007	| Number of files and folders
Bytes 0x0008 - 0x67FF	| File/Folder metadata
-----------------------------------------------------------------------

The format for each 268-byte metadata entry for files/folders is as follows:

-----------------------------------------------------------------------
Bytes 0x0000 - 0x00FF	| Name (ASCII or some other encoding for kana)
Bytes 0x0100 - 0x0107	| Some kinda hash or checksum
Bytes 0x0108 - 0x010B	| Entry Type
-----------------------------------------------------------------------

The name of the file/folder should be null-terminated, otherwise the Play-Yan will consider the entry invalid.

The Entry Type describes what kind of item was found within the filesystem. If Bit 0 is set, the Play-Yan will register the item as a Video File. If Bit 1 is set, the Play-Yan will register the item as a Music File. If neither Bit 0 nor Bit 1 is set, the Play-Yan will register the item as a Folder. This behavior is only applicable when reading Music Files, however. When reading Video Files, all videos present on the SD card are returned and folders are ignored. That is to say, the Get Filesystem Information automatically acts recursively for Video Files. When used for Music Files, it acts exclusively on the current directory.

The second parameter determines what types of files will be returned. If this parameter is set to 0x01, the Play-Yan will only return Video Files when reading entries from SD Card Data. If this parameter is set to 0x02, the Play-Yan will only return Music Files when reading entries from SD Card Data.

-----------------------------------------------------------------------
Command 0x201 - Change Current Directory - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000201
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

Changes the current directory the Play-Yan will look for new files and folders. The folder to change into must be passed as a null-terminated string for Parameter 1. The Play-Yan is capable of traversing up and down directories through this mechanism. The Play-Yan software is programmed to automatically search through various folders and sub-folders in order to map out existing music or video files. If the string in Parameter 1 is just "..", the Play-Yan will move upwards by one folder, allowing it to backtrack through previous directories.

-----------------------------------------------------------------------
Command 0x500 - Grab Video Thumbnail Data - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000500
Bytes 0x04 - 0x07	| Unknown
Bytes 0x08 - 0x0B	| Unknown
Bytes 0x0C - 0x0F	| Video Length in Milliseconds
-----------------------------------------------------------------------

After the 0x500 command is issued, a corresponding Game Pak IRQ signals that the Play-Yan is ready to provide a 60x40 thumbnail image for a video file. For the specifics regarding reading these thumbnails, refer to the appropiate section below.

The Video Length in Milliseconds is the overall total playtime for a specific video. This data is passed from the Play-Yan to its software when accessing a video's thumbnail. Unlike music, videos do not constantly update the position of the trackbar via Game Pak IRQs while playing. Instead, the Play-Yan's software handles that when the timestamp is updated. It will use the value specified here in conjunction with the Current Video Position (see the 0x700 command) to calculate how far along the video has progressed.

-----------------------------------------------------------------------
Command 0x600 - Grab ID3 Data - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000600
Bytes 0x04 - 0x07	| Unknown (must be non-zero to grab data)
-----------------------------------------------------------------------

This command instructs the Play-Yan to grab ID3 data for a given song. It always precedes the 0x800 command when playing music since the Play-Yan displays the ID3 information onscreen during this time. The exact purpose of Bytes 0x04 - 0x07 are unknown, however, this value must be non-zero to indicate that the ID3 data exists at all. After this command has executed, the necessary ID3 data can be read via the SD Card Data interface. The format of ID3 data is as follows:

-----------------------------------------------------------------------
Bytes 0x0000 - 0x0003	| Unused (zeroes)
Bytes 0x0004 - 0x0044	| Song Title
Bytes 0x0045 - 0x008B	| Artist Name
-----------------------------------------------------------------------

Each entry (for title and artist name) is a null-terminated string encoded as ASCII or some other encoding for kana.

-----------------------------------------------------------------------
Command 0x700 - Play Video/Grab Video Frame - 2 IRQs*
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000700
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
Bytes 0x04 - 0x07	| Video Length Counter
Bytes 0x08 - 0x0B	| Frame Size in Bytes
Bytes 0x18 - 0x1B	| Current Video Position
-----------------------------------------------------------------------

These interrupts are responsible for alerting the Play-Yan's software when a new video frame is ready for display, as well as the current position within a video as it is playing. The first IRQ initializes the process, while the second IRQ repeats indefinitely until the end of the video.

Each time the second IRQ is fired, the Current Video Position is updated. The Play-Yan software uses this to determine the minutes/seconds timestamp. Its value is expressed in milliseconds. This IRQ fires every time a video frame needs to be displayed, therefore it should match the video's framerate. Each increment of the Current Video Position should thus reflect that. E.g. for a video playing at 30 frames-per-second, the Current Video Position value increases by approximately 0x21 or 0x22.

The frame itself is read similarly to video thumbnails. Refers to the appropiate section below for more details. The size of the frame is the video's resolution (typically 240x160) in 15-bit color pixels. Therefore, this value is usually 0x12C00.

*The second IRQ constantly fires for the duration of the video for as many frames need to be updated each second.

-----------------------------------------------------------------------
Command 0x701 - Stop Video Playback - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000701
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

Stops the current video file that is playing.

-----------------------------------------------------------------------
Command 0x800 - Play Music File - 2 IRQs*
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000800
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
Bytes 0x0C - 0x0F	| Unknown
Bytes 0x10 - 0x13	| Unknown
Bytes 0x14 - 0x17	| Track Bar Position
Bytes 0x18 - 0x1B	| Play Time in Seconds 
-----------------------------------------------------------------------

After the 0x800 command is issued, a Game Pak IRQ is generated when the Play-Yan hardware begins processing an audio file. This command always follows the 0x600 command.

The Track Bar Position indicates how far along the visual slider has moved across the screen for the duration of the song. It seems to work on a scale of 0x0000 to 0x6400. To move the track bar accurately, this value should increment by (0x6400 / Song Length in Seconds) on average every second. When fast-forwarding or rewinding, this value changes accordingly.

The Play Time in Seconds represents the amount of time elapsed while playing the current song. Unlike the Current Video Position for the Play Video command, here the number of seconds passed is directly returned. That is to say, a value of 0x1E represents a time of 00:00:30 (30 seconds), value of 0x3C represents a time of 00:01:00 (1 minute, e.g. 60 seconds), and a value of 0xFF represents a time of 00:04:16 (4 minutes, 16 seconds, e.g. 256 seconds). Again, fast-forwarding or rewinding will change the result returned by the Play-Yan.

*The second IRQ constantly fires for the duration of the music.

-----------------------------------------------------------------------
Command 0x801 - Stop Music Playback - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000801
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

Stops the current music file that is playing.

-----------------------------------------------------------------------
Command 0x2000 - Play Sound Effect - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

Only 1 IRQ is fired for this command. It appears to force the Play-Yan to generate a brief sound effect, typically used for menus or when playing Garage Games. The sound effect (something like a chirp) is the same in all instances. It is necessary for the Play-Yan itself to generate the sound effects rather than the GBA because the Play-Yan may need to push samples through the built-in headphone. The Play-Yan is responsible for generating all sound (music, video, and sound effects), and it decides whether or not to use the headphone jack or the GBA's speakers as output.

-----------------------------------------------------------------------
Command 0x3000 - Check For Key File - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40003000
Bytes 0x04 - 0x07	| Key File Exists Flag
-----------------------------------------------------------------------

This command prompts the Play-Yan Micro to check the root directory of the SD card for the presence of a key file. The file should be named "play_yanmicro.ini". If this file exists, it proceeds to open it and try and parse the contents of the text file. If it can't find the file, it will boot up anyway and resort to using default settings. The second 32-bit value returned by this IRQ indicates whether the file was found. A value of zero indicates the file is available, while any non-zero value indicates a problem.

-----------------------------------------------------------------------
Command 0x3001 - Read Key File Data - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40003001
Bytes 0x04 - 0x07	| Key File Is Open Flag
Bytes 0x08 - 0x0B	| Key File Size
-----------------------------------------------------------------------

This command opens and reads the contents of the key file on the Play-Yan Micro. After executing this command, the key file can be read back as SD Card data. The second return value for this IRQ is a flag detailing the file's status. A value of zero indicates it was successfully opened, while any non-zero values indicates a problem. The third return value is the size of the key file in bytes. If the key file cannot be opened during this stage, the Play-Yan Micro will use default settings. After reading the key file, the Play-Yan Micro will parse and validate the results. If there is an issue here, the software will still boot up with default settings, however, it will display an icon representing a bad key file.

-----------------------------------------------------------------------
Command 0x3003 - Close Key File - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40003003
-----------------------------------------------------------------------

This command presumably closes the key file. The Play Yan Micro only executes this command if the key file was previously opened.

-----------------------------------------------------------------------
Command 0x8000 - Get Cartridge Status - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40008000
Bytes 0x04 - 0x07	| SD Card Status
-----------------------------------------------------------------------

A single value is returned for the overall status of the Play-Yan cartridge. This can be used to determine if an appropiate SD card has been inserted or if there are any problems. As the SD card is essential for the Play-Yan, this is the first command executed when booting. Setting the following bits indicates specific errors, and the Play-Yan will halt booting up and display an appropiate message:

-----------------------------------------------------------------------
Bit 0	| The cartridge is in bad condition
Bit 1	| No SD card detected or incompatible card inserted
Bit 2	| Filesystem error
-----------------------------------------------------------------------

Setting Bits 0 and 1 together produces the same "cartridge is in bad condition error". Setting Bits 0 and 2 together produces a general error. If no bits are set, this indicates there were no problems.

-----------------------------------------------------------------------
Command 0x10000 - Sleep - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80010001
-----------------------------------------------------------------------

This command is called right before the Play-Yan forces the GBA hardware into low-power STOP mode via a software interrupt. After the 0x10000 command, the Play-Yan itself will evidently enter into some kind of low-power state as well. It seems to wake up automatically when the GBA exits STOP mode. At that time, the Play-Yan will generate a Game Pak IRQ to indicate that the hardware is awake and ready to use.

-----------------------------------------------------------------------
Command 0x800000 - Unknown - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40800000
Bytes 0x04 - 0x07	| SD Card Status
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

This command is issued shortly after Get SD Card Status. It's purpose is currently unknown. It generates 1 IRQ, which also returns the card's status.

For each Game Pak IRQ, the first 4 bytes acts as a sort of 32-bit "ID" for the command used. This helps the Play-Yan software figure out what exactly triggered the IRQ in the first place. Typically, this ID is simply the command itself OR'ed with 0x40000000 or 0x80000000, although some exceptions such as the Sleep command do exist. When the ID has been OR'ed with 0x40000000, this means the Play-Yan is directly responding to a command issued by the software and generating an appropiate Game Pak IRQ. IDs OR'ed with 0x80000000, on the other hand, represent Game Pak IRQs generated by the Play-Yan on its own. Again, this is generally used to signal the end of certain internal operations. In such cases, the software explicitly waits and treats the Play-Yan hardware as busy with a given task.

During boot, however, after the software has uploaded a copy of firmware from ROM to the Play-Yan, the Play-Yan will generate an initial Game Pak IRQ, unprompted by any command. This alerts software that the Play-Yan hardware is finally ready and can now accept commands. The response data for this IRQ is 0x80000100. The software will pause indefinitely until it receives this IRQ.

[Play-Yan] : Reading Video Frames and Video Thumbnails

Use the following process to read thumbnail data after issuing the 0x500 command:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = 0x0000
PY_DATA_ADDR = 0x0000
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
READ DATA FROM 0xB000500 THROUGH 0xB0006FF
-----------------------------------------------------------------------

Data can be read sequentially in 512-byte blocks without the need for writing to other registers. Simply waiting for Bit 4 of PY_FIRM_STAT is sufficient. Each frame or thumbnail will be the size as specified by the 0x500 or the 0x700 command, which ordinarily is 60x40 and 240x160, respectively. Both use 15-bit pixels, and their format is an exact match for the Game Boy Advance's bitmap mode (BG Mode 3). In total, the Play-Yan will typically provide 0x12C0 bytes of data for each thumbnail and 0x12C00 for each video frame.

A 0x500 command must be issued for each thumbnail the Play-Yan needs to process. Each page in the Play-Yan's file browser can only contain 6 videos, therefore, the Play-Yan's software only issues 6 of these commands at a time. If a page has less than 6 entries, only that many 0x500 commands need to be sent. It seems a 0x2000 command is always issued before the first 0x500 command; this may be the mechanism that tells the Play-Yan which videos need thumbnails generated.

For video frames, the 0x700 command is only issued once. Subsequent Game Pak IRQs are automatically generated by the video processing hardware for each frame, at which point the Play-Yan can read back this data and display them using BG Mode 3 for fullscreen bitmap display.

[Play-Yan] : Garage Games

The original Play-Yan allowed users to access 13 minigames called "Garage Games". After the Play-Yan launched, Nintendo released them on their website in a weekly fashion. Users downloaded a special .ASF file, and when stored on an SD card, the Play-Yan would start the game. The entire game took place in the 60x40 window dedicated to video thumbnails. Contrary to most available information, these Garage Games are technically not "DLC". Each Garage Game already exists in the Play-Yan ROM and the .ASF files contain no executable code. However, the Garage Games are normally inaccessible without the .ASF files present. The files Nintendo provided act as a sort of key that unlocks the content.

Each .ASF file is a valid video and will generate a thumbnail preview on the Play-Yan. This thumbnail acts as a fingerprint that the Play-Yan can use to identify an individual file. The 0x12C0 bytes of thumbnail data is quickly hashed into a 32-bit number and compared against a list of expected values. Should the thumbnail's hash match that internal list, the Play-Yan recognizes it as a Garage Game.

It should also be noted that the video file's name has to match as well. If the file name is incorrect, the Play-Yan won't bother creating a hash and will simply treat it as a regular video file. This behavior can be reproduced by renaming any of the .ASF files from Nintendo. The names of each Garage Game is case-sensitive as well; they all need to be uppercase in order to work. A list of all the Garage Games and their 32-bit hashes is provided below:

AVOID		0xF8CB9008
BAT		0xD911FE57
CREDIT		0x02F86041
FIRE		0x0D78A9FE
FISH		0x5741DE47
INSECT		0x4D5E5AEB
JUMP		0x748C5BAF
KEEPER		0x3FEBEFE5
MEMORY		0x90119AE6
NEKOROID	0xD839D809
NOSE		0x86D3BA78
TRIPLE		0xD5C0A40B
WAVE		0xE7DCD82B

The hash can be calculated using the following psuedo-code:

-----------------------------------------------------------------------
HASH = 0
INDEX = 0

WHILE INDEX NOT EQUAL TO 0x960
	HASH = HASH + 16-BIT THUMBNAIL PIXEL DATA
	HASH = HASH ROTATE RIGHT 31
	INCREMENT INDEX BY 1
-----------------------------------------------------------------------

Although this hashing prevents most ordinary videos from randomly generating a thumbnail that triggers the Garage Game to play, the hashing method is prone to collisions. It is possible, therefore, to specifically create a thumbnail that matches any of the above listed hashes, in effect creating "bootleg" Garage Games.

[Play-Yan] : Key File

The key file is a simple text file the Play-Yan Micro reads on when starting up. The file name must be "play_yanmicro.ini" and must be stored in the SD card's root directory. The Play-Yan Micro uses this to change various settings automatically for the user. Note that the key file is exclusive to the Play-Yan Micro and is not used at all for the original Play-Yan. Below is the default key file provided by Nintendo, along with an explanation of the entries and their values:

-----------------------------------------------------------------------
PLAY_YAN_Design=1
PLAY_YAN_StartMode=1
PLAY_YAN_VolumeAdd=0
PLAY_YAN_AudioPlayMode=0
PLAY_YAN_AudioBass=0
PLAY_YAN_AudioWide=0
PLAY_YAN_VideoPlayMode=0
PLAY_YAN_VideoBright=0
-----------------------------------------------------------------------

PLAY_YAN_Design: Changes the user-interface theme between Pictogram and Mario (values 0 and 1 respectively).

PLAY_YAN_StartMode: Determines whether Videos or Music will be the default selected option on the main menu after booting (values 0 and 1 respectively).

PLAY_YAN_VolumeAdd: Determines the initial level of volume for all media. Uses values -18 to 9 for mute volume to just below the max (does not use the 10 highest levels of volume).

PLAY_YAN_AudioPlayMode: Determines how songs are played, such as loop through all songs, loop over a single song continuously, loop over songs randomly, or play all songs in order once (values 0 through 3 respectively).

PLAY_YAN_AudioBass: Determines whether the bass is left at default levels or amplified (values 0 and 1 respectively).

PLAY_YAN_AudioWide: Determines the level of stereo sound amplification (values 0 through 6).

PLAY_YAN_VideoPlayMode: Determines how videos are played, such as play a single video once, loop over a single video continously, play all videos once, or loop over all videos (values 0 through 3 respectively).

PLAY_YAN_VideoBright: Determines the level of brightness adjustment for video playback (values 0 through 5).

Glucoboy

General Hardware Information

Accessing Glucose Data

Index Overview

[Glucoboy] : General Hardware Information

The Glucoboy is a cartridge for the Game Boy Advance that featured the unique ability to process diabetic testing strips. Released on November 14, 2007 exclusively in Australia, it was designed by inventor Paul Wessel and produced by Guidance Interactive. The goal was to encourage children with juvenile diabetes to regularly check their blood sugar and to keep their levels in check. The Glucoboy would record the player's glucose and award points based on how well it fit within a healthy range. These Glucose Reward Points (GRPs) were used to unlock new minigames and in-game items. It was the first time such a medical was officially licensed for sale on any of Nintendo's platforms.

[Glucoboy] : Accessing Glucose Data

For the most part, the GBA does not directly deal with any of the glucose checking or blood testing. Instead, other components within the Glucoboy handle that and merely present the results, which the GBA can read back like any other value in memory. To that end, the Glucoboy offers a single, multipurpose 1-byte register mapped to the address 0xE000000. Internally, the Glucoboy's ROM refers to this as the "MAGIC PORT". In this document, it is more aptly renamed as GLUCO_CNT. By reading and writing to GLUCO_CNT, data can be extracted regarding the current GRPs earned from testing. Other miscellaneous hardware info about the Glucoboy can also be retrieved.

To access data on the Glucoboy, an index must first be written to GLUCO_CNT. Different data — such as normal GRPs earned today or bonus GRPs earned that day — are stored at different indices. Once an index is set, the Glucoboy triggers a Game Pak IRQ. Following this, 1-byte, 4-bytes, or 6-bytes must be read from/written to GLUCO_CNT, depending on the index. For example, in the case that an index returns 4-bytes of data, GLUCO_CNT must be read a total of 4 times, once per byte. All data is read/written MSB-first, therefore, software must also manually adjust LSB-first values on the GBA. Additional Game Pak IRQs indicate when the next byte is ready to read/write. Evidently, Game Pak IRQs are generated after a brief delay when accessing GLUCO_CNT.

Below is the typical proceedure used by the Glucoboy's software:

-----------------------------------------------------------
6-byte Index Access
-----------------------------------------------------------
WRITE INDEX TO GLUCO_CNT
	WAIT FOR GAMEPAK IRQ

READ OR WRITE BYTE 5 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 4 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 3 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 2 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 1 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 0 AT GLUCO_CNT
-----------------------------------------------------------


-----------------------------------------------------------
4-byte Index Access
-----------------------------------------------------------
WRITE INDEX TO GLUCO_CNT
	WAIT FOR GAMEPAK IRQ

READ OR WRITE BYTE 3 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 2 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 1 AT GLUCO_CNT
	WAIT FOR GAMEPAK IRQ
READ OR WRITE BYTE 0 AT GLUCO_CNT
-----------------------------------------------------------


-----------------------------------------------------------
1-byte Index
-----------------------------------------------------------
WRITE INDEX TO GLUCO_CNT
	WAIT FOR GAMEPAK IRQ

READ OR WRITE BYTE 0 AT GLUCO_CNT
-----------------------------------------------------------

[Glucoboy] : Index Overview

Below is a brief list of all known indices and their currently understood functions:

-----------------------------------------------------------
Index	| Size 	| Description
-----------------------------------------------------------
0x20	| 4	| Read System Date
0x21	| 4	| Read Daily GRPs Earned
0x22	| 4	| Read Bonus GRPs Earned
0x23	| 4	| Read Current Number of Good Days
0x24	| 4	| Read Number of Good Days Until Bonus Rewarded
0x25	| 4	| Read Hardware Flags
0x26	| 4	| Read LD Threshold
0x27	| 4	| Read Serial Number
0x31	| 1	| Read Unknown Flag
0x32	| 1	| Read Unknown Flag
0x60	| 4	| Write System Date
0x61	| 4	| Write Daily GRPs Earned
0x62	| 4	| Write Bonus GRPs Earned
0x63	| 4	| Write Current Number of Good Days
0x64	| 4	| Write Number of Good Days Until Bonus Rewarded
0x65	| 4	| Write Hardware Flags
0x66	| 4	| Write LD Threshold
0x67	| 4	| Write Serial Number
0xE0	| 1	| Read Unknown Flag
0xE1	| 1/6*	| Write Game Stats (*Write 6 bytes, Read 1 byte)
0xE2	| 1	| Read Unknown Flag
-----------------------------------------------------------

A number of these indices do not appear to be used except for debugging. During normal operation, data for the System Date, Hardware Flags, LD Threshold, and Device Serial Number are read but ultimately unused. A hidden test menu inside the Glucoboy ROM can read and write to all of them, however. While these indices provide useful information about the Glucoboy, they are technically not required for the games, which focus on GRPs.

The size of each index indicates how many bytes are read or written when accessing them. A more detailed explanation of known indices follows:

Index 0x20 - Read System Date

This index returns the current system date according to the Glucoboy's RTC. The clock is used internally to decide if glucose testing has been performed on a consistent schedule in order to give out GRPs. The Glucoboy software does not take advantage of this outside of debugging. 4 bytes are returned representing a date. The complete 32-bit value uses these fields for time:

-----------------------------------------------------------
Bits	| Description
-----------------------------------------------------------
0  - 5	| Minutes (0 - 59)	
6  - 11	| Hours (0 - 23)
12 - 16	| Days (1 - 31)
20 - 23	| Months (1 - 12)
24 - 30	| Years (2001 - 2100)
-----------------------------------------------------------

Days and Months always start counting at 1. That is to say, a binary value of 0 will translate to 1, so the maximum value for each category should be 11 and 30 respectively.

Years starts counting at 2100. That is to say, a binary value of 0 will translate to the year 2100. A binary value of 1 will translate to the year 2001, and so on. Essentially, this value can be added to 2000 to get the current date, with 0 being a special case.

Index 0x21 - Read Daily GRPs Earned

This represents the amount of GRPs earned on any specific day. It is added to the Total GRPs earned. This value is checked each and every time the Glucoboy boots up, so a constant value of 10, for example, would continually add 10 GRPs every time the game is loaded. In practice, this value was updated after a blood test was performed. The exact amount would be determined by factors such as whether the levels were healthy and whether the test was done in accordance to a regular schedule. The GBA does not seem to have access to the components that calculated GRPs, so it only reads whatever the hardware reports.

The 4 bytes returned by this index form an signed 32-bit integer. Only positive numbers are valid, so the maximum allowed value is therefore 2147483647.

Index 0x22 - Read Bonus GRPs Earned

This represents the amount of bonus GRPs earned by maintaining healthy glucose levels over a specific number of days. The Glucoboy would likely update this when the "Current Number of Good Days" value was greater than or equal to the "Number of Good Days Until Bonus Rewarded" value. These bonus GRPs are added to the Total GRPs once read. The exact amount of bonus GRPs granted as part of the Glucoboy's internal algorithms is not known.

The 4 bytes returned by this index form an signed 32-bit integer. Only positive numbers are valid, so the maximum allowed value is therefore 2147483647.

Index 0x23 - Read Current Number of Good Days

This index represents the number of continuous "good days", i.e. days were the player consistently checked their glucose levels and those same levels were within an acceptable range. Failing to meet those requirements would presumably reset the this value.

The 4 bytes returned by this index form an signed 32-bit integer. Only positive numbers are valid, so the maximum allowed value is therefore 2147483647.

Index 0x24 - Read Number of Good Days Until Bonus Rewarded

This index represents the number of remaining "good days" needed until the bonus GRPs would be granted. Logically, this value would decrease by one every 24-hours, so long as the players glucose levels were kept in check regularly. The exact amount of days until players can get bonus GRPs was part of the Glucoboy's internal algorithms and as such is not currently known.

The 4 bytes returned by this index form an signed 32-bit integer. Only positive numbers are valid, so the maximum allowed value is therefore 2147483647.

Index 0x25 - Read Hardware Flags

This index represents a set of hardware status flags for the Glucoboy. Only 7-bits of the 32-bit index value is used as such:

-----------------------------------------------------------
Bit	| Description
-----------------------------------------------------------
0	| GMEM FAULT
1	| PMEM FAULT
2 	| INCENTIVE
3	| PNEW STATS
4	| MEASUREMENT
5	| GMETER FAULT
6	| PMETER FAULT
-----------------------------------------------------------

The following descriptions are estimates of each bit's likely meaning. Keep in mind these are guesses for the time being.

"GMEM FAULT" and "PMEM FAULT" refer to errors in the memory allocated for blood testing result. The Glucoboy may separate memories for general glucose test result and postprandial glucose test results. If those areas of memory have issues, they would probably be reported here.

"INCENTIVE" refers to the Glucoboy's proprietary method of determining how it gave out GRPs. This was dicated by factors such as timeliness in testing, frequency in testing, and whether or not glucose levels were healthy. This flag probably indicates that the player had met these conditions.

"PNEW STATS" possibly refers to new data tracking postprandial glucose levels, conceivably an update to some kind of statistic used to measure the player's performance in relation to INCENTIVE.

"MEASUREMENT" possibly indicates a new glucose reading has been done.

"GMETER FAULT" and "PMETER FAULT" refer to failures with the actual glucose and postprandial meters.

Despite "GMEM/GMETER FAULT" and "PMEM/PMETER FAULT" being potentially serious hardware issues, the Glucoboy software does not take any specific actions on them outside of debugging. For example, the player is not warned if any of these components stops working, although, it may affect retrieving GRPs, which does display an error message.

Index 0x26 - Read LD Threshold

This index holds the value of the "LD Threshold", which possibly refers to a "Low-Data Threshold". This would represent the minimum number of samples from glucose testing needed to get an accurate test.

The 4 bytes returned by this index form an unsigned 27-bit integer. It is used to represent values ranging from 00000000 - 99999999.

Index 0x27 - Read Serial Number

This index holds the value of some kind of serial number for the Glucoboy. It is currently unknown if this would have been a per-device serial number or something broader to distinguish versions and revisions.

The 4 bytes returned by this index form an unsigned 27-bit integer. It is used to represent values ranging from 00000000 - 99999999.

Index 0x31 - Read Unknown Flag

The exact purpose of this index is unknown, however, it seems to act as a flag. Reading any non-zero value causes the Glucoboy to register an error when retrieving GRPs.

Index 0x32 - Read Unknown Flag

The exact purpose of this index is unknown, however, it seems to act as a flag. Reading any non-zero value causes the Glucoboy to register an error when retrieving GRPs.

Index 0x60 - Write System Date

This index is used to set the current system date for the Glucoboy's built-in RTC. This index only appears in the debugging menu. It receives 4 bytes representing a date. See Index 0x20 above for the format.

Index 0x61 - Write Daily GRPs Earned

This index sets the amount of GRPs earned on any specific day. It receives 4 bytes representing a signed 32-bit integer. This index is not used by the Glucoboy ROM except for debugging, as setting Daily GRPs is a task left for other components of the Glucoboy's hardware during blood testing.

Index 0x62 - Write Bonus GRPs Earned

This index sets the amount of bonus GRPs earned by maintaining healthy glucose levels over a specific number of days. It receives 4 bytes representing a signed 32-bit integer. This index is not used by the Glucoboy ROM except for debugging, as setting Bonus GRPs is a task left for other components of the Glucoboy's hardware during blood testing.

Index 0x63 - Write Current Number of Good Days

This index sets the number of continuous "good days", i.e. days were the player consistently checked their glucose levels and those same levels were within an acceptable range. It receives 4 bytes representing a signed 32-bit integer. This index is not used by the Glucoboy ROM except for debugging, as setting number of "good days" is a task left for other components of the Glucoboy's hardware during blood testing.

Index 0x64 - Write Number of Good Days Until Bonus Rewarded

This index sets the number of remaining "good days" needed until the bonus GRPs would be granted. It receives 4 bytes representing a signed 32-bit integer. This index is not used by the Glucoboy ROM except for debugging, as setting number of "good days" needed to unlock a bonus is a task left for other components of the Glucoboy's hardware during blood testing.

Index 0x65 - Write Hardware Flags

This index sets the hardware status flags for the Glucoboy. It receives a 32-bit integer, but only the first 7-bits actually represent the flags. This index is only See Index 0x25 above for the format.

Index 0x66 - Write LD Threshold

This index sets the value of the "LD Threshold". It only appears in the debugging menu. The index receives 4 bytes that form an unsigned 27-bit integer, which must have valid values of 00000000 - 99999999.

Index 0x67 - Write Serial Number

This index sets the value of some kind of serial number for the Glucoboy. It only appears in the debugging menu. The index receives 4 bytes that form an unsigned 27-bit integer, which must have valid values of 00000000 - 99999999.

Index 0xE0 - Read Unknown Flag

The exact purpose of this index is unknown, however, it seems to act as a flag. Reading any non-zero value causes the Glucoboy to register an error when retrieving GRPs.

Index 0xE1 - Write Game Stats

Index 0xE2 - Read Unknown Flag

The exact purpose of this index is unknown, however, it seems to act as a flag. Reading any non-zero value causes the Glucoboy to register an error when retrieving GRPs.

Campho Advance

General Hardware Information

I/O Registers

ROM Data Sections

Data Format

Commands

Bootstrap ROM

Program ROM

Graphics ROM

Camera Capture

Configuration and Contact Data

Telephony

Modem Test Mode

System Compatibility

[Campho Advance] : General Hardware Information

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.

[Campho Advance] : 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.

[Campho Advance] : 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.

[Campho Advance] : Data Format

Due to the way the Campho Advance was made (possibly as a result of some flaw in the way it handles addressing) 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 13) OR (INPUT_16 LSR 3))

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

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.

[Campho Advance] : 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.

[Campho Advance] : 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.

[Campho Advance] : 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.

[Campho Advance] : 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.

[Campho Advance] : 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

//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 + INDEX] = DATA_VAL

	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.

[Campho Advance] : 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.

[Campho Advance] : 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		| Internal Phone Function
0x03		| 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.

[Campho Advance] : 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.

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.

As a somewhat unrelated side note, for whatever reason, pressing L and R (and ignoring the B button) 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 User Test Mode with a rotated screen. Curiously, the controls flip accordingly as well, so pressing Up on the D-Pad acts as it should when manipulating menus. This screen rotation seems deliberate and intentional, but its purpose is currently unknown. The Campho Advance's manual makes no mention of this at all.

[Campho Advance] : 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. Whether due to the unique power requirements of the cartridge or the novel way it streams ROM data, the cause of this failure remains unknown. Nevertheless, the likely culprit is the way in which DS firmware tries to read Slot-2 when turning on the system, which differs significantly from the GBA BIOS.

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.

Ubisoft Thrustmaster Pedometer

General Hardware Information

Device Detection

Reading Steps

[Ubisoft Thrustmaster Pedometer] : General Hardware Information

The Ubisoft Thrustmaster Pedometer is a Slot-2 NDS device that came bundled with My Weight Loss Coach / My Health Coach: Manage Your Weight. It simply counts the user's steps and transfers that number to the software.

[Ubisoft Thrustmaster Pedometer] : Device Detection

The software will read some values from the GBA cart space between 0x8000000 and 0x801FFFF. Those values are somewhat difficult to accurately and consistently map out byte-by-byte; one explanation is that open bus behavior may affect reading. However, the following psuedo-code will allow the software to properly detect the presence of the pedometer:

//Read individual bytes from GBA cart space
if address AND 1
	return 0xF7
else
	return 0xF0 OR ((address AND 0x1F) SHIFT RIGHT 1)

[Ubisoft Thrustmaster Pedometer] : Reading Steps

Steps are stored in the area where the DS would normally access SRAM/FRAM/Flash in GBA carts. 5 bytes are used, one for each displayable digit:

0xA000000	Ones
0xA000001	Tens
0xA000002	Hundreds
0xA000003	Thousands
0xA000004	Ten Thousands

The values range from 0xF0 to 0xF9, with only the lower half of the byte being relevant. The maximum number of steps the pedometer can track is 99999. To properly access each value, the memory location should be read at least 4 times with a brief delay in between, such as one frame (~16ms). If the delays are not used, the pedometer returns 0xF0. These locations appear to be read-only, so software cannot manually set the pedometer's step count.

However, if the memory location 0xA00000C is read, the pedometer resets the step count. The supported software does this whenever it records data from the pedometer.

HCV-1000

General Hardware Information

Compatible Games

Device Detection

I/O Registers

Operation

Barcodes

[HCV-1000] : General Hardware Information

The HCV-1000 is a Slot-2 NDS device designed to read barcodes from cards. Produced by Sega and released in 2006, it came bundled with Oshare Majo Love and Berry: DS Collection, Kouchuu Ouja Mushiking Super Collection, Card de Asobu! Hajimete no DS. By scanning various cards, certain items/characters were unlocked in each of the games.

[HCV-1000] : Compatible Games

Card de Asobu! is the only title that absolutely requires the HCV-1000 to play. Without the device, the game will not reach the main screen and will stall with an error message/animation. The other two games are still playable without the HCV-1000 and without the bonuses it provides, thereby limiting some aspects of gameplay.

[HCV-1000] : Device Detection

The software will read some values from the GBA cart space between 0x8000000 and 0x801FFFF. The following psuedo-code will allow software to properly detect the presence of the HCV-1000:

//Read individual bytes from GBA cart space
if address AND 1
	return 0xFD
else
	return 0xF0 OR ((address AND 0x1F) SHIFT RIGHT 1)

[HCV-1000] : I/O Registers

-------------------------------------
HCV_CNT (R/W)	0xA000000
-------------------------------------
Bit 0		(R) Camera status, 1 = On, 0 = Off		(W) Turn camera on = 1, Turn camera off = 0 		
Bit 1		(R) Current barcode strip, 1 = Gap, 0 = Bar	(W) ???
Bit 2		N/A
Bit 3		N/A
Bit 4		(R) Barcode processing flag			(W) 0 = Clear flag
Bit 5		(R) Barcode orientation flag			(W) 0 = Clear flag
Bit 6		(R) Scan error flag				(W) 0 = Clear flag
Bit 7		(R) Scanning status, 1 = In progess, 0 = Done	(W) Start scanning = 1, Stop scanning = 0
-------------------------------------

Camera Status: When scanning cards, this must be set high. Doing this turns on the red light and the camera. If needed, this bit can be read to determine whether the camera is on or off.

Current Barcode Strip: A "1" indicates a gap, while a "0" indicates a bar. Although this data is exposed to software, reading Bit 1 is not necessary to obtain barcode data. The HCV-1000 automatically outputs that information to HCV_DATA. It's possible to write to this bit, but its affect is unknown.

Barcode Processing Flag: This flag is set to "1" whenever the HCV-1000 begins processing barcode data for HCV_DATA. It is not set to "0" when all of the data is finished. Reading Bit 7 should be used to determine if scanning is complete.

Barcode Orientation Flag: Describes the format of the data in HCV_DATA. If this flag is "0" this means the barcode data is meant to be read in ascending order (0xA000010, 0xA000011, 0xA000012, etc). If this flag is "1", that means the barcode data is meant to be read in descending order (0xA00001F, 0xA00001E, 0xA00001D, etc).

Scan Error Flag: If this flag is "1", it indicates a problem occurred at some point while a card was scanned. Any bytes in HCV_DATA may be unreliable.

Scanning Status: It must be set high to start the scanning process. It will remain high until the HCV-1000 has finished processing the barcode. At that point, Bit 7 is automatically set low and the bytes in HCV_DATA will represent barcode data.

Bits 2 and 3 are not used. While all of the other bits are writable, Bits 4-6 may not be set high by NDS software. Writing "0" to those bits will set them low, however, in effect clearing them.

-------------------------------------
HCV_DATA (R)	0xA000010 - 0xA00001F
-------------------------------------
0xA000010
...
0xA00001F	1 byte of processed barcode data
-------------------------------------

16 bytes are set at this location for incoming barcode data in the form of an ASCII encoded string. Once Bit 0 and Bit 7 in HCV_CNT are both set high, the HCV-1000 continually attempts to grab any barcode data on its own and puts the results here.

All barcodes must be in Code39 with a maximum length of 16 characters. The ASCII string in HCV_DATA is the human-readable form of the barcode, e.g. *12345-ABCDEFG*. If a barcode has less than 16 characters, HCV_DATA appends the value 0x5F to the string for the rest of the length.

The barcode data may come in "reversed" depending on which direction the card was swiped, therefore Bit 5 of HCV_CNT can be referenced to read the bytes in the correct order. Alternatively, NDS software can simply read the bytes in any order and check for both barcodes. Whether or not the barcode data is reversed, any 0x5F values in HCV_DATA will always appear at the end (0xA00001F, 0xA00001E, 0xA00001D, ... for example).

[HCV-1000] : Operation

The NDS must use proper memory timings in order to correctly access the HCV-1000. Compatible games set EXMEMCNT to 0xE877. When using incorrect timings, the I/O registers become inaccessible (reading zero constantly).

While it is possible to continually read Bit 1 of HCV_CNT and measure the delays between each transition and manually calculate barcode values, the HCV-1000 provides built-in decoding. NDS software need only perform the following steps:

  1. Set HCV_CNT to 0x81 (turn on camera + start scanning).
  2. Read HCV_CNT and wait for the HCV-1000 to clear Bit 7 of that register.
  3. Check Bit 6 of HCV_CNT for errors and abort if any detected.
  4. Read 16 bytes from HCV_DATA.
  5. Set HCV_CNT to 0x00 (turn off camera + clear flags).
  6. Repeat as necessary.

[HCV-1000] : Barcodes

Below is a list of known and verified barcodes used in the games. Note that with the exception of Card de Asobu, this section is not yet complete.

---------------------------------------------------
Card de Asobu! Hajimete no DS
---------------------------------------------------
Barcode 	| Name
---------------------------------------------------
*AA01C0RD00V01*	| あひる
*AA02D0NC00V01*	| いぬ 
*AA0380GC00V01*	| うさぎ
*AA04F0T000V01*	| えんぴつ
*AA05A0RB00V01*	| おにぎり
*AA47CKRC00V01*	| かえる
*AA07DK0E00V01*	| ききゅう
*AA082KRC00V01*	| くじら
*AA099KSG00V01*	| けむし
*AA104KRC00V01*	| こあら
*AA110SRF00V01*	| さくら
*AA121SYE00V01*	| しょうばうしゃ
*AA132SKB00V01*	| すいか
*AA149SMG00V01*	| せみ
*AA15MSMB00V01*	| そらまめ
*AA16OTKA00V01*	| たいこ
*AA17DTPF00V01*	| ちゅーりっぷ
*AA18KTMD00V01*	| つばめ
*AA199TSG00V01*	| てんとうむし
*AA20GTRA00V01*	| とらいあんぐる
*AA21CNSB00V01*	| なす
*AA227NRD00V01*	| にわとり
*AA238NM000V01*	| めいぐるみ
*AA24RNKC00V01*	| ねこ
*AA25ANR000V01*	| のこぎり
*AA26OHTD00V01*	| はと
*AA277HRF00V01*	| ひまわり
*AA28KHNE00V01*	| ふね
*AA293HTE00V01*	| へりこぷたー
*AA30GHRG00V01*	| ほたる
*AA310MR000V01*	| まくら
*AA327MTG00V01*	| みつばち
*AA338MS000V01*	| むぎわらばうし
*AA34LMN000V01*	| めがね
*AA35YM0A00V01*	| もっきん
*AA366YGC00V01*	| やぎ
*AA378YRF00V01*	| ゆり
*AA38SYTE00V01*	| よっと
*AA390RPA00V01*	| らっぽ
*AA40PRGB00V01*	| りんご
*AA418RB000V01*	| るびー
*AA42XR0B00V01*	| れもん
*AA43SRTE00V01*	| ろけっと
*AA446WNC00V01*	| わに
*AA45SWW000V01*	| カードをさがす
*AA46Z00000V01*	| ん
---------------------------------------------------


---------------------------------------------------
Oshare Majo Love and Berry: DS Collection
---------------------------------------------------
Barcode 	| Name
---------------------------------------------------
*OUQV-9AU5JD*	| TD-01
*O3OH4749GJG*	| TD-02
*OUSGC3RO6KD*	| TF-01
*OUMQ9CDKT4D*	| TF-02
*OUSPY5Q69GD*	| TH-01
*OUMPDRQ69VD*	| TH-02
---------------------------------------------------

Magic Reader

General Hardware Information

Device Detection

I/O Registers

Two-Wire Interface: Reading

Two-Wire Interface: Writing

Control Flow

Card List and Index Values

[Magic Reader] : General Hardware Information

Beast Shinden: Ultimate Beast Battlers for the NDS used a special Slot-2 device called the "Magic Reader", which allowed players to scan collectible trading cards to battle opponents. Released in 2007 by Konami, the game makes heavy use of the scanning functionality, and the accessory is required for the software. While the card game itself is yet another monster fighting TCG, the scanning process itself was unique. Whereas all previous card reading devices on the DMG, GBC, GBA, and NDS involved swiping a card through a slot, the Magic Reader detects the card when hovered over its sensor.

[Magic Reader] : Device Detection

The software will read some values from the GBA cart space between 0x8000000 and 0x801FFFF. The following psuedo-code will allow software to properly detect the presence of the Magic Reader:

//Read individual bytes from GBA cart space
if address AND 1
	return 0xFB
else
	return 0xFF

[Magic Reader] : I/O Registers

-------------------------------------
MR_CNT 	(R/W)	0xA000000
-------------------------------------
Bit 0	(W) 	Serial Clock aka SCK 		
Bit 1	(R/W) 	Serial Data IO aka SDIO
Bit 2	(W) 	NDS Read (1) or Write (0) Flag
Bit 3	N/A
Bit 4	N/A
Bit 5	N/A
Bit 6	(W)	Power On Optical ID?	
Bit 7	N/A

SCK and SDIO are used for the so-called "two-wire interface" between the NDS and the Optical ID decoder. Using those two bits, the NDS communicates with the Magic Reader to send commands as well as retrieve image data. SCK must be pulsed from LOW to HIGH (0 to 1) by the NDS to start or continue receiving or sending data. The Magic Reader can signal to the NDS that it has data available to read by setting SDIO LOW, however.

Although the two-wire interface's protocol makes read and write operations explicitly different, MR_CNT appears to use Bit 2 to indicate the direction I/O direction. For reads, this bit is set HIGH, but for writes it is set LOW. Oddly enough, this is the inverse of SDIO when sending the Read/Write bit used for the two-wire interface.

Bit 6 appears to be set by the NDS before powering on the Optical ID decoder, effectively waking it from sleep mode. In that case, the Magic Reader should set SDIO low to indicate it has data for the NDS to read (the OIDCmd_PowerOn value).

It is important to note that when reading MR_CNT, all bits except for Bit 1 are always set HIGH. In effect, when reading MR_CNT, only two values are ever returned: 0xFB or 0xFF.

[Magic Reader] : Two-Wire Interface: Reading

The Magic Reader must set SDIO LOW to indicate to the NDS that data is available to read. This is often in response to a command sent by the NDS, or in some cases by setting Bit 6 of MR_CNT. Once the NDS recognizes that the Magic Reader is requesting a read, the following happens:

  1. NDS sets SCK and SDIO LOW and sets Bit 2 of MR_CNT HIGH for the duration of the transfer.
  2. NDS sets SCK HIGH and sets SDIO LOW to indicate a read operation for the two-wire interface.
  3. NDS sets SCK and SDIO LOW to begin data transmission.
  4. NDS sets SCK and SDIO HIGH, then reads MR_CNT. The SDIO bit indicates incoming data from the Magic Reader arriving MSB first.
  5. NDS sets SCK LOW and SDIO HIGH. Steps 5-6 are done a total of 23 times to receive a 23-bit value from the Magic Reader.
  6. NDS sets SCK LOW and SDIO HIGH and sets Bit 2 of MR_CNT LOW to indicate that the transfer is complete.

Below is an example of how the NDS would read data from the Magic Reader:

-------------------------------------
INIT TRANSFER
-------------------------------------
READ  -> 0xFB	//SDIO = LOW, Magic Reader has data to send
WRITE -> 0x04	//SCK = LOW, SDIO = LOW, Bit 2 set HIGH for duration of transfer
WRITE -> 0x05	//SCK = HIGH, SDIO = LOW, sets R/W bit
WRITE -> 0x04	//SCK = LOW, SDIO = LOW, transfer data now
-------------------------------------
TRANSFER DATA
-------------------------------------
WRITE -> 0x07	//SCK = HIGH, SDIO = HIGH, data is available now
READ  -> xxxx	//SDIO = Bit 22
WRITE -> 0x06	//SCK = LOW, SDIO = HIGH

WRITE -> 0x07	//SCK = HIGH, SDIO = HIGH, data is available now
READ  -> xxxx	//SDIO = Bit 21
WRITE -> 0x06	//SCK = LOW, SDIO = HIGH

...

WRITE -> 0x07	//SCK = HIGH, SDIO = HIGH, data is available now
READ  -> xxxx	//SDIO = Bit 1
WRITE -> 0x06	//SCK = LOW, SDIO = HIGH

WRITE -> 0x07	//SCK = HIGH, SDIO = HIGH, data is available now
READ  -> xxxx	//SDIO = Bit 0
WRITE -> 0x06	//SCK = LOW, SDIO = HIGH
-------------------------------------
END TRANSFER
-------------------------------------
Write -> 0x02	//SCK = LOW, SDIO = HIGH, end communications
-------------------------------------

The data for each bit is available after clocking SCK HIGH. The value of SDIO is valid until SCK is set HIGH again. Even after setting SCK LOW, MR_CNT can still be read and SDIO will reflect the serial 23-bit data. Juushinden, the only official software that uses the Magic Reader, reads MR_CNT after setting SCK LOW, for example.

Switching SCK from LOW to HIGH has several timing conditions. SCK should be set LOW for a minimum of 2μs during the transfer and should ideally not exceed 64μs. Going further than 64μs stops the transfer. SCK should be set HIGH for a minimum of 2μs. The 23-bit data format is described below:

-------------------------------------
Magic Reader Data
-------------------------------------
Bit 0  - Bit 17		Optical ID Index
Bit 18 - Bit 19		Reserved (Always 0)
Bit 20			Battery Status
Bit 21			Data Type (Command/Index)
Bit 22			Reserved (Always 1)
-------------------------------------

Bits 0 through 17 represent the Optical ID Index. The SN9P701FG-005 automatically takes image data from the SN9S102C and converts it into a binary number. The image data is similar to e-Reader dot-code or QR codes, so they can be reduced to a single value. Different models of the SN9P701-00X support different amounts of indices. The SN9P701FG-005 supports a total of 65536 indices with a range of 0x0000 to 0xFFFF. There are extra indices up to 0x3FFEF reserved for future use. Indices above 0x3FFEF have special usages:

-------------------------------------
Extended Index Usage
-------------------------------------
0x3FFF0 - 0x3FFFA	Reserved for internal use
0x3FFFB			Null response when no usable data is returned to NDS
0x3FFFC - 0x3FFFF	Captured image not recognized
-------------------------------------

The battery status is a single bit that describes whether the SN9P701 has a high or low battery (1 or 0, respectively).

The data type describes what the NDS is receiving. If Bit 21 is set LOW, then the Magic Reader is returning a regular index after having processed an image. If Bit 21 is set HIGH, the Magic Reader is responding to a command with pre-set data:

-------------------------------------
Command Responses
-------------------------------------
0x60FFF8	OIDCmd_PowerOn
0x60FFF7	OIDCmd_PowerDown
0x60FFF1	OIDCmd_SystemReset
-------------------------------------

[Magic Reader] : Two-Wire Interface: Writing

The NDS can transfer a command to the Magic Reader like such:

  1. NDS sets SCK and SDIO LOW and sets Bit 2 of MR_CNT LOW for the duration of the transfer.
  2. NDS sets SCK and SDIO HIGH to indicate a write operation for the two-wire interface.
  3. NDS sets SCK LOW and sets SDIO HIGH to begin data transmission.
  4. NDS sets SCK HIGH and sets SDIO accordindly to trasmit 1 bit of the command MSB first.
  5. NDS sets SCK LOW and maintains the same SDIO level from Step 4. Steps 4-5 are done a total of 8 times to send an 8-bit command to the Magic Reader.
  6. NDS sets SCK LOW and SDIO HIGH and sets Bit 2 of MR_CNT LOW to indicate that the transfer is complete.

Below is an example of how the NDS would send the 0xA3 command:

-------------------------------------
INIT TRANSFER
-------------------------------------
Write -> 0x00	//SCK = LOW, SDIO = LOW, signals start of operation
Write -> 0x03	//SCK = HIGH, SDIO = HIGH, sets R/W bit 
Write -> 0x02	//SCK = LOW, SDIO = HIGH, transfer data now
-------------------------------------
TRANSFER DATA
-------------------------------------
Write -> 0x03	//SCK = HIGH, SDIO = Bit 7 (1)
Write -> 0x02	//SCK = LOW

Write -> 0x01	//SCK = HIGH, SDIO = Bit 6 (0)
Write -> 0x00	//SCK = LOW

Write -> 0x03	//SCK = HIGH, SDIO = Bit 5 (1)
Write -> 0x02	//SCK = LOW

Write -> 0x01	//SCK = HIGH, SDIO = Bit 4 (0)
Write -> 0x00	//SCK = LOW

Write -> 0x01	//SCK = HIGH, SDIO = Bit 3 (0)
Write -> 0x00	//SCK = LOW

Write -> 0x01	//SCK = HIGH, SDIO = Bit 2 (0)
Write -> 0x00	//SCK = LOW

Write -> 0x03	//SCK = HIGH, SDIO = Bit 1 (1)
Write -> 0x02	//SCK = LOW

Write -> 0x03	//SCK = HIGH, SDIO = Bit 0 (1)
Write -> 0x02	//SCK = LOW
-------------------------------------
END TRANSFER
-------------------------------------
Write -> 0x02	//SCK = LOW, SDIO = HIGH, end communications
-------------------------------------

Like reading on the two-wire interface, switching SCK from LOW to HIGH while writing has several timing conditions. SCK should be set LOW for a minimum of 2μs during the transfer and should ideally not exceed 64μs. Going further than 64μs stops the transfer. SCK should be set HIGH for a minimum of 2μs.

Depending on the command sent, the Magic Reader may immediately reply with its own data (setting SDIO LOW to indicate a read request). Below are the supported commands for the Magic Reader:

Command 0x24 - Unknown Command

This appears after UserCMD_AutoSleepFunDisable (0xA3). It does not appear to expect a response from the Magic Reader.

Command 0x30 - UserCmd_CheckOIDStatus

Instructs the Optical ID to return its status. Magic Reader will typically reply with OIDCmd_PowerOn, OIDCmd_PowerDown, OIDCmd_SystemReset, a valid index, or a null response.

Command 0x50 - UserCmd_NonClearAutoSleepTimerIfOIDDetect

Instructs the Optical ID to not clear the auto-sleep timer when reading an index.

Command 0x56 - UserCMD_PowerDownOID

Instructs the Optical ID to enter sleep mode.

Command 0xA0 - UserCMD_AutoSleepFunEnable

Instructs the Optical ID to enable the auto-sleep timer.

Command 0xA3 - UserCMD_AutoSleepFunDisable

Instructs the Optical ID to disable the auto-sleep timer.

Command 0xA6 - UserCMD_TriggerToClearAutoSleepTimer

Manually clears the auto-sleep timer.

Command 0xAC - UserCMD_ClearAutoSleepTimerIfOIDDetect

Instructs the Optical ID to clear the auto-sleep timer when reading and index.

[Magic Reader] : Control Flow

Below is the general control flow used for Juushinden. Note that the full functionality of the SN9P701FG-005 is not necessarily used. There are generally 2 phases: 1 for the initial startup (shortly after the game boots) and the other used when reading cards.

Initial Startup Sequence

  1. NDS writes 0x42 to MR_CNT to force Power On. For this step, EXMEMCNT is set to 0xE003. For all subsequent steps, Bits 0-1 of EXMEMCNT are set LOW.
  2. Magic Reader sets SDIO LOW to indicate a read request. NDS reads OIDCmd_PowerOn from Magic Reader.
  3. NDS sends UserCMD_AutoSleepFunDisable and unknown command 0x24.
  4. NDS continually sends UserCMD_PowerDownOID and waits for Magic Reader to respond with OIDCmd_PowerDown.

Card Reading Sequence

  1. NDS writes 0x42 to MR_CNT to force Power On. For this step, EXMEMCNT is set to 0xE003. For all subsequent steps, Bits 0-1 of EXMEMCNT are set LOW.
  2. Magic Reader sets SDIO LOW to indicate a read request. NDS reads OIDCmd_PowerOn from Magic Reader.
  3. NDS sends UserCMD_AutoSleepFunDisable and unknown command 0x24.
  4. NDS continually reads MR_CNT for incoming read requests from the Magic Reader. A 23-bit index value is then read.
  5. NDS should compare the last index from the last read request and validate the value.

[Magic Reader] : Card List and Index Values

There are total of 240 cards for Juushinden released in 4 sets of 60. There are also an unknown amount promotional cards. For the regular sets, the index values returned by the Magic Reader roughly matches the number printed on the card itself.

-------------------------------------
Set 1 - 第一弾「大いなる覚醒の時」
-------------------------------------
Card #	| Index	| Name
-------------------------------------
JS1-01	| 0000	| アバレ ピッグ
JS1-02	| 0001	| アダーガニ
JS1-04	| 0003	| レッドバンサー  
JS1-06	| 0005	| イカレコング
JS1-07 	| 0006	| タコ力士
JS1-08	| 0007	| ナックルリザード  
JS1-09 	| 0008	| イーグルカンフー
JS1-10	| 0009	| バルキー バイソン 
JS1-11	| 000A	| バクルオン
JS1-12	| 000B	| ブラックドーベル	
JS1-13	| 000C	| ガオー
JS1-14	| 000D	| 剛力獣神ガオー
JS1-15	| 000E	| モドリ玉	
JS1-18	| 0011	| ダイバクハーン
JS1-20	| 0013	| ソードザック
JS1-21	| 0014	| スルメボーイ 
JS1-22	| 0015	| 八つ裂きバチ
JS1-23	| 0016	| カワ・ウソン	
JS1-25	| 0018	| クワガイアス
JS1-26	| 0019	| スカルドレイン
JS1-28	| 001B	| ヨロイガエル
JS1-32	| 001F	| ザバット
JS1-33	| 0020	| シャア
JS1-37	| 0024 	| シールドブレイク
JS1-38	| 0025	| ソードブレイク
JS1-39	| 0026	| 聖なる闘技場
JS1-41	| 0028	| ポメ剣士
JS1-42	| 0029	| シロクマックス
JS1-43	| 002A	| アチョーモンキー
JS1-47	| 002E	| ハイエナガード
JS1-48	| 002F	| ヘビダイル
JS1-49	| 0030	| ブルドクター
JS1-50	| 0031	| エンゼルスワン	
JS1-52	| 0033	| 怪力エレファン
JS1-53	| 0034	| タイガ
JS1-57	| 0038	| いでよ鋼の盾
JS1-59	| 003A	| 炎の闘技場

The cards themselves use tiny carbon dots to produce an index value. According to the OID specification, carbon ink can replace K when using CMYK. Black colors would need to be reproduced by merging CMY dots in close proximity to one another. At any rate, these dots are meant to absorb light rather than reflect it. The CMOS inside the Magic Reader can't detect these dots, so these "empty" spots form a pattern that can be recognized and converted into a number. These dots are not completely invisible to the human eye, however. Ordinary cameras are capable of capturing them. The dots occupy the entire face of the card with the exception of the borders and likely the silver text of some cards.

Mobile Adapter GB

General Hardware Information

Compatible Games

Protocol - Packet Format

Protocol - Flow of Communication

Protocol - Commands

Configuration Data

[Mobile Adapter GB] : General Hardware Information

The Mobile Adapter GB was an accessory designed to allow the Game Boy Color, and later the Game Boy Advance, to connect online via cellular networks in Japan. Released on January 27, 2001, it supported a limited number of games before service was shutdown on December 14, 2002. Many of the compatible games supported features such on mail clients, downloadable bonus content, player-versus-player modes, and even online tournaments. It represented Nintendo's first official attempt at online gaming for its handhelds.

Below, the Mobile Adapter variants are explained in further detail:

Blue 	-> Used to connect PDC phones.
Yellow	-> Used to connect cdmaOne phones.
Red	-> Used to connect DDI phones.
Green	-> Would have been used to connect PHS phones, but this version was never released.

[Mobile Adapter GB] : Compatible Games

There are currently 22 known games that are compatible with the Mobile Adapter:

Game Boy Color : 6 Total

Game Boy Advance : 16 Total

Two games were planned but later cancelled: beatmaniaGB Net Jam for the GBC and Horse Racing Creating Derby for the GBA.

The GBA game Yu-Gi-Oh! Duel Monsters 5 Expert 1 contains code for the Mobile Adapter, but despite being built with the library it does not appear to use it. This functionality may have been planned and later abandoned.

[Mobile Adapter GB] : Protocol - Packet Format

On the GBC, the Mobile Adapter operates using the fastest available setting (64KB/s) by setting Bits 0 and 1 of the SC register (0xFF02) high. It also uses an internal clock for all transfers. Communication is comparable to that of the Game Boy Printer, where the Game Boy sends packets with header, data, command, and checksum sections. On the GBA, the Mobile Adapter operates in NORMAL8 mode using a shift clock of 256KHz. Below is a chart breaking down the Mobile Adapter packet format used by the Game Boy or Mobile Adapter when acting as the sender. For response data sent by the receiver, refer to the next section.

-------------------------------------------------
Section			| Length		
-------------------------------------------------
Magic Bytes : 0x99 0x66	| 2 bytes
Packet Header		| 4 bytes
Packet Data		| 0-254 bytes
Packet Checksum		| 2 bytes
Acknowledgement	Signal	| 2 bytes
-------------------------------------------------


-------------------------------------------------
Packet Header
-------------------------------------------------
Byte 1			| Command ID
Byte 2			| Unknown/Unused (0x00)
Byte 3			| High byte of Packet Data length
Byte 4			| Low byte of Packet Data length
-------------------------------------------------


-------------------------------------------------
Packet Data
-------------------------------------------------
Bytes 0-254		| Arbitrary data
-------------------------------------------------


-------------------------------------------------
Packet Checksum	
-------------------------------------------------
Byte 1			| High byte of 16-bit sum
Byte 2			| Low byte of 16-bit sum
-------------------------------------------------


-------------------------------------------------
Acknowledgement Signal
-------------------------------------------------
Byte 1			| Device ID
Byte 2			| Command ID
-------------------------------------------------

The magic bytes are simply a pair of bytes used to identify the start of a Mobile Adapter packet.

Packet Data is arbitrary data and varies in length and content. On the Game Boy Color, it has a maximum size of 254 bytes. This restriction may be applied via software and appears to come from the fact that the Packet Data and Packet Checksum are lumped together, thus their total lengths must not exceed 256 bytes. Attempting to send more than 254 bytes of packet data causes communications errors in all supported GBC games. Evidence suggests GBA games can use Bytes 3 and 4 of the Packet Header to specify Packet Data size (possibly up to 64KB). The Mobile Adapter discards any packets bigger than 255 bytes, effectively forcing the high byte of the packet data length to be 0.

Data greater than the maximum packet length may be broken up into multiple packets, however. For example, when sending a large binary file such as an image or executable code, multiple packets are transferred from the Mobile Adapter to the Game Boy while the TCP transfer is ongoing.

The Packet Checksum is simply the 16-bit sum of all previous header bytes and all previous packet data bytes. It does not include the magic bytes. The checksum is transmitted big-endian.

After the checksum, a simple 2-byte Acknowledgement Signal is sent. The first byte is the Device ID OR'ed with the value 0x80. The second byte is 0x00 for the sender. The receiver transfers the Command ID from the Packet Header XOR'ed by 0x80. This essentially confirms what role the Game Boy is acting in. If it is the receiver, it is expecting to read information from the Packet Data from the Mobile Adapter. If it is the sender, it is pushing information from its own Packet Data to the Mobile Adapter. For example, with Command 0x19, the Game Boy is explicitly requesting data from the adapter, and with Command 0x1A the Game Boy is explicitly sending data to the adapter.

The Command ID byte in the Acknowledgement Signal may also be used for the receiver to indicate an error. If the checksum verification fails, the receiving side will send error 0xF1. This causes the sender to immediately re-attempt sending the packet up to 4 times. If the command isn't implemented/supported by the receiving Mobile Adapter, error 0xF0 will be sent. Error 0xF2 indicates an internal error, such as the Mobile Adapter's TCP/telephone transfer buffer being full.

The device ID determines what kind of hardware each side is communicating with. Below are the possible values and their meaning:

-------------------------------------------------
Device ID	| OR Value	| Device Type
-------------------------------------------------
0x00		| 0x80		| Game Boy Color
0x01		| 0x81		| Game Boy Advance
0x08		| 0x88		| PDC Mobile Adapter (Blue)
0x09		| 0x89		| cdmaOne Mobile Adapter (Yellow)
0x0A		| 0x8A		| PHS Mobile Adapter (Green)
0x0B		| 0x8B		| DDI Mobile Adapter (Red)
-------------------------------------------------

[Mobile Adapter GB] : Protocol - Flow of Communication

Even though the protocol effectively enables 2-way communication between the Game Boy and a remote server, the handheld is expected to oversee all transmissions to the adapter itself. That is to say, the typical "master-slave" model often used for Game Boy serial I/O still applies in some sense. Once the server starts responding, the Game Boy has to continually initiate another transfer to the adapter (setting Bit 7 of 0xFF02 high) to keep reading any additional bytes that were sent.

It is up to the game software itself to handle secondary protocols (such as HTTP, POP3, or SMTP) which involve one side specifically acting as the sender or receiver. For example, after opening a TCP connection to an HTTP server and issuing the 0x15 command (Data Transfer), the software will determine whether the Game Boy is acting as a sender (making an HTTP request) or a receiver (receiving an HTTP response). Generally, this goes back and forth. The Game Boy sends information via its Packet Data, while the Mobile Adapter responds with 0xD2 "wait" bytes until the Game Boy finishes its TCP transfer. When the Game Boy's TCP transfer is done, the adapter sends any information from the server in its Packet Data while the Game Boy responds with 0x4B "wait" bytes. The chart below illustrates this concept and details what bytes are transferred by each side depending on their current role:

-------------------------------------------------------------------------------------------------------------------------------------------------
Device		| Role		| Magic Bytes	| Packet Header | Packet Checksum	| Packet Data	| Acknowledgement Signal
-------------------------------------------------------------------------------------------------------------------------------------------------
Game Boy	| Sender	| 0x96 0x66	| Arbitrary	| Arbitrary		| Arbitrary	| Device ID OR 0x80 + 0x00
Mobile Adapter	| Receiver	| 0xD2 0xD2	| 0xD2 0xD2 ... | 0xD2 0xD2 ... ... ...	| 0xD2 0xD2 ...	| Device ID OR 0x80 + Command ID XOR 0x80
-------------------------------------------------------------------------------------------------------------------------------------------------
Game Boy	| Receiver	| 0x4B 0x4B	| 0x4B 0x4B ... | 0x4B 0x4B ... ... ...	| 0x4B 0x4B ...	| Device ID OR 0x80 + Command ID XOR 0x80
Mobile Adapter	| Sender	| 0x96 0x66	| Arbitrary	| Arbitrary		| Arbitrary	| Device ID OR 0x80 + 0x00
-------------------------------------------------------------------------------------------------------------------------------------------------

When beginning communications with the Mobile Adapter, the Game Boy typically assumes the role of sender first.

Many games appear to follow a certain order of commands initially. This may have been part of some kind of standard library available to developers in order to connect to an ISP. The commands most commonly look like this:

------------
Command 0x10		Begin Session. First is perhaps to test the presence of the Mobile Adapter
Command 0x11		Close Session.
Command 0x10		Begin Session. Open session for configuration data
------------
Command 0x19		Read Configuration Data. Grab first 96 bytes
Command 0x19		Read Configuration Data. Grab second 96 bytes
Command 0x11		Close Session.
Command 0x10		Begin Session. Open session to read configuration data again
Command 0x19		Read Configuration Data. Grab first 96 bytes
Command 0x19		Read Configuration Data. Grab second 96 bytes
------------
Command 0x17		Check Telephone Status if not busy
Command 0x12		Dial Telephone. Should be the ISP's number stored in configuration data
Command 0x21		ISP Login
Command 0x28		DNS Query
------------

From there, the software decides what next (if anything) needs to be done after successfully connecting to the internet.

When the GBC or GBA first start communicating with the Mobile Adapter, the first byte sent in response will be garbage data. Sending this first byte causes the Mobile Adapter to exit sleep mode, and the GBC or GBA will then have to wait a short interval (around 100ms) before starting communications proper. If it doesn't, the Mobile Adapter might send more garbage. Afterwards, however, it will reply with 0xD2 as its "idle" byte until a command is finished being sent. The Mobile Adapter enters sleep mode after 3 seconds since the last serial byte was transmitted. This implicitly cancels the command currently being processed, closes all connections currently open and ends the session.

[Mobile Adapter GB] : Protocol - Commands

Command 0x0F - Empty

Data Sent: N/A. Empty Packet Data

Doesn't incite a reply from the adapter at all, aside from the Acknowledgement Signal. Presumably used to ping the adapter, not seen in any games in the wild.

Command 0x10 - Begin Session

Data Sent: "NINTENDO" ASCII string. 8 bytes only, not null-terminated

Data Received: "NINTENDO" ASCII string. 8 bytes only, not null-terminated

Sent to the adapter at the beginning of a session. The Game Boy sends an ASCII string containing "NINTENDO" and the adapter replies with a packet containing the same data. It must be noted that the adapter will not respond to other commands until it receives this command. If this command is sent twice, it returns an error.

Command 0x11 - End Session

Data Sent: N/A. Empty Packet Data

Data Received: N/A. Empty Packet Data

Sent to the adapter at the end of a session. The Packet Data is empty, and the length is zero bytes. This command causes all connections to be closed, and the phone to be hung up.

Command 0x12 - Dial Telephone

Data Sent: 1 unknown byte + telephone number

Data Received: N/A. Empty Packet Data

Instructs the adapter to dial a telephone number. The first byte's purpose is unknown, but seems to vary depending on the adapter type. 0 is sent for the blue/PDC adapter, 1 is sent for the green/PHS or red/DDI adapters, and 2 for the yellow/cdmaOne adapter. For unknown reasons, the blue adapter also accepts 16, the red adapter also accepts 9, and the yellow adapter doesn't actually verify this value. The following data is the telephone number represented in ASCII values, consisting of decimal numbers "0" through "9", as well as "#" and "*". Any ASCII values not within this range are ignored. The maximum length of the phone number is 32 bytes.

Command 0x13 - Hang Up Telephone

Data Sent: N/A. Empty Packet Data

Data Received: N/A. Empty Packet Data

Instructs the adapter to close a telephone connection. This implicitly disconnects any open TCP/UDP connections. The Packet Data is empty, and the length is zero bytes.

Command 0x14 - Wait For Telephone Call

Data Sent: N/A. Empty Packet Data

Data Received: N/A. Empty Packet Data

Instructs the adapter to wait for and pick up an incoming call. This returns inmediately if there is no call to pick up, with an error packet with code 0. The Packet Data is empty, and the length is zero bytes.

Command 0x15 - Transfer Data

Data Sent: Connection ID + Arbitrary Data (optional)

Data Received: Connection ID + Arbitrary Data (optional)

Used to transfer data over TCP after command 0x23 (Open TCP Connection), transfer data over UDP after command 0x25 (Open UDP connection), or transfer data over the phone line after either 0x12 (Dial Telephone) or 0x14 (Wait For Telephone Call) have successfully been called. Only TCP/UDP communication is possible after a 0x21 (ISP Login) command, and the first byte indicates the connection that's being transferred over, as multiple can be opened simultaneously. If it's a mobile connection, the first byte is ignored, usually being set to 0xFF.

Generally, additional data is appended, although it is not required, such as when waiting for the server/other phone to send a reply. Large chunks of data greater than 254 bytes must be broken down into separate packets. While a connection is active, the Command ID in the Reply is 0x15 for the sender and 0x95 for the receiver. When a TCP connection is closed by the remote server (e.g. when an HTTP response has finished), and there's no leftover data to be received by the Game Boy, the Command ID in the Reply becomes 0x1F for the sender and 0x9F for the receiver, with a packet length of 0. Additionally, for TCP connections, if no data is sent, this command will wait for data to be received up to 1 second, before sending a reply.

During a phone-to-phone communication, no disconnection is detected, instead being indicated by the 0x17 (Telephone Status) command. However, most games implement this instead through a timeout during which no data has been received.

Command 0x16 - Reset

Data Sent: N/A. Empty Packet Data

Data Received: N/A. Empty Packet Data

This command does the same as sending commands 0x11 (End Session), followed by 0x10 (Begin Session). Additionally, it resets SIO32 Mode to the default state. Presumably used to reset the adapter, though not seen in any games in the wild.

Command 0x17 - Telephone Status

Data Sent: N/A. Empty Packet Data

Data Received: 3 bytes

Typically sent to the adapter before dialing. Also used to test the telephone status before opening a TCP connection, or to constantly ping the phone to make sure it's still active.

The reply is 3 bytes. The first byte indicates the phone's status, where 0xFF is returned if the phone is disconnected. If the phone isn't disconnected, bit 2 indicates whether the phone line is "busy" (i.e. in a call/picked up), and bit 0 indicates the presence of an incoming call (this remains if the incoming call is picked up). As such, the valid values are 0, 1, 4 and 5. Software may check bit 2 to know if the phone line is still connected. Most software doesn't seem to care about bit 0, but Net de Get: Mini Game @ 100 refuses to work with bit 0 set (value 5).

The second byte is related to the adapter type, where the blue/PDC adapter returns 0x4D, and the red/DDI and yellow/cdmaOne adapters return 0x48, though the actual meaning is unknown. The third byte is unknown, and usually hardcoded to 0. However, Pokemon Crystal reacts to the third byte being 0xF0 by allowing the player to bypass the 10 min/day battle time limit.

Command 0x18 - SIO32 Mode

Data Sent: 1 byte

Data Received: N/A. Empty Packet Data

This command is generally sent after Command 0x10. It enables/disables SIO32 Mode, which is useful for GBA games to be able to send more data, faster. The sent byte must be 1 to enable SIO32 mode, and 0 to disable it. SIO32 mode implies that any transmission will happen in chunks of 4 bytes instead of 1, which has implications with respect to the alignment of the communication.

When SIO32 mode is on, the packet data will be aligned to a multiple of 4 bytes, padding the remaining bytes with 0, and this won't be reflected in the packet length field. Similarly, the Acknowledgement Signal gains 2 padding bytes (hardcoded 0, not verified) at the end. Since the entire transmission (including Magic Bytes) is sent in chunks of 4, this means that the checksum is sent along with either the packet length (if length is 0) or the last 2 bytes of the packet (if length is not 0), and the acknowledgement signal is sent in the next chunk.

SIO32 Mode will only be toggled after the reply to this packet has been sent. The adapter should be allowed at least 100ms to toggle, as it might otherwise start sending garbage.

Command 0x19 - Read Configuration Data

Data Sent: 1 byte offset + 1 byte read length

Data Received: 1 byte offset + Requested Configuration Data

Requests data from the adapter's 256-byte configuration memory. The first byte sent to the adapter is the offset. The second byte sent is the length of data to read. The adapter responds with the same offset byte followed by configuration data from the adapter's internal memory. The maximum amount of data that can be requested at once is 128 bytes, and the adapter may return an error if the game requests more data. Most software send 2 of these commands to read 96-byte chunks, for a total of 192 bytes, which is the area of this memory that is actually used.

Command 0x1A - Write Configuration Data

Data Sent: 1 byte offset + Configuration Data to Write

Data Received: 1 byte offset

Writes data to the adapter's 256-byte configuration memory. The first byte sent to the adapter is the offset. The following bytes are the data to be written in the adapters internal memory. A maximum of 128 bytes may be written at once.

Command 0x21 - ISP Login

Data Sent: 1 byte Login ID Length + Login ID + 1 byte Password Length + Password + 4 bytes DNS Address #1 + 4 bytes DNS Address #2

Data Received: 4 bytes assigned IP + 4 bytes assigned DNS Address #1 + 4 bytes assigned DNS Address #2 /p>

Logs into the DION dial-up service, after calling it with command 0x12 (Dial Telephone), allowing the adapter to connect to the internet. Both the Login ID and Password are prefixed with bytes declaring their lengths, with a maximum length of 0x20. The IPv4 DNS addresses are 4 bytes each, with a single byte representing one octet. The reply contains the assigned IP address and DNS addresses. If the game sets either of the DNS addresses to 0, the adapter may assign the DNS address on its own, and return that in the reply, otherwise, the reply's DNS addresses are 0.0.0.0.

Command 0x22 - ISP Logout

Data Sent: N/A. Empty Packet Data

Data Received: N/A. Empty Packet Data

Logs out of the DION service. This command causes all connections to be closed.

Command 0x23 - Open TCP Connection

Data Sent: 4 bytes for IP Address + 2 Bytes for Port Number

Data Received: 1 byte Connection ID

Opens a TCP connection at the given IP address on the given port, after logging into the DION dial-up service. The IPv4 IP address is 4 bytes, with a single byte representing one octet. The port number is big-endian. Depending on which port the TCP connection opens (25, 80, 110), different protocols can be accessed on a server (SMTP, HTTP, and POP respectively). Handling the details of the protocol itself depends on the software and the server. The Mobile Adapter is merely responsible for opening the connection and handling TCP transfers such as when using Command 0x15. The reply contains the Connection ID, which must be used when using Command 0x15 (Transfer Data). The maximum amount of connections on a real adapter is 2.

Command 0x24 - Close TCP Connection

Data Sent: 1 byte Connection ID

Data Received: 1 byte Connection ID

Closes an active TCP connection.

Command 0x25 - Open UDP Connection

Data Sent: 4 bytes for IP Address + 2 Bytes for Port Number

Data Received: 1 byte Connection ID

Opens a UDP connection at the given IP address on the given port, after logging into the DION dial-up service. It's an analog of Command 0x23 (Open TCP Connection), but opens a UDP connection instead. This UDP connection is bound to the specified IP address and Port until it's closed. When using Command 0x15 (Transfer Data) with a UDP connection, it's impossible to know the sender of any received data, as it isn't verified.

Command 0x26 - Close UDP Connection

Data Sent: 1 byte Connection ID

Data Received: 1 byte Connection ID

Closes an active UDP connection.

Command 0x28 - DNS Query

Data Sent: Domain Name

Data Received: 4 bytes for IP Address

Looks up the IP address for a domain name, using the DNS server addresses sent in Command 0x21. This command also accepts an ASCII IPv4 address (as parsed by the inet_addr(3) function of POSIX), converting it into a 4-byte IPv4 address instead of querying the DNS server. The domain name is in ASCII and may contain zeroes, which truncate the name.

Command 0x3F - Firmware Version

Data Sent: N/A. Empty Packet Data

Data Received: N/A. Empty Packet Data

On a real Mobile Adapter, this causes it to send firmware version information through the serial pins on the phone connector, and enter a state in which no other commands can be used. Presumably, this enters a test mode of some kind. Likely not used by any games.

This command may not be used if the phone line is in use. The only way to resume sending commands after this one is sent, is sending Command 0x16 (Reset), or, exclusively on the blue adapter, Command 0x11 (End Session) may also be used.

Command 0x6E - Error Status

Data Sent: N/A. Adapter sends this in response to a failed command

Data Received: 1 byte for command that failed + 1 byte for error status

If a previously sent command fails, the adapter will respond with this instead, indicating the command that failed as well as a brief status code. The error statuses for one command do not indicate the same error for another command, so context matters when parsing the codes. The following commands and their known error status codes are listed below:

0x10: Error Code 0x01 - Sent twice
0x10: Error Code 0x02 - Invalid contents

0x11: Error Code 0x02 - Still connected/failed to disconnect(?)

0x12: Error Code 0x00 - Telephone line is busy
0x12: Error Code 0x01 - Invalid use (already connected)
0x12: Error Code 0x02 - Invalid contents (first byte isn't correct)
0x12: Error Code 0x03 - Communication failed/phone not connected
0x12: Error Code 0x04 - Call not established, redial

0x13: Error Code 0x01 - Invalid use (already hung up/phone not connected)

0x14: Error Code 0x00 - No call received/phone not connected
0x14: Error Code 0x01 - Invalid use (already calling)
0x14: Error Code 0x03 - Internal error (ringing but picking up fails)

0x15: Error Code 0x00 - Invalid connection/communication failed
0x15: Error Code 0x01 - Invalid use (Call was ended/never made)

0x16: Error Code 0x00 - Still connected/failed to disconnect(?)

0x18: Error Code 0x02 - Invalid contents (first byte not either 1 or 0)

0x19: Error Code 0x00 - Internal error (Failed to read config)
0x19: Error Code 0x02 - Read outside of config area/too big a chunk

0x1A: Error Code 0x00 - Internal error (Failed to write config)
0x1A: Error Code 0x02 - Write outside of config area/too big a chunk

0x21: Error Code 0x01 - Invalid use (Not in a call)
0x21: Error Code 0x02 - Unknown error (some kind of timeout?)
0x21: Error Code 0x03 - Unknown error (internal error?)

0x22: Error Code 0x00 - Invalid use (Not logged in)
0x22: Error Code 0x01 - Invalid use (Not in a call)
0x22: Error Code 0x02 - Unknown error (some kind of timeout?)

0x23: Error Code 0x00 - Too many connections
0x23: Error Code 0x01 - Invalid use (Not logged in)
0x23: Error Code 0x03 - Connection failed

0x24: Error Code 0x00 - Invalid connection (Not connected)
0x24: Error Code 0x01 - Invalid use (Not logged in)
0x24: Error Code 0x02 - Unknown error (???)

0x25: Error Code 0x00 - Too many connections
0x25: Error Code 0x01 - Invalid use (Not logged in)
0x25: Error Code 0x03 - Connection failed (though this can't happen)

0x26: Error Code 0x00 - Invalid connection (Not connected)
0x26: Error Code 0x01 - Invalid use (Not logged in)
0x26: Error Code 0x02 - Unknown error (???)

0x28: Error Code 0x01 - Invalid use (not logged in)
0x28: Error Code 0x02 - Invalid contents/lookup failed

[Mobile Adapter GB] : Protocol - Configuration Data

The Mobile Adapter has small area of built-in memory designed to store various settings for its configuration. It only uses 192 bytes but data is readable and writable via the Commands 0x19 and 0x1A respectively. These fields are filled out when running the initial setup on Mobile Trainer. The memory is laid out as describe below:

--------------------------
0x00 - 0x01		::	"MA" in ASCII. The "Mobile Adapter" header.
0x02			::	Set to 0x1 during Mobile Trainer registration and 0x81 when registration is complete
0x04 - 0x07		::	Primary DNS server (210.196.3.183)
0x08 - 0x0B		::	Secondary DNS server (210.141.112.163)
0x0C - 0x15		::	Login ID in the format gXXXXXXXXX. Mobile Trainer only allows 9 editable characters
0x2C - 0x43		::	User email address in the format XXXXXXXX@YYYY.dion.ne.jp
0x4A - 0x5D		::	SMTP server in the format mail.XXXX.dion.ne.jp
0x5E - 0x70		::	POP server in the format pop.XXXX.dion.ne.jp
0x76 - 0x8D		::	Configuration Slot #1
0x8E - 0xA5		::	Configuration Slot #2
0xA6 - 0xBD		::	Configuration Slot #3
0xBE - 0xBF		::	16-bit big-endian checksum
--------------------------

Each configuration slot may contain an 8-byte telephone number to be used to connect to the ISP and a 16-byte ID string. The telephone number is stored in a variant of binary-coded decimal, where 0x0A represents the "#" key, 0x0B represents the "*" key, and 0x0F marks the end of the telephone number. These slots may have been intended to allow users to connect online using ISPs besides DION at some point, however, Nintendo never implemented any such plans.

If the Mobile Adapter is connected to a PDC or CDMA device, the telephone number defaults to #9677 with an ID string of "DION PDC/CDMAONE". If the Mobile Adapter is connected to a PHS or DDI device, the telephone number defaults to 0077487751 with an ID string of "DION DDI-POCKET". Only the first slot is configured by Mobile Trainer; it fills the rest with 0xFF and 0x00 bytes. An unidentified device (as reported by the Device ID in the Acknowledgement Signal of a packet) causes the Mobile Adapter to overwrite all configuration data with garbage values.

The checksum is simply the 16-bit sum of bytes 0x00 - 0xBD.

All software compatible with the Mobile Adapter appears to read the configuration data first and foremost. If the data cannot be read or if there is a problem with the data, they will refuse to even attempt logging in to the DION dial-up service. Generally, they return the error code 25-000 in that situation.

If any compatible software attempts to read or write configuration data outside the allotted 256 bytes via commands 0x19 and 0x1A, the entire I/O operation is cancelled. No data is written even if the initial offset is within the 256 bytes. No data is returned either, as both commands respond with Error Status packets.

EX Monopoly

General Information

Server Structure

information.cgb

query_T.cgb, query_M.cgb

0.regist.cgb

10.temporary.cgb

String Format

[EX Monopoly] : General Information

EX Monopoly is a Game Boy Advance game published by Takara and released on July 13, 2001. Using the Mobile Adapter, players were able to download news as well as participate in the Mobile Cup, a monthly competition in which players would play three COM games and upload the sum of their scores.

[EX Monopoly] : Server Structure

EX Monopoly is currently known to access the following URLs:

[EX Monopoly] : information.cgb

This file should be exactly 2,560 (0xA00) bytes in size. If not, the rest will be filled in with whatever was last downloaded. This is then divided into 64 lines, and each line is divided into 20 pairs of bytes. The last pair of each line must begin with 0xFE, except the last line, which must be 0xFF. Otherwise, the file is marked as corrupt. Additionally, any line where all but the last pair begin with 0xA3 is marked as empty. If all lines in the file are empty, the file is marked as corrupt. If the file is not corrupt, the game scans each pair of bytes and does the following:

These tiles are then drawn to the main scrolling text window.

[EX Monopoly] : query_T.cgb, query_M.cgb

These two files have the same format, but query_T.cgb is given a "today" value of 00 and gives data for all time while query_M.cgb is given a "today" value corresponding to the current or previous month and gives data only for that month. Both files are retreived via a POST request in the format "myname=<80 hex digits>&today=<2 hex digits>", and have the following format:

----------------------------------
File format
----------------------------------
0x00				::  High byte of ranking count (N). Should always be zero.
0x01				::  Low byte of ranking count (N). Should be 10 or less.
0x02 - ...			::  Ranking entries.
0x02 + 56*N			::  Two bytes. If both are 0x00, the player's ranking is not present.
0x04 + 56*N			::  Player's ranking entry, optional.

----------------------------------
Ranking entries - 56 bytes each
----------------------------------
0x00 - 0x03			::  Rank number in big endian.
0x04 - 0x2B			::  "myname" data, see below.
0x2C - 0x33			::  "myscore" data, see below.
0x34				::  Player's gender: 0x00 = male, 0x01 = female.
0x35				::  Player's age.
0x36				::  Player's state/prefecture.
0x37				::  "today" value: high 4 bits are a year number (mod 16), low 4 bits are a month number.

----------------------------------
myname - 40 bytes
----------------------------------
0x00 - 0x03			::  Player's name, right-padded with 0xFF.
0x04 - 0x23			::  Player's email, right-padded with 0x00.
0x24				::  "today" value, see above.
0x25 - 0x27			::  Always 0x00, but not checked on download.

----------------------------------
myscore - 8 bytes
----------------------------------
0x00 - 0x03			::  Total score. Always divisible by 5, and never more than 60.
0x04 - 0x07			::  Total cash in dollars.

[EX Monopoly] : 0.regist.cgb

When the player uploads their total score, the game sends two POST requests to this file in the same format: myname, myscore, gender, age, state, today. These values are sent as raw bytes. The difference between the two requests is that the first has both of its "today" values set to 00, while the second has both values correct. The server MUST NOT send a response body (i.e. file data), as the game will not close its connections and will fail to request 10.temporary.cgb.

[EX Monopoly] : 10.temporary.cgb

After both requests to 0.regist.cgb, the game sends a final POST request to this file in the format "myscore=<8 hex digits>". The server responds in the following format:

0x00 - 0x01			::  If both are 0x00, no rank number is present.
0x02 - 0x05			::  Rank number in big endian, optional.

If the rank number is greater than 10, the player will be told that they are unranked.

[EX Monopoly] : String Format

Characters 0xF1-0xFD (inclusive) are ignored by most text processing code, including the code used for all downloaded files. Character 0xFE is a line break, and character 0xFF terminates a string. Characters 0x200-0x25E (inclusive), which can only be used in information.cgb, correspond to ASCII 0x20-0x7E (inclusive), except that character 0x23C (ASCII 0x5C) is a yen symbol (¥).

	0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F
0x00	あ	い	う	え	お	か	き	く	け	こ	さ	し	す	せ	そ	た
0x10	ち	つ	て	と	な	に	ぬ	ね	の	は	ひ	ふ	へ	ほ	ま	み
0x20	む	め	も	や	ゆ	よ	ら	り	る	れ	ろ	わ	を	ん	ゃ	ゅ
0x30	ょ	。	、	が	ぎ	ぐ	げ	ご	ざ	じ	ず	ぜ	ぞ	だ	ぢ	づ
0x40	で	ど	ば	び	ぶ	べ	ぼ	ぱ	ぴ	ぷ	ぺ	ぽ	ア	イ	ウ	エ
0x50	オ	カ	キ	ク	ケ	コ	サ	シ	ス	セ	ソ	タ	チ	ツ	テ	ト
0x60	ナ	ニ	ヌ	ネ	ノ	ハ	ヒ	フ	ヘ	ホ	マ	ミ	ム	メ	モ	ヤ
0x70	ユ	ヨ	ラ	リ	ル	レ	ロ	ワ	ヲ	ン	ャ	ュ	ョ	ー	!	ガ
0x80	ギ	グ	ゲ	ゴ	ザ	ジ	ズ	ゼ	ゾ	ダ	ヂ	ヅ	デ	ド	バ	ビ
0x90	ブ	ベ	ボ	パ	ピ	プ	ペ	ポ	$	0	1	2	3	4	5	6
0xA0	7	8	9	 	ァ	ィ	ゥ	ェ	ォ	ッ	?	ヴ	っ	家	軒	抵
0xB0	当	価	格	建	設	水	道	費	抖	鉄	会	社	電	力	地	中
0xC0	海	公	井	通	ぁ	ぃ	ぅ	ぇ	ぉ	゛	゜	枚	倍	A	B	C
0xD0	D	E	F	G	H	I	J	K	L	M	N	O	P	Q	R	S
0xE0	T	U	V	W	X	Y	Z	%	:	⋯	♪	♥︎	~	男	女	位
0xF0	才	入	口	交	渉

Game Boy Wars 3

General Information

Server Structure

0.map_menu.txt

map/map_****.cgb

charge/****.cgb

mbox/mbox_serial.txt

mbox/mbox_**.cgb

0.youhei_menu.txt

[Game Boy Wars 3] : General Information

Game Boy Wars 3 is a turn-based war strategy game for the GBC, similar in gameplay to Nectaris. The online capabilities of the software consist of downloading custom maps, viewing messages and news from the developers, and unlocking premium mercenary units in battle.

[Game Boy Wars 3] : Server Structure

Game Boy Wars 3 is currently known to access the following URLS (asterisks indicate variable characters):

[Game Boy Wars 3] : 0.map_menu.txt

This file dictates the price in yen for maps. Although every map should have cost 10 yen, the game allows for different prices to exist for any map. The file is simply text with the following format:

[Minimum Map #]		[Maximum Map #]		[Price in yen]

Each line defines a minimum and maximum map number to create a range of maps and the price that will apply to all of them. All values are 4-digits written in ASCII, and whitespace may be tabs or spaces. Before downloading a map, players must specify a 4 digit ID corresponding to the number of the map they want. If 0.map_menu.txt does not specify a range that includes that ID, that map is unavailble for download.

This file specifies that no service charge should apply, as the filename is prefixed with "0".

[Game Boy Wars 3] : map/map_****.cgb

This is the binary data for a downloadable map. The 4 digit ID previously specified by a player prior to download determines the full filename that the game will request. For example, if the ID 1337 is used, map_1337.cgb will be requested. The format is exactly the same as the custom maps that players can create themselves.

----------------------------------
Map Structure
----------------------------------
0x00 - 0x01			::	0x20, 0x00. Seems to be an identifier, but the game does not care what values these bytes are.
0x02 - 0x03			::	16-bit sum of map size. LSB first. Calculated as 0x19F + (400 - (map width * map height))
0x04				::	8-bit sum of all data until EOF. Calculated as 0xFE - (a, b, c, ...)
0x20 - 0x2B			::	String for map name
0x2C				::	Map width (Min: 20, Max: 50)
0x2D				::	Map height (Min: 20, Max: 50)
0x2E ... 			::	Map tiles
...				::	Unit tiles (if any)
EOF				::	The last byte is 0xFF

The map tiles are 8-bit numbers that determine what type of terrain or buildings are placed on the grid (e.g. plains, mountains, forest, main base, factory, etc).

----------------------------------
Map Tiles
----------------------------------
0x00				::	Null space. Black tile that is "out of bounds".
0x01				::	Red Star base
0x02				::	Red Star city
0x03				::	Red Star ruined city
0x04				::	Red Star factory
0x05				::	Red Star ruined factory
0x06				::	Red Star airport
0x07				::	Red Star ruined airport
0x08				::	Red Star simple airport
0x09				::	Red Star harbor
0x0A				::	Red Star ruined harbor
0x0B				::	Red Star Transmission Tower
0x0C				::	White Moon base
0x0D				::	White Moon city
0x0E				::	White Moon ruined city
0x0F				::	White Moon factory
0x10				::	White Moon ruined factory
0x11				::	White Moon airport
0x12				::	White Moon ruined airport
0x13				::	White Moon simple airport
0x14				::	White Moon harbor
0x15				::	White Moon ruined harbor
0x16				::	White Moon Transmission Tower
0x17				::	Neutral city
0x18				::	Neutral ruined city	
0x19				::	Neutral factory
0x1A				::	Neutral ruined factory
0x1B				::	Neutral airport
0x1C				::	Neutral ruined airport
0x1D				::	Neutral harbor
0x1E				::	Neutral ruined harbor
0x1F				::	Neutral Transmission Tower
0x20				::	Plains
0x21				::	Highway
0x22				::	Bridge
0x23				::	Bridge
0x24				::	Mountains
0x25				::	Forest
0x26				::	Wasteland
0x27				::	Desert
0x28				::	River
0x29				::	Sea
0x2A				::	Shoal
0x2B - 0xFF			::	These appears to be invalid, glitchy, or null tiles

The game does not do any error-checking on the maps besides checking the 16-bit map size sum and the 8-bit data sum. If those are valid, the game will run it. Maps that would typically be impossible to create through the normal editor (maps lacking a Red Star/White Moon base, maps with null spaces, maps with Transmission Towers) can be downloaded and played.

If the 16-bit map size sum and 8-bit data sum are invalid, the game will complain when first booting. The actual map data is not deleted from SRAM, rather it simply becomes inaccessible from any in-game menus. Making a new map for that map slot will overwrite it, however.

Units can be placed on a map, but they are separate from the actual map data. After the map tile data is finished, unit tile data comes next. Each unit tile consists of 3 bytes:

----------------------------------
Unit Tile Bytes
----------------------------------
0x00				::	X position on map
0x01				::	Y position on map
0x02				::	Unit ID

The IDs are as follows:

----------------------------------
Unit IDs
----------------------------------
0x00				::	N/A. No unit appears
0x01				::	Invalid (DEL tile)
0x02				::	Red Star Infantry
0x03				::	White Moon Infantry
0x04				::	Red Star Missile Infantry
0x05				::	White Moon Missle Infantry
0x06				::	Red Star Merc Infantry
0x07				::	White Moon Merc Infantry
0x08				::	Red Star Construction Vehicle
0x09				::	White Moon Construction Vehicle
0x0A				::	Red Star Supply Vehicle
0x0B				::	White Moon Supply Vehicle
0x0C				::	Red Star Supply Vehicle S
0x0D				::	White Moon Supply Vehicle S
0x0E				::	Red Star Transport Truck
0x0F				::	White Moon Transport Truck
0x10				::	Red Star Transport Truck S
0x11				::	White Moon Transport Truck S
0x12				::	Red Star Combat Buggy
0x13				::	White Moon Combat Buggy
0x14				::	Red Star Combat Buggy S
0x15				::	White Moon Combat Buggy S
0x16				::	Red Star Combat Vehicle
0x17				::	White Moon Combat Vehicle
0x18				::	Red Star Combat Vehicle S
0x19				::	White Moon Combat Vehicle S
0x1A				::	Red Star Armored Transport Truck	
0x1B				::	White Moon Armored Transport Truck
0x1C				::	Red Star Armored Transport Truck S
0x1D				::	White Moon Armored Transport Truck S
0x1E				::	Red Star Rocket Launcher
0x1F				::	White Moon Rocket Launcher
0x20				::	Red Star Rocket Launcher S
0x21				::	White Moon Rocket Launcher S
0x22				::	Red Star Anti-Air Tank
0x23				::	White Moon Anti-Air Tank
0x24				::	Red Star Merc Anti-Air Tank
0x25				::	White Moon Merc Anti-Air Tank
0x26				::	Red Star Anti-Air Missile
0x27				::	White Moon Anti-Air Missile
0x28				::	Red Star Anti-Air Missile S
0x29				::	White Moon Anti-Air Missile S
0x2A				::	Red Star Artillery
0x2B				::	White Moon Artillery
0x2C				::	Red Star Artillery S
0x2D				::	White Moon Artillery S
0x2E				::	Red Star Anti-Infantry Tank
0x2F				::	White Moon Anti-Infantry Tank
0x30				::	Red Star Anti-Infantry Tank S
0x31				::	White Moon Anti-Infantry Tank S
0x32				::	Red Star Tank Destroyer
0x33				::	White Moon Tank Destroyer
0x34				::	Red Star Tank Destroyer S
0x35				::	White Moon Tank Destroyer S
0x36				::	Red Star Tank
0x37				::	White Moon Tank
0x38				::	Red Star Merc Tank
0x39				::	White Moon Merc Tank
0x3A				::	Red Star Fighter Jet A
0x3B				::	White Moon Fighter Jet A
0x3C				::	Red Star Fighter Jet B
0x3D				::	White Moon Fighter Jet B
0x3E				::	Red Star Fighter Jet S
0x3F				::	White Moon Fighter Jet S
0x40				::	Red Star Attack Aircraft A
0x41				::	White Moon Attack Aircraft A
0x42				::	Red Star Attack Aircraft B
0x43				::	White Moon Attack Aircraft B
0x44				::	Red Star Attack Aircraft S
0x45				::	White Moon Attack Aircraft S
0x46				::	Red Star Bomber
0x47				::	White Moon Bomber
0x48				::	Red Star Merc Bomber
0x49				::	White Moon Merc Bomber
0x4A				::	Red Star Transport Aircraft
0x4B				::	White Moon Transport Aircraft
0x4C				::	Red Star Aerial Tanker
0x4D				::	White Moon Aerial Tanker
0x4E				::	Red Star Attack Helicopter
0x4F				::	White Moon Attack Helicopter
0x50				::	Red Star Attack Helicopter S
0x51				::	White Moon Attack Helicopter S
0x52				::	Red Star Anti-Sub Helicopter
0x53				::	White Moon Anti-Sub Helicopter
0x54				::	Red Star Transport Helicopter
0x55				::	White Moon Transport Helicopter
0x56				::	Red Star Transport Helicopter S
0x57				::	White Moon Transport Helicopter S
0x58				::	Red Star Aegis Warship
0x59				::	White Moon Aegis Warship
0x5A				::	Red Star Merc Frigate
0x5B				::	White Moon Merc Frigate
0x5C				::	Red Star Large Aircraft Carrier
0x5D				::	White Moon Large Aircraft Carrier
0x5E				::	Red Star Small Aircraft Carrier	
0x5F				::	White Moon Small Aircraft Carrier
0x60				::	Red Star Transport Warship
0x61				::	White Moon Transport Warship
0x62				::	Red Star Supply Tanker
0x63				::	White Moon Supply Tanker
0x64				::	Red Star Submarine
0x65				::	White Moon Submarine
0x66				::	Red Star Submarine S
0x67				::	White Moon Submarine S
0x68				::	Red Star "Dummy" unit
0x69				::	White Star "Dummy" unit
0x6A				:: 	Invalid (DEL tile)
0x6B - 0xFF			::	Invalid (glitchy tiles)

Again, besides the basic additive checksumming, the game does not validate whether some units logically make sense when placed on a map (e.g. submarines on top of a mountain or in a forest). The in-game editor prevents such things from happening, however, downloaded maps can essentially do whatever they want. This includes populating the battlefield with the DLC mercenary units that would normally be available exclusively via the Transmission Tower. Mercenary units are not available through the in-game editor, however, downloaded maps can be freely edited, so such units can be deleted.

[Game Boy Wars 3] : charge/****.cgb

This file is requested after a map has sucessfully been downloaded or a mercenary unit has been unlocked. The filename is the price of the service in yen. This price is specified in either 0.map_menu.txt or 0.youhei.txt. The game largely appears to ignore the contents of the file and instead merely wants to confirm an HTTP 200 response from the server. Requesting that file incurs a service charge and is the mechanism behind Game Boy Wars 3's paid DLC. Neither 0.map_menu.txt or 0.youhei.txt check to make sure the 4-digit prices are valid ASCII numbers such as "30" or "10" and will blindly send whatever characters are written in those files.

[Game Boy Wars 3] : mbox/mbox_serial.txt

This file contains a list of strings when accessing the Message Center. mbox_serial.txt points the game to a mailbox file to download. It appears every string should be a number, e.g. ASCII characters 0x30 - 0x39. A total of 16 lines are parsed. If the contents of the strings have changed since the last time the player has downloaded from the Message Center, this indicates that a new message should be downloaded from that mailbox. The simplest method of managing mbox_serial.txt would be to set all lines at a baseline number (e.g. 0000) and increment each line when that mailbox features a new message (e.g. change line 0 from 0000 to 0001). If multiple lines are changed, multiple messages will be downloaded.

The previous strings (if any) are stored locally on the Game Boy Wars 3 cartridge RAM, and the game uses that to determine if anything should be downloaded at all. If no strings have been updated, Game Boy Wars 3 will not attempt to download any of the mailboxes.

Evidently, these mbox_serial.txt may need some formatting to correctly display the date for a mailbox's message, however, this information is currently unknown.

[Game Boy Wars 3] : mbox/mbox_**.cgb

This file contains the message to display from a mailbox. The exact url is determined by mbox_serial.txt. If the first line's string in mbox_serial.txt is updated, the game downloads mbox_00.cgb. If the second line's string in mbox_serial.txt is updated, the game downloads mbox_01.cgb, and so on. There are only 16 mailboxes available: mbox_00.cgb to mbox_15.cgb.

The format appears to be pure text, except that the first 7 characters are ignored. Messages can be displayed in ASCII. Hiragana and katakana are available as well, however, their format is currently unknown. The mbox_**.cgb file MUST end CRLF, otherwise the game does not know to stop parsing data and starts overwriting all kinds of RAM.

[Game Boy Wars 3] : 0.youhei_menu.txt

This file is requested when players use the Transmission Tower during a battle. It's merely a list that details the price in yen for each mercenary unit. The format is as follows:

[Price for Merc Infantry]
[Price for Merc AA Tank]
[Price for Merc Tank]
[Price for Merc Bomber]
[Price for Merc Frigate]

This file specifies that no service charge should apply, as the filename is prefixed with "0".

Hello Kitty no Happy House

General Information

Server Structure

Email

Item Codes

[Hello Kitty no Happy House] : General Information

Hello Kitty no Happy House is a Game Boy Color title featuring furniture collection, minigames, and online communication. The game revolves around interacting with Hello Kitty, gaining new furniture, and decorating the "Happy House". As it concerns the Mobile Adapter GB, Hello Kitty no Happy House boasts basic email capabilities. Through the email service, users could share different furniture as presents.

[Hello Kitty no Happy House] : Server Structure

Hello Kitty no Happy House is not known to access any resource via HTTP. Instead, it simply communicates with a SMTP server and POP3 server for sending and receiving email respectively.

[Hello Kitty no Happy House] : Email

Email can be sent and received in Hello Kitty no Happy House, much like Mobile Trainer. The game offers similar tools to write the email, helping users fill out subjects, addresses, and content, and viewing the mailbox for received items. The game also sends "presents" to another user via email. The standard email format looks something like this (note that xxxx, yyyy, and zzzz parts are not exact lengths, consider them as variables):

From: =?ISO-2022-JP?xxxxxxxxxxxxxxxxxxxxxxxx <yyyy@zzzz.dion.ne.jp>
To: =?ISO-2022-JP?xxxxxxxxxxxxxxxxxxxxxxxx <yyyyyyyyy>
Subject: =?ISO-2022-JP?xxxxxxxxxxxxxxxxxxxxxxxx
MIME-Version: 1.0
Content-Type: text/plain; charset="ISO-2022-JP"
Content-Transfer-Encoding: 7bit
X-Mailer: Hello Kitty Happy House
X-Game-title: HKITTY_HH
X-Game-code: CGB-BK7J-00
[content of email]

The game uses two additional custom SMTP email headers to send furniture to another player. These headers are parsed for a 3-letter ASCII code which determines the item received. After the "X-Game-code" header, the following would be inserted before the content of the email:

X-GBmail-type: exclusive
X-HKH-HOUSE: [3-letter code]

The codes appear to be simple, e.g. "AAE" for a framed picture and "AIG" for a green rug.

[Hello Kitty no Happy House] : Item Codes

Below are a list of 3-letter codes and the items they generate when used in the email header. If the game does not recognize the code, a present icon will appear next to the email, but no item is actually received.

---------------------------------------------------
Codes			| Item
---------------------------------------------------
AAB			Heart Clock
AAC			Pendulum Clock
AAD			Futuristic Clock
AAE			Landscape Painting
AAF			Pop Art Painting
AAG			Kitty Elastomer
AAH			Bronze Angel Statue
AAI 			Bronze Goddess Statue
AAJ			Bronze Kitty Statue
AAK	ABA		Hanging Scroll
AAL	ABB		Dragon Pennant
AAM	ABC		Noble Pennant
AAN	ABD		Wide TV
AAO	ABE		Cute TV
AAP	ABF		Wall-mounted TV
AAQ	ABG		Digital Component Stereo
AAR	ABH		Component Stereo
AAS	ABI		Gramophone
AAT	ABJ		Massage Chair
AAU	ABK	ACA	"Sexy" Massage Chair
AAV	ABL	ACB	Relaxing Chair
AAW	ABM	ACC	Globe
AAX	ABN	ACD	Cosmic Globe
AAY	ABO	ACE	Miniature House
AAZ	ABP	ACF	Pink Chest
ABQ	ACG		Japanese Drawer
ABR	ACH		Toy Case
ABS	ACI		Japanese Vase
ABT	ACJ		Western Vase
ABU	ACK	ADA	Arabian Vase
ABV	ACL	ADB	Tetra Aquarium
ABW	ACM	ADC	Turtle Aquarium
ABX	ACN	ADD	Arowana Aquarium
ABY	ACO	ADE	Floor Light
ABZ	ACP	ADF	Standing Light
ACQ	ADG		Mood Light
ACR	ADH		Doggy Doll
ACS	ADI		Sheep Doll
ACT	ADJ		Lion Doll
ACU	ADK	AEA	Puppet Storage Box
ACV	ADL	AEB	Robot Base
ACW	ADM	AEC	Doll House
ACX	ADN	AED	Magazine Rack
ACY	ADO	AEE	Letter Rack
ACZ	ADP	AEF	Bookstand
ADQ	AEG		Hat Stand
ADR	AEH		Coat Stand
ADS	AEI		Dear Daniel Doll
ADT	AEJ		Pink Living Room Furniture
ADU	AEK	AFA	Blue Living Room Furniture
ADV	AEL	AFB	White Living Room Furniture
ADW	AEM	AFC	Thai Living Room Furniture
ADX	AEN	AFD	Chinese Living Room Furniture
ADY	AEO	AFE	Asian Living Room Furniture
ADZ	AEP	AFF	Japanese Living Room Furniture
AEQ	AFG		Wooden Japanese Chestnut Living Room Furniture
AER	AFH		Wajima Lacquer Living Room Furniture
AES	AFI		Cozy Living Room Furniture
AET	AFJ		Checkered Living Room Furniture
AEU	AFK	AGA	Pop Living Room Furniture
AEV	AFL	AGB	Old Living Room Furniture
AEW	AFM	AGC	Old-fashioned Living Room Furniture
AEX	AFN	AGD	Antique Living Room Furniture
AEY	AFO	AGE	Heart-themed Living Room Furniture
AEZ	AFP	AGF	Apple-themed Living Room Furniture
AFQ	AGG		Flower-themed Living Room Furniture
AFR	AGH		Red Kotatsu
AFS	AGI		Blue Kotatsu
AFT	AGJ		Yellow Kotatsu
AFU	AGK	AHA	Extravagant Living Room Furniture
AFV	AGL	AHB	Elegant Living Room Furniture
AFW	AGM	AHC	Hello Kitty-themed Living Room Furniture
AFX	AGN	AHD	Red Art Studio
AFY	AGO	AHE	Blue Art Studio
AFZ	AGP	AHF	Elegant Art Studio
AGQ	AHG		Model Train
AGR	AHH		Toy Blocks
AGS	AHI		Playing House Set
AGT	AHJ		Standing Table
AGU	AHK	AIA	Flower-pattern Table
AGV	AHL	AIB	Glass Table
AGW	AHM	AIC	Japanese Flower Arranged Desk
AGX	AHN	AID	Flower Arrangement
AGY	AHO	AIE	Bonsai
AGZ	AHP	AIF	Red Carpet
AHQ	AIG		Green Carpet
AHR	AIH		Blue Carpet (says blue, looks purple)
AHS	AII		Blue Playground Slide
AHT	AIJ		Red Playground Slide (says red, looks pink)
AHU	AIK	AJA	White Playground Slide
AHV	AIL	AJB	Easy Chair
AHW	AIM	AJC	Tranquil Chair
AHX	AIN	AJD	Relaxing Chair
AHY	AIO	AJE	Gold Tearoom
AHZ	AIP	AJF	Silver Tearoom
AIQ	AJG		Play Set
AIR	AJH		Changing-clothes Box
AIS	AJI		Changing-clothes Case
AIT	AJJ		Strange Box
AIU	AJK	AKA	Somersault Platform
AIV	AJL	AKB	Jump Sheet
AIW	AJM	AKC	Trampoline
AIX	AJN	AKD	Pink Refrigerator
AIY	AJO	AKE	Wood-grain Refrigerator
AIZ	AJP	AKF	Play Refrigerator
AJQ	AKG		White Iron
AJR	AKH		Green Iron
AJS	AKI		Purple Iron
AJT	AKJ		Brown Builder (workout set)
AJU	AKK	ALA	Purple Builder (workout set)
AJV	AKL	ALB	Green Builder (workout set)
AJW	AKM	ALC	Brown Runner (treadmill)
AJX	AKN	ALD	Red Runner (treadmill, says red, looks pink)
AJY	AKO	ALE	Blue Runner (treadmill)
AJZ	AKP	ALF	Flower Piano
AKQ	ALG		Star Piano
AKR	ALH		Classic Piano
AKS	ALI		Crystal Ball Set
AKT	ALJ		Fortune-Telling Set
AKU	ALK	AMA	Tarot Card Divination

Mario Kart Advance

General Information

Server Structure

index.cgb

rule.cgb

total.cgb

query.cgb

0.dlghost.cgb, 0.dlghost2.cgb, 0.dlghost3.cgb

0.dlghostdr.cgb, 0.dlghostst.cgb, 0.dlghostid.cgb

0.entry.cgb

String Format

[Mario Kart Advance] : General Information

Mario Kart Advance is the 3rd entry in the famed Mario Kart series. Its debut on the Game Boy Advance supported the Mobile Adapter GB for online connectivity. The game features options such as a Mobile GP where users could compete against others based on their completion times. Players could also download ghost data for specific race tracks.

[Mario Kart Advance] : Server Structure

Mario Kart Advance is currently known to access the following URLs:

Asterisks in the above URLs are filled with a relevant string from index.cgb.

[Mario Kart Advance] : index.cgb

This is a text file with 21 lines, each containing 255 bytes or less, and a 22nd empty line. The first 20 lines correspond to the 20 Super Circuit tracks in the game (the 16 initial tracks and the first 4 unlockable tracks), while the final line corresponds to the current Mobile GP. These lines are used to fill ranking and upload URLs.

[Mario Kart Advance] : rule.cgb

This is a text file describing the current Mobile GP rules. It has 13-45 lines, using CR/LF line endings, in the following format:

Line 1				::  File name to join (http://gameboy.datacenter.ne.jp/cgb/download?name=/01/AGB-AMKJ/*), 20 bytes or less.
Line 2				::  First day to download and view these rules (YYYYMMDD).
Line 3				::  Last day to download these rules (YYYYMMDD).
Line 4				::  First day to download and view the next set of rules (YYYYMMDD).
Line 5				::  Last day to download the next set of rules (YYYYMMDD).
Line 6				::  First day to join and upload rankings (YYYYMMDD).
Line 7				::  Last day to join and upload rankings (YYYYMMDD).
Line 8				::  First day to download and view rankings (YYYYMMDD).
Line 9				::  Last day to download and view rankings (YYYYMMDD).
Line 10				::  Special rules (8 hex digits, see below).
Line 11				::  Track number (2 digits).
Line 12				::  Number of tries when joining (2 digits).
Line 13				::  Number of lines in description (2 digits).
Lines 14+			::  Description.

Each digit of the special rules (line 10) specifies a different rule as follows:

Rules with "enable" are enabled when their digit is not zero.

[Mario Kart Advance] : total.cgb

This file is downloaded when downloading rankings. It simply contains a four-byte integer in big endian representing the number of ranked ghosts, used to inform which rank numbers the game requests for its overall ranking category.

[Mario Kart Advance] : query.cgb

This file is downloaded after total.cgb via a POST request in the format "myid=<32 hex digits>&myrecord=<4 hex digits>&pickuprecord=<4 hex digits>&state=<2 hex digits>&driver=<2 hex digits>&rk_1=<8 hex digits>&rk_2=<8 hex digits>&rk_3=<8 hex digits>&rk_4=<8 hex digits>&rk_5=<8 hex digits>&rk_6=<8 hex digits>&rk_7=<8 hex digits>&rk_8=<8 hex digits>&rk_9=<8 hex digits>&rk_10=<8 hex digits>&rk_11=<8 hex digits>", where the "pickuprecord" value is the player's actual record while the "myrecord" value is 1/100 second slower, and the "rk_*" values are the rank numbers to be displayed in the overall rankings category. The file itself has the following format:

----------------------------------
File format
----------------------------------
* Global ranking set.
* High byte of rival count.
* Low byte of rival count.
* Up to eleven rival ranking entries.
* Global player rank.
* Eleven overall ranking entries.
-- The file ends here for Mobile GP. --
* State ranking set.
* State player rank.
* Driver ranking set.
* Driver player rank.
* 4 bytes: Global number of ranked players in big endian.

----------------------------------
Ranking set
----------------------------------
0x00				::  High byte of year number.
0x01				::  Low byte of year number.
0x02				::  Month number.
0x03				::  Day number.
0x04				::  Hour number.
0x05				::  Minute number.
0x06 - 0x09			::  Number of ranked players in big endian.
0x0A - 0x0D			::  Number of total players in big endian.
0x0E				::  High byte of top 10 count (N <= 11).
0x0F				::  Low byte of top 10 count (N <= 11).
0x10 - ...			::  Up to eleven top 10 ranking entries.

----------------------------------
Ranking entry
----------------------------------
0x00 - 0x03			::  Rank number in big endian.
0x04				::  Driver number.
0x05 - 0x09			::  Nickname.
0x0A				::  High byte of race time.
0x0B				::  Low byte of race time.
0x0C - 0x1B			::  Kart ID.

----------------------------------
Player rank
----------------------------------
0x00 - 0x01			::  If both are 0x00, rank number is not present.
0x02 - 0x05			::  Rank number in big endian, optional.
(0x06 - 0x07)			::  If both are 0x00, extended info is not present.
(0x08 - 0x0B)			::  Extended rank number in big endian, optional. Seems to overrule the prior rank number.
(0x0C)				::  Extended driver number, optional.
(0x0D)				::  High byte of extended race time, optional.
(0x0E)				::  Low byte of extended race time, optional.

----------------------------------
Overall ranking entry
----------------------------------
0x00 - 0x01			::  If both are 0x00, ranking entry is not present.
0x02 - 0x1D			::  Ranking entry, optional.

[Mario Kart Advance] : 0.dlghost.cgb, 0.dlghost2.cgb, 0.dlghost3.cgb

These files are downloaded via POST requests in varying formats: 0.dlghost.cgb, used when downloading by global rank, receives "ghostrank=<8 hex digits>&state=00&driver=00"; 0.dlghost2.cgb, used when downloading by race time, receives "ghostscore=<4 hex digits>&state=00&driver=00", where the "ghostscore" value is 1/100 second slower than the requested time; and 0.dlghost3.cgb, used when downloading by kart ID, receives "myid=<32 hex digits>&state=00&driver=00". They all share the following format:

0x0000				::  High byte of year number, not used.
0x0001				::  Low byte of year number, not used.
0x0002				::  Month number, not used.
0x0003				::  Day number, not used.
0x0004				::  Hour number, not used.
0x0005				::  Minute number, not used.
0x0006 - 0x0009			::  Global number of ranked players in big endian.
0x000A - 0x000B			::  If both are 0x00, the file ends here.
0x000C				::  Driver number.
0x000D - 0x0011			::  Nickname.
0x0012				::  High byte of race time.
0x0013				::  Low byte of race time.
0x0014 - 0x1013			::  Ghost data.
0x1014 - 0x1023			::  Kart ID.
0x1024 - 0x1027			::  Global number of ranked players in big endian.
0x1028 - 0x102B			::  Unknown, not used.
0x102C - 0x102F			::  State number of ranked players in big endian.
0x1030 - 0x1033			::  Driver number of ranked players in big endian.

[Mario Kart Advance] : 0.dlghostdr.cgb, 0.dlghostst.cgb, 0.dlghostid.cgb

These files are downloaded via POST requests in the same format as 0.dlghost.cgb. 0.dlghostdr.cgb is used for downloading by driver, 0.dlghostst.cgb is used for downloading by state, and 0.dlghostid.cgb would be used for downloading globally, but is replaced by 0.dlghost.cgb. All three share the following format:

0x0000				::  High byte of year number, not used.
0x0001				::  Low byte of year number, not used.
0x0002				::  Month number, not used.
0x0003				::  Day number, not used.
0x0004				::  Hour number, not used.
0x0005				::  Minute number, not used.
0x0006 - 0x0009			::  Global number of ranked players in big endian.
0x000A - 0x000B			::  If both are 0x00, the file ends here.
0x000C - 0x001C			::  Kart ID, optional.

[Mario Kart Advance] : entry.cgb

This file is uploaded to via a POST request. The downloaded data is irrelevant. The uploaded data is in the following format:

0x0000 - 0x000F			::  Kart ID.
0x0010				::  Track number.
0x0011				::  Driver number.
0x0012 - 0x0016			::  Nickname.
0x0017				::  State number.
0x0018 - 0x0019			::  Unknown.
0x001A				::  High byte of race time.
0x001B				::  Low byte of race time.
0x001C - 0x101B			::  Ghost data.
0x101C - 0x102B			::  Player's name.
0x102C - 0x1037			::  Player's phone number.
0x1038 - 0x103F			::  Player's postal code.
0x1040 - 0x10BF			::  Player's home address.

Outside of Mobile GP, personal info is not uploaded: the two numbers are filled with forward slashes, and the other two text fields are filled with asterisks. Otherwise, on an unmodified game, the postal code is always seven digits followed by a lowercase letter "p".

[Mario Kart Advance] : String Format

These characters are taken directly from the game's Shift-JIS decoding function. 0x00 is used as a terminator, and is usually invoked using two or four consecutive null bytes in ROM strings, or using a CR/LF line terminator in downloaded strings, rather than actually using 危.

	0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F
0x00	危	!	”	#	$	%	’	&	(	)	*	+	,	ー	.	/
0x10	0	1	2	3	4	5	6	7	8	9	:	;	<	=	>	?
0x20	@	A	B	C	D	E	F	G	H	I	J	K	L	M	N	O
0x30	P	Q	R	S	T	U	V	W	X	Y	Z	[	¥	]	^	_
0x40	‘	a	b	c	d	e	f	g	h	i	j	k	l	m	n	o
0x50	p	q	r	s	t	u	v	w	x	y	z	{	|	}	〜	 
0x60	ぁ	あ	ぃ	い	ぅ	う	ぇ	え	ぉ	お	か	が	き	ぎ	く	ぐ
0x70	け	げ	こ	ご	さ	ざ	し	じ	す	ず	せ	ぜ	そ	ぞ	た	だ
0x80	ち	ぢ	っ	つ	づ	て	で	と	ど	な	に	ぬ	ね	の	は	ば
0x90	ぱ	ひ	び	ぴ	ふ	ぶ	ぷ	へ	べ	ぺ	ほ	ぼ	ぽ	ま	み	む
0xA0	め	も	ゃ	や	ゅ	ゆ	ょ	よ	ら	り	る	れ	ろ	わ	を	ん
0xB0	ァ	ア	ィ	イ	ゥ	ウ	ェ	エ	ォ	オ	カ	ガ	キ	ギ	ク	グ
0xC0	ケ	ゲ	コ	ゴ	サ	ザ	シ	ジ	ス	ズ	セ	ゼ	ソ	ゾ	タ	ダ
0xD0	チ	ヂ	ッ	ツ	ヅ	テ	デ	ト	ド	ナ	ニ	ヌ	ネ	ノ	ハ	バ
0xE0	パ	ヒ	ビ	ピ	フ	ブ	プ	ヘ	ベ	ペ	ホ	ボ	ポ	マ	ミ	ム
0xF0	メ	モ	ャ	ヤ	ュ	ユ	ョ	ヨ	ラ	リ	ル	レ	ロ	ワ	ヲ	ン

Mobile Trainer

General Information

Server Structure

index.html

Web Browser

Email

[Mobile Trainer] : General Information

Mobile Trainer is utility software designed as a configuration tool for the Mobile Adapter GB. It also served as a basic web-browser and email client when connected to the Mobile System GB network. The cartridge came bundled with every Mobile Adapter and was released on January 27, 2001.

[Mobile Trainer] : Server Structure

Mobile Trainer is currently known to access the following URL:

Although a few other URLs are present within the ROM, the above is the only ones observed in actual use. Additionally, Mobile Trainer is currently known to access POP3 mail servers on port 110 and SMTP servers on port 25.

[Mobile Trainer] - index.html

This is the "Home Page" for the Mobile Adapter. News and updates published by Nintendo would appear here periodically. Other pages could be accessed if the Home Page had links. Beyond a few screenshots, not much else has been recorded about the content and structure of the Home Page.

[Mobile Trainer] - Web Browser

Mobile Trainer features a barebones web-browser supported a limited subset of HTML. The following HTML elements are known to render:

Manual URL input is not possible from the browser. As such, it is restricted to the Home Page and whatever links appear in the index.html file. Bookmarks can be saved, however, and accessed without having to go through the Home Page. Manually editing the save file would allow bookmarks to point to arbitrary URLs.

Accessing the Home Page and associated links is timed, as the Mobile Adapter keeps an active connection to the server, thus a service charge (from the wireless provider) would be applied for the total time spent browsing. Handily enough, there is an option within the browser to cut the connection and freeze the timer.

<img> tags will only work with 1BPP BMP files. There are several additional restrictions:

Just about everything else in the BMP file and image header is ignored. Most image editors will produce a BMP that works fine with the Mobile Trainer web-browser. Some BMPs may need minor alterations. For example, GIMP may set the number of color maps but otherwise typically produce a valid BMP for Mobile Trainer (in which case, the incorrect bytes can be manually changed in a hex editor).

[Mobile Trainer] : Email

Email could be sent and received by Mobile Trainer. Users would have to register a DION account and would receive their information (email address, password, etc). Other game servers on the Mobile System GB network could send email to this account for various reasons. Pokemon Crystal, for example would send an email if a deposited Pokemon had been traded with another player. The email server itself is essentially a standard POP3 and SMTP server for receiving and sending email. The email format sent follows this format roughly (keep in mind the xxxx and yyyy and zzzz parts are not exactly lengths, consider them variable).

MIME-Version: 1.0
From: xxxx@yyyy.dion.ne.jp (=?ISO-2022-JP?zzzzzzzzzzzzzzzz)
To: [email_address]
Subject: =?ISO-2022-JP?xxxx
X-Game-title: MOBILE TRAINER
X-Game-code: CGB-B9AJ-00
Content-Type: text/plain; charset=iso-2022-jp
[content_of_email]

As the above makes clear, emails are sent using ISO-2022 character encodings. The recepient's email address is not checked or verified by Mobile Trainer. It will blindly hand over the mail to the SMTP server, only showing the user and error if the server reports a problem. It is unknown if there were restrictions on which email addresses the Mobile System GB would service (only other DION email for Mobile Adapter customers, or anyone anywhere?) Email can be sent and received from the same menu. A small animation appears of the player walking to a digital post office and sending mail and receiving any new mail afterwards.

Also of note: there is absolutely no encryption done and any POP or SMTP transfer. While the limited nature, obscurity, and short lifespan of the Mobile System GB network probably prevented any major security concerns from appearing, by modern standards it is a security nightmare. For example, when retrieving mail via the POP3 server, both user ID and password are transmitted in plaintext. Those two pieces of information would be enough to impersonate another user for any other Mobile Adapter compatible game.

Net de Get: Mini Game @ 100

General Information

Server Structure

h0000.cgb

RomList.cgb

cgb/download?name=/A4/CGB-BMVJ/*

Download Wrapper

Minigame Format

String Format

MBC6 Flash Operation

[Net de Get] : General Information

Net de Get is a Game Boy Color game published by Konami and released on June 12, 2001. In addition to being one of the select few GBC games to support the GB Mobile Adapter, it is the only known game to use the MBC6. This special cartridge allowed the Game Boy to download minigames from the internet and save them locally to flash memory for offline play. Players could browse an online list of available software and purchase them.

[Net de Get] : Server Structure

Net de Get is currently known to access the following URLs:

Although a few other URLs are present within the ROM, the above are the only ones observed in actual use.

[Net de Get] : h0000.cgb

Once some of the default minigames have been played, the "セーバ" or "Server" option in the main menu unlocks. After the user's password is given, this file is then downloaded via HTTP GET. The purpose of h0000.cgb is simply to display the text "ミニゲームリスト" or "Minigame List". Selecting this downloads RomList.cgb via HTTP GET. The format of h0000.cgb is described below:

----------------------------------
Header - 4 bytes
----------------------------------
0x0000 - "M"			::	0x4D
0x0001 - "N"			::	0x4E
0x0002 - "G"			::	0x47
0x0003 - "L"			::	0x4C

----------------------------------
Text offset - 6 bytes
----------------------------------
0x0004 - Offset			::	Offset to text string. Calculated as 10 + (Offset * 5).
0x0005 - ???			:: 	0x0005 through 0x0009 seem to be ignored.
0x0006 - ???			::
0x0007 - ???			::
0x0008 - ???			::
0x0009 - ???			::

[Net de Get] : RomList.cgb

After downloading h0000.cgb, the next file is RomList.cgb. This file contains a list of all available minigames the server has to offer. It also displays how many 8KB blocks of flash memory are required for the download, as well as the type of minigame being downloaded.

----------------------------------
Entry Count - 1 byte
----------------------------------
0x00 - Number of entries	::	(1 - ?) Maximum not currently known.

----------------------------------
Data Offsets - 2 bytes each
----------------------------------
0x01				::	Low byte of 16-bit internal offset to RomsList.cgb data structure.
0x02				::	High byte of 16-bit internal offset to RomsList.cgb data structure. 
...				::	Repeat offsets as needed.

----------------------------------
Data Structure
----------------------------------
0x00	 			::	Number of memory blocks necessary for the download (modulus 100). Should be 0x00 - 0x63 ideally.
0x01				::	Mini-game icon type. See Icon Type below for details.
0x08 - 0x0A			::	Disables download (grayed out text). All 3 must be zero, otherwise download is disabled.
0x0C - 0x0F			::	Disables menu item completely (no text, item not selectable). All 4 must be zero, otherwise menu item is disabled.
0x10				::	String Length 1. Each menu item should ideally be 12 characters or less (font is fixed width). Used for minigame name.
0x11 - ...			::	Menu Item Text (see String Format below).
0x11 + String Length 1		::	String Length 2. Each menu item draws additional text to a small on-screen textbox. Used brief explanations about minigame. Ideal max is 0xF.
0x11 + 1 + String Length 1 	::	Additional textbox string.
0x11 + 6 + String Length 1 & 2	::	Unique ID for download. 8 characters max.

Minigames have their own categories and can be assigned their own specific icons. The following bytes dictate what icon is drawn:

----------------------------------
Icon Type
----------------------------------
0x00				::	Question Mark		不定その他	Unspecified other aka misc.
0x01				::	Boxing Glove		アクション	Action
0x02				::	Green Head		パズル		Puzzle
0x03				::	Running Person		オーソドックス	Orthodox aka Platformer?
0x04				::	Sword			アールピージー	RPG
0x05				::	Green Sheet		シミュレーション 	Simulation
0x06				::	Fighter Jet		シューティング	Shooter/Shooting game 
0x07				::	Red Square		アドベンチャー	Adventure 
0x08				::	Blue Square (P)		プログラム	Program i.e. a full minigame, as opposed to additional data.
0x09				::	Green Square (D)	???		???
0x0A				::	Red Square (A)		アペンド		Additional minigame data.
0x0B				::	Brown Square (S)	???		???

Each mini game has two icons. The first describes the main type, "Program" for the main minigame, or "Append" for additional data or content. The 2nd icon describes the sub-type for the minigame. Apparently for minigame downloads, the main type is forcibly set to "Program". Byte 0x01 of the data structure controls only the 2nd icon, the sub-type. In that regard, only values of 0x00 through 0x07 are contextually correct. It should also be noted that two other main types seem to exist (the Green and Brown squares), but they are unused, or at least have no mention whatsoever in the game manual.

[Net de Get] : cgb/download?name=/A4/CGB-BMVJ/*

The GB Mobile Adapter attempts to access this URL for downloading minigames. The file containing the minigame is appended to the base URL. The appended part should be 12 characters, 4 for the price in yen, followed by 8 characters for rest of the unique ID. Although it is unknown if this really was the case, it would make sense to use the minigame ID (e.g. "G000") along with ".cgb". Thus a full URL would be something like:

http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/1234G000.cgb

Note that the filename of the minigame should start with numbers (the price) since this indicates a service fee for the download. The server responds with the required binary data. Net de Get will blindly receive data, regardless of what it is. That is to say, no error checking of the minigame itself is done during the download phase.

[Net de Get] : Download Wrapper

Rather than simply downloading the minigame data as-is, Net de Get expects minigames to have come in a sort of wrapper file. This consists of a brief header followed by the actual minigame data as described in the next section below. The wrapper header is as follows:

0x00:				::	Offset to the rest of the wrapper data. This is the 1-byte value + 1, so 1-256.
Offset + 0x00			::	???
Offset + 0x01			::	For most minigame downloads, this should be 0x00. When set to 0x05, it seems to do a block-fill operation on the MBC6 Flash ROM.
Offset + 0x02			::	???
Offset + 0x03			::	???
Offset + 0x04			::	Minigame size (low-byte).
Offset + 0x05			::	Minigame size (high-byte). Should not be zero.
Offset + 0x06			::	???
Offset + 0x07			::	???
Offset + 0x08 ...		::	Minigame data (as described below in Minigame Format).

The minigame is copied to various RAM locations (SRAM and WRAM) until it is finally written to Flash. A maximum of 0x200 bytes is copied at a time. The wrapper, however, expects a 0x100 "footer" to be inserted after each of the 0x200 chunks. This is only necessary if the minigame size is greater than 0x200 bytes. For example, if a minigame is only 0x100 bytes, then the footer can be ignored, although such a small size is rather impractical. Additionally, only the last footer technically needs to be correctly formatted. The default footer is as follows:

0x00, 0x00, 0x01, 0x00,
0x02, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00,
0x06, 0x00, 0x07, 0x00,
0x08, 0x00, 0x09, 0x00,
0x0A, 0x00, 0x0B, 0x00,
0x0C, 0x00, 0x0D, 0x00,
0x0E, 0x00, 0xFF, 0x00,
... (the remaining 224 bytes should be 0x00).

So in summary, the wrapper effectively looks like this:

Wrapper Header ->
	Minigame Data Chunk (0x200 max)
		Footer (0x100)
	Minigame Data Chunk (0x200 max)
		Footer (0x100)
	...

Note that the footer is written to SRAM later on, not flash. Improperly formatted footers may crash the game when booting or trying to access the minigame menu. There are other valid footers, but the default above is the only one tested extensively. It is currently unknown exactly how this data should be formatted.

[Net de Get] : Minigame Format

The minigame format is essentially the same as that found on the MBC6 ROM. Using the base address of the Flash ROM bank, minigames look like so:

0x00 - 0x02			::	Typically contains a JR or JP instuction.
0x05 				::	Number of memory blocks used by the minigame.
0x06				::	Primary minigame icon.
0x07				::	Secondary minigame icon.
0x09 - 0x0C			::	Game ID, simply in the format "Gxyz" where "xyz" are three numbers. E.g. the first minigame ID in the Net de Get ROM is "G000"
0x0F - ...			::	Text for game title. Null terminated, but nothing stops it from being too long. Text can technically spill over multiple lines.
0x24 - ...			::	Text for dialog box. Null terminated.
0x44				::	If this is 0xFF, it prints the game title, otherwise the title is blank. Oddly enough, the dialog box is unaffected and always printed.
0x6D - 0x6E			::	Always 0x3B, 0xB3. Acts like a watermark for valid minigames. Net de Get checks this specifically to tell if a game is on Flash ROM.
0x6F - ...			::	Code + Data.

Generally, the jump instruction goes right to Byte 0x6F, but not always. When the minigame is selected from the menu and the play (あそぶ) option is selected, the MBC6 switches Bank 0 (0x4000 - 0x5FFF) with Flash ROM, then performs a CALL 0x4000, which in turn executes the jump instruction and starts the minigame. It should also be noted that the downloaded minigame code is actually executed from Flash ROM rather than copying it somewhere else first like WRAM.

Unlike the previous icons from RomList.cgb, each minigame's primary icon can be specified. The secondary minigame icon is nearly identical to the format in RomList.cgb, but contains some variations:

----------------------------------
Primary Minigame Icon Type
----------------------------------
0x00				::	Gray Square (P)		プログラム	Program i.e. a full minigame, as opposed to additional data. Might be "disabled" since it's gray.
0x01				::	Blue Square (P)		プログラム	Program i.e. a full minigame, as opposed to additional data.
0x02				::	Green Square (D)	???		???
0x03				::	Green Square (D)	???		???
0x04				::	Red Square (A)		アペンド		Additional minigame data.
0x05				::	Gray Square (A)		アペンド		Additional minigame data (disabled?).
0x06				::	Gray Square (A)		アペンド		Additional minigame data (disabled?).
0x07				::	Gray Square (A)		アペンド		Additional minigame data (disabled?).
0x08				::	Brown Square (S)	???		???

----------------------------------
Secondary Minigame Icon Type
----------------------------------
0x00				::	Question Mark		不定その他	Unspecified other aka misc.
0x01				::	Boxing Glove		アクション	Action
0x02				::	Green Head		パズル		Puzzle
0x03				::	Running Person		オーソドックス	Orthodox aka Platformer?
0x04				::	Sword			アールピージー	RPG
0x05				::	Green Sheet		シミュレーション 	Simulation
0x06				::	Fighter Jet		シューティング	Shooter/Shooting game 
0x07				::	Green Square		アドベンチャー	Adventure

For the secondary icon, everything above 0x08 results in garbage tile data being drawn on-screen. 0x07 is the same icon as in RomList.cgb, except the color is now green instead of Red. Strangely enough, the game manual only shows the red version of that icon.

[Net de Get] : String Format

Blank entries represent values that are not used and can effectively be treated as spaces.

        0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
0x00
0x10         !    "    #    $    %    &    '    (    )    *    +    ‘    -    .    /
0x20    0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ?
0x30    [    ¥    ]    x    ÷    {    |    }    ˜    @    ⌜    ⌟    —    ~    、    。
0x40         A    B    C    D    E    F    G    H    I    J    K    L    M    N    O
0x50    P    Q    R    S    T    U    V    W    X    Y    Z    ✜    ‥    ^    _    ’
0x60         a    b    c    d    e    f    g    h    i    j    k    l    m    n    o
0x70    p    q    r    s    t    u    v    w    x    y    z    Ⓐ    Ⓑ


0x80    ぁ    あ    ぃ    い    ぅ    う    ぇ    え    ぉ    お    か    き    く    け    こ    さ        
0x90    し    す    せ    そ    た    ち    っ    つ    て    と    な    に    ぬ    ね    の    は
0xA0    ひ    ふ    へ    ほ    ま    み    む    め    も    ゃ    や    ゅ    ゆ    ょ    よ    ら
0xB0    り    る    れ    ろ    ゎ    わ    を    ん    →    ←    ↑    ↓    •
0xC0    ァ    ア    ィ    イ    ゥ    ウ    ェ    エ    ォ    オ    カ    キ    ク    ケ    コ    サ
0xD0    シ    ス    セ    ン    タ    チ    ッ    ツ    テ    ト    ナ    ニ    ヌ    ネ    ノ    ハ      
0xE0    ヒ    フ    ヘ    ホ    マ    ミ    ム    メ    モ    ャ    ヤ    ュ    ユ    ョ    ヨ    ラ 
0xF0    リ    ル    レ    ロ    ヮ    ワ    ヲ    ン    ☎    ♪    ☺    ☺    ★    ❤     ゚     ゙

A couple of things to note, since some characters listed are not quite the same in Unicode as they are on Net de Get:

[Net de Get] : MBC6 Flash Operation

The MBC6 writes games to Flash ROM for long-time data storage. Although technically it has a limited number of lifetime writes, it does not rely on a battery unlike cartridge SRAM for DMG/GBC games. The MBC6 uses the MX29F008TC-14. While no specific documentation about the MX29F008TC-14 is available, the following information has been reverse-engineered based on how Net de Get's code expects Flash ROM to work.

Zen Nihon GT Senshuken

General Information

Server Structure

gtconfig.cgb

gtrkconfig.cgb

100.gtexcrs***.cgb

gtgst00.cgb - gtgst06.cgb

Ghost Data

gtrk00.cgb - gtrk06.cgb

Rank Entry

[Zen Nihon GT Senshuken] : General Information

Zen Nihon GT Senshuken (released as Top Gear GT Championship in the west) is a behind-the-car racing game for the Game Boy Advance. It served as a launch title in Japan and supported the Mobile Adapter GB for several functions including downloading custom racetracks and ghost car data, as well as uploading race result to get ranked.

[Zen Nihon GT Senshuken] : Server Structure

Zen Nihon GT Senshuken is currently known to access the following URLs:

[Zen Nihon GT Senshuken] : gtconfig.cgb

This file configures downloads for additional courses, Time Trial Ghosts, and online mobile rankings. gtconfig.cgb is only 200 bytes (0xC8) in size, as the game will not process any data beyond that. The format is as follows:

----------------------------------
File Structure
----------------------------------
0x00	 			::	Unknown data.
0x01				::	Enables Time Trial Ghost downloads for select race tracks.
0x02				::	Numerical suffix for downloadable course
0x03				::	Unknown data.
0x04 - 0xC3			::	Dynamic URL data for mobile rank files. Uses ASCII characters.
0xC4 - 0xC7			::	A 32-bit checksum for all bytes from 0x00 - 0xC3. All bytes are added, one-by-one. Checksum stored LSB first.

When downloading Time Trial Ghosts, the game will display 7 menus, 1 for each race track. For Byte 0x01, each of the bits from Bit 0 through Bit 6 controls whether an individual track is enabled. Setting the bit to "0" enables it, while setting the bit to "1" disables it.

When downloading extra courses, Byte 0x02 is converted to Base 10 (decimal) and appended to the file name as a 3 digit number. For example, if the value of Byte 0x02 is 0x30, the game will download the file "100.gtexcrs048.cgb" for the course.

The dynamic URL data is an ASCII string terminated with a null character (0x00). The string points the game to the file gtrkconfig.cgb as well as the gtrk00.cgb through gtrk06.cgb files. Apparently, some portions of the string are ignored when the game makes the actual HTTP GET request. For example, if the string is "gameboy.datacenter.ne.jp/cgb/", the GET request only appears as "/cgb/". Any text prior to the first "/" character is effectively removed. This string is exclusively used for files related to mobile ranking.

[Zen Nihon GT Senshuken] : gtrkconfig.cgb

The purpose of this file is similar to gtconfig.cgb. It controls which menus to display for online mobile rankings. It has a total length of 8 bytes. The last 4 bytes compose a simple additive checksum of the file's first half. The format is as follows:

----------------------------------
File Structure
----------------------------------
0x00				::	Enables mobile rankings for select race tracks
0x01 - 0x03 			::	Unknown data.
0x04 - 0x07			::	A 32-bit checksum for all bytes from 0x00 - 0x03. All bytes are added, one-by-one. Checksum stored LSB first.

When downloading mobile rankings, the game will display 7 menus, 1 for each race track. For Byte 0x00, each of the bits from Bit 0 through Bit 6 controls whether an individual track is enabled. Setting the bit to "0" enables it, while setting the bit to "1" disables it.

[Zen Nihon GT Senshuken] : 100.gtexcrs***.cgb

This file represents a custom racetrack that can be downloaded from the servers and saved on the player's game cartridge. It is available through the Mobile Menu and selecting Course Download. A 100 yen service charge is attached to each download. The "***" part of the file name is replaced by Byte 0x02 of gtconfig.cgb when converted into a 3-digit decimal. The file length is 272 bytes total. The format is as follows:

----------------------------------
Racetrack Download Format
----------------------------------
0x0000 - 0x0003 		::	Unknown 32-bit value. Seems to be ignored.
0x0004 - 0x001B			::	10 character title plus terminating character. Uses a custom 16-bit character encoding.
0x001C - 0x010B			::	Racetrack data.
0x010C - 0x010F			::	A 32-bit checksum for all bytes from 0x0000 - 0x010B. All bytes are added, one-by-one. Checksum stored LSB first.

The format of the racetrack data is identical to the same data saved on the cartridge when a user creates their own custom track. Each racetrack consists of a 10x6 grid wherein blocks of the track are positioned. The binary data for the racetracks allocates 4 bytes for each block. Blocks are arranged left to right, top to bottom. The format is as follows:

----------------------------------
Racetrack Block Format
----------------------------------
0x00				::	Block Type. 0x01 = Straight Track, 0x02 = Turn, 0x03 = Starting Position.
0x01				::	Turn Type or Starting Position Type.
0x02				::	Must be 0x01 to signal a valid block.
0x03				::	Not used, reads 0x00.

Depending on whether the block is a turn or a starting position, Byte 0x01 has different meanings. They are listed below:

----------------------------------
Block Turn Types
----------------------------------
0x00				::	East-to-South turn.
0x01				::	South-to-West turn.
0x02				::	West-to-North turn.
0x03				::	North-to-East turn.

----------------------------------
Block Starting Position Types
----------------------------------
0x00				::	Start race facing East.
0x01				::	Start race facing South.
0x02				::	Start race facing West.
0x03				::	Start race facing North.

[Zen Nihon GT Senshuken] : gtgst00.cgb - gtgst06.cgb

These 7 files represent menus for different ghost data that can be downloaded. From this menu, the player can choose a specific ghost from a specific track and then proceed to save it to the game cartridge. Each file 0x9E4 bytes long. Together, they give the player access to 210 sets of ghost data for each of the 7 race courses available (30 per track). The file for each .cgb file is as follows

----------------------------------
Ghost Menu File Structure
----------------------------------
0x0000 - 0x0001			::	Year of last update, LSB first.
0x0002				::	Month of last update.
0x0003				::	Day of last update.
0x0004 - 0x0007			::	Unknown data.
0x000A - 0x09DF			::	Ghost Data Entries.
0x09E0 - 0x09E3			::	A 32-bit checksum for all bytes from 0x0000 - 0x09DF. All bytes are added, one-by-one. Checksum stored LSB first.

----------------------------------
Ghost Data Entries
----------------------------------
0x00				::	Unknown data.
0x01				::	Weather condition for ghost data (0 = Sunny, 1 = Rain). 
0x02				::	Car type used for ghost data.
0x03				::	Car transmission used for ghost data (0 = Automatic, 1 = Manual).
0x04 - 0x0B			::	Unknown data.
0x0C - 0x0D			::	Handicap Weight. 16-bit value stored LSB first. Max value is 990, game displays values as units of 10 (e.g. 10, 20, 30, 40...) May be zero.
0x0E - 0x23			::	Ghost Name. 10 characters plus terminating character. Uses a custom 16-bit character encoding.
0x24 - 0x27			::	Ghost Time. 32-bit value stored LSB first. See notes below on format
0x28 - 0x33			::	Unknown data.
0x34 - 0x55			::	URL to download the ghost data. Uses ASCII characters.

Each Ghost Data Entry takes up 84 bytes. Once the player selects an entry, the game goes on to download the file specified by the URL. The URL in the entry is limited to 32 characters. Ultimately, if the URL is something like "myghostfile.cgb", the game ends up downloading from the following address:

http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/myghostfile.cgb

The total time used for the ghost is stored in a 32-bit value. The overall time works based on 1/100s of a second. To calculate the total time, start counting at zero and add according to this table:

----------------------------------
Ghost Entry Time Format
----------------------------------
0x00				::	Time = Time + (1/100) * Byte Value
0x01				::	Time = Time + (256 * (1/100)) * Byte Value
0x02				::	Time = Time + (65536 * (1/100)) * Byte Value
0x03				::	Time = Time + (16777216 * (1/100)) * Byte Value

The maximum time alotted for any Ghost 99 minutes, 99 seconds, and 99 hundreths of a second.

[Zen Nihon GT Senshuken] : Ghost Data

The actual Ghost Data downloaded from the servers is saved to Flash RAM inside the cartridge. A fairly large portion of the 64KB of backup data is reserved just for Time Trial ghosts, and out of all the downloadable content, Ghost Data is potentially the largest. The file format is described below.

----------------------------------
Ghost Data File Format
----------------------------------
0x00				::	Race Track.
0x01				::	Weather condition for ghost data (0 = Sunny, 1 = Rain). 
0x02				::	Car type used for ghost data.
0x03				::	Car transmission used for ghost data (0 = Automatic, 1 = Manual).
0x04 - 0x0B			::	Unknown data.
0x0C - 0x0D			::	Handicap Weight. 16-bit value stored LSB first. Max value is 990, game displays values as units of 10 (e.g. 10, 20, 30, 40...) May be zero.
0x0E - 0x23			::	Ghost Name. 10 characters plus terminating character. Uses a custom 16-bit character encoding.
0x24 - 0x27			::	Ghost Time. 32-bit value stored LSB first. See notes above on format.
0x28 - 0x33			::	Unknown data.
0x34 - EOF			::	Track Movement Data.

The format for the metadata is largely the same as the ghost menu. Byte 0 is used here, however, to define the specific race track the ghost belongs to. This forces the game to run that exact course, regardless of which menu it was downloaded from online. A list of all possible options follows:

----------------------------------
Ghost Race Track Values
----------------------------------
0x00				::	Twin Ring Motegi
0x01				::	Fuji Speedway
0x02				::	Sportsland Sugo
0x03				::	Ti Circuit Aida
0x04				::	Central Park Mine Circuit
0x05				::	Suzuka Circuit
0x06				::	EDIT - 1st custom course name
0x07				::	EDIT - 2nd custom course name
0x08				::	EDIT - 3rd custom course name
0x09				::	Twin Ring Motegi (Mirror)
0x0A				::	Fuji Speedway (Mirror)
0x0B				::	Sportsland Sugo (Mirror)
0x0C				::	Ti Circuit Aida (Mirror)
0x0D				::	Central Park Mine Circuit (Mirror)
0x0E				::	Suzuka Circuit (Mirror)
0x0F				::	EDIT - (Mirror) 1st custom course name
0x10				::	EDIT - (Mirror) 2nd custom course name
0x11				::	EDIT - (Mirror) 3rd custom course name

Time Trial Ghost Data can apply to custom courses as well, thus allowing players of Zen Nihon GT to both download a unique track from the server as well as a ghost for it as well. Mirrored versions of each course is also available.

The Track Movement Data is a recording of a car's movements along the race course. For the downloaded file, it has the exact same format as regular Time Trial ghosts made locally by the player and saved on the cartridge. Zen Nihon GT essentially copy + pastes this section to Flash RAM as is.

No checksum is need for this file. The Track Movement Data uses 32-bit checksums periodically (approximately once every 4KB) to ensure data integrity, however.

[Zen Nihon GT Senshuken] : gtrk00.cgb - gtrk06.cgb

These files are the online mobile rankings. Players could sumbit their completion times for a certain race track (in the form of a Time Trial Ghost) and the fastest times would be listed for all to see. It was essentially a somewhat static leaderboard, as it required the player to manually send data to the servers. The exact URL is specified by the first string in gtconfig.cgb. Each file is 0xA34 bytes long. The format is as follows:

----------------------------------
Mobile Ranking File Format
----------------------------------
0x0000 - 0x0001			::	Year of last update, LSB first.
0x0002				::	Month of last update.
0x0003				::	Day of last update.
0x0004				::	Hour of last update.
0x0005				::	Minute of last update.
0x0006 - 0x0007			::	Unknown Data.
0x0008 - 0x0A2F			::	Mobile Rank Entries.
0x0A30 - 0x0A33			::	A 32-bit checksum for all bytes from 0x0000 - 0x0A2F. All bytes are added, one-by-one. Checksum stored LSB first.

Each file corresponds to a different race track and contains 50 entries. Each entry is 52 bytes long. The format of these entries (nearly identical to Ghost Data Entries) is as specified:

----------------------------------
Mobile Rank Entry
----------------------------------
0x00				::	Unknown Data.
0x01				::	Weather condition for ghost data (0 = Sunny, 1 = Rain).
0x02				::	Car type used for the race.
0x03				::	Car transmission used for the race (0 = Automatic, 1 = Manual).
0x04 - 0x0B			::	Unknown Data.
0x0C - 0x0D			::	Handicap Weight. 16-bit value stored LSB first. Max value is 990, game displays values as units of 10 (e.g. 10, 20, 30, 40...) May be zero.
0x0E - 0x23			::	Player Name
0x24 - 0x27			::	Course Completion Time. 32-bit value stored LSB first. Same format as Ghost Time, see notes above.
0x28 - 0x33			::	Unknown Data. Appears to be three 32-bit values that must be non-zero.

[Zen Nihon GT Senshuken] : Rank Entry

Players could enter their Time Trial Ghosts to participate in online mobile rankings. Zen Nihon GT transfers to Ghost Data to the server and the leaderboard would be updated. It is unknown if the process was manually handled by server administrators or if server-side software automatically parsed and sorted the fastest times. The game transmits the data as part of an email attachment via SMTP. The format of the sent email is as follows:

From: xxxxxxxx@yyyy.dion.ne.jp
To: 
Subject: GT-CHAMP-ENTRY
X-Game-code: AGB-AGTJ-00
X-Game-title: GT-CHAMP
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="--AGB-AGTJ"
----AGB-AGTJ
Content-Type: text/plain; charset=iso-2022-jp
Context-Transfer-Encoding: 7bit
-----------------------
【全日本GT選手権】でランキング登録が失敗している可能性があります。
-----------------------
----AGB-AGTJ
Content-Type: application/octec-stream; name="gtent**.cgb"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="gtent**.cgb"
DATA
DATA
DATA
----AGB-AGTJ--

The attached file varies depending on which race track was recorded in the Time Trial Ghost. The server will receive files from gtent00.cgb through gtent06.cgb.

The message, encoded as ISO-2022 JP translates to: "There is a possibility that ranking registration has failed in the [All Japan GT Championship]."