Dan Docs

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

windwakr - Various NDS peripheral reverse engineering

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

Link Cable Compatibility

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 is a rather bulky add-on that snaps on top of the original DMG (the gray "brick")
- Barcode Boy requires 2 AA batteries (with a DMG-01, that brings the total to 6 AA necessary to play any Barcode Boy game)
- Barcode Boy games are always labeled with a "B.B." logo with a little card.
- Includes a very, very short Link Cable
- Unlike the Barcode Taisen Bardigun reader, the Barcode Boy has no button. It is always "ON" when switched on, thus draining batteries even while not scanning

[Barcode Boy] : Compatible Games

Only 5 Barcode Boy games are known to exist:

- Battle Space
- Monster Maker Barcode Saga
- Kattobi Road
- Family Jockey 2
- Famista 3

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:

- Handshake -> Send [0x10, 0x07, 0x10, 0x07] : Receive [0xFF, 0xFF, 0x10, 0x07]
- Start Barcode Data Transmission -> [0x02]
- Stop Barcode Data Transmission -> [0x03]

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] : Link Cable Compatibility

The Barcode Boy requires 5V power via Pin 1 of the Link Cable. As such it is incompatible with all official Link Cables (DMG-04, MGB-008, MGB-010, and CGB-003) since each one lacks Pin 1. However, the Link Cable included with the Barcode Boy is a special case that does have Pin 1 present. When using the Barcode Boy's Link Cable, it is possible to connect it to a Game Boy Pocket/Light/Color system with the MGB-004, as the adapter exposes Pin 1.

[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 (DMG-ABEJ-JPN) and (DMG-ABEJ-JPN-1)
- MBC3 + RTC + Battery Saves (Same as Pokemon Gold and Silver)
- Compatible with DMG, SGB, and GBC systems
- Japanese-text only (hiragana/katakana only, a bit of a blessing given 8x8 fonts are not the best for kanji)
- Supports Link Cable for multiplayer
- Comes with 1 card-reader powered by 3 AAA batteries
- Comes with 5 cards bundled (only 3 have barcodes, the other 2 are just collectables?)
- Some cards come as cut-outs from a cardboard sheet
- Reader connects to DMG/GBC serial port for communication

[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 is a gray "hub" with 3 input ports for Gen 1 Link Cables.
- DMG-07 is largely designed for Gen 1 Link Cables and DMG models. MGB-010s allow any Game Boy (up to the Micro) to connect as Players 2-4.
- Player 1 comes with a built-in cable (Gen 1). All other players need extra cables.
- Player 1 needs to be a DMG model unless an MGB-004 adapter is used.
- DMG-07 uses a Motorola 402038 for multiplexing stuff.

[DMG-07] : Compatible Games

- America Oudan Ultra Quiz
- Chachamaru Panix
- Downtown Nekketsu Koushinkyoku: Dokodemo Daiundoukai
- Faceball 2000
- F1 Race
- F1 Pole Position
- Janshirou
- Janshirou II
- Jantaku Boy
- Jinsei Game Densetsu
- Nakajima Satoru F-1 Hero GB World Championship '91
- Nekketsu Koukou Dodge Ball-Bu
- Super Momotarou Dentetsu
- Super R.C. Pro-Am
- Top Rank Tennis
- Trax
- Trump Boy II
- Uno: Small World
- Uno: Small World 2
- Wave Race
- Yoshi's Cookie

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.

- Zok Zok Heroes (CGB-BZHJ-JPN)
- MBC5 + Battery Saves
- GBC Only
- Comes with 1 Full Changer accessory
- Full Changer uses one CR2032
- Full Changer contains 4 Hall effect sensors to detect movement
- Full Changer has a series of status lights and blinks/beeps when swung correctly

[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 0xFF56 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 0xFF56 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 0xFF56 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 0xFF56 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 comes with one IR port. Capable of sending and receiving an IR signal (two separate diodes).
- Turning on the IR light does drain battery, hence not recommended to leave it on when not in use
- IR port can communicate with non-GBC devices, e.g. anything that sends an IR signal (TV remotes, Wiimotes, household lamps, etc)

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

    - The Adventures of the Smurfs				Exchange character portraits
    - Animal Breeder 3					Matchmaking between animals raised by the player
    - Animal Breeder 4					Exchange animals or have them marry
    - Austin Powers: Oh Behave!				Trade items and messages
    - Austin Powers: Welcome to My Underground Lair!	Trade items and messages
    - Bakuten Shoot Beyblade				Engage in 1-on-1 battles
    - Beyblade: Fighting Tournament				Trade Beyblades + parts. Engage in 1-on-1 battles
    - Boku no Camp-jou					Exchange money earned from hunting and fishing
    - Bomberman B-Daman Bakugaiden V: Final Mega Tune	Obtain different armor from TV remote signals
    - Bomberman Max: Blue Champion				Combine Charaboms/Trade completed levels/Unlock hidden areas
    - Bomberman Max: Red Challenger				Combine Charaboms/Trade completed levels/Unlock hidden areas
    - Carl Lewis Alhletics 2000				Ubi Key -> Unlocks Decathalon mode
    - Catz							Trade Petz and Toyz
    - Chee-Chai Alien					Enhances IR sensor to detect artificial light sources. Catch/trade Chaliens
    - Dancing Furby						Sends signal to Furby doll, Furby reacts based on dance performance
    - Data Navi Pro Yakyuu					Send/Receive baseball team data
    - Data Navi Pro Yakyuu 2				Send/Receive baseball team data
    - Dogz							Trade Petz and Toyz
    - Doki Doki Densetsu: Mahoujin Guru Guru		Fight card battles using magic circles from the game
    - Donkey Kong Country					Transfer pictures to stickerbook
    - Doraemon Memories - Nobita no Omoide Daibouken	Unlocks secret levels via TV remote input
    - Dr. Rin Ni Kiitemite!					Do fortune-telling with a friend and exchange stickers
    - Dungeon Savior					Transfer a Guardian from one game to another
    - Flipper & Lopaka					Ubi Key -> Unlocks a bonus "Ubi Key Level"
    - Game Boy Wars 3					Wireless multiplayer
    - GB Harobots						Create new Robo Data via infrared signals
    - Gran Duel: Shinki Dungeon no Hihou			Trade cards
    - Gyouten Ningen Batseelor: Dakutoru Gai no Yabo	Exchange collectible stickers
    - Hamster Paradise 3 (Churi)				Exchange e-mail
    - Hamster Paradise 4					Exchange hamsters
    - Hamtaro: Ham-Hams Unite!				Trade Hamtaro's clothes
    - Harry Potter and the Sorceror's Stone			Trade "Famous Witches and Wizards" cards
    - Harry Potter and the Chamber of Secrets		Trade "Famous Witches and Wizards" cards
    - Herohero-kun						Exchange personal profiles
    - Hunter x Hunter: Hunter no Keifu			Use "D-Trans" from Yu-Gi-Oh to meet Card Hunter Augu and unlock a hidden "Muuou" scenario
    - Hype: The Time Quest					Ubi Key -> Unlocks a bonus level
    - Inspector Gadget: Operation Madkactus			Ubi Key -> Unlocks a bonus level
    - Jisedai Begoma Battle Beyblade			Trade Beyblades
    - Kaijin Zona						Receive randomized puzzles via IR signals
    - Kakurenbo Battle Monster Tactics			Send/Receive Montaku. Wager Montaku via "takupon" game against another player
    - Konchuu Hakase 2					Exchange collectible insects
    - Lego Island 2						Swap trading cards
    - Lemmings VS						View Win/Loss records with other players
    - Lode Runner: Dom Dom no Yabou				Exchange custom-made levels
    - Looney Tunes Collector: Alert!			Wireless multiplayer for 3 minigames
    - Looney Tunes: Marvin Strikes Back!			Wireless multiplayer for 3 minigames
    - Love Hina Pocket					Trade custom-made stickers
    - Mary-Kate and Ashley Pocket Planner			Send and receive "G-mail" messages
    - Mickey's Racing Adventure				Send and receive messages. Unlocks a secret race track in Mickey's Speedway USA
    - Mickey's Speedway USA					Communicates with Mickey's Racing Adventure to unlock a secret race track
    - Mission Impossible					Send and receive messages, notes, addresses + custom TV remote
    - NHL Blades of Steel					Trade individual hockey players
    - NHL Blades of Steel 2000				Trade individual hockey players
    - Papyrus						Ubi Key -> Unlocks a bonus level
    - Perfect Dark						Trade multiplayer maps and other unlockables
    - Playmobil Interactive: Laura				Ubi Key -> Unlocks "Catch the Hazelnuts" minigame
    - Pocket Cooking					Exchange original dishes
    - Pocket Family GB 2					Transfer characters and data
    - Pocket Soccer						Trade individual soccer players
    - Pokemon Pinball					Trade/combine Top Scores
    - Pokemon Gold						Mystery Gift + Send trainer data to Viridian City Trainer House
    - Pokemon Silver					Mystery Gift + Send trainer data to Viridian City Trainer House
    - Pokemon Crystal					Mystery Gift + Send trainer data to Viridian City Trainer House
    - Pokemon Trading Card Game				"Card Pop" to generate random cards. Trade individual cards. Trade deck configurations
    - Pokemon Card GB2: Here Comes Team GR!			"Card Pop" to generate random cards. Trade individual cards. Trade deck configurations
    - Qui Qui						Battle against another opponent
    - Rayman						Ubi Key -> Unlocks secret level Ubi Cliff
    - Return of the Ninja					Trade "Ninja Cards"
    - Rugrats: Totally Angelica				Send/Receive messages, clothes, hairstyles, and accessories
    - The Road to El Dorado					Ubi Key -> Unlocks a secret level similar to Levels 6 and 7
    - Sakura Taisen GB					Send step-based "Points" to GBC from Pocket Sakura, or between two GBCs
    - Shin Megami Tensei Devil Children White		Used for "Infrared Fusion" to strengthen some demons, obtain rare ones
    - Soukoban Densetsu: Hikari to Yami no Yuni		Send/Receive custom-made levels/puzzles
    - Spirou: The Robot Invasion				Ubi Key -> Unlocks a bonus level
    - Super Black Bass: Real Fight				Exchange items like lures and tackles
    - Super Doll Licca-chan: Kisekae Daisakusen		Send/Receive clothes
    - Super GALS! Juran					Exchange "sign cards" with personal information and messages written on them
    - Super Mario Bros. DX					Trade/combine Top Scores
    - Super Mimel GB: Mimel Bear no Happy Town		Send e-mails to other players from Mimel Bear and gain extra points
    - Suzuki Alstare Extreme Racing				Ubi Key -> Unlocks the Extreme Championship mode
    - Sweet Ange						Send/Receive mail, commemorative photos, cards, and recipes
    - Taxi 2						Ubi Key -> Unlocks a special "Ubi Key" course
    - Tonic Trouble						Ubi Key -> Unlocks a bonus level/demo
    - Toonsylvania						Ubi Key -> Unlocks a bonus level with extra lives and items
    - Tottoko Hamtaro: Tomodachi Daisakusen Dechu		Used for a "friend finding" feature, matches other players to different hamsters
    - Tsuri Sensei 2					Trade items with other players
    - V.I.P.						Ubi Key -> Unlocks a bonus "Ubi Key Level"
    - Les Visiteurs						Ubi Key -> Unlocks a bonus "Ubi Key Level"
    - Warlocked						Trade wizards
    - Yu-Gi-Oh! Duel Monsters II: Dark Duel Stories		Connect to other players via "D-Trans" and receive special cards
    - Zok Zok Heroes					Transmit "Cosmic Characters" from Full Changer accessory to transform hero

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.

Although Hudson eventually adopted the GBC's native IR functionality over the HuC-1 and HuC-3, one of their games continued to offer GB KISS-like features. Jisedai Begoma Battle Beyblade calls its version "IR Kiss", however, it's mostly an exact copy of the standard GB KISS interface capable of sending and receiving files or messages. This remains incompatible with previous GB KISS titles due to the different positioning of the IR diodes in the GBC and HuC-1/HuC-3. As far as it is known, Hudson never developed IR Kiss after Jisedai Begoma Battle Beyblade.

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

- 1-Player Init: These only require one GBC to initiate IR transfers. Both GBCs typically wait for an infrared signal. When one player presses a button, the GBC starts sending pulses. This setup is not unlike how 2-Player Serial I/O is handled (with master and slave Game Boys). Examples include Super Mario Bros. DX score exchange and the GBC-to-GBC Mystery Gifts in Pokemon Gold/Silver/Crystal. Most IR compatible games fall into this group.
- 2-Player Init: Transfers require both GBCs to initiate at roughly the same time. Examples include Pokemon Pinball score exchange, Pokemon TCG's "Card Pop", and trading/fighting Charaboms in the Bomberman games.
- Active Object Init: Transfers require the GBC to interact with another non-GBC device capable of both sending and receiving infrared signals. These objects are designed to work specifically with GBCs and send pulses in much the same manner as a GBC would. Examples include Mystery Gifts via the Pokemon Pikachu 2 and trading Points via the Pocket Sakura.
- Inactive Object Init: Transfers require the GBC to interact with another non-GBC device capable of sending infrared signals but not necessarily receiving them. These objects may not be designed to work specifically with GBCs (notable exception is the Full Changer). Communication is input-only for these cases. Examples include Zok Zok Heroes, Chee Chai Alien, the Bomberman Max games' special stages, and Mission Impossible's TV remote feature.

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

- Comes in a long, bulky blue cartridge.
- Requires 4 AAA batteries to work, has ON/OFF switch + light.
- Sonar device attaches via a 3.5mm jack inside the cartridge.
- Sonar device has a super long cord, with yellow foam around the actual audio hardware.
- Manual says operating tempurature range (使用温度範囲) is between 5C and 50C (no ice fishing, do not use in a hot spring).
- Cartridge uses the MBC1S, virtually identical to the MBC1, but has sonar capabilities built-in.
- Officially capable of probing depths of 20m, but has an option for 30m.
- Internally, MBC1S is two PCBs (MBC and sonar) linked together by 5 soldered wires.

[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 Power Antenna + Bug Sensor are small, plastic add-ons that fit into the serial port of a GBC or GBA
- 3 versions exist, each one being specifically designed for Telefang 1, Telefang 2, or Bugsite
- Each version is virtually the same device in a different shell. Each of the above games can use any version of the Power Antenna or Bug Sensor*
- Depending on serial input from the game, the red LED will light up or turn off

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

- The Turbo File GB rectangular, black device about the size of a GBC.
- Data is transmitted via the Link Cable and Serial Input/Output.
- It has a slot at the top for accepting memory cards.
- The unit requires 4 AAA batteries to power on.
- Save data is flash-based (LH28F800BVE-TTL10 by Sharp) and therefore is not erased when removing batteries.
- The Turbo File GB comes with 1MB of internal storage separated into 8KB blocks.
- Each memory card is also 1MB of storage separated into 8KB blocks.
- A small red LED indicates R/W activity.
- Like other ASCII Turbo File Products, the Turbo File GB has a physical Write-Protect switch.
- The product code for the Turbo File GB is ASC-1501T.
- The product code for the memory card is ASC-1502C.

[Turbo File GB] : Compatible Games

- RPG Tsukuru GB
- Uchuu Nin Tanaka Tarou De RPG Tsukuru GB2

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

- Released for Singer's 150th anniversary.
- Has a compartment near the back to hold the Link Cable.
- Nearly identical to the Jaguar JN-100 in all physical aspects.
- Unlike the JN-2000, the IZEK 1500 lacks a connection for an embroidery arm. The power cable is also detachable.
- Comes in only 1 color (blue/teal).

Jaguar JN-100

- Nearly identical to the Singer IZEK-1500 in all physical aspects.
- Unlike the JN-2000, the JN-100 lacks a connection for an embroidery arm. The power cable is built in.
- Comes in 6 colors (pink, clear, pale green, blue, violet, orange).

Jaguar JN-2000

- Different body style from the JN-100 or IZEK-1500. Very similar to the Jaguar SP-3000 series or the Singer CE-200.
- Link Cable is not inside a compartment. It sits as part of a slot where the Game Boy is supposed to rest. Power cable is built in.
- Comes with an embroidery arm, the EM-2000.
- Comes in 1 color (red).

All machines are compatible with the single prong version YC-485 foot controller.

[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

- [x] IZEK-1500
- [x] JN-100
- [x] JN-2000

[#] Raku x Raku Mishin

- [x] IZEK-1500
- [x] JN-100
- [x] JN-2000

[*] Raku x Raku Moji

- [-] IZEK-1500
- [-] JN-100
- [!] JN-2000

[*] Raku x Raku Cut Shuu

- [-] IZEK-1500
- [-] JN-100
- [!] JN-2000

[*] Jaguar Mishin Sashi Senyou Soft: Mario Family

- [-] IZEK-1500
- [-] JN-100
- [!] JN-2000

[*] Kanji Shishuu

- [-] IZEK-1500
- [-] JN-100
- [!] JN-2000

[*] Kirby Family

- [-] IZEK-1500
- [-] JN-100
- [!] JN-2000

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

- Stitches preset patterns, custom patterns, buttonholes, and Latin characters.

Raku x Raku Mishin

- Stitches preset patterns, custom patterns, buttonholes, some Latin characters, and kana.

Raku x Raku Moji

- Embroiders kana, some Latin characters, and some kanji.

Raku x Raku Cut Shuu

- Embroiders designs (e.g. rocket ship, flowers, a dog, etc).

Jaguar Mishin Sashi Senyou Soft: Mario Family

- Embroiders various Mario-themed designs (mushroom, super star, Yoshi, etc).

Kanji Shishuu

- Embroiders kana, some Latin characters, and a wide range of kanji.

Kirby Family

- Embroiders various Kirby-themed designs (Waddle Dee, King DeDeDe, Adeleine, etc).

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

GB KISS LINK

General Hardware Information

Compatible Games

GBF Infrared Protocol Overview

GBF Infrared Protocol Low Level

GBF Infrared Protocol In-Depth

Nectaris Map Infrared Protocol

Nectaris GB Map Data

Nectaris PC Map Data

[GB KISS LINK] : General Hardware Information

The GB KISS LINK is an infrared modem that connects to PCs in order to send/receive data from Game Boys. It was made by Hudson and released on March 6, 1998. The unit sold through mail order to the ASCII Corporation and was compatible with select titles that featured HuC-1 and HuC-3 cartridge mappers. The infrared connectivity allowed data to flow freely between the user's PC and the Game Boys. It was most prominently used to transfer GBF files and Nectaris maps, some of which could be downloaded from Hudson's website.

- Unit came as a plain PCB protected only by a wrap-around plastic cover
- Powered by a single 9V battery
- Featured 2 infrared diodes for sending and receiving signals
- Connected to PC via D-SUB25 serial cable
- Required PC special Windows 95 software and drivers to use
- Officially uses the model number HC-749

[GB KISS LINK] : Compatible Games

Only a handful of games used HuC-1 and HuC-3 mappers. Within this group, an even smaller selection took advantage of the GB KISS LINK for downloadable content provided online by Hudson. The list below notes these titles along with what kinds of features were enabled by the GB KISS LINK.

Nectaris GB

- Mapper: HuC-1
- Downloading custom maps

Pocket Family GB

- Mapper: HuC-3
- Downloading custom alarm songs, a family photo event, and new characters

Other games are more broadly compatible with the GB KISS menu, a standardized menu that allows content to be shared between other Game Boys or via the GB KISS LINK. These, however, were not known to specifically have any downloadable content from Hudson.

- Daikaiju Monogatori: The Miracle of the Zone
- GBKiss Mini Games
- Pocket Bomberman
- Robot Poncots (Sun, Star, Moon, and Comic BomBom Versions)
- Super B-Daman Fighting Phoenix

All of the above titles (Nectaris GB and Pocket Family GB included) can access the GB KISS Menu, which can be used to send or receive GBF files. The sender or recipient can be another Game Boy or the GB KISS LINK. Nectaris GB, however, has a separate mode for transmitting map files. As a result, GBF and map files have different protocols.

[GB KISS LINK] : GBF Infrared Protocol Overview

The GB KISS LINK uses a specific protocol to communicate with GB KISS compatible software to transfer GBF files. This protocol appears to be the same regardless if the sender or receiver is a Game Boy or the GB KISS LINK. Below is a high-level description of how the protocol works:

    ----------------------------------------------------------------------------------------------------------------------
    Sender							| Receiver
    ----------------------------------------------------------------------------------------------------------------------
    1)  Read Receiver ID String				| 1)  Return ID String
    2)  Send Transfer Start Flag				| 2)  Get Transfer Start Flag
    3)  Start Session					| 3)  Wait
    4)  Send Title and Icon data				| 4)  Get Title and Icon Data, Return File Search Input + Echo
    5)  Search File						| 5)  Return File Metadata and Echo of Title and Icon data
    6)  Unknown Read					| 6)  Return Unknown Data
    7)  Prep File Data Transfer				| 7)  Wait
    8)  Send History Data					| 8)  Get History Data, Return ACK Data
    9)  Send File Data					| 9)  Get File Data, Return ACK Data
    10) End File Data Transfer				| 10) Return File Metadata and ACK Data
    11) Send Cartridge Code					| 11) Get Cartridge Code, Return ACK Data
    12) Send Transfer End Flag				| 12) Get Transfer End Flag
    13) End Session						| 13) End Session
    ----------------------------------------------------------------------------------------------------------------------

The sender dictates the flow of communications by sending a pair of "magic bytes" (0x48 and 0x75) along with a 10-byte command packet in the following format:

    ---------------------------------------------------------
    Byte	| Description
    ---------------------------------------------------------
    0	| Transfer Status
    1	| Command Byte
    2	| Local Address Lo
    3	| Local Address Hi
    4	| Remote Address Lo
    5	| Remote Address Hi
    6	| Data Operation Length
    7	| Parameter
    ---------------------------------------------------------

Transfer Status is a bit-field that alerts the receiver if any errors have occured on the sender's side. Most GB KISS LINK software, seem to ignore this as long as the value is non-zero. When transferring a GBF file, the sender normally uses a constant value of 0x30 for the Transfer Status.

The Command Byte tells the receiver what operation is being performed during the transfer. Its value indicates whether the receiver should wait for the next command or start returning data. There are a just a few commands used for GBF file transfers:

    ---------------------------------------------------------
    Command	| Description
    ---------------------------------------------------------
    0x00	| Start/Stop Session
    0x02	| Send Title and Icon Data
    0x03	| File Search
    0x04	| Start/Stop File Data Transer
    0x08	| Read Remote RAM
    0x0A	| Send File Data
    0x0B	| Write Remote RAM
    ---------------------------------------------------------

Local/Remote Addresses are often analogous to Source/Destination Addresses, depending on the command. This allows the sender to specify where in RAM to pull data and where to push it when the receiver gets it.

Data Operation Length specifies how many bytes a given command should read or write, if applicable. Some commands may repurpose this byte for other uses (such File Search).

The final byte is a miscellaneous parameter that changes context based on the command. For example, often times it is used to specify which slot within the GB KISS Menu the GBF file will be written to.

At the very end of a command packet, an 8-bit checksum is sent out. This is the sum of all previous 8 bytes bitwise complemented and incremented by 1:

    SUM = SUM OF ALL BYTES
    SUM = ~SUM
    SUM = SUM + 1

For any command that sends data, those bytes come immediately after the command packet checksum. Additionally, the data is requires its own checksum at the end. Altogether, a complete command from the sender will look like this:

    ---------------------------------------------------------
    1) Command Packet
    2) Command Checksum
    3) Data Bytes
    4) Data Checksum
    ---------------------------------------------------------

Between each command from the sender and response from the receiver, a brief handshake is exchanged between both sides. The values used for these handshakes changes depending on which side is currently sending data. The handshake is as follows:

    ---------------------------------------------------------
    Sending Data		| Receiving Data
    ---------------------------------------------------------
    0xAA			| 0x55
    0xC3			| 0x3C
    ---------------------------------------------------------

For example, when using the Read Remote RAM command, the sender initiates the handshake with the value 0xAA and waits for a 0x55 response. The sender then issues the byte 0xC3 and waits for a 0x3C response. When the receiver returns RAM data for the command, the roles are reversed. In this case, the sender must wait for the 0xAA and 0xC3 values and respond accordingly with 0x55 and 0x3C.

[GB KISS LINK] : GBF Infrared Protocol Low Level

Individual bytes are transferred MSB-first. In an ideal environment, pulses representing a "1" bit have an ON-OFF transition of ~720 CPU cycles. Pulses representing a "0" bit have an ON-OFF transition of ~460 cycles. These numbers likely do not reflect real-world infrared timings, however, they do illustrate what the software itself considers acceptable. The ON period should be around ~200 cycles at minimum. Certain portions of the infrared protocol have unusual timings, chiefly the handshakes in between commands, and so-called "pings" that happen in between command and data bytes.

Handshakes start with a dummy pulse typically lasting around ~560 cycles. Afterwards, each bit is transferred. Following the last bit is a final pulse about ~1220 cycles long, which acts as a sort of stop signal:

    ---------------------------------------------------------
    Handshake Pulses
    ---------------------------------------------------------
    560		| Dummy Pulse
    xxx		| Bits 7 - 0
    1220		| Stop Pulse
    ---------------------------------------------------------

When transitioning from the handshake to sending/receiving a command, the sender initiates another Dummy Pulse. The ON phase of this pulse should be rather long (~400 cycles seems safe). Before this pulse completes, the receiver will trigger a very brief "ping" pulse. This lasts about ~100 cycles on average. This ping is done for the magic bytes as well as every byte of the command packet. The final ping is used to send the Command Checksum. The ping pulse may be a bit longer when the receiver needs some additional time to process data. This is commonly observed when verifying checksums. In any case, the sender should still issue a Dummy Pulse and wait for the ping to finish.

[GB KISS LINK] : GBF Infrared Protocol In-Depth

This section will go through the entire protocol to transfer a GBF file step-by-step, outlining all of the data used by both the sender and receiver. Parts with "..." represent bytes with variable values. To begin, the sender constantly sends out the first byte of a handshake (0xAA) and briefly waits for a response. If there is no response, the process keeps looping until it the receiver is ready of the user quits the transfer manually. Once the receiver is detected, the handshake continues and afterwards the sender will request the receiver's ID with a Read Remote RAM command:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x08			| Command Byte (Read Remote RAM)
    0x02 - 0x03	| 0xCE00		| Local Address
    0x04 - 0x05	| 0xCE00		| Remote Address
    0x06		| 0x10			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| 0x1C			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

The receiver the responds with an ASCII string: "GB KISS MENU ". This string must be an exact match, otherwise the sender will fail to initialize continue after a certain point. The receiver's response looks like this:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x00			|
    0x01		| 0x02			|
    0x02 - 0x0F	| "GB KISS MENU "	| Receiver ID String
    0x10		| ...			| GB KISS Menu Slot Number
    0x11		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The receiver also sends the Slot Number where the GBF file will be written to the GB KISS Menu. After getting the receiver's ID, the sender will write a flag in the receiver's RAM indicating that a transfer is about to start:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x0B			| Command Byte (Write Remote RAM)
    0x02 - 0x03	| 0xCE00		| Local Address
    0x04 - 0x05	| 0xCE00		| Remote Address
    0x06		| 0x01			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| 0x28			| Command Checksum
    0x09		| 0x01			| Data Byte (Tranfer Start Flag)
    0x0A		| 0xFF			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

For all Write Remote RAM commands, the receiver simply responds with the Data Checksum it was sent. Next, the sender must begin the session as such:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x00			| Command Byte (Start/Stop Session)
    0x02 - 0x03	| 0xCE00		| Local Address
    0x04 - 0x05	| 0xCE00		| Remote Address
    0x06		| 0x01			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| 0x33			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

There is a significant delay (about 1/4 of a second) after starting a session, probably so both sides can prepare for the coming transfers as well as changing the background tiles to indicate on-screen to the users that the transfer has begun. Next, Title and Icon data is transferred from the sender's GBF file:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x02			| Command Byte (Send Title and Icon Data)
    0x02 - 0x03	| 0xC700		| Local Address
    0x04 - 0x05	| 0xC50C		| Remote Address
    0x06		| ...			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| ...			| Command Checksum
    0x09 - ...	| ...			| Title and Icon Data
    ...		| ...			| Title and Icon Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The length of Title and Icon Data is specified by the Byte 0x04 of the GBF file. The receiver responds with some data that can be used for the File Search function along with an echo of Title and Icon Data that was just sent:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x90			| Transfer Status
    0x01		| 0x00			|
    0x02  - 0x03	| 0xC500		| Remote Address
    0x04		| ...			| Title and Icon Length
    0x05		| 0xC4			|
    0x06  - 0x07	| 0x0000		|
    0x08		| ...			| Checksum
    0x09  - 0x12	| ...			| File Search Input
    0x13		| ...			| Title and Icon Length
    0x14  - 0x108	| ...			| Title and Icon Data
    0x109		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The Transfer Status here represents whether or not the receiver already has a GBF file that matches what the sender is trying to transfer. The value 0x80 means an existing file is present, which prompts the sender to confirm if the file will be sent anyway. The value 0x90 indicates no matching file is present. The actual content of the GBF file may be different or updated, something that isn't communicated when just sending the Title and Icon. This should be considered a preliminary check at best for users to detect duplicate files. All infrared activity is paused until the sender makes a choice to send the file or quit the transfer immediately.

The total length of this transfer is *ALWAYS* 265 bytes. Since the Title and Icon data will not fill up this space, it seems random RAM bytes are transferred towards the very end before the Data Checksum. The format for File Search Input is currently not known. Note that in the case that a GBF file does not have its own icon, only the Title data will actually be transferred. The 11 bytes sent here are copied and used by the sender later on.

If a duplicate file is not sent, the connection is closed and with a command to stop the current session. Otherwise, a new command is sent to indicate that the receiver will delete the current file and write the the incoming GBF file data (potentially moving it to a new slot as well).

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x06			| Command Byte (Continue File Transfer)
    0x02 - 0x03	| 0xC700		| Local Address
    0x04		| 0x10			|
    0x05		| 0x09			|
    0x06		| 0x08			|
    0x07		| 0x23			| Parameter
    0x08		| ...			| Command Checksum
    0x09 - ...	| ...			| Echo of File Search Input + Title and Icon Length/Data
    ...		| ...			| Echo Checksum
    ----------------------------------------------------------------------------------------------------------------------

This command essentially copies all the data from the original response to the Send Title and Icon Data command. It appears to force the receiver to accept the incoming file and mark the old data to be deleted. The 4 parameters after the Local Address are used for currently unknown purposes, however, they appear to be constant values, at least as far as most GB KISS transfers are concerned. Once this command is finished, the sender must repeat the above Send Title and Icon Data. At this point, the receiver's Transfer Status value will read 0x90.

After the Send Title and Icon Data command, the sender writes to the receiver's RAM:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x0B			| Command Byte (Write Remote RAM)
    0x02 - 0x03	| 0xCE00		| Local Address
    0x04 - 0x05	| 0xCE00		| Remote Address
    0x06		| 0x01			| Data Operation Length
    0x07		| ...			| Parameter (GB KISS Menu Slot Number)
    0x08		| ...			| Command Checksum
    0x09		| 0x05			| Data Byte (Tranfer Start Flag)
    0x0A		| 0xFB			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The parameter used above is the Slot Number for the GB KISS Menu. Again, the receiver responds with the Data Checksum that was just sent. The File Search command is called next:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x03			| Command Byte (File Search)
    0x02  - 0x03	| 0xC700		| Local Address
    0x04  - 0x05	| ...			| Raw File Size
    0x06		| ...			| GB KISS Menu Slot Number
    0x07		| ...			| GBF Flags
    0x08		| ...			| Command Checksum
    0x09  - 0x108	| ...			| File Search Input
    0x109		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The Raw File Size is the data within a GBF file *after* metadata has been stripped. That is to say, it's the data that comes after the File Size, Flags, Cartridge Code, Title+Icon Size, Creator Code, Title Data, Icon Data, and History Data. Depending on the GBF file, metadata can range in size from 6 to 256 bytes. The data following that is the "raw" data for a GBF file. Once again, the sender specifies the GB KISS Menu Slot Number. It also sets the GBF Flags, which is Byte 0x02 of the GBF file. File Search Input is an exact copy of the response data from the Send Title and Icon Data command, so this command is always 265 bytes total. The receiver sends the following data in response to the File Search command:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x80			| Transfer Status
    0x01		| 0x00			|
    0x02  - 0x03	| 0xC500		| Local Address
    0x04  - 0x05	| 0xC50C		| Remote Address
    0x06		| 0x00			|
    0x07		| ...			| ??? Used as a parameter for next Read Remote RAM command
    0x08		| ...			| Checksum
    0x09  - 0x0A	| ...			| ???
    0x0B		| 0x00			|
    0x0C  - 0x0D	| ...			| Metadata Size
    0x0E  - 0x0F	| ...			| Metadata Size
    0x10  - 0x11	| ...			| Total File Size
    0x12		| ...			| GBF Flags
    0x13		| 0xFF			|
    0x14		| ...			| Title and Icon Size
    0x15  - 0x108	| ...			| Title and Icon Data
    0x109		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

After this, the sender requests an unknown read from the receiver. It uses whatever parameter was previously Byte 0x07 of the above File Search response:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x08			| Command Byte (Read Remote RAM)
    0x02 - 0x03	| 0xCE00		| Local Address
    0x04 - 0x05	| 0xDFFC		| Remote Address
    0x06		| 0x02			| Data Operation Length
    0x07		| ...			| Parameter (Byte 0x07 from previous response data)
    0x08		| ...			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

The response data appears to be constant no matter what kind of GBF file is being transferred:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x05			|
    0x01		| 0x02			|
    0x02		| 0xFB			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

Next, the sender sends a command that appears to prep both sides to start uploading file data. Interestingly, History Data seems to be included as part of the file upload process despite being metadata:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x04			| Command Byte (Start/Stop File Data Transfer)
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xFFD2		| Remote Address
    0x06		| 0x2E			| Data Operation Length (no data sent, but this is the max length of History Data)
    0x07		| 0x00			| Parameter
    0x08		| 0x08			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

The receiver then sends an ACK packet of data:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x40			| Transfer Status
    0x01		| 0x01			|
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xFFD2		| Remote Address
    0x06 - 0x07	| ...			| Metadata Size
    0x08		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

Next, the sender transfers any History Data available. This command is always called even if the GBF file has no History Data. In that case, the Data Operation Length is simply zero.

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x0A			| Command Byte (Send File Data)
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xC600		| Remote Address
    0x06		| ...			| Data Operation Length (length of History Data)
    0x07		| 0x00			| Parameter
    0x08		| ...			| Data Checksum
    0x09 - 0x36	| ...			| History Data
    0x37		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The receiver returns the following ACK packet:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x80			| Transfer Status
    0x01		| 0x00			|
    0x02 - 0x03	| 0xC500		| Local Address
    0x04		| ...			| Length of History Data
    0x05		| 0xC4			|
    0x06		| ...			| Length of History Data
    0x07		| 0x00			|
    0x08		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

Finally, both sides are now ready to send the Raw File Data for a GBF file. The sender issues the Send File Data command for as many times as it takes to transfer the entire file. Each command can only transfer 256 bytes of file data at max. If the Data Operation Length is zero, that means the full 256 bytes are transferred. Any non-zero length indicates the very last bytes of a file, assuming it is not divisiable by 256. Additionally, the Parameter is always set to 0x01 while a file transfer is incomplete. The last transfer switches this parameter to 0x00.

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x0A			| Command Byte (Send File Data)
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xC600		| Remote Address
    0x06		| ...			| Data Operation Length (0x00 = 256 bytes)
    0x07		| 0x00 or 0x01		| Parameter (0x01 = Transfer in Progress, 0x00 = Final Transfer)
    0x08		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

For every one of these commands, the receiver sends an ACK packet in response. The first one is used while the file transfer is in progress, while the second is used for the final transfer:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x80			| Transfer Status
    0x01		| 0x00			|
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xC500 		| Remote Address
    0x06		| 0x00			|
    0x07		| 0x01			| Parameter
    0x08		| 0xF5			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x80			| Transfer Status
    0x01		| 0x00			|
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xC403 		| Remote Address
    0x06		| 0x03			|
    0x07		| 0x00			| Parameter
    0x08		| 0xF1			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

Once all the file data has been sent, the transfer is ended. There is a curious 16-bit value used after the Local Address, which is calculated as 0x03 - (File Size - Raw File Size). The command looks like this:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x04			| Command Byte (Start/Stop File Data Transfer)
    0x02 - 0x03	| 0xC50B		| Local Address
    0x04 - 0x05	| 0xFF0B		| 0x03 - (File Size - Raw File Size)
    0x06		| 0x00			| Data Operation Length (no data sent)
    0x07		| 0x00			| Parameter
    0x08		| 0xF2			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

Again, the receiver sends an ACK packet for the Start/Stop File Data Transfer command:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x40			| Transfer Status
    0x01		| 0x01			|
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xFF0B		| 0x03 - (File Size - Raw File Size)
    0x06 - 0x07	| ...			| Metadata Size
    0x08		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The last bit of data from the sender, oddly enough, is the Cartridge Code, Byte 0x03 of the GBF file:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x0A			| Command Byte (Send File Data)
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xC50A		| Remote Address
    0x06		| 0x01			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| 0x31			| Command Checksum
    0x09		| ...			| Cartridge Code
    0x0A		| ...			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The receiver sends this ACK packet afterwards:

    ----------------------------------------------------------------------------------------------------------------------
    Receiver Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x80			| Transfer Status
    0x01		| 0x00			|
    0x02 - 0x03	| 0xC500		| Local Address
    0x04 - 0x05	| 0xC401 		| Remote Address
    0x06		| 0x01			|
    0x07		| 0x00			| Parameter
    0x08		| 0xF5			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

Before finishing up communications, the sender sets the Transfer End Flag with a Write Remote RAM command:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x0B			| Command Byte (Write Remote RAM)
    0x02 - 0x03	| 0xCE00		| Local Address
    0x04 - 0x05	| 0xCE00		| Remote Address
    0x06		| 0x01			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| 0x28			| Command Checksum
    0x09		| 0x02			| Data Byte (Tranfer End Flag)
    0x0A		| 0xFE			| Data Checksum
    ----------------------------------------------------------------------------------------------------------------------

The receiver responds with the Data Checksum value. Now the transfer is just about complete. The very last command from the sender ends the session. Note that the command is exactly the same as starting it. No parameters have changed:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x00			| Command Byte (Start/Stop Session)
    0x02 - 0x03	| 0xCE00		| Local Address
    0x04 - 0x05	| 0xCE00		| Remote Address
    0x06		| 0x01			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| 0x33			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

[GB KISS LINK] : Nectaris Map Infrared Protocol

The infrared protocol used by Nectaris GB is much simpler than that used for GBF files. In this mode, the GB KISS LINK always takes on the role of sender, even if the map data itself is technically being transferred to it. The main difference is whether the GB KISS LINK reads remote RAM stored on the Game Boy or writes to it. The following steps are done when the GB KISS LINK communicates with the Game Boy:

    ----------------------------------------------------------------------------------------------------------------------
    GB KISS LINK						| Game Boy
    ----------------------------------------------------------------------------------------------------------------------
    1)  Read Receiver ID String				| 1)  Return ID String
    							|
    	** If ID is "RECEIVE" **			| 	** If ID is "RECEIVE" **
    	2a) Send 1st 256 bytes of map data		| 	2a) Receive 1st 256 bytes of map data
    	3a) Send 2nd 256 bytes of map data		| 	3a) Receive 2nd 256 bytes of map data
    							|
    	** If ID is "TRANCE" **				|	** If ID is "TRANCE **
    	2b) Receive 1st 256 bytes of map data		|	2b) Send 1st 256 bytes of map data
    	3b) Receive 2nd 256 bytes of map data		|	3b) Send 2nd 256 bytes of map data
    							|
    4) End Session						| 4) End Session
    ----------------------------------------------------------------------------------------------------------------------

When the user chooses to send or receive a map, Nectaris GB will write a short ASCII string in RAM and 0xD000. The GB KISS LINK will read this with the Read Remote RAM command. Depending on the value, the GB KISS LINK will then determine if it needs to send or receive a map. The device must issue 2 Write Remote RAM commands or 2 Read Remote SRAM commands as described below:

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x0B			| Command Byte (Write Remote RAM)
    0x02 - 0x03	| 0xD000 and 0xD100	| Local Address
    0x04 - 0x05	| 0xD000 and 0xD100	| Remote Address
    0x06		| 0x00			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| ...			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------
    Sender Bytes	| Value			| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| 0x30			| Transfer Status
    0x01		| 0x09			| Command Byte (Read Remote SRAM)
    0x02 - 0x03	| 0x4000+		| Local Address
    0x04 - 0x05	| 0x4000+		| Remote Address
    0x06		| 0x00			| Data Operation Length
    0x07		| 0x00			| Parameter
    0x08		| ...			| Command Checksum
    ----------------------------------------------------------------------------------------------------------------------

Sending maps from the GB KISS LINK to the Game Boy uses fixed addresses. The destination/source of the 1st 256 block of map data is at 0xD000. The destination/source of the 2nd block of map data is at 0xD100.

When the GB KISS LINK receives a map from the Game Boy, Nectaris GB will transfer a single byte after the "TRANCE" string. This value represents an offset to the map's data in SRAM. Map data is reserved for the 3rd SRAM bank, however, the Read Remote RAM command treats the entire 32KB as a single addressable block of memory. In other words, map data begins at 0x4000. The offset represents increments of 512 bytes. For example, an offset of 0x07 points to map data at 0x4E00.

Neither the Write Remote RAM commands nor the Read Remote SRAM commands appear to use the Parameter byte. When reading the ID string from a Game Boy, the Data Operation Length should be 0x07 at a minimum. Additionally, the length should be 0x00 when reading and writing each 256 byte block of map data.

[GB KISS LINK] : Nectaris GB Map Data

Nectaris GB largely separates unit placement data and terrain placement data. Unit placement data is saved in SRAM while terrain placement data is mostly hardcoded into ROM. Game Boy-to-Game Boy transfers primarily only deal with unit placement data. It is currently unknown if GB KISS LINK transfers are supposed to pull terrain data from Nectaris GB's ROM or if Hudson provided PC versions of these maps. These Game Boy-to-PC transfers via the GB KISS LINK were handled by Hudson's unit placement program, UnitEdit.exe. Maps measure in at 15x10 on-screen tiles.

The unit placement data for Game Boy maps follows this format:

    ----------------------------------------------------------------------------------------------------------------------
    Bytes		| Value		| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x0000 - 0x0005	| "NECTAR"	| Magic Bytes
    0x0006		| 0x20 - 0x47	| Map ID
    0x0007		| 0x04		| Map Type (Construction Map Data)
    0x0008 - 0x000D | ...		| Map Name
    0x000E - 0x000F | 0xFF		| Padding?
    0x0010 - 0x0013 | 0x00		| Padding?
    0x0014 - 0x002B | ...		| Terrain Data
    0x002C - 0x017B | ...		| Unit Data
    0x017C - 0x017D | ...		| Cursor Position
    0x017E - 0x017F | 0x00		| Unknown Data
    0x0180 - 0x01E3 | 0xFF		| Padding?
    0x01E4 - 0x01FE | 0x00		| Padding?
    0x01FF		| ...		| Checksum
    ----------------------------------------------------------------------------------------------------------------------

The Map ID determines which set of terrain data from ROM is used for a given map. Indexing begins at 0x20 and can access all 40 maps available for Nectaris GB. Campaign maps use lower values from 0x00 to 0x1F, although Nectaris GB does not appear to allow editing campaign maps.

The Map Type determines how the map will be interpreted by Nectaris GB. For example, other values signify a campaign or multiplayer map. For GB KISS LINK transfers, this value is meant to be constant.

The Map Name is a 6-byte ASCII field. For construction map data, this field typically contains the name "EMAPxx" where "xx" is the string "01" through "40". Campaign maps use their 6-character names here.

A very small amount of terrain data is alotted for construction map data. These are often used to put factories on the map, although the format allows for any kind of terrain (mountains, bridges, valleys, etc) to appear. These tiles will overwrite any of the original terrain data found from ROM. The format of terrain data is as follows:

    ----------------------------------------------------------------------------------------------------------------------
    Bytes		| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| X Coordinate
    0x01		| Y Coordinate
    0x02		| Terrain Type
    ----------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------
    Value		| Terrain Type
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| Flat Land
    0x01		| Road
    0x02		| Hill
    0x03		| Wasteland
    0x04		| Valley
    0x05		| Mountain
    0x06		| Bridge
    0x07		| Bridge
    0x08		| Union Base
    0x09		| Guicy Base
    0x0A		| Union Factory
    0x0B		| Guicy Factory
    0x0C		| Nuetral Factory
    ----------------------------------------------------------------------------------------------------------------------

There are 336 bytes dedicated to the actual units placed on a map. Data for each unit uses 6 bytes. As a result, a maximum of 56 units may be placed on any given map. The format of unit data is as follows:

    ----------------------------------------------------------------------------------------------------------------------
    Bytes		| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| Unit Type
    0x01		| X Coordinate
    0x02		| Y Coordinate
    0x03		| Unit Level
    0x04		| 0xFF
    0x05		| Unit Quantity
    ----------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------
    Value		| Unit Type (Translated Codename)
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| M77 (Porcupine)
    0x01		| FX-1 (Falco)
    0x02		| AX-87 (Javi)
    0x03		| EF-88 (Hunter)
    0x04		| T-79 (Grizzly)
    0x05		| PT-6 (Armadillo)
    0x06		| S-61 (Bison)
    0x07		| GS-81 (Slug)
    0x08		| GT-86 (Monster)
    0x09		| HMB-2 (Giant)
    0x0A		| TT-1 (Lenet)
    0x0B		| SG-4 (Nashorn)
    0x0C		| MR-22 (Estol)
    0x0D		| MB-5 (Rabbit)
    0x0E		| MB-4 (Lynx)
    0x0F		| AAG-4 (Seeker)
    0x10		| MM107 (Hawkeye)
    0x11		| SS-80 (Monoculus)
    0x12		| GX-77 (Munks?)
    0x13		| GX-87 (Dabek?)
    0x14		| CBX-1 (Draper)
    0x15		| NC-1 (Mule)
    0x16		| C-61 (Pelican)
    ----------------------------------------------------------------------------------------------------------------------

Setting Bit 7 of the Unit Type byte will add that unit to the Guicy forces. Otherwise, if Bit 7 is unset, the unit will be added to the Union forces.

When construction map data is saved, the X/Y Coordinates of the cursor are also stored. Nectaris GB, however, does not appear to use the data to restore the cursor position when opening a map to edit (nor does it appear to be used when saving map data for campaign battles).

The checksum is a simple 8-bit value calculated by adding all bytes from 0x0000 to 0x01FE. This bytes must be correct, otherwise Nectaris GB will raise an error when receiving maps from the GB KISS LINK.

[GB KISS LINK] : Nectaris PC Map Data

The PC version of Nectaris combines terrain and unit placement data into a single file, unlike Nectaris GB. As a result, each PC map is completely self-contained, however, there is no fixed size either. There are 2 different formats depending on the version used:

    ----------------------------------------------------------------------------------------------------------------------
    Bytes		| Value		| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x0000 - 0x000F | "NEC MAP 1.0"	| Magic Bytes
    0x0010 		| ...		| Map Width
    0x0011		| ...		| Map Height
    0x0012 - ...	| ...		| Terrain Data
    ...    - ...	|		| Unit Data
    EOF		| 0xFF		| EOF Marker
    ----------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------
    Bytes		| Value		| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x0000 - 0x000F | "NEC MAP 1.1"	| Magic Bytes
    0x0010 - 0x0015 | ...		| Map Name
    0x0016 - 0x0017 | 0x00		| Padding?
    0x0018		| ...		| Map Width
    0x0019		| ...		| Map Height
    0x001A - ...	| ...		| Terrain Data
    ...    - ...	| ...		| Unit Data
    EOF		| 0xFF		| EOF Marker
    ----------------------------------------------------------------------------------------------------------------------

The first version omits the Map Name. Additionally, it uses a more compact data format for terrain and unit data. In both versions, terrain bytes are ordered starting from the top-left and ending at the bottom-right of the map. Each row of the map is stored one after the others. The difference between versions is that V0 uses simple 8-bit values for each terrain tile. V1, however, pads this out to 16-bits, where the 2nd byte is 0x00. A typical 16x11 map, for example, will have exactly 176 bytes of terrain data in V0 and 352 in V1. Both versions use the following format for units data:

    ----------------------------------------------------------------------------------------------------------------------
    Bytes		| Description
    ----------------------------------------------------------------------------------------------------------------------
    0x00		| Unit Type
    0x01		| X Coordinate
    0x02		| Y Coordinate
    ----------------------------------------------------------------------------------------------------------------------

Unit Types use the same format as Nectaris GB (see section above). Once again, setting Bit 7 of the Unit Type byte makes the unit part of the Guicy army, while leaving Bit 7 unset makes the unit part of the Union Army. Terrain data is a bit more elaborate than Nectaris GB. More tiles are available for the PC version, allowing it to show greater details like craters, large boulders, and complex roads. The following is a list of which values generates specific terrain data. Note that road orientations are described as routes according to clock-wise compass directions (North first, East, South, then West).

    ----------------------------------------------------------------------------------------------------------------------
    Value		| Terrain Type					| Road Shape (if applicable)
    ----------------------------------------------------------------------------------------------------------------------
    0x01		| Mountain					|
    0x02		| Mountain					|
    0x03		| Mountain					|
    0x04		| Mountain					|
    0x05		| Mountain					|
    0x06		| Mountain					|
    0x07		| Wasteland					|
    0x08		| Mountain					|
    0x09		| Flat Land					|
    0x0A		| Mountain					|
    0x0B		| Flat Land					|
    0x0C		| Mountain					|
    0x0D		| Mountain					|
    0x0E		| Flat Land					|
    0x0F		| Mountain					|
    0x10		| Mountain					|
    0x11		| Mountain					|
    0x12		| Flat Land					|
    0x13		| Mountain  (Single Tile)			|
    0x14		| Flat Land					|
    0x15		| Flat Land					|
    0x16		| Mountain					|
    0x17		| Mountain					|
    0x18		| Mountain					|
    0x19		| Mountain					|
    0x1A		| Flat Land					|
    0x1B		| Flat Land					|
    0x1C		| Wasteland					|
    0x1D		| Flat Land					|
    0x1E		| Mountain					|
    0x1F		| Mountain					|
    0x20		| Mountain					|
    0x21		| Mountain					|
    0x22		| Mountain					|
    0x23		| Flat Land					|
    0x24		| Flat Land					|
    0x25		| Flat Land					|
    0x26		| Mountain					|
    0x27		| Mountain					|
    0x28		| Mountain					|
    0x29		| Flat Land					|
    0x2A		| Flat Land					|
    0x2B		| Mountain					|
    0x2C		| Mountain					|
    0x2D		| Flat Land					|
    0x2E		| Mountain					|
    0x2F		| Mountain					|
    0x30		| Mountain					|
    0x31		| Flat Land					|
    0x32		| Flat Land					|
    0x33		| Horizontal Road, Flat Land on North Side	| ━
    0x34		| Flat Land					|
    0x35		| Flat Land					|
    0x36		| Mountain					|
    0x37		| Mountain					|
    0x38		| Flat Land					|
    0x39		| Flat Land					|
    0x3A		| Flat Land (Single Tile)			|
    0x3B		| Flat Land					|
    0x3C		| Flat Land					|
    0x3D		| Flat Land					|
    0x3E		| Flat Land					|
    0x3F		| Mountain					|
    0x40		| Wasteland					|
    0x41		| Wasteland					|
    0x42		| Wasteland					|
    0x43		| Wasteland					|
    0x44		| Hill						|
    0x45		| Hill (Single Tile)				|
    0x46		| Flat Land					|
    0x47		| Flat Land					|
    0x48		| Wasteland					|
    0x49		| Wasteland					|
    0x4A		| Wasteland					|
    0x4B		| Hill						|
    0x4C		| Hill						|
    0x4D		| Hill 						|
    0x4E		| Flat Land					|
    0x4F		| Flat Land					|
    0x50		| Wasteland					|
    0x51		| Wasteland					|
    0x52		| Wasteland					|
    0x53		| Flat Land					|
    0x54		| Hill						|
    0x55		| Hill						|
    0x56		| Flat Land (Crater)				|
    0x57		| Flat Land (Crater)				|
    0x58		| Wasteland					|
    0x59		| Wasteland					|
    0x5A		| Hill						|
    0x5B		| Hill						|
    0x5C		| Hill						|
    0x5D		| Hill						|
    0x5E		| Flat Land (Crater)				|
    0x5F		| Flat Land (Crater)				|
    0x60		| Union Base					|
    0x61		| Mountain					|
    0x62		| Guicy Base					|
    0x63		| Guicy Factory					|
    0x64		| Flat Land					|
    0x65		| Hill						|
    0x66		| Flat Land					|
    0x67		| Flat Land					|
    0x68		| Flat Land					|
    0x69		| Wasteland					|
    0x6A		| Hill						|
    0x6B		| Flat Land					|
    0x6C		| Flat Land					|
    0x6D		| Hill						|
    0x6E		| Hill						|
    0x6F		| Flat Land					|
    0x70		| Neutral Factory				|
    0x71		| Flat Land					|
    0x72		| Hill						|
    0x73		| Wasteland					|
    0x74		| Hill						|
    0x75		| Union	Factory					|
    0x76		| Flat Land					|
    0x77		| Flat Land					|
    0x78		| Mountain					|
    0x79		| Flat Land					|
    0x7A		| Mountain					|
    0x7B		| Wasteland					|
    0x7C		| Flat Land					|
    0x7D		| Union Factory					|
    0x7E		| Flat Land					|
    0x7F		| Mountain					|
    0x80		| Mountain					|
    0x81		| Mountain					|
    0x82		| Mountain					|
    0x83		| Mountain					|
    0x84		| Mountain					|
    0x85		| Mountain					|
    0x86		| Flat Land					|
    0x87		| Flat Land					|
    0x88		| Mountain					|
    0x89		| Mountain					|
    0x8A		| Flat Land					|
    0x8B		| Flat Land					|
    0x8C		| Mountain					|
    0x8D		| Flat Land					|
    0x8E		| Guicy Base					|
    0x8F		| S-SE Elbow Road (Leads to Guicy Base)		| ┗
    0x90		| Hill						|
    0x91		| Hill						|
    0x92		| Hill						|
    0x93		| Mountain					|
    0x94		| Mountain					|
    0x95		| NE Road (Leads to Guicy Base)			| /
    0x96		| Vertical Road (Leads to Guicy Base)		| ┃
    0x97		| Mountain					|
    0x98		| Flat Land					|
    0x99		| Valley					|
    0x9A		| Valley					|
    0x9B		| T-Junction Road				| ┳
    0x9C		| Valley					|
    0x9D		| Horizontal Road (Guicy Base on South Side)	| ━
    0x9E		| Valley					|
    0x9F		| Mountain					|
    0xA0		| Valley					|
    0xA1		| Valley					|
    0xA2		| Valley					|
    0xA3		| Valley					|
    0xA4		| Valley					|
    0xA5		| Flat Land					|
    0xA6		| Wasteland					|
    0xA7		| Valley					|
    0xA8		| Valley					|
    0xA9		| Valley					|
    0xAA		| Valley					|
    0xAB		| Valley					|
    0xAC		| Valley					|
    0xAD		| Valley					|
    0xAE		| Valley					|
    0xAF		| T-Junction Road				| ┣╸
    0xB0		| Horizontal Road (Dead End on Right Side)	| ━
    0xB1		| Horizontal Road (Flat Land on South Side)	| ━
    0xB2		| Horizontal Road (Flat Land on North Side)	| ━
    0xB3		| Horizontal Road (Dead End on Left Side)	| ━
    0xB4		| NE->N Elbow Road				| ┛
    0xB5		| SE Road					| \
    0xB6		| E-NE and Horizontal Road			| ━<
    0xB7		| Valley					|
    0xB8		| NE Road					| /
    0xB9		| N->NE Elbow Road				| ┏
    0xBA		| NE->N Elbow Road				| ┛
    0xBB		| NE Bridge					| /
    0xBC		| Valley					|
    0xBD		| Vertical Road 				| ┃
    0xBE		| Vertical Road					| ┃
    0xBF		| Horizontal Road Neutral Factory to the North	| ━
    0xC0		| Mountain					|
    0xC1		| Mountain					|
    0xC2		| SE->S Elbow Road				| ┓
    0xC3		| Mountain					|
    0xC4		| Mountain					|
    0xC5		| N->SE and N->SW 3-Way Junction Road		| ⅄
    0xC6		| S-SE Elbow Road				| ┗
    0xC7		| Mountain					|
    0xC8		| Mountain					|
    0xC9		| Mountain					|
    0xCA		| Flat Land					|
    0xCB		| Flat Land					|
    0xCC		| Wasteland					|
    0xCD		| Flat Land					|
    0xCE		| Mountain					|
    0xCF		| Flat Land					|
    0xD0		| Mountain					|
    0xD1		| Wasteland					|
    0xD2		| Mountain					|
    0xD3		| Mountain					|
    0xD4		| Flat Land					|
    0xD5		| Mountain					|
    0xD6		| Mountain					|
    0xD7		| Flat Land					|
    0xD8		| Mountain					|
    0xD9		| Mountain					|
    0xDA		| Mountain					|
    0xDB		| Flat Land					|
    0xDC		| Mountain					|
    0xDD		| Flat Land					|
    0xDE		| Mountain					|
    0xDF		| Vertical Bridge				| ┃
    0xE0		| Valley					|
    0xE1		| Valley					|
    0xE2		| Valley					|
    0xE3		| Valley					|
    0xE4		| Mountain					|
    0xE5		| Mountain					|
    0xE6		| Mountain					|
    0xE7		| W-NW and Horizontal Road			| >━
    0xE8		| Flat Land					|
    0xE9		| Flat Land					|
    0xEA		| Mountain					|
    0xEB		| Flat Land					|
    0xEC		| Mountain					|
    0xED		| Mountain					|
    0xEE		| Mountain					|
    0xEF		| Mountain					|
    0xF0		| Flat Land					|
    0xF1		| Flat Land					|
    0xF2		| Mountain					|
    0xF3		| Mountain					|
    0xF4		| Mountain					|
    0xF5		| Mountain					|
    0xF6		| Flat Land					|
    0xF7		| Mountain					|
    0xF8		| Mountain					|
    0xF9		| Mountain					|
    0xFA		| Mountain					|
    0xFB		| Mountain					|
    0xFC		| Mountain					|
    0xFD		| Mountain					|
    0xFE		| Mountain					|
    0xFF		| Mountain					|
    ----------------------------------------------------------------------------------------------------------------------

Unlike maps for Nectaris GB, the PC version does not use checksums. Instead, the last byte of each file is simply 0xFF to mark EOF.

It is currently unknown exactly how Hudson's UnitEdit.exe program converted between GB and PC versions of maps and whether or not only certain types of maps were capable of conversion. An archived version of UnitEdit.exe still exists, however, this earlier version lacks the updates Hudson made to work with the GB KISS LINK. Many of the PC terrain types are used to add an increased level of detail and variety to maps, but they can be simplified to match the Game Boy versions.

Some of the above terrain types are marked as "Single Tile", meaning they represent the closest direct conversion to Nectaris GB, since the graphics occupy a single, isolated tile and are typically not meant to be stitched together with others.

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.

- Soul Doll Adapter is a small pod that connects to the GBA via a short Link Cable
- The adapter also has a locking mechanism to keep the Soul Doll in place
- Presumably compatible with all Soul Dollz manufactured*
- Each Soul Doll is a small plastic figurine with a built-in IC at the bottom
- Each Soul Doll uses a 24LC08 serial EEPROM controller, stores 1KB of data

*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
    0x317 - 0x318	| Extended Legend ID
    0x351		| Training Bonus
    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
    0x317 - 0x318	| Extended Legend ID
    0x351		| Training Bonus
    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. Some Soul Dolls use a longer ID that expands to 24-bits. This combines the 8-bit value from 0x302 and the 16-bit value from 0x317 - 0x318. This extension is stored MSB first. The chart below lists the Legendz obtainable via the extended IDs (format is 8-bit ID :: 16-bit extension):

    0x02 :: 0x002C = Blazedragon (A)?
    0x02 :: 0x0055 = Greedo Unawakened Version
    0x02 :: 0x0104 = Blazedragon (C)?
    0x02 :: 0x0122 = GW Nicol
    0x29 :: 0x004F = Griffin
    0x29 :: 0x005D = Griffin (Elemental Version)?
    0x29 :: 0x0163 = Griffin Zan Armed
    0x2A :: 0x0040 = Bigfoot
    0x2A :: 0x004B = Bigfoot (Elemental Version)?
    0x2A :: 0x013B = Bigfoot Cure Armed
    0x2F :: 0x0073 = Colonel Windragon (A)
    0x2F :: 0x0104 = Colonel Windragon Strike Armed
    0x2F :: 0x01E8 = True Windragon
    0x30 :: 0x0078 = Colonel Blazedragon (A)
    0x30 :: 0x0122 = Colonel Blazedragon Zoldyck Armed
    0x40 :: 0x0064 = Chibi Ranshiin
    0x40 :: 0x0140 = Ranshiin (A)?

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_2 & 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 Gates come in 3 hardware revisions: the original Battle Chip Gate, Progress Gate, and Beast Link Gate (Battle Network 4, 5, and 6 respectively).
- Each Battle Chip Gate accepts physical Battle Chips into a slot on the top or side of the unit (Progress Chip Gate and Beast Link Gate do the latter).
- Each Battle Chip Gate exposes a Link Cable port on its side, allowing for multiplayer while using the device.
- Each Battle Chip Gate uses semi-retractable clamps (similar the the GBA-GCN cable) to keep the unit stable and in place.
- Internally, Battle Chips are essentially simple electronic circuits. Their configuration effectively represents a numerical ID to the Battle Chip Gates, which the games then use.

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

- The MPOS is a small attachment that fits into the GBA serial port and has a circular slot for figurines
- Each figurine is entirely plastic, having no electronic parts whatsoever
- Each figurine has a hollow base with different spokes extending slightly from the bottom
- Once a figurine is inserted and secured inside the slot, these spokes push down on a sensitive pads beneath the surface
- Internally, the MPOS uses two Texas Instruments HC165 parallel load-shift registers to output data to the GBA serially

[Multi Plust On System] : Compatible Games

- Bouken Yuuki Pluster World: Densetsu no Plust Gate
- Bouken Yuuki Pluster World: Densetsu no Plust Gate EX
- Bouken Yuuki Pluster World: Pluston GP

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

There are 22 identified Pluster characters spread over 136 figurines. Each one is associated with a unique 16-bit ID that will generate that character in the games. There are multiple variants of figurines, therefore the Plusters themselves have multiple valid IDs, since the configuration of the spokes is different. These variants may grant special stat bonuses, for example stronger defense or offense in the RPGs, or faster acceleration or different color schemes in the racing game.

Figurines from the PF-EX series are only compatible with Bouken Yuuki Pluster World: Densetsu no Plust Gate EX. They will not be recognized by either Bouken Yuuki Pluster World: Densetsu no Plust Gate or Bouken Yuuki Pluster World: Pluston GP.

    ==============================================
    PF001 :: Beetma
    ==============================================
    Beetma Advance			0x1780
    Beetma Attack			0x1740
    Beetma Guard			0x16C0
    Beetma Extra			0x1720
    Beetma Power			0x1682
    Beetma Rare #1			0x1642
    Beetma Basic			0x1786
    Beetma Rare #2			0x1746

    ==============================================
    PF002 :: Wyburst
    ==============================================
    Wyburst Advance			0x16A0
    Wyburst Attack			0x1660
    Wyburst Guard			0x17E0
    Wyburst Extra			0x1710
    Wyburst Power			0x17C2
    Wyburst Rare #1			0x1622
    Wyburst Basic			0x16C6
    Wyburst Rare #2			0x1726

    ==============================================
    PF003 :: Gabrian
    ==============================================
    Gabrian Basic			0x1690
    Gabrian Attack			0x1650
    Gabrian Guard			0x17D0
    Gabrian Extra			0x1630
    Gabrian Power			0x17A2
    Gabrian Rare #1			0x1762

    ==============================================
    PF004 :: Molly
    ==============================================
    Molly Basic			0x1798
    Molly Attack			0x1758
    Molly Guard			0x16D8
    Molly Extra			0x1738
    Molly Power			0x16B2
    Molly Rare #1			0x1672

    ==============================================
    PF005 :: Hania
    ==============================================
    Hania Basic			0x1688
    Hania Attack			0x1648
    Hania Guard			0x17C8
    Hania Extra			0x1628
    Hania Power			0x1792
    Hania Rare #1			0x1752

    ==============================================
    PF006 :: Zagarian
    ==============================================
    Zagarian Basic			0x17A4
    Zagarian Attack			0x1764
    Zagarian Guard			0x16E4
    Zagarian Extra			0x1614
    Zagarian Power			0x16CA
    Zagarian Rare #1		0x172A

    ==============================================
    PF007 :: Tan Q
    ==============================================
    Tan Q Basic			0x1794
    Tan Q Attack			0x1754
    Tan Q Guard			0x16D4
    Tan Q Extra			0x1734
    Tan Q Power			0x16AA
    Tan Q Rare #1			0x166A

    ==============================================
    PF008 :: Wariarm
    ==============================================
    Wariarm Basic			0x17B0
    Wariarm Attack			0x1770
    Wariarm Guard			0x16F0
    Wariarm Extra			0x1708
    Wariarm Power			0x16E2
    Wariarm Rare #1			0x1612

    ==============================================
    PF009 :: Doryuun
    ==============================================
    Doryuun Basic			0x16B8
    Doryuun Attack			0x1678
    Doryuun Guard			0x17F8
    Doryuun Extra			0x1704
    Doryuun Power			0x17F2
    Doryuun Rare #1			0x160A

    ==============================================
    PF010 :: Fezard
    ==============================================
    Fezard Basic			0x17A8
    Fezard Attack			0x1768
    Fezard Guard			0x16E8
    Fezard Extra			0x1618
    Fezard Power			0x16D2
    Fezard Rare #1			0x1732

    ==============================================
    PF011 :: Mashanta
    ==============================================
    Mashanta Basic			0x1684
    Mashanta Attack			0x1644
    Mashanta Guard			0x17C4
    Mashanta Extra			0x1624
    Mashanta Power			0x178A
    Mashanta Rare #1		0x174A

    ==============================================
    PF012 :: Gingardo
    ==============================================
    Gingardo Basic			0x16B4
    Gingardo Attack			0x1674
    Gingardo Guard			0x17F4
    Gingardo Extra			0x160C
    Gingardo Power			0x17EA
    Gingardo Rare #1		0x171A

    ==============================================
    PF013 :: Torastorm
    ==============================================
    Torastorm Basic			0x178C
    Torastorm Attack		0x174C
    Torastorm Guard			0x16CC
    Torastorm Extra			0x172C
    Torastorm Power			0x169A
    Torastorm Rare #1		0x165A

    ==============================================
    PF014 :: Gongoragon
    ==============================================
    Gongoragon Basic		0x16AC
    Gongoragon Attack		0x166C
    Gongoragon Guard		0x17EC
    Gongoragon Extra		0x171C
    Gongoragon Power		0x17DA
    Gongoragon Rare #1		0x163A

    ==============================================
    PF015 :: Mighty V
    ==============================================
    Mighty V Basic			0x169C
    Mighty V Attack			0x165C
    Mighty V Guard			0x17DC
    Mighty V Extra			0x163C
    Mighty V Power			0x17BA
    Mighty V Rare #1		0x177A

    ==============================================
    PF016 :: Dorastorm
    ==============================================
    Dorastorm Basic			0x17BC
    Dorastorm Attack		0x177C
    Dorastorm Guard			0x16FC
    Dorastorm Extra			0x1702
    Dorastorm Power			0x16FA
    Dorastorm Rare #1		0x1606

    ==============================================
    PF-EX001 :: Beetma EX
    ==============================================
    Beetma EX Basic			0x1666
    Beetma EX Attack		0x17E6
    Beetma EX Guard			0x1716
    Beetma EX Extra			0x1696
    Beetma EX Power			0x1656
    Beetma EX Rare #1		0x17D6

    ==============================================
    PF-EX002 :: Varouze
    ==============================================
    Varouze Basic			0x1636
    Varouze Attack			0x17B6
    Varouze Guard			0x1776
    Varouze Extra			0x16F6
    Varouze Power			0x170E
    Varouze Rare #1			0x168E

    ==============================================
    PF-EX003 :: Gigajoule
    ==============================================
    Gigajoule Basic			0x164E
    Gigajoule Attack		0x17CE
    Gigajoule Guard			0x162E
    Gigajoule Extra			0x17AE
    Gigajoule Power			0x176E
    Gigajoule Rare #1		0x16EE

    ==============================================
    PF-EX004 :: Birdnick
    ==============================================
    Birdnick Basic			0x161E
    Birdnick Attack			0x179E
    Birdnick Guard			0x175E
    Birdnick Extra			0x16DE
    Birdnick Power			0x173E
    Birdnick Rare #1		0x16BE

    ==============================================
    PF-EX005 :: Poseihorn
    ==============================================
    Poseihorn Basic			0x167E
    Poseihorn Attack		0x17FE
    Poseihorn Guard			0x1701
    Poseihorn Extra			0x1681
    Poseihorn Power			0x1641
    Poseihorn Rare #1		0x17C1

    ==============================================
    PF-EX006 :: Tera
    ==============================================
    Tera Basic			0x1621
    Tera Attack			0x17A1
    Tera Guard			0x1761
    Tera Extra			0x16E1
    Tera Power			0x1611
    Tera Rare #1			0x1791

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 a rectangular, white device a little smaller than an AGB-001.
- Data is transmitted via the Link Cable and Serial Input/Output.
- It has a slot at the top for accepting memory cards.
- The unit requires 4 AAA batteries to power on.
- Save data is flash-based (LH28F800BVE-TTL10 by Sharp) and therefore is not erased when removing batteries.
- The Turbo File Advance comes with 1MB of internal storage separated into 8KB blocks.
- Each memory card is also 1MB of storage separated into 8KB blocks. Turbo File Advance memory cards are now blue instead of yellow.
- A small red LED indicates R/W activity.
- Like other previous ASCII Turbo File products, Sammy's Turbo File Advance has a physical Write-Protect switch.
- The product code for the Turbo File GB is SMY-1701TA.
- The product code for the memory card is SMY-1703EM.

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

- Derby Stallion Advance
- RPG Tsukuru Advance

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.

- The AGB-006 is a small attachment that fits into the GBA serial port providing IR functionalities
- Has 2 IR diodes, one for receiving and one for transmitting
- Very similar in size and shape to the connecting end of a DOL-011 (Gamecube-to-GBA cable)
- Compatible with CDZ-01 Diablotiger, CDZ-02 Cyclops, and CDZ-EX Diablotiger B

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

- The VRS is similar to other connection tracks like the Carrera 61512. It adds a bulkier hub, however.
- Uses 2 switches built into the each lane to provide digital lap counting.
- Uses 2 built-in Link Cables for GBA connectivity.
- Accepts 2 standard Carrera GO!!! hand controls.
- Must be powered externally, as opposed to many later Carrera connection tracks that use batteries.
- Uses a red LED light to indicate power-on and data transfer modes.
- Officially referred to as the Carrera 20802.

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

- Free Run: Used as a practice mode.
- Timed Run: 2-player race. Player with the most laps in a given time limits wins.
- Lap Race: 2-player race. Complete a given amount of laps. Player with lowest total time wins.
- Catch-Up: 2-player race. Players compete to lap one another.
- Ghost Race: Records 1 lap for a lane. The lap can be "played back" on that same lane while racing against it on another.
- Stop Watch: GBA acts as a stop watch, recording detailed lap time results.

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.

- Runs on a CR2032 battery. Appears sensitive to battery charge levels, and even alerts players when battery is low/unusable.
- Has one 3rd Generation Link Cable port to communicate with a GBA.
- Features a small 32x32 LCD dot matrix display for minor graphics.
- Uses 3 buttons (forward, back, select) for menu navigation and playing minigames.
- Produces sounds via built-in speaker.
- Functions as a regular watch with time of day, current calendar date, and alarms.

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

- Start Signal
- Data & Command Upload
- Data Download
- Stop Signal

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.

- Uses a Sharp LH28F800BLE to provide flash memory.
- Cartridge capacity is 8M / 1MB.
- Features a permanent 8KB read-only ID sector.
- Maps ROM data to upper end of address space.
- Comes in a purple plastic shell that is identical to other normal cartridges.
- Contains no EEPROM, SRAM, or FRAM. All save data is written via flash commands.

[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

Game Boy Player Copy Protection

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.

- Comes in an oversized black and white shell.
- Accepts SmartMedia cards from a slot on the side.
- The cartridge itself contains no hardware to accelerate audio/video playback. It is strictly for the GBA's CPU to read data.
- The cartridge has many hardware functions for reading and navigating FAT12 filesystems.
- The cartridge contains 12KB of firmware responsible for loading, decrypting, decoding, and playing media.
- The cartridge also has 5KB of firmware responsible for handling errors.
- Small "lock files" are encrypted with 128-bit DES as an anti-piracy measure. Each AM3 SmartMedia card has an ID that the adapter can retrieve.
- SmartMedia cards came in 32MB for TV shows/episodes, and 64MB for full-length movies.

[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 a 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 card 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 of 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-3		(R/W)		Operation Type
    ...
    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 5 operations available. Because Bit 0 of AM_BLK_STAT executes these operations, they can 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
    -----------------------------------------------------------

The most common operations are reading data blocks from SmartMedia Card or firmware. This simply maps data of a specified length from either source to AM_BLK_ADDR.

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.

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 command updates the current file size the CPU will read. When a new file is chosen, AM_FILE_SIZE *does not* update automatically. 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 12KB of Firmware

If the CPU tries to read more 12KB of firmware, the read pointer essentially resets itself as zero. Reading a 13th 1KB data block will simply read the 1st 1KB data block (e.g. the bootloader. Note that when reading the 12th 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 12KB 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] : Game Boy Player Copy Protection

In addition to the encrypted "lock file", the Advance Movie Adapter's firmware can also enable or disable compatibility with the Game Boy Player. Depending on the data on the SmartMedia card, publishers could choose whether or not they wanted to protect their videos from potentially playing on TVs (and thus susceptible to recording devices). Unlike the Game Boy Advance Video series by Majesco, not every video for the Advance Movie Adapter was locked down in this regard. For example, while the Pokemon videos prohibited use of the Game Boy Player, the Detective Conan episodes did not.

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

- Comes in an oversized black or white cartridge that hangs over the backside of a Game Boy Advance.
- Comes with a red LED at the bottom to indicate activity.
- Comes with a built-in microphone along with a Line-In port.
- Requires 1 AA battery to operate.
- Requires a CompactFlash card to operate.
- Internally, PCB is split into two main sections connected together.
- Supports audio output through a headphone jack.
- Supports playing MP3 files, recording voice memos as WAV files, and recording music/karaoke as custom GB3 files.
- Capable of operating independently from the Game Boy Advance. Has physical buttons to control playback.

[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

Firmware Update

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

- Features a normal-sized SD card reader.
- Can handle card capacities up to 2GB, depending on the manufacturer.
- Not compatible with SDHC, SDXC, or SDUC cards.
- Uses hardware decoding for media files via an Alpha Mosiac VC01.
- Uploads firmware on boot, and can optionally update with the correct files on an SD card.
- Features a slightly larger than normal cartridge shell.
- Has a 3.5mm audio jack to output sound and bypass the GBA's speakers.
- Generates video thumbnails and parses some ID3 tags (ID3v1 through ID3v2.4).
- Videos use ASF or MP4 containers with G.726 or AAC as audio codecs, respectively.
- Both ASF and MP4 files use MPEG-4 (MP4S) as the video codec.
- Maximum of 30 frames-per-second for video.
- The original version has 13 "Garage Games" built into the ROM, unlockable with special video files.

[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 I/O 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.

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 - Advance Frame			| Advance Frame Speed						| N/A
    0x904 - Resume Music/Video Playback	| N/A								| N/A
    0x905 - Seek Forwards/Backwards		| Seek Speed							| Seek Position
    0x906 - Sleep During Playback		| Sleep Status, 0 = Is Sleeping, 1 = Is Awake			| 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 - Check For Firmware		| N/A								| N/A
    0x8001 - Load Firmware			| 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 0x903 Advance Frame Command moves the current video playback position forward by the number of frames specified in Parameter 1. The Play-Yan software only ever uses a value of 0x01 for this command, thus in practice it always advances by a single frame. This command is used when video playback is paused. Note that there does not appear to be a corresponding command to step backwards by a given amount of frames while paused. The Play-Yan software somewhat gets around this by temporarily unpausing playback, calling the Seek Backwards command, and quickly pausing the video again.

- 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, values 0x01 - 0x03 moves forward; higher values skip ahead further. Values 0xFFFFFFFF through 0xFFFFFFFD move backwards; lower values rewind more. For the Play-Yan Micro, the parameters are 16-bit, therefore rewinding uses values 0xFFFF through 0xFFFD instead.

  Additionally for videos, when setting Parameter 1 to 0x00, Parameter 2 acts as a specific seek position. This allows video playback to jump to a fixed timestamp. The Play-Yan's software uses this feature to continue videos if the user exits before it finishes. The value of Parameter 2 appears to be a frame number. Note that while the Play-Yan software automatically records the frames count when exiting a video, it always restarts the playback several seconds (~5 to 6) prior to the exit. If a video is cancelled too early, the software won't even bother offering the user the option to continue playback and will simply restart from the beginning.

- The 0x906 Sleep During Playback command uses Parameter 1 to indicate whether the Play-Yan hardware should enter or exit Sleep Mode while playing music. Note that this Sleep Mode is different from the GBA's. Here, the cartridge will continously generate audio through its built-in headphone jack. After issuing the 0x906 command to enter Sleep Mode, the Play-Yan's software will separately put the GBA into a low-power mode Halt state. This command is also different from the 0x10000 Enter Sleep Mode command. Most importantly, 0x906 command does not generate Game Pak IRQs when exiting Sleep Mode. Additionally, this command is only available to the user when headphones are plugged in.

  The GBA and Play-Yan will briefly exit Sleep Mode when a song ends. The Play-Yan will generate a Game Pak IRQ for the 0x801 Stop Music Playback command at that time. The Play-Yan's software will then re-enter Sleep Mode on its own after a few seconds unless the user intervenes.

- 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 first 4 bytes of return data is simply 0x80000100 or 0x80001000. This signifies the end of certain internal operations within the Play-Yan, generally related to firmware loading, or audio/video playback. 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 - 1 IRQ
    -----------------------------------------------------------------------
    Bytes 0x00 - 0x03	| 0x40000200
    Bytes 0x04 - 0x07	| 0x01 or 0x02
    -----------------------------------------------------------------------

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 UTF-8 for kana and kanji)
    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 string encoding can be plain ASCII for Latin script, or UTF-8 when using Japanese characters.

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 - 1 IRQ
    -----------------------------------------------------------------------
    Bytes 0x00 - 0x03	| 0x40000201
    -----------------------------------------------------------------------

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 for Latin script or Shift-JIS for kana and kanji. While the Play-Yan supports parsing ID3v2 tags, it does not support several text encodings. Unicode strings are not recognized for this command. As such, the text encoding flag for a tag inside the actual MP3 should be 0x00 (for ISO-8859-1). Additionally, while this implies it should technically support extended ASCII characters, the Play-Yan does not have the font to render them.

    -----------------------------------------------------------------------
    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 0x10 - 0x13	| Audio Buffer Size
    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, updating the current playback position within a video, and updating the video's audio. The first IRQ initializes the process, while the second IRQ repeats indefinitely until the end of the video.

There are 2 distinct types of Game Pak IRQs generated continuously when playing a video file. The first updates video data and the current timestamp, while the second updates the audio data. If Audio Buffer Size is non-zero, only the audio is updated, otherwise video is updated. Do note that when headphones are plugged in, the Play-Yan only generates Game Pak IRQs that update video data.

The Current Video Position's value is expressed in milliseconds. As this IRQ fires every time a video frame needs to be displayed, the value incremented should match the video's framerate. E.g. for a video playing at 30 frames-per-second, the Current Video Position value increases by approximately 0x21 or 0x22. The video frame itself is read similarly to video thumbnails. Refer to the appropiate section below for more details. The size of the frame is the video's resolution on the GBA (typically 240x160) in 15-bit color pixels. Therefore, this value is usually 0x12C00.

Sample data is read from the SD Card Data interface. The data is equally split into left and right audio buffers. Typically, the buffer will always be 0x480 samples total unless the very end of a video has fewer than that remaining. Videos always use a sample rate of 8192Hz.

*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 - 1 IRQ
    -----------------------------------------------------------------------
    Bytes 0x00 - 0x03	| 0x40000701
    -----------------------------------------------------------------------

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.

There are 2 distinct types of Game Pak IRQs generated continuously when playing an audio file. The first updates audio samples that the GBA can read from a buffer and push out to its own speakers. The second updates the trackbar exclusively. The Play-Yan's audio processing hardware will alert the CPU when it has converted samples from an MP3 file into samples compatible with the GBA's DMA channels. Those samples can read from SD Card data. The maximum amount of samples the Play-Yan can buffer is 0x480 bytes.

For updating audio samples, only the bytes 0x10 through 0x13 need be non-zero. If those bytes are zero, then the Play-Yan software will interpret the IRQ data as representing an update to the trackbar, in which case bytes 0x14 through 0x1B should hold values appropiate for the current playback time. Do note that when headphones are plugged in, the Play-Yan only generates Game Pak IRQs that update the trackbar position. In this case, the Play-Yan's hardware handles pushing out audio samples, therefore an audio buffer is not needed.

Sample data is read from the SD Card Data interface. The data is equally split into left and right audio buffers. Typically, the buffer will always be 0x480 samples total unless the very end of a song has fewer than that remaining. Music always uses a sample rate of 16384Hz.

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

    -----------------------------------------------------------------------
    Command 0x801 - Stop Music Playback - 1 IRQ
    -----------------------------------------------------------------------
    Bytes 0x00 - 0x03	| 0x40000801
    -----------------------------------------------------------------------

Stops the current music file that is playing.

    -----------------------------------------------------------------------
    Command 0x2000 - Play Sound Effect - 1 IRQ*
    -----------------------------------------------------------------------
    Bytes 0x00 - 0x03	| 0x80001000
    Bytes 0x10 - 0x13	| Audio Buffer Size
    -----------------------------------------------------------------------

This command generates a brief sound effect from the Play-Yan. It is typically used for menus or when playing Garage Games. The default sound effect (something like a chirp) is the same in all instances. It is necessary for the Play-Yan itself to generate these 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 also determines whether or not the headphone jack or the GBA's speakers will be used as output. Samples for the sound effect are embedded within firmware, so the sound itself can be changed in theory.

Sound effects use an audio buffer much like music and videos do, with the same format. The audio buffer size of sound effects, however, is generally extremely short, measuring in at only 0x2BA samples. While the original Play-Yan uses a set sample rate of 8192Hz for sound effects, the Play-Yan Micro switches from 16384Hz during the intro animation to 8192Hz for all subsequent operations. Do note that these IRQs are not generated when headphones are plugged into the Play-Yan.

*This IRQ constantly fires for the duration of the sound effect.

    -----------------------------------------------------------------------
    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 - Check For Firmware - 1 IRQ
    -----------------------------------------------------------------------
    Bytes 0x00 - 0x03	| 0x40008000
    Bytes 0x08 - 0x0B	| Firmware File Status
    -----------------------------------------------------------------------

This command is used to determine if a firmware update file is present on the root of the SD card. If both Bit 0 and Bit 1 are set for the Firmware File Status, the Play-Yan software will take steps to load in the new firmware file. In this case, the Play-Yan's code also calls the 0x8001 command immediately after writing to firmware.

    -----------------------------------------------------------------------
    Command 0x8001 - Load Firmware - 1 IRQ
    -----------------------------------------------------------------------
    Bytes 0x00 - 0x03	| 0x80000100
    Bytes 0x04 - 0x07	| SD Card Status
    -----------------------------------------------------------------------

This command seems to load a firmware update file if it's present. 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 in general. Non-zero values for the SD Card Status represent specific errors. The Play-Yan will halt and display the following messages:

    -----------------------------------------------------------------------
    0x01	| カートリッジが調子悪いみたい...
    	| The cartridge seems to be in bad shape...
    -----------------------------------------------------------------------
    0x02	| SDカードが調子悪いみたい... 電源を切ってSDカードをチェックしてネ。
    	| The SD card seems to be in bad shape... Turn off the power and check the SD card.
    -----------------------------------------------------------------------
    0x03	| SDカードが入ってないヨ! 電源を切って SDカードを入れてネ。
    	| There's no SD card! Turn off the power and insert an SD card.
    -----------------------------------------------------------------------
    0x04	| ファイルがおかしいみたい。
    	| The file seems to be wrong.
    -----------------------------------------------------------------------
    0x05+	| エラーが出ちゃいました...
    	| An error occurred...
    -----------------------------------------------------------------------

This command is called at various points when the new firmware is apparently executing, such as during boot and when the user switches between Music and Video menus.

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

This command is issued shortly after the Check For Firmware command, and only if no firmware update file was found. Its purpose is currently unknown.

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.

Writing the value 0xA5A50032 to the firmware address 0x10000400 appears to generate a Game Pak IRQ. This is first done during boot, after the software has uploaded a copy of firmware from ROM to the Play-Yan. This special firmware write also occurs at various times when a firmware update file has been detected (notably before entering the Music or Videos menus). The response data for this IRQ is always 0x80000100, and the Play-Yan software will pause indefinitely until this IRQ is handled. However, this IRQ is not generated when the Play-Yan exits Sleep Mode. This special write seems to cause the Play-Yan to execute any data currently written to firmware.

[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. The Play-Yan will only use the first frame of a given video to generate a thumbnail.

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

[Play-Yan] : Firmware Update

Both the original Play-Yan and the Play-Yan Micro have the ability to update their internal firmware when the appropiate file is provided in the root directory of the SD card. This update is applied after the default firmware is loaded from ROM. Apparently the default firmware contains a hard-coded string that will be used for the update. The original Play-Yan looks for a file called "playan.fup", while the Micro version looks for a file called "play_yanmicro.fup".

Nintendo only ever released a firmware update file for the original Play-Yan, in July of 2005. The update added MP4 support (MPEG-4 as the video codec and stereo AAC as the audio codec), bringing the original model inline with the later Micro version. This firmware update file measures in at around 554KB and is still available to download from Nintendo's Japanese website. No firmware update file for the Play-Yan Micro is known to exist, however.

The following is the current working theory of how firmware update is processed:

1. Default firmware from ROM is loaded into firmware and executed at boot.

2. Later during boot, the 0x8000 command is issued to determine if a firmware update file is present.

3. If a firmware update file is present, a small portion of default firmware from ROM is rewritten and executed.

4. Immediately afterwards, the 0x8001 command is issued. This seems to automatically load and execute the firmware update file.

5. The Play-Yan's software checks the SD card status as reported by 0x8001 to make sure no errors occurred.

Steps 3 through 5 appear to repeat every time the user enters the Music or Videos menu. It is important to note that this happens only after boot, or when switching from Music to Videos or switching from Videos to Music. Exiting the Music menu and re-entering the Music menu, for example, does not trigger the above process. As the firmware file is quite massive for the GBA, it appears the firmware file is not read manually byte-by-byte (in contrast to the Nintendo MP3 Player). The 0x8001 command likely handles loading and validating the firmware update file.

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.

- Comes in an oversized white cartridge with an ovular top-end.
- Comes with a segmented LCD screen capable of displaying a few digits for glucose levels.
- Has "M" and "C" buttons on the sides of the LCD screen, which should work similarly to other glucose meters (e.g. FreeStyle Freedom Lite).
- Has a slot for accepting blood testing strips at the very top.
- Uses a coin cell battery, presumably to power the unit's glucose checking functions as well as an internal real-time clock.
- Has a USB slot on the lower side of the unit.
- The PCB is split into two main sections: top for glucose checking hardware, bottom for GBA ROM and EEPROM.
- Top PCB contains a Texas Instruments M430FG437, presumably used to handle glucose checking and managing the RTC.

[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

This index is used to write various information about the games (Lost Star Saga, Knock'em Downs, Solar Wing, Plexus, and Raccoon Rancher) to the Glucoboy. This appears to be data such as high scores and possibly time played. Although this information is stored in EEPROM as part of a normal game save, an additional copy is made for the Glucoboy internally. This index receives 6 additional bytes as parameters. Game Stats uses 60 bytes in total, so this index must be written to multiple times to complete the data.

The Glucoboy writes to Game Stats sequentially when using the 0xE1 index. That is to say, each time it writes data to the index, it moves onto the next category automatically until all 10 have been edited. The table below shows the order of each category and what each value represents:

    -----------------------------------------------------------
    Category 	| Description
    -----------------------------------------------------------
    VCSECS		| Number of seconds played for Lost Star Saga
    VCHIGH		| High Score for Lost Star Saga
    KDSECS		| Number of seconds played for Knock'em Downs
    KDHIGH		| High Score for Knock'em Downs
    SWSECS		| Number of seconds played for Solar Wing
    SWHIGH		| High Score for Solar Wing
    PLSECS		| Number of seconds played for Plexus
    PLHIGH		| High Score for Plexus
    RRSECS		| Number of seconds played for Raccoon Rancher
    RRHIGH		| High Score for Raccoon Rancher
    -----------------------------------------------------------

The index accepts two inputs spread across 6 bytes. The first is a 16-bit value followed by a 32-bit value. The 16-bit value appears to be constant, as the Glucoboy ROM always sets it to 0x3000. The 32-bit value represents the actual integer to write to a given category. Both of these inputs are written LSB-first, which stands in contrast to every other index.

When reading this index, it seems to act as a flag, and any non-zero value causes the Glucoboy to register and error when retrieving GRPs.

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.

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

[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 on the catridge data bus) some of the 16-bit values read from or written to the cartridge need to be adjusted in a very specific way. This documentation will refer to this process as "warping" and "unwarping". The former refers to reading 16-bit values from the Campho Advance and changing them to get the expected binary output. The latter refers to writing 16-bit values to the Campho Advance in a format it expects to receive. The math for warping and unwarping is specified below:

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

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

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

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

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

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

[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 - 0x03	| Data Length. Always 0x0004 (0x8000 when warped)
    0x04 - 0x05	| Internal Phone Function
    0x06 - 0x07	| Modem Status
    ------------------------------------------------------------------------

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

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

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

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

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

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

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

[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. The Modem Test is not mentioned at all in the Campho Advance's manual.

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

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

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

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

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

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

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

[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. The likely culprit is the novel way the Campho Advance streams ROM data, which conflicts with the DS firmware as it tries to read Slot-2 when turning on the system. Ultimately, the entire process on the DS differs significantly from the normal GBA BIOS startup routine, which the Campho Advance was heavily tailored around.

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

Nintendo MP3 Player

General Hardware Information

Hardware Registers

Accessing Firmware

Index Overview

Reading SD Card Data

Commands

Firmware Update

[Nintendo MP3 Player] : General Hardware Information

Following in the footsteps of the original Play-Yan and Play-Yan Micro, the Nintendo MP3 Player was launched in Europe on December 8, 2006. This unique cartridge was very similar to other products in the AGS-006 lineup. Now, however, the device played MP3 music files exclusively, getting rid of any video playback components. Due to this change, the underlying hardware and software had significant differences from the earlier Play-Yans.

- Features a normal-sized SD card reader.
- Can handle card capacities up to 2GB, depending on the manufacturer.
- Not compatible with SDHC, SDXC, or SDUC cards.
- Uses hardware decoding. Not an Alpha Mosaic VC01 like previous Play-Yan models.
- Uploads firmware on boot, and can optionally update with the correct files on an SD card.
- Features a slightly larger than normal cartridge shell.
- Has a 3.5mm audio jack to output sound and bypass the GBA's speakers.
- Can parse some ID3 tags (ID3v1, ID3v1.1, ID3v2, and mixed ID3v1/ID3v2 tags).
- Supports MP3 bits rates of 32k to 320k bps, CBR, VBR, and ABR.
- Supports sampling frequencies of 8KHz to 48KHz.

[Nintendo MP3 Player] : Hardware Registers

The Nintendo MP3 Player uses a very small selection of registers in the 0xE000000 memory region, relying on serial reads and writes to access firmware, send commands, and handle audio playback.

    ----------------------------------------------------------------------------------------------------------------------
    Hardware Register	|  Address	| Description
    ----------------------------------------------------------------------------------------------------------------------
    NMP_CONTROL		| 0xE000000	| Control register used to issue commands and send data to the cartridge.
    NMP_DATA_IN		| 0xE004000 	| Input data for the cartridge.
    NMP_DATA_OUT		| 0xE006000	| Output data from the cartridge.
    NMP_PARAMETER		| 0xE008000	| Selects data indices and commands.
    ----------------------------------------------------------------------------------------------------------------------

All registers are 16-bit and MSB first. As such, care must be taken when reading/writing with hardware that is LSB-based (such as the GBA's ARM7 CPU). Additionally, due to the serial nature of the registers, the lower value must always be read/written first. The NMP's software, resorts to accessing these registers one byte at a time (e.g. 0xE000000 first, then 0xE000001) to resolve both issues.

[Nintendo MP3 Player] : Accessing Firmware

Like the original Play-Yan and Play-Yan Micro, the NMP loads default firmware from the cartridge's ROM onto special hardware inside the device. This ensures a baseline, working version of the firmware necessary to decode MP3s is always present, especially in case a firmware upgrade goes awry. To write firmware, the software first sets an index, presumably representing a location in internal memory where the firmware resides. Afterwards, it starts writing values. The index itself is expressed in terms of 16-bit units, so the absolute memory location is twice the value of the index.

The following process is used to access firmware:

    ------------------------------------------------------------------------
    NMP_CONTROL_LO = 0x10
    NMP_CONTROL_HI = 0x10

    NMP_PARAMATER_LO = INPUT_PARAMETER_HI
    NMP_PARAMETER_HI = INPUT_PARAMETER_LO

    NMP_CONTROL_LO = 0x00
    NMP_CONTROL_HI = 0x00

    NMP_PARAMATER_LO = INDEX_HI
    NMP_PARAMETER_HI = INDEX_LO
    ------------------------------------------------------------------------

From there, data can be read or written by from either NMP_DATA_IN or NMP_DATA_OUT as 16-bit values. It is currently unknown what purpose the different values of INPUT_PARAMETER serves. Common values appear to be 0x0000 through 0x0003.

Although the Nintendo MP3 Player has the ability to update its firmware just like its Play-Yan predecessors, it's unclear if this was actually ever done for this version. The cartridge specifically looks for a file named "meteor.fup", but it does not appear any such file was ever offered to users by Nintendo.

After the firmware is completely loaded from the NMP's ROM, a single Game Pak IRQ is automatically generated, which begins the boot process, very similar to how the Play-Yan models operate.

[Nintendo MP3 Player] : Index Overview

While most indices appear to be used for accessing firmware, some have other purposes. These are accessed in a similar manner to firmware. Here, however, the value representing INPUT_PARAMATER is always 0x0000:

    ------------------------------------------------------------------------
    NMP_CONTROL_LO = 0x10
    NMP_CONTROL_HI = 0x10

    NMP_PARAMATER_LO = 0x00
    NMP_PARAMETER_HI = 0x00

    NMP_CONTROL_LO = 0x00
    NMP_CONTROL_HI = 0x00

    NMP_PARAMATER_LO = ACCESS_INDEX_HI
    NMP_PARAMETER_HI = ACCESS_INDEX_LO
    ------------------------------------------------------------------------

A list of known indices and their functions follows:

    ------------------------------------------------------------------------
    Index	| Description
    ------------------------------------------------------------------------
    0x0000	| Access SD Card Data
    0x00FF	| Data Flush
    0x0100	| Get Game Pak IRQ Status Data
    0x0101	| Access ID3 Data
    0x010F	| Send Command / Get Ticks
    0x0110	| Check Cartridge I/O Busy Flag
    0x----	| Left Audio Buffer
    0x----	| Right Audio Buffer
    ------------------------------------------------------------------------

Index 0x0000 : Access SD Card Data

This index is accessed after issuing a command that expects to receive data from the SD card. That data is available at NMP_DATA_OUT.

Index 0x00FF : Data Flush

This index typically accessed after commands are issued. It seems like it's used to flush input data. After accessing this index, 16-bits are written to NMP_DATA_IN, with the value being 0x0000.

Index 0x0100 : Get Game Pak IRQ Status Data

This index is accessed immediately following a Game Pak IRQ. The NMP's software reads 16 bytes of status data from NMP_DATA_OUT related to the recent IRQ. This status data contains the Command ID associated with the IRQ as well as any additional parameters for the command. These parameters are used to update various things such as the music trackbar, music timestamp, fast forward/rewind, speed, volume, etc. Typically, the NMP's software will read the first 8 bytes of status data to determine if it's valid, then proceed to read the entire 16 bytes.

Index 0x0101 : Access ID3 Data

This index is access after issuing the 0x0040 command. Data for ID3 tags is available at NMP_DATA_OUT.

Index 0x010F : Send Command / Get Ticks

This index has two uses when writing to NMP_DATA_OUT and when reading from NMP_DATA_IN. When writing, it is used to send a command. A series of 16-bit values are then written to NMP_DATA_OUT. When reading, this access gets the current internal "ticks" from the NMP. A single 16-bit value is read from NMP_DATA_OUT, which is used as a measurement for time-keeping. For the most part, the NMP's software wants to ensure that the hardware is actually running, i.e. the 16-bit ticks values should increase periodically. The software reads it once per-frame and times out several actions if the ticks haven't advanced for a full second (i.e. during the initial boot phase, it will completely reset everything and try re-uploading firmware).

Index 0x0110 : Check Cartridge I/O Busy Flag

This index is accessed immediately following the last access to 0x0100. It's used to get the cartridge's I/O busy status. After accessing this index, a single 16-bit value from NMP_DATA_OUT is read. Any non-zero values indicate that the cartridge is still busy, presumbly with data from a previous Game Pak IRQ. This index can be accessed indefinitely until NMP_DATA_OUT returns zero, at which point additional commands can be issued.

Index 0x---- : Left Audio Buffer

This index is accessed after issuing the 0x0050 command and the NMP generates internal Game Pak IRQs with a Command ID that reads 0x8100. The status data for those internal IRQs will have 16-bit values that determine the exact index the NMP will assign for its audio buffers. This value appears arbitrary, so the index may not have a fixed position. The data is available at NMP_DATA_OUT and represents 8-bit samples compatible with the GBA's DMA sound channels. These samples, must be read in 16-bit units, however. When reading these samples with the GBA CPU, the MSB represents the first sample, while the LSB represents the second sample.

Index 0x---- : Right Audio Buffer

This index is much the same as the Left Audio Buffer. Accessing this will pull up the second portion of the overall audio buffer, which contains 8-bit samples packed in 16-bit units. The only thing different about this index is its location. See further notes below regarding how the exact index is calculated.

[Nintendo MP3 Player] : Reading SD Card Data

SD Card Data can be accessed after a Game Pak IRQ is raised in response to a command. Simply access the 0x0000 index and read data from NMP_DATA_OUT. The process is as follows:

    ------------------------------------------------------------------------
    NMP_CONTROL_LO = 0x10
    NMP_CONTROL_HI = 0x10

    NMP_PARAMATER_LO = 0x00
    NMP_PARAMETER_HI = 0x00

    NMP_CONTROL_LO = 0x00
    NMP_CONTROL_HI = 0x00

    NMP_PARAMATER_LO = 0x00
    NMP_PARAMETER_HI = 0x00

    DATA_BYTE_HI = NMP_DATA_OUT_HI
    DATA_BYTE_LO = NMP_DATA_OUT_HI
    ...
    ... REPEAT READS AS NECESSARY
    ...
    ------------------------------------------------------------------------

Commands expect different lengths of data from the SD Card, so there is no set general set limit. Bytes should be read according to the specific command and its context (e.g. an IRQ with a Command ID of 0x8100 may have variable lengths of bytes to read for the audio buffer).

[Nintendo MP3 Player] : Commands

Commands can be sent to the Nintendo MP3 Player after accessing the 0x010F index. Data consists of a stream of 16-bit words written to NMP_DATA_IN. These commands are responsible for operating nearly everything about the cartridge, from upgrading firmware, reading directory information from the SD card, and playing music. The process of sending a command is as follows:

    ------------------------------------------------------------------------
    NMP_DATA_IN_LO = COMMAND_ID_HI
    NMP_DATA_IN_HI = COMMAND_ID_LO

    NMP_DATA_IN_LO = PARAMETER_VALUE_HI
    NMP_DATA_IN_HI = PARAMETER_VALUE_LO

    ...

    NMP_CONTROL_LO = 0x04
    NMP_CONTROL_HI = 0x04
    ------------------------------------------------------------------------

At a minimum, a command must write its ID and an additional 16-bits of parameter data. Some commands, such as 0x10, use zeroes for their parameter data, and do not seem to require a flush via the 0xFF index. For commands that require more bytes for parameters, that data is simply written accordingly to NMP_DATA_IN. Writing 0x0404 to NMP_CONTROL appears to signal to the cartridge that command input is finished. A list of all known commands and details about them are listed below:

    ----------------------------------------------------------------------------------------------------------------------------------------------
    Command	ID				| Parameters				| SD Card Data
    ----------------------------------------------------------------------------------------------------------------------------------------------
    0x0010 - Begin File/Folder List		|					| 1 File/Folder Entry
    0x0011 - Continue File/Folder List	|					| 1 File/Folder Entry
    0x0020 - Change Directory		| Directory Name			|
    0x0030 - Unknown Command		|					|
    0x0040 - Grab ID3 Data			| Music Filename, Access Index		| ID3 Tags For Title and Artist
    0x0050 - Play Music File		| Music Filename			|
    0x0051 - Stop Music Playback		|					|
    0x0052 - Pause Music Playback		|					|
    0x0053 - Resume Music Playback		|					|
    0x0060 - Seek Forwards/Backwards	| Stream Position, Seek Direction	|
    0x0070 - Unknown Command		|					|
    0x0080 - Adjust Volume			| New Volume				|
    0x0200 - Play Sound Effect		|					|
    0x0300 - Check For Firmware File	| Firmware Upgrade Filename		|
    0x0301 - Read Firmware File		|					|
    0x0303 - Close Firmware File		|					|
    0x0500 - Enter Sleep Mode		|					|
    0x0501 - Exit Sleep Mode		|					|
    ----------------------------------------------------------------------------------------------------------------------------------------------

Sometimes the NMP's hardware will generate Game Pak IRQs on its own. While not exactly commands, these IRQs produce data that can be read in much the same way. That is to say, they'll have a Command ID, Status Data, and SD Card Data if applicable.

    ----------------------------------------------------------------------------------------------------------------------------------------------
    Command	ID				| Parameters				| SD Card Data
    ----------------------------------------------------------------------------------------------------------------------------------------------
    0x8001 - Initialize NMP Hardware	|					|
    0x8100 - Update Audio			| Audio Buffer / Trackbar / Timestamp	| Audio Samples
    0x8600 - Headphone Status		| Headphone Plugged-In Flag		|
    ----------------------------------------------------------------------------------------------------------------------------------------------

For any and all ASCII strings sent to or returned by these commands, each character is encoded as a 16-bit MSB value. Each character uses 16-bits. As an example, sending the character "A" for a command parameter involves writing 0x00 to NMP_DATA_IN_LO first, then 0x41 to NMP_DATA_IN_HI later. The overall string is transferred or received from the first character to the last character in order, e.g. the filename "music.mp3" has "m" as the first character and "3" as the final one. Strings must be null terminated as well. Additionally, each string may use extended ASCII encoding. Unlike the original Play-Yan and Play-Yan Micro, the NMP has the font to render extended characters. ID3 tags may also use UTF-16LE encoding as long as the characters are Latin script, however, UTF-8 encoding is not supported.

For each Game Pak IRQ, the first 16-bits of Status Data acts as a sort of "ID" for the command used. Typically, this ID is simply the command itself OR'ed with 0x4000 or 0x8000. Once again, this has parallels to how the Play-Yans operate. When the ID has been OR'ed with 0x4000, this means the NMP is directly responding to a command issued by the software and generating an appropiate Game Pak IRQ. IDs OR'ed with 0x8000, on the other hand, represent Game Pak IRQs generated by the NMP itself.

Below is a list of all known commands along with their parameters, Status Data, and their SD Card Data if applicable.

    -----------------------------------------------------------------------
    Command 0x0010 - Begin File/Folder List
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4010
    Byte 0x0002 - 0x0003	End of List Flag	0x0000 or 0x0001
    -----------------------------------------------------------------------
    SD Card Data:

    Byte 0x0000 - 0x020B	File/Folder Name	ASCII String
    Byte 0x020C - 0x020D	File/Folder Flag	0x01 = Folder, 0x02 = File
    Byte 0x020E - 0x020F	N/A			Unused
    -----------------------------------------------------------------------

This command begins reading the names of every file and folder in the current directory of the SD card. The starting location on boot is the SD card's root directory. Unlike the Play-Yans, the NMP reads only 1 file or folder at a time rather than grabbing multiple entires all at once. In order to read the names of all files and folders, the 0x0011 command must be called. For any given directory, the 0x0010 command is only issued once.

The Status Data consists of the Command ID and an End of List Flag. If this flag is non-zero, it means a valid file or folder has been found on the filesystem. If this flag reads zero, that means there are no more files or folders within a directory. As this is the first command called when searching for files and folders, this indicates an empty directory.

The SD Card Data reads 528 bytes in all, with the first 524 being reserved for the file or folder's name. Note, however, that the NMP's software will use far less than that. The next 4 bytes after that dictates whether the entry is a file or a folder. Technically any unsigned value less than or equal to 0x01 represents a folder, and any unsigned value greater than or equal to 0x02 represents a file.

    -----------------------------------------------------------------------
    Command 0x0011 - Continue File/Folder List
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4010
    Byte 0x0002 - 0x0003	End of List Flag	0x0000 or 0x0001
    -----------------------------------------------------------------------
    SD Card Data:

    Byte 0x0000 - 0x020B	File/Folder Name	ASCII String
    Byte 0x020C - 0x020D	File/Folder Flag	0x01 = Folder, 0x02 = File
    Byte 0x020E - 0x020F	N/A			Unused
    -----------------------------------------------------------------------

This command continues reading the names of every file and folder in the current directory of the SD card. The starting location on boot is the SD card's root directory. Whereas the 0x0010 is called only once for a given directory, the 0x0011 must be called repeatedly until it detects no more files or folders. This is done by checking the End of List Flag in its Status Data. Otherwise, this command is exactly like its counterpart described above.

    -----------------------------------------------------------------------
    Command 0x0020 - Change Directory
    -----------------------------------------------------------------------
    Parameters :

    Byte 0x0000 - 0x0209	New Directory		ASCII String
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4020
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

Changes the current directory that the NMP will use to look for folder or music files. It accepts an ASCII string for the new directory. To go backwards one directory, the string ".." is used.

    -----------------------------------------------------------------------
    Command 0x0040 - Grab ID3 Data
    -----------------------------------------------------------------------
    Parameters :

    Byte 0x0000 - 0x0209	Music Filename		ASCII String
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4040
    Byte 0x0006 - 0x0007	Access Index		0x0101
    -----------------------------------------------------------------------
    SD Card Data:

    Byte 0x0000 - 0x0087	Song Title		ASCII String
    Byte 0x0088 - 0x010F	Song Artist		ASCII String
    -----------------------------------------------------------------------

Requests the ID3 data for a given MP3 file. It will only return the song's Title and Artist fields. Each field is allotted a total of 68 characters. The NMP's software calls this command before actually playing a file.

This command returns a 16-bit Index in Status Data that must first be accessed before reading the actual data through the SD Card interface. It seems as though the first time this command is called, the software assumes Access Index can be any arbitrary value, however, subsequent commands to grab ID3 data expect the value to be 0x0101.

    -----------------------------------------------------------------------
    Command 0x0050 - Play Music File
    -----------------------------------------------------------------------
    Parameters :

    Byte 0x0000 - 0x0209	Music Filename		ASCII String
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4050
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

Begins playback of the specified audio file. This command itself does not deal with audio data, rather, it instructs the hardware to start generating samples. After issuing this command, the NMP will periodically generate additional Game Pak IRQs that have the 0x8100 Command ID and return either audio sample data or updates to the timestamp and trackbar progress.

    -----------------------------------------------------------------------
    Command 0x0051 - Stop Music Playback
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4051
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

This command halts all music playback and ends all Game Pak IRQs for audio samples or timestamp and trackbar progress. The NMP software returns control of the menu to player so they can navigate the current directory for folders or music files.

    -----------------------------------------------------------------------
    Command 0x0052 - Pause Music Playback
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4052
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

This command temporarily pauses music playback. Game Pak IRQs for audio samples or timestamp and trackbar progress are put on hold until another command is issued to resume playback.

    -----------------------------------------------------------------------
    Command 0x0053 - Resume Music Playback
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4053
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

This command resumes music playback after it has been temporarily put on hold. Game Pak IRQs for audio samples or timestamp and trackbar progress will continue after sending this command.

    -----------------------------------------------------------------------
    Command 0x0060 - Seek Forwards/Backwards
    -----------------------------------------------------------------------
    Parameters :

    Byte 0x0000		Stream Position		0x0000 - 0x0063
    Byte 0x0001		Seek Direction
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4060
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

This command adjusts the current playback position for audio forwards or backwards. The Stream Position parameter represents the current playback position as a percentage (0% to 99%). Seek Direction is an 8-bit value that determines whether the new playback position moves ahead or rewinds. To change the playback position, this command must be called repeatedly (approximately every 15 frames or so) while incremented or decrementing the Seek Direction.

For moving forwards, the initial value of Seek Direction should be 0x00 and increase by 0x10 every time this command is sent. For moving backwards, the initial value of Seek Direction should be 0xF0 and decrease by 0x10 every time this command is sent. The NMP will interpret these changes in Seek Direction and alter the playback position accordingly. Note that since Seek Direction observes 8-bit overflow and underflow. When seeking forward, 0xF0 will roll over into 0x00 on the next command, and when seeking backward, 0x00 will roll over into 0xF0.

Seek Direction is incremented/decremented continuously as long as the user holds down Left or Right on the D-Pad while playing music. It will scale the amount of seconds passed for each instance of the 0x0060 command. The default is 2 seconds, but for every 5 or so instances of the 0x0060 command, another second is added. Due to the way Seek Direction works, the NMP will need to be sent at least 2 0x0060 commands before it actually begins seeking, causing a brief delay when first pressing Left or Right.

    -----------------------------------------------------------------------
    Command 0x0080 - Adjust Volume
    -----------------------------------------------------------------------
    Parameters :

    Byte 0x0000 - 0x0001	New Volume		0x0000 - 0x002E
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4080
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

This command adjusts the volume of music playback. The new volume is passed as a parameter, which ranges from 0x00 to 0x2E. Note that this command only affects the volume when using headphones in the cartridge's 3.5mm jack (not the GBA's). It will not change the volume when using any of the GBA for audio output. Users are expected to manually adjust the volume dial/slider on the handheld. A Game Pak IRQ is generated when inserting or removing headphones, which alerts the software on the current headphone status.

    -----------------------------------------------------------------------
    Command 0x0200 - Play Sound Effect
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4200
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

Plays a sound effect during certain actions, such as selecting menus. The sound effect comes from firmware, just like the Play-Yan models. The NMP hardware will convert the sound effect into samples compatible with the GBA. The 0x0200 command only starts this process; an additional Game Pak IRQ is generated with a Command ID of 0x8100, which supplies the audio data via the SD Card interface.

    -----------------------------------------------------------------------
    Command 0x0300 - Check For Firmware File
    -----------------------------------------------------------------------
    Parameters :

    Byte 0x0000 - 0x0209	Filename		ASCII String
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4300
    Byte 0x0002 - 0x0003	File Exists Flag	0x00 = File Found, 0x01 = No File
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

This command requests a firmware update file (specifically "meteor.fup") from the SD card if it exists. May be similar to the Check For Key File command on the Play-Yan Micro. If the File Exists Flag from Status Data is zero, the NMP will attempt to open the file and read its contents using additional commands, otherwise it aborts that process immediately.

A total of 522 bytes are used as parameter data, which is simply an ASCII-encoded string for the update file.

    -----------------------------------------------------------------------
    Command 0x0301 - Read Firmware File
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4301
    Byte 0x0002 - 0x0003	File Opened Flag	0x00 = Opened, 0x01 = Not Opened
    Byte 0x0008 - 0x0009	File Size
    -----------------------------------------------------------------------
    SD Card Data:

    Byte 0x0000 - Size	File Contents
    -----------------------------------------------------------------------

This command appears to read the firmware file if it exists. The File Opened Flag determines whether or not the file was successfully opened. If that is the case, the contents of the file are available to read via the SD Card interface. The File Size determines how many bytes should be read from the SD Card. Note that while the File Size can be read as a 32-bit value, the NMP software forcibly masks it to 16-bits.

It appears that if the contents of the firmware update file do not match what the NMP's software expects, it aborts actually trying to load that data into firmware. Although no real firmware update file for the NMP exists, the cartridge's ROM suggests it had a specific header, similar to the firmware updates for the original Play-Yan.

    -----------------------------------------------------------------------
    Command 0x0303 - Close Firmware File
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x4303
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

This command appears to close the firmware file if it was previously opened.

    -----------------------------------------------------------------------
    Command 0x8001 - Initialize NMP Hardware
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x8001
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

After firmware copied from ROM and written to the NMP on boot, the cartridge generates a Game Pak IRQ with this Command ID. The software will wait indefinitely for this IRQ to fire. It will also periodically timeout and attempt to re-upload firmware again. This IRQ signals that the firmware was successful in loading and running on the NMP. As such, it is the very first Game Pak IRQ used after the GBA is turned on.

    -----------------------------------------------------------------------
    Command 0x8100 - Update Audio
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x8100
    Byte 0x0002 - 0x0003	Audio Buffer Size	0x0000 - 0x0480
    Byte 0x0004 - 0x0005	Access Index
    Byte 0x0008		Trackbar Position	0x00 - 0x63
    Byte 0x000C - 0x000F	Song Timestamp
    -----------------------------------------------------------------------
    SD Card Data: (The below numbers are an example, assuming Audio Buffer Size = 0x480)

    Byte 0x0000 - 0x023F 	Audio Buffer 1
    Byte 0x0000 - 0x023F	Audio Buffer 2
    -----------------------------------------------------------------------

After issuing either the 0x50 or 0x200 commands, the NMP hardware will begin generating Game Pak IRQs that return audio samples via the SD Card interface. These IRQs return a lot of Status Data that indicates what is being updated.

The first is a 16-bit value that dictates the Audio Buffer Size in bytes. Its maximum value is 0x0480, and it should also be divisable by 4 (the NMP software forcibly masks it anyway). Typically, while playing a song, the NMP will constantly update audio with an Audio Buffer Size of 0x480, except for the very last samples of a song, which may not evenly be divisable by 0x480 and thus must use a smaller remainer as the size. The second piece of Status Data is a 16-bit value that indicates the Index that must be accessed before any audio samples are read. Unlike the 0x0040 command used to grab ID3 data, the Access Index here is completely arbitrary and determined by the hardware, i.e. it may not always have a fixed value.

Trackbar Position represents current playback position as a percentage. 0% is at the very beginning of a song, 50% is at the exact middle of a song, and 99% is at the very end of a song. Going further actually pushes the trackbar indicator offscreen. As such, this value only accepts an 8-bit value with a range of 0 to 99.

Song Timestamp is the current playback position is seconds. Although it should technically work as 32-bit value, it actually seems to work best as a 24-bit MSB value, using bytes 0x0F, 0x0C, and 0xD in that order. Whereas these bytes add multiple powers of 2 (65536, 256, and 1) to the timestamp, bytes 0x0E adds 1216 seconds to the timestamp.

If the Access Index is zero, that means the cartridge is updating the Trackbar Position and Song Timestamp. In this case, no audio samples are returned. Otherwise, the specified Index is accessed and data is read through the SD Card interface. The data is split into 2 separate buffers, a Left Audio Buffer and Right Audio Buffer. Each buffer is half the length of Audio Buffer Size. For example, when using 0x480 as the Audio Buffer size, the Left Audio Buffer and Right Audio Buffer will each have a length of 0x240 bytes.

Before reading any audio samples, the GBA's CPU must first access the correct index. Afterwards, the sample data becomes available through the SD Card interface. Essentially, the Access Index returned as Status Data represents a virtual address that describes where to grab samples from the NMP. Each address in the Access Index is equal to 16-bits of sample data (a pair of 8-bit samples accessed as a single unit). The first half of this virtual address space is dedicated to the Left Audio Buffer, while the latter half is dedicated to the Right Audio Buffer. For example, if the Audio Buffer Size is 0x480, and the NMP sets the Access Index to 0x200, then the Left Audio Buffer starts at Access Index 0x200, and the Right Audio Buffer starts at Access Index 0x320. Refer to the chart below for more details:

    -----------------------------------------------------------------------------------------------------------------------
    Index 0x200       | Index 0x201       |  ... ... ... ...   | Index 0x320       | Index 0x321	   |   ... ... ... ...
    -----------------------------------------------------------------------------------------------------------------------
    L Samples 000-001 | L Samples 002-003 | L Samples 003-575  | R Samples 000-001 | R Samples 002-003 | R Samples 003-575
    -----------------------------------------------------------------------------------------------------------------------

Once the index for either the Left or Right Audio Buffer is accessed, sample data for the entire channel's buffer can be read from the SD Card interface continually until the buffer is full. When switching between channels, however, a new index must be accessed.

Game Pak IRQs with the Command ID 0x8100 are also generated for sound effects. Functionally, there is no difference between the Status Data used for music or sound effects. The NMP software, however, will only play sound effects if no music is currently playing. Obviously, however, the Trackbar Position and Song Timestamp values are unused/irrelevant for sound effects.

When headphones are plugged into the NMP, the cartridge only generates Game Pak IRQs that update the trackbar position. With headphones, audio data is processed by the NMP's own hardware and output separately from the GBA's sound system.

    -----------------------------------------------------------------------
    Command 0x8600 - Headphone Status
    -----------------------------------------------------------------------
    Parameters : N/A
    -----------------------------------------------------------------------
    Status Data :

    Byte 0x0000 - 0x0001	Command ID		0x8600
    Byte 0x0002 - 0x0003	Headphone Flag		0x00 = No Headphones, 0x01 = Headphones plugged-in
    -----------------------------------------------------------------------
    SD Card Data: N/A
    -----------------------------------------------------------------------

Whenever headphones are inserted or removed from the NMP's 3.5mm jack, a Game Pak IRQ is generated. Additionally, immediately after the NMP hardware has been initialized, the cartridge generates a Game Pak IRQ with this Command ID (ensuring that headphones are detected after booting). The IRQ reports the status of whether headphones are plugged-in/removed, using a single byte in Status Data as a flag. Note that this IRQ is only generated for headphones inside the cartridge itself and is completely unrelated to the GBA's or DS' 3.5mm jack.

[Nintendo MP3 Player] : Firmware Update

The NMP apparently has the ability to update its built-in firmware. After loading the default firmware from ROM, it will search for an update file called "meteor.fup". This functionality is similar to the original Play-Yan that expanded its features (such as MP4 support). Strangely enough, it seems no such firmware update file was ever published by Nintendo. The NMP manual makes no mention of this functionality either. Currently, it remains unknown what sort of upgrades any new firmware might have brought or why Nintendo decided to leave upgrades as a future option. At any rate, it is completely unused at this time.

One interesting detail is that the maximum file size for firmware was supposed to be 65,536 bytes. This is significantly lower than the only known firmware update given for original Play-Yan, which came in around 554KB. The firmware for the NMP was likely far less complicated, perhaps as a result of the hardware lacking any video decoding and focusing exclusively on audio processing.

The firmware update file has to follow some sort of format to be considered valid. The NMP software checks for the presence of the string "Nintendo MP3 Player firmware update program" at the very start of the file's data, much like the original Play-Yan expects of its firmware updates.

Agatsuma TV Tuner

General Hardware Information

I/O Registers

Data Transfer Protocol

Commands

Flash Memory

Audio

AGB-P-ZTVJ

[Agatsuma TV Tuner] : General Hardware Information

The Agatsuma TV Tuner (ATVT) is a cartridge for the Game Boy Advance that allowed users to watch analog broadcast TV. It was released exclusively in Japan on April 29, 2006. Created by Agatsuma Entertainment Inc., it was the only officially licensed TV tuner for the GBA. It also allows for composite A/V input.

- Comes in a very large, bulky, black cartridge (about the size of an original DS folded).
- Has an adjustable antenna on the upper left side that extends and rotates.
- Requires 6 AA batteries to work.
- Features dual-speakers on the front to bypass the GBA's audio system.
- Features a volume dial on the lower left side.
- Has a composite A/V input port on the lower right side.
- Has a 3.5mm headphone jack on the lower right side.
- Has a port on the back side for an external antenna connection.
- Comes with at least 256 bytes of flash memory to save configuration data.
- Only compatible with analog broadcasts (NTSC-J).
- Tunes into 62 channels.
- Capable of receiving signals from 55.25MHz to 801.25MHz.
- Uses a Philips FQ1236/P H-3 as the actual TV tuner.

[Agatsuma TV Tuner] : I/O Registers

The ATVT has several memory-mapped registers that deal with TV operations as well as writing to its internal flash memory.

    -----------------------------------------------------------
    Address				| I/O Name
    -----------------------------------------------------------
    0x8000000			| TV_FLASH_INIT
    0x8000AAA			| TV_FLASH_CMD0
    0x8000554			| TV_FLASH_CMD1
    0x8020000 - 0x80200FF		| TV_FLASH_DATA
    0xA800000 - 0xA812BFF		| TV_FRAME_BUFFER
    0xE000000			| TV_CNT_A
    0xE000001			| TV_CNT_B
    0xE000002			| TV_CNT_C
    0xE000003			| TV_CNT_D
    -----------------------------------------------------------

TV_FLASH_INIT deals specifically with two standard flash commands, 0x90 (Enter ID Mode) and 0xFF (Reset). All other flash commands have to write to TV_FLASH_CMD0 and TV_FLASH_CMD1. A small section of what is normally cartridge ROM is instead reserved for 256 bytes of flash memory.

The ATVT provides video as full 240x160 frames, in the form of a 15bpp bitmap image. The frame buffer is available to read directly.

4 separate control registers are used to issue TV-related commands. The bulk of the work falls on TV_CNT_A and TV_CNT_B. TV_CNT_C and TV_CNT_D have lesser roles; writing to these locations overwrites the values in their counterparts. That is to say, writing to TV_CNT_C overwrites TV_CNT_A, and writing to TV_CNT_D overwrites TV_CNT_B. This is often done to zero out and reset those registers (presumably without affecting something about their operations).

[Agatsuma TV Tuner] : Data Transfer Protocol

In order to send commands or read data from commands, the CPU writes bytes serially to using TV_CNT_A or TV_CNT_B. The register used depends on which commands are being issued. Here, only Bit 0 and Bit 1 are used to clock the transfer and represent I/O data.

    -----------------------------------------------------------
    Bit 0	| I/O Data
    Bit 1	| Clock (0 = LOW, 1 = HIGH)
    -----------------------------------------------------------

The ATVT uses the I2C protocol for data transfers, but the specifics of how it is implemented on the GBA are detailed in this section. Depending on the command, TV_CNT_A must have Bits 2, 6, and 7 set HIGH (essentially OR'ed 0xC4), while TV_CNT_B must have Bit 6 set HIGH (essentially OR'ed by 0x40). The high-level protocol for issuing commands looks something like this:

    -----------------------------------------------------------
    START SIGNAL

    TRANSFER BYTE
    ACKNOWLEDGE SIGNAL

    TRANSFER BYTE
    ACKNOWLEDGE SIGNAL

    ...

    READ BYTE (only used for some read commands)
    ACKNOWLEDGE SIGNAL (only used for read commands)

    STOP SIGNAL
    -----------------------------------------------------------

The Start Signal involves setting the clock HIGH twice, while sending 1 then 0 as data:

    -----------------------------------------------------------
    Start Signal
    -----------------------------------------------------------
    1) Set Clock High and set I/O Data to 1
    2) Set Clock High and set I/O Data to 0
    -----------------------------------------------------------

The Start Signal always follows a Stop Signal, or is the first signal sent to the ATVT at all post-boot. After the Start Signal, individualy bytes can be transferred bit-by-bit. Bytes are sent MSB-first. Each bit requires 4 writes to TV_CNT_A or TV_CNT_B. The process is described below:

    -----------------------------------------------------------
    Transfer Bit
    -----------------------------------------------------------
    1) Set Clock LOW
    2) Set I/O Data to transfer bit
    3) Set Clock HIGH
    4) Set Clock LOW
    -----------------------------------------------------------

After repeating those steps 8 times, a full byte has been transferred to the ATVT. Once the transfer is complete, an Acknowledgement Signal must be sent as well. This signal consists of 4 writes to TV_CNT_A or TV_CNT_B as such:

    -----------------------------------------------------------
    Acknowledgement Signal
    -----------------------------------------------------------
    1) Set Clock LOW and set I/O Data to 0
    2) Set I/O Data 1
    3) Set Clock HIGH
    4) Set Clock LOW and set I/O Data to 1
    -----------------------------------------------------------

If there is more incoming data for a command, the process for transferring bytes begins immediately. However, if there is no more data, a Stop Signal must be sent:

    -----------------------------------------------------------
    Stop Signal
    -----------------------------------------------------------
    1) Set Clock LOW and set I/O Data to 0
    2) Set Clock HIGH
    3) Set Clock HIGH and set I/O Data to 1
    -----------------------------------------------------------

Some commands return 8-bit data from the ATVT. After the last byte of the command has been transferred and acknowledged, this 8-bit data is read immediately (i.e., the read occurs before a Stop Signal). As with transferring bytes, reading bytes is done serially. The process for that is as follows:

    -----------------------------------------------------------
    Read Bit
    -----------------------------------------------------------
    1) Set Clock LOW and set I/O Data to 1
    2) Set Clock HIGH
    3) Read Bit 0 of TV_CNT_A or TV_CNT_B
    -----------------------------------------------------------

This is done a total of 8 times until the byte is fully read out.

[Agatsuma TV Tuner] : Commands

By writing certain bytes to the ATVT (using the protocol described above) the CPU can send several commands to the device. The first byte is the address frame. The last two bytes of a command are 16-bit parameters. As is typical of I2C, Bit 0 of the address frame determines whether the command will read or write values. In the case of read commands, no parameter bytes are used. A list of known commands is shown in the table below along with whether the command uses TV_CNT_A or TV_CNT_B:

    ----------------------------------------------------------------------------------------------------------------------
    Command Name		| Address Frame		|Command Pattern	|Register
    ----------------------------------------------------------------------------------------------------------------------
    Unknown Command		| 86 			| xx xx			| TV_CNT_B
    Read Channel Status	| 87			|			| TV_CNT_B
    Change Channel		| C0			| xx xx			| TV_CNT_B
    Unknown Command		| D8			| 00			| TV_CNT_A
    Switch to AV Input Mode	| D8			| 02 E0			| TV_CNT_A
    Switch to TV Mode	| D8			| 02 E1			| TV_CNT_A
    Set Video Contrast	| D8			| 10 xx			| TV_CNT_A
    Set Video Brightness	| D8			| 11 xx			| TV_CNT_A
    Unknown Command		| D8			| 14			| TV_CNT_A
    Set Video Hue		| D8			| 15 xx			| TV_CNT_A
    Unknown Command		| D8			| 1E xx			| TV_CNT_A
    Clear Video Frame	| D8			| 0D 80			| TV_CNT_A
    Render Video Frame	| D8			| 0D 00			| TV_CNT_A
    Read Command Data	| D9			| 			| TV_CNT_A
    ----------------------------------------------------------------------------------------------------------------------

Command 86 xx xx - Unknown Command

This command appears related to changing the channel. It is called 3 times before reading the channel status or changing the channel frequency. The 16-bit parameters always follow this pattern:

    -----------------------------------------------------------
    Byte	1		| Byte 2
    -----------------------------------------------------------
    0x00			| 0x56
    0x01			| 0x30
    0x02			| 0x44
    -----------------------------------------------------------

The second byte of the first 16-bit parameter changes depending on the channel frequency. If the frequency is between 55.25MHz and 159.9375MHz inclusive, the value is 0x41. If the frequency is between 160MHz and 441.9375MHz inclusive, the value is 0x42. If the frequency is greater than 442MHz, the value is 0x44.

Command 87 - Read Channel Status

This command returns an 8-bit value representing the status of the current channel's reception. If the ATVT detects a valid TV signal, it will return the value 0xC0. Any other value seems to indicate that no proper reception was found for that channel, at least on the frequency assigned for it.

Command C0 xx xx - Change Channel

This command changes the current channel. This command is called twice. For the first call, its parameters form a 16-bit value that represents the channel's frequency in MHz. The lowest frequency possible is 55.25MHz and is representing by the hex value 0x0650. The highest possible frequency is 801.25MHz and is represented by the hex value 0x34F0. Essentially, increasing/decreasing the 16-bit value by 1 changes the frequency by 0.0625MHz.

For the second call, the 16-bit parameter uses 3 values depending on the channel frequency. If the frequency is between 55.25MHz and 159.9375MHz inclusive, the value is 0x8641. If the frequency is between 160MHz and 441.9375MHz inclusive, the value is 0x8642. If the frequency is greater than 442MHz, the value is 0x8644.

The Change Channel command is called when the user manually switches between saved channels, when scanning for available channels, and when manually tuning channels.

Command D8 00 - Unknown Command

This command is used right after the Render Video Frame command. It returns a single byte.

Command D8 02 E0 - Switch to AV Input Mode

This command is used to switch video input from TV signals to composite A/V input whenever the user presses the Select button.

Command D8 02 E1 - Switch to TV Mode

This command is used to switch video input from composite A/V input to TV signals whenever the user presses the Select button.

Command D8 10 xx - Set Video Contrast

This command sets the contrast of all video output. It accepts a single signed 8-bit value (2's complement), where the lowest value (-128) represents the minimum contrast and the highest value (127) represents the maximum contrast.

Command D8 11 xx - Set Video Brightness

This command sets the brightness of all video output. It accepts a single signed 8-bit value (2's complement), where the lowest value (-128) represents the minimum brightness and the highest value (127) represents the maximum brightness.

Command D8 14 - Unknown Command

This command is used after the Render Video Frame command and right after the command D8 00. It returns a single byte.

Command D8 15 xx - Set Video Hue

This command sets the hue of all video output. It accepts a single signed 8-bit value (2's complement), where the lowest value (-128) represents the minimum hue and the highest value (127) represents the maximum hue. Although this feature is labeled as hue by the ATVT itself, functionally it manipulates the saturation, with lower values skewing video more towards grayscale, but never completely so.

Command D8 1E xx - Unknown Command

This command is used right before the Render Video Frame and Clear Video Frame commands. It accepts an 8-bit parameter. The ATVT appears to set this to a constant value of either 0x06 when rendering a frame or 0x26 when clearing a frame.

Command D8 0D 80 - Clear Video Frame

This command appears to clear the internal video frame, or at least prepare the hardware to render the next video frame.

Command D8 0D 00 - Render Video Frame

This command renders any video frame from TV signals or the A/V input source. After issuing this command, 15bpp image data is available to read at the address range 0xA800000 - 0xA812BFF.

Command D9 - Read Command Byte

This command reads a single byte that represents the result of several unidentified commands. Specifically, it is used in conjection with the D8 00 and D8 14 commands.

[Agatsuma TV Tuner] : Flash Memory

The ATVT uses a very small amount of flash memory to store data such as brightness, contrast, and hue preferences, as well as a list of favorited channels and their frequencies. Below is a chart of known flash commands used by the ATVT:

    -----------------------------------------------------------
    0x80, 0x30	| Erase Sector
    0x90		| Enter ID Mode
    0xA0		| Write 16-bit Value
    0xF0		| Terminate Command (force end of write)
    0xFF		| Reset
    -----------------------------------------------------------

To issue either the Enter ID Mode or Reset commands, the CPU writes directly to TV_FLASH_INIT. Although the ATVT supports grabbing the manufacturer ID, this value isn't used by the device, and the software doesn't bother even reading it. The other 2 flash commands, Erase Sector and Write Data work as follows:

    -----------------------------------------------------------
    Erase Sector
    -----------------------------------------------------------
    1) Write 0xAA to TV_FLASH_CMD0
    2) Write 0x55 to TV_FLASH_CMD1
    3) Write 0x80 to TV_FLASH_CMD0

    4) Write 0xAA to TV_FLASH_CMD0
    5) Write 0x55 to TV_FLASH_CMD1
    6) Write 0x30 to TV_FLASH_DATA
    -----------------------------------------------------------

Typically for a sector erase command, the sector number would be part of the address when writing 0x30 (e.g. flash memory working on 4KB sector would do use a format like 0x802-000 for the ATVT). However, since only a very small and limited amount of flash memory is available on the ATVT, the software is hardcoded to use only the first sector, thus it always defaults to 0x8020000. After erasing a sector, Terminate Command is called to make sure the write is finished. That command is executed by simply writing 0xF0 to TV_FLASH_CMD0.

    -----------------------------------------------------------
    Write 16-bit Value
    -----------------------------------------------------------
    1) Write 0xAA to TV_FLASH_CMD0
    2) Write 0x55 to TV_FLASH_CMD1
    3) Write 0xA0 to TV_FLASH_CMD0
    4) Write MSB to TV_FLASH_DATA + INDEX
    5) Write LSB to TV_FLASH_DATA + INDEX + 1
    -----------------------------------------------------------

It should be noted that all I/O for the ATVT's flash memory is 16-bit, however, most registers only expect 8-bit values. Writing data is the only known area where all 16-bits are used. Like most flash memory, simply reading directly from the address range assigned to flash will pull its data. No special commands are necessary to read TV_FLASH_DATA.

[Agatsuma TV Tuner] : Audio

Audio output appears to be handled by the ATVT itself. Given the complexities of trying to convert live over-the-air audio to GBA compatible samples, as well as the quality of the GBA audio system, Agatsuma likely chose to bypass that all and have the ATVT directly handle audio. It may have been a technologically simpler approach too. At any rate, there doesn't seem to be any audio handling code in the ATVT's ROM at all either.

[Agatsuma TV Tuner] : AGB-P-ZTVJ

Prior to its release, news reports circa 2006 noted that the ATVT was to have a GBA game code of "AGB-P-ZTVJ". The "Z" would have indicated a special media cartridge in the same category of the GBA Jukebox and Play-Yan. Strangely enough, however, the ATVT itself has no external markings bearing this game code. Neither its box nor instruction pamplet have this information either. Generally the last 4 characters of the game code match data in the ROM header, but the ATVT uses "dtv0". Although the ATVT was marketed as a DS accessory, it is physically a GBA cartridge. Despite being officially licensed by Nintendo themselves, the ATVT appears somewhat anamalous in this regard compared to nearly every other GBA cartridge. The only similar case is the Campho Advance, which did not receive an official game code despite being licensed as well.

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.

- The Ubisoft Thrustmaster Pedometer is relatively large and bulky. Designed to be compatible with the original NDS model, so it sticks out a bit on NDS Lite units.
- Has a 5-digit LCD screen to display current steps. When plugged into an NDS, the numbers are upside-down (despite boxart showing them flipped correctly).
- Takes a single CR2032 battery that can be replaced from a slot on the side.
- Has a physical RESET button to set step count to zero.

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

- The HCV-1000 is a white add-on that sticks out of Slot-2. It has a thin gap where cards slide through
- A red light inside the gap turns on when the scanner is activated by software
- A small guard can be added or removed to better suit an NDS Lite or original NDS Slot-2
- The HCV-1001 variant is pink instead of white, the only difference being its status as a limited edition

[HCV-1000] : Compatible Games

- Oshare Majo Love and Berry: DS Collection
  Unlocks various clothes/outfits before playing minigames
- Kouchuu Ouja Mushiking Super Collection
  Unlocks different beetles used for battles
- Card de Asobu! Hajimete no DS
  Selects Japanese kana/object used for educational 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.

- The Magic Reader is a dark-gray add-on that sticks out of Slot-2. It has a bulb at one end housing an optical sensor
- A small guard can be added or removed to better suit an NDS Lite or original NDS Slot-2
- Uses a Sonix SN9S102C image sensor
- Uses a Sonix SN9P701FG-005 Optical ID decoder

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

Wantame Card Scanner

General Hardware Information

Barcode Transmission Protocol

[Wantame Card Scanner] : General Hardware Information

On November 22, 2007, Capcom released an action-rhythm game called Wantame Music Channel: Doko Demo Style for the Nintendo DS. It was part of the "Won!Tertainment" franchise developed in conjunction with Takara Tomy. Players can dress up as different dogs wearing various outfits by scanning physical cards with barcodes printed on them. This game was a port of the larger arcade version that was also capable of scanning the very same cards. The portable scanner for the DS offically was never officially given a name or product code, so for the purposes of this documentation is referred to simple as the Wantame Card Scanner.

Doko Demo Style shares some gameplay concepts with Oshare Majo and Sega's HCV-1000. Design-wise, the Wantame Card Scanner is also very similar in operation to the Wave Scanner, another device that Capcom and Takara Tomy collaborated on.

- Uses DS microphone plug to transmit data.
- Uses Slot-2 only for stability. There is no ROM chip or PCB connected to the Slot-2 pins.
- Powered by 3 LR44 batteries.
- Features a detachable guard for Slot-2 to better fit the original DS or DS Lite.
- Compatible with DSi models thanks to microphone cable.
- Has a red LED to indicate card scanning or errors.
- Microphone cable is tucked under the bottom of the unit.
- Has a reset button on the backside.
- Uses 12 character barcodes in Code-128 C format.
- Produces samples at approximately 400.005Hz.

[Wantame Card Scanner] : Barcode Transmission Protocol

The Wantame Card Scanner translates barcodes into sound pulses via the DS microphone. By reading samples, the game grabs the barcode data as individual bits, verifies the integrity of the data, then checks to see if the barcode is valid for the game. Note that the arcade version was continually updated all the way through Fall 2009, therefore, some cards are incompatible with the DS version. The transmission protocol consists of the following parts:

    ---------------------------------------------------------
    Protocol Stage	| Description
    ---------------------------------------------------------
    ACK Signal	| Initial pulses
    Barcode MSB	| Upper 10-bits
    Barcode LSB	| Lower 32-bits
    Check Digit	| Code-128 C checksum
    ---------------------------------------------------------

The ACK Signal alerts the game of incoming data. Normally, microphone input would be zero (assuming no noise from the Wantame Card Scanner). The game will wait for 2 separate LOW-to-HIGH transitions. At a minimum, each LOW and HIGH period should be sampled at least 9 times, but less than 16. The following psuedo-code can be used to determine whether a sample from the microphone is LOW or HIGH:

    MIC_SAMPLE = READ_DS_MIC()
    MIC_SAMPLE = MIC_SAMPLE * 2
    MIC_SAMPLE = MIC_SAMPLE AND 0xFF

    IF MIC_SAMPLE LESS THAN 0x48
    	SAMPLE_TYPE = LOW

    ELSE
    	SAMPLE_TYPE = HIGH

After sending the ACK Signal, the Wantame Card Scanner sends a continuous stream of 49 bits. Depending on the length of the LOW part of the the LOW-to-HIGH transition, a "0" or a "1" will be recorded. If the LOW portion measures at 6 or more samples, this represents a "1" in the bitstream, otherwise it represents a "0". Importantly, each LOW and HIGH portion must measure at least 3 samples, and the total duration of the LOW-to-HIGH transition must not exceed 16 samples.

The first 42-bits of the stream represent the barcode as a hexadecimal number, and the final 7 bits represent the barcode's checksum. The barcode is split across 2 32-bit integers, with the the upper 10-bits received first, and lower 32-bits received immediately afterwards. However, each integer receives its bits big endian first, and the same is true of the Check Digit.

The format of the barcode data itself uses 7-bits to represent Code-128 C values. These values range from 00 to 99. Each barcode uses 12 characters, but these are "doubled up" in pairs so that only 6 Code-128 C values are necessary. As an example, a barcode such as "011128531729" can be encoded into hexadecimal as such:

    ---------------------------------------------------------
    Barcode Pair	| Raw Hex Value		| Shift
    ---------------------------------------------------------
    "01"		| 0x01			| 35
    "11"		| 0x0B			| 28
    "28"		| 0x1C			| 21
    "53"		| 0x35			| 14
    "17"		| 0x11			| 7
    "29"		| 0x1D			| 0
    ---------------------------------------------------------

    FINAL_VALUE = ((0x01 LSL 35) OR (0x0B LSL 28) OR (0x1C LSL 21) OR (0x35 LSL 14) OR (0x11 LSL 7) OR (0x1D))

The result for this case would be 0x8B38D489D, which would get split up into 0x08 for the 10-bit segment and 0xB38D489D for the 32-bit segment. Continuing with the example barcode of "011128531729", the Check Digit can be calculated as such:

    ---------------------------------------------------------
    Barcode Pair	| Sum
    ---------------------------------------------------------
    "01"		| Sum += (1 * 1)
    "11"		| Sum += (11 * 2)
    "28"		| Sum += (28 * 3)
    "53"		| Sum += (53 * 4)
    "17"		| Sum += (17 * 5)
    "29"		| Sum += (29 * 6)
    ---------------------------------------------------------
    		| Sum += 105
    		| Sum = (Sum % 103)
    ---------------------------------------------------------

Essentially, the first pair is multiplied by 1 and added to the sum, the second pair is multiplied by 2 and added to the sum, and so on and so forth for the other pairs. After that, a value of 105 is added to the sum, then a modulo of 103 is applied to the sum for the final result. For this example it would be 0x41.

After all of these signals are transferred from the Wantame Card Scanner via microphone input, the rest of the samples should go LOW until a new scan.

Wave Scanner

General Hardware Information

Data Transmission Protocol

Barcodes

[Wave Scanner] : General Hardware Information

On December 14, 2006, Capcom released an action role-playing game called Ryuusei no Rockman in Japan, later renamed Mega Man Star Force in other territories. It was something of a continuation of the Mega Man Battle Network series. Like the earlier Battle Network games, Capcom partnered with Takara Tomy to create an accessory known as the Wave Scanner. It was combination electronic LCD toy and video game peripheral. As a standalone unit, it let users fight viruses with swipeable cards and level up. When attached to the Nintendo DS, the player's level could be used in-game to boost their stats and power up Mega Man by granting an immediate Star Force transformation. During battle, users could swipe cards to enhance their attacks as well.

The peripheral shares some heritage with the Battle Chip Gates on the GBA. Additionally, it served as a template for the Wantame Card Scanner that Capcom and Takara released less than a year later.

- Features a small LCD screen to display limited graphics.
- Features a small rotating dial that can be pressed in 3 directions.
- Features a 2 face buttons.
- Uses DS microphone plug to transmit data.
- Microphone cable is tucked under the bottom of the unit.
- Uses a separate 3.5mm headphone jack for audio output (unrelated to DS connectivity).
- Uses Slot-2 only for stability. There is no ROM chip or PCB connected to the Slot-2 pins.
- Powered by 3 AAA batteries.
- Compatible with DSi models thanks to microphone cable.
- Uses 12 character barcodes in Code-128 C format.
- Came in 4 versions: Pegasus, Leo, Dragon, and DX (Pegasus).
- Produces samples at approximately 400.005Hz.

[Wave Scanner] : Data Transmission Protocol

The Wave Scanner translates data into sound pulses via the DS microphone. By reading samples, the game grabs the barcode or level data as individual bits, verifies the integrity of the data, then checks to see if the data is valid for the current game mode. The transmission protocol is very basic and consists of the following 2 parts:

    ---------------------------------------------------------
    Protocol Stage	| Description
    ---------------------------------------------------------
    ACK Signal	| Initial pulses
    Barcode/Level	| 32-bits
    ---------------------------------------------------------

The ACK signal alerts the game to incoming data. It consists of a single HIGH-to-LOW transition of microphone samples. At a minimum, each LOW and HIGH period should be sampled at least 9 times, but less than 16. The following psuedo-code can be used to determine whether a sample from the microphone is LOW or HIGH:

    MIC_SAMPLE = READ_DS_MIC()
    MIC_SAMPLE = MIC_SAMPLE * 2
    MIC_SAMPLE = MIC_SAMPLE AND 0xFF

    IF MIC_SAMPLE LESS THAN 0x58
    	SAMPLE_TYPE = LOW

    ELSE
    	SAMPLE_TYPE = HIGH

After sending the ACK Signal, the Wave Scanner sends a continuous stream of 32 bits. Depending on the length of the HIGH part of the the HIGH-to-LOW transition, a "0" or a "1" will be recorded. If the HIGH portion measures at 6 or more samples, this represents a bit whose value is "1", otherwise it represents a bit whose value is "0". Importantly, each HIGH and LOW portion must measure at least 3 samples, and the total duration of the HIGH-to-LOW transition must not exceed 16 samples.

As both barcode data and level data are 32-bits long, the data type being transmitted is generally determined by the top 8 or 6 most significant bits (i.e. Bits 24-31 for level data, and Bits 26-31 for barcode data). Additionally, Ryuusei no Rockman will manually validate the data on its own. The format for each type of data is listed and explained below:

    ---------------------------------------------------------
    Wave Scanner Level Data
    ---------------------------------------------------------
    Bits 00 - 07	| XOR Check Digit
    Bits 08 - 14	| Wave Scanner Level (1 - 99)
    Bits 15 - 16	| Wave Scanner Type (1, 2, or 3)
    Bits 17 - 23	| Constant (0x40)
    Bits 24 - 31	| Constant (0x42)
    ---------------------------------------------------------

The Wave Scanner's level occupies Bits 8 - 14 and has a valid decimal integer in the range of 1 - 99.

The Wave Scanner Type (Leo, Pegasus, and Dragon) is determined by Bit 15 - 16. A value of "1" indicates a Leo Wave Scanner. A value of "2" represents a Pegasus Wave Scanner. A value of "3" represents a Dragon Wave Scanner.

The upper 15-bits are constant values, 0x42 and 0x40. That is to say, only Bits 23, 25, and 30 are set.

The XOR Check Digit ensures a small amount of data integrity during transmission. It is simply the XOR'd values of the upper 24-bits of data split into 8-bit values. In other words, the XOR Check Digit is calculated as follows:

    CHECK DIGIT = (BITS 8 - 15) XOR (BITS 16 - 23) XOR (BITS 24 - 31)

    ---------------------------------------------------------
    Wave Card Barcode Data
    ---------------------------------------------------------
    Bits 00 - 07	| XOR Check Digit
    Bits 08 - 13	| 6th Barcode Character Code
    Bits 14 - 19	| 5th Barcode Character Code
    Bits 20 - 25	| 4th Barcode Character Code
    Bits 26 - 31	| Constant (0x10)
    ---------------------------------------------------------

Although the Wave Scanner's Wave Cards are in Code-128 C format, only use the last 3 character codes identify any specific card. The alphanumeric representation of each barcode for all Wave Cards uses the format 040000XXYYZZ, where only XXYYZZ change. As Code-128 C converts a single character code into 2 alphanumeric characters, XXYYZZ are the 4th, 5th, and 6th character codes of the barcode. These are encoded as individual 6-bit values when transmitted via the Wave Scanner. The upper 6-bits of the 32-bit barcode data is a simple constant value where only Bit 30 is set.

[Wave Scanner] : Barcodes

Character Cards are special cards that effectively end up being duplicates of other cards in terms of overall effect, and in some cases they even duplicate the actual barcodes. For example, C-02 "Rockman" has the same barcode as S-133 "Recover 200", and the Character Card makes explicit note that it restores 200 HP. Often, Character Cards will have the same outcome as using the "SP" version of a Mega Card. These ones seem to be denoted with the barcode pattern 04000024xxxx.

For whatever reason, the Ice Meteor cards are marked as "BC-xxx" instead of "S-xxx". This may stand for "Battle Card" and is perhaps a typo. It's possible it also stands for "Best Combo", however, outside of glitches, attacks powered up by the Wave Scanner disqualify players from achieving a Best Combo.

    Standard Cards
    ----------------------------------------------------------------------------------------------------------------------
    Card ID	| Barcode	| English Name			| Japanese Name
    ----------------------------------------------------------------------------------------------------------------------
    S-001	| 040000060019	| Canon				| キャノン
    S-002	| 400000060026	| Plus Canon			| プラスキャノン
    S-003	| 400000060031	| Heavy Canon			| ヘビーキャノン
    S-004	| 040000060044	| Plasma Gun 1			| プラズマガン 1
    S-005	| 040000060055	| Plasma Gun 2			| プラズマガン 2
    S-006	| 040000060100	| Plasma Gun 3			| プラズマガン 3
    S-007	| 040000060107	| Gatling Gun 1			| ガトリング 1
    S-008	| 040000060122	| Gatling Gun 2			| ガトリング 2
    S-009	| 040000060135	| Gatling Gun 3			| ガトリング 3
    S-010	| 040000060136	| Air Spread			| エアスプレッド
    S-011	| 040000060154	| Radar Missile 1		| レーダーミサイル 1
    S-012	| 040000060160	| Radar Missile 2		| レーダーミサイル 2
    S-013	| 040000060210	| Radar Missile 3		| レーダーミサイル 3
    S-014	| 040000000212	| Heat Ball 1			| ヒートボール 1
    S-015	| 040000000222	| Heat Ball 2			| ヒートボール 2
    S-016	| 040000000240	| Heat Ball 3			| ヒートボール 3
    BC-017	| 040000060246	| Ice Meteor 1			| アイスメテオ 1
    BC-018	| 040000060260	| Ice Meteor 2			| アイスメテオ 2
    BC-019	| 040000060262	| Ice Meteor 3			| アイスメテオ 3
    S-020	| 040000060317	| Stun Knuckle			| スタンナックル
    S-021	| 040000060325	| Poison Knuckle		| ポイズンナックル
    S-022	| 040000060330	| Freeze Knuckle		| フリーズナックル
    S-023	| 040000060343	| Sword				| ソード
    S-024	| 040000060354	| Wide Sword			| ワイドソード
    S-025	| 040000060363	| Long Sword			| ロングソード
    S-026	| 040000060406	| Blazing Edge			| リュウエンザン
    S-027	| 040000060421	| Tidal Edge			| スイゲツザン
    S-028	| 040000060424	| Strike Edge			| ライメイザン
    S-029	| 040000060435	| Arbo Edge			| タイボクゼン
    S-030	| 040000060444	| Break Sabre			| ブレイクサーベル
    S-031	| 040000060460	| Ground Wave 1			| グランドウェーブ 1
    S-032	| 040000060500	| Ground Wave 2			| グランドウェーブ 2
    S-033	| 040000060512	| Ground Wave 3			| グランドウェーブ 3
    S-034	| 040000060522	| Jet Attack 1			| ジェットアタック 1
    S-035	| 040000060530	| Jet Attack 2			| ジェットアタック 2
    S-036	| 040000060546	| Jet Attack 3			| ジェットアタック 3
    S-037	| 040000060550	| Power Bomb 1			| パワーボム 1
    S-038	| 040000060562	| Power Bomb 2			| パワーボム 2
    S-039	| 040000060608	| Power Bomb 3			| パワーボム 3
    S-040	| 040000060616	| Ghost Pulse 1			| ゴーストパルス 1
    S-041	| 040000060631	| Ghost Pulse 2			| ゴーストパルス 2
    S-042	| 040000060644	| Ghost Pulse 3			| ゴーストパルス 3
    S-043	| 040000060655	| Fire Ring 1			| モエリング 1
    S-044	| 040000060700	| Fire Ring 2			| モエリング 2
    S-045	| 040000060707	| Fire Ring 3			| モエリング 3
    S-046	| 040000060712	| Time Bomb 1			| カウントボム 1
    S-047	| 040000060725	| Time Bomb 2			| カウントボム 2
    S-048	| 040000060736	| Time Bomb 3			| カウントボム 3
    S-049	| 040000060745	| Fire Bazooka 1		| ファイアバズーカ 1
    S-050	| 040000060752	| Fire Bazooka 2		| ファイアバズーカ 2
    S-051	| 040000060802	| Fire Bazooka 3		| ファイアバズーカ 3
    S-052	| 040000060814	| Tail Burner 1			| テイルバーナー 1
    S-053	| 040000060824	| Tail Burner 2			| テイルバーナー 2
    S-054	| 040000060832	| Tail Burner 3			| テイルバーナー 3
    S-055	| 040000060838	| Wide Wave 1			| ワイドワェーブ 1
    S-056	| 040000060852	| Wide Wave 2			| ワイドワェーブ 2
    S-057	| 040000060900	| Wide Wave 3			| ワイドワェーブ 3
    S-058	| 040000060910	| Chain Bubble 1		| チェインバブル 1
    S-059	| 040000060918	| Chain Bubble 2		| チェインバブル 2
    S-060	| 040000060924	| Chain Bubble 3		| チェインバブル 3
    S-061	| 040000060937	| Green Ink			| グリーンインク
    S-062	| 040000060948	| Blue Ink			| ブルーインク
    S-063	| 040000060957	| Purple Ink			| パープルインク
    S-064	| 040000061000	| Sticky Rain 1			| ネバーレイン 1
    S-065	| 040000061015	| Sticky Rain 2			| ネバーレイン 2
    S-066	| 040000061028	| Sticky Rain 3			| ネバーレイン 3
    S-067	| 040000061039	| Cloud Shot 1			| クラウドシュート 1
    S-068	| 040000061048	| Cloud Shot 2			| クラウドシュート 2
    S-069	| 040000061055	| Cloud Shot 3			| クラウドシュート 2
    S-070	| 040000061060	| Thunder Ball 1		| サンダーボール 1
    S-071	| 040000061108	| Thunder Ball 2		| サンダーボール 2
    S-072	| 040000061118	| Thunder Ball 3		| サンダーボール 3
    S-073	| 040000061126	| Voltic Eye 1			| ボルティックアイ 1
    S-074	| 040000061142	| Voltic Eye 2			| ボルティックアイ 2
    S-075	| 040000061146	| Voltic Eye 3			| ボルティックアイ 3
    S-076	| 040000061158	| Flicker Kick 1		| ホタルゲリ 1
    S-077	| 040000061204	| Flicker Kick 2		| ホタルゲリ 2
    S-078	| 040000061212	| Flicker Kick 3		| ホタルゲリ 3
    S-079	| 040000061228	| Jumbo Hammer 1		| ジャンボハンマー 1
    S-080	| 040000061232	| Jumbo Hammer 2		| ジャンボハンマー 2
    S-081	| 040000061243	| Jumbo Hammer 3		| ジャンボハンマー 3
    S-082	| 040000061252	| Mop Lance 1			| モジャランス 1
    S-083	| 040000061305	| Mop Lance 2			| モジャランス 2
    S-084	| 040000061310	| Mop Lance 3			| モジャランス 3
    S-085	| 040000061323	| Fokx-Fu 1			| ヘンゲノジュツ 1
    S-086	| 040000061334	| Fokx-Fu 2			| ヘンゲノジュツ 2
    S-087	| 040000061343	| Fokx-Fu 3			| ヘンゲノジュツ 3
    S-088	| 040000061350	| Vulcan Seed 1			| バルカンシード 1
    S-089	| 040000061401	| Vulcan Seed 2			| バルカンシード 2
    S-090	| 040000061404	| Vulcan Seed 3			| バルカンシード 3
    S-091	| 004000061414	| Brave Sword 1			| ブレイブソード 1
    S-092	| 004000061432	| Brave Sword 2			| ブレイブソード 2
    S-093	| 004000061438	| Brave Sword 3			| ブレイブソード 3
    S-094	| 040000061452	| Junk Cube 1			| ジャンクキューブ 1
    S-095	| 040000061454	| Junk Cube 2			| ジャンクキューブ 2
    S-096	| 040000061500	| Junk Cube 3			| ジャンクキューブ 3
    S-097	| 040000061518	| Synchro Hook 1		| シンクロフック 1
    S-098	| 040000061524	| Synchro Hook 2		| シンクロフック 2
    S-099	| 040000061538	| Synchro Hook 3		| シンクロフック 3
    S-100	| 040000061540	| Power Song			| パワーソング
    S-101	| 040000061550	| Quake Song			| クエイクソング
    S-102	| 040000061562	| Trip Song			| トリップソング
    S-103	| 040000061612	| Maoi Fall 1			| モアイフォール 1
    S-104	| 040000061618	| Maoi Fall 2			| モアイフォール 2
    S-105	| 040000061626	| Maoi Fall 3			| モアイフォール 3
    S-106	| 040000061636	| Big Axe 1			| ビッグアックス 1
    S-107	| 040000061648	| Big Axe 2			| ビッグアックス 2
    S-108	| 040000061662	| Big Axe 3			| ビッグアックス 3
    S-109	| 040000061704	| Magic Crystal 1		| マジクリスタル 1
    S-110	| 040000061712	| Magic Crystal 2		| マジクリスタル 2
    S-111	| 040000061723	| Magic Crystal 3		| マジクリスタル 3
    S-112	| 040000061736	| Black Hole 1			| ブラックホール 1
    S-113	| 040000061751	| Black Hole 2			| ブラックホール 2
    S-114	| 040000061758	| Black Hole 3			| ブラックホール 3
    S-115	| 040000061803	| Berserk Sword 1		| ベルセルカソード 1
    S-116	| 040000061814	| Berserk Sword 2		| ベルセルカソード 2
    S-117	| 040000061827	| Berserk Sword 3		| ベルセルカソード 3
    S-118	| 040000061832	| Green Burst			| グリーンバースト
    S-119	| 040000061839	| Ice Burst			| アイスバースト
    S-120	| 040000061848	| Poison Burst			| ポイズンバースト
    S-121	| 040000061860	| Typhoon Dance			| タイフーンダンス
    S-122	| 040000061910	| Jamming Punch			| ジャミングパンチ
    S-123	| 040000061916	| Jamming Machine Gun		| ジャミングマシンガン
    S-124	| 040000061924	| Whistle			| ホイッスル
    S-125	| 040000061934	| Bombalizer			| ボムライザー
    S-126	| 040000061946	| Anti Sword			| シラハドリ
    S-127	| 040000061960	| Recover 10			| リカバリー 10
    S-128	| 040000062002	| Recover 30			| リカバリー 30
    S-129	| 040000062010	| Recover 50			| リカバリー 50
    S-130	| 040000062020	| Recover 80			| リカバリー 80
    S-131	| 040000062033	| Recover 120			| リカバリー 120
    S-132	| 040000062048	| Recover 150			| リカバリー 150
    S-133	| 040000062055	| Recover 200			| リカバリー 200
    S-134	| 040000062100	| Recover 300			| リカバリー 300
    S-135	| 040000062111	| Barrier			| バリア
    S-136	| 040000062118	| Barrier 100			| バリア 100
    S-137	| 040000062129	| Barrier 200			| バリア 200
    S-138	| 040000062136	| Aura				| オーラ
    S-139	| 040000062155	| Invisible			| インビジブル
    S-140	| 040000062156	| Spirit Fury			| セイレイノイカリ
    S-141	| 040000062206	| Poison Apple			| ドクリンゴ
    S-142	| 040000062212	| Double Cross			| ウラギリノススメ
    S-143	| 040000062230	| Giga Mine			| ギガマイン
    S-144	| 040000062240	| Grass Stage			| クサムラステージ
    S-145	| 040000062242	| Ice Stage			| アイスステージ
    S-146	| 040000062256	| Gravity Stage			| グラビティステージ
    S-147	| 040000062262	| Guard Null Stage		| ゼシエンステージ
    S-148	| 040000062316	| Holy Panel			| ホーリーパネル
    S-149	| 040000062326	| Paralyze Plus			| マビプラス
    S-150	| 040000062328	| Attack+10			| アタック+10
    ----------------------------------------------------------------------------------------------------------------------

    Mega Cards
    ----------------------------------------------------------------------------------------------------------------------
    Card ID	| Barcode	| English Name			| Japanese Name
    ----------------------------------------------------------------------------------------------------------------------
    M-181	| 040000062826	| Taurus Fire			| オックスファイア
    M-182	| 040000062836	| Taurus Fire EX		| オックスファイア EX
    M-183	| 040000062838	| Taurus Fire SP		| オックスファイア SP
    M-184	| 040000062852	| Cygnus Wing			| キグナスウィング
    M-185	| 040000062858	| Cygnus Wing EX		| キグナスウィング EX
    M-186	| 040000062912	| Cygnus Wing SP		| キグナスウィング SP
    M-187	| 040000062922	| Harp Note			| ハープ・ノート
    M-188	| 040000062924	| Harp Note EX			| ハープ・ノート EX
    M-189	| 040000062938	| Harp Note SP			| ハープ・ノート SP
    M-190	| 040000062944	| Libra Scales			| リブラ・バランス
    M-191	| 040000062963	| Libra Scales EX		| リブラ・バランス EX
    M-192	| 040000063000	| Libra Scales SP		| リブラ・バランス SP
    M-193	| 040000063013	| Queen Ophiuca			| オヒュカスクイーン
    M-194	| 040000063028	| Queen Ophiuca EX		| オヒュカスクイーン EX
    M-195	| 040000063056	| Queen Ophiuca SP		| オヒュカスクイーン SP
    M-196	| 040000063044	| Gemini Spark			| ジェミニスパーク
    M-197	| 040000063055	| Gemini Spark EX		| ジェミニスパーク EX
    M-198	| 040000063104	| Gemini Spark SP		| ジェミニスパーク SP
    M-199	| 040000063109	| Cancer Bubble			| キャンサバブル
    M-200	| 040000063116	| Cancer Bubble EX		| キャンサバブル EX
    M-201	| 040000063127	| Cancer Bubble SP		| キャンサバブル SP
    M-202	| 040000063140	| Wolf Woods			| ウルフフォレスト
    M-203	| 040000063155	| Wolf Woods EX			| ウルフフォレスト EX
    M-204	| 040000063162	| Wolf Woods SP			| ウルフフォレスト SP
    M-205	| 040000063207	| Crown Thunder			| クラウンサンダー
    M-206	| 040000063218	| Crown Thunder EX		| クラウンサンダー EX
    M-207	| 040000063231	| Crown Thunder SP		| クラウンサンダー SP
    M-208	| 040000063236	| Pegasus Magic			| ペガサスマジック
    M-209	| 040000063243	| Pegasus Magic EX		| ペガサスマジック EX
    M-210	| 040000063252	| Pegasus Magic SP		| ペガサスマジック SP
    M-211	| 040000063301	| Leo Kingdom			| レオキングダム
    M-212	| 040000063316	| Leo Kingdom EX		| レオキングダム EX
    M-213	| 040000063323	| Leo Kingdom SP		| レオキングダム SP
    M-214	| 040000063332	| Dragon Sky			| ドラゴンスカイ
    M-215	| 040000063343	| Dragon Sky EX			| ドラゴンスカイ EX
    M-216	| 040000063356	| Dragon Sky SP			| ドラゴンスカイ SP
    ----------------------------------------------------------------------------------------------------------------------

    Giga Cards
    ----------------------------------------------------------------------------------------------------------------------
    Card ID	| Barcode	| English Name			| Japanese Name
    ----------------------------------------------------------------------------------------------------------------------
    G-231	| 040000063613	| Pegasus Magic GX		| ペガサスマジック GX
    G-232	| 040000063622	| Aqua+50			| アクア+50
    G-233	| 040000063633	| Ox Tackle			| オックスタックル
    G-234	| 040000063636	| Break Time Bomb		| ブレイクカウントボム
    G-235	| 040000063651	| Dark Sword			| ダークソード
    G-236	| 040000063658	| Leo Kingdom GX		| レオキングダム GX
    G-237	| 040000063703	| Fire+50			| ファイア+50
    G-238	| 040000063714	| Gemini Thunder		| ジェミニサンダー
    G-239	| 040000063727	| Darkness Hole			| ダークネスホール
    G-240	| 040000063732	| Life Aura			| ドリームオーラ
    G-241	| 040000063751	| Dragon Sky GX			| ドラゴンスカイ GX
    G-242	| 040000063752	| Wood+50			| ウッド+50
    G-243	| 040000063801	| Gorgon Eye			| ゴルゴンアイ
    G-244	| 040000063816	| Destroy Missle		| デストロイミサイル
    G-245	| 040000063823	| Poison Pharoah		| ポイズンファラオ
    G-247	| 040000063843	| Andromeda			| アンドロメダ
    ----------------------------------------------------------------------------------------------------------------------

    Character Cards
    ----------------------------------------------------------------------------------------------------------------------
    Card ID	| Barcode	| English Name			| Japanese Name
    ----------------------------------------------------------------------------------------------------------------------
    C-01	| 040000060031	| Rockman			| ロックマン
    C-02	| 040000062055	| Rockman			| ロックマン
    C-06	| 040000063236	| Ice Pegasus			| アイスペガサス
    C-09	| 040000240020	| Taurus Fire			| オックスファイア
    C-10	| 040000240027	| Cygnus Wing			| キグナスウィング
    C-11	| 040000240032	| Harp Note			| ハープ・ノート
    C-12	| 040000240045	| Libra Scales			| リブラ・バランス
    C-13	| 040000240056	| Queen Ophiuca			| オヒュカス・クイーン
    C-14	| 040000240101	| Gemini Spark			| ジェミ・スパーク
    C-15	| 040000240108	| Cancer Bubble			| キャンサ・バブル
    C-16	| 040000240123	| Wolf Woods			| ウルフ・フォレスト
    C-17	| 040000240136	| Crown Thunder			| クラウン・サンダー
    ----------------------------------------------------------------------------------------------------------------------

Bayer Didget Glucose Meter

General Hardware Information

Device Detection

Accessing Didget Data

Index Overview

Point Calculation

[Bayer Didget Glucose Meter] : General Hardware Information

The Bayer Didget Glucose Meter is a Slot-2 device for the Nintendo DS capable of processing diabetic testing strips. Created by Bayer AG, it was designed to interact with the game Knock'em Downs: World's Fair and released on May 8th, 2009 in the United States and later in September for Europe. After having bought the rights to the earlier Glucoboy, Bayer repurposed the hardware for the Nintendo DS, resulting in the Didget. This newer version is largely the same as its predecessor, and the premise behind the game is unchanged. Players unlock points by regularly testing their blood sugar levels and staying within healthy levels. These points are then used to purchase minigames, items, costumes, and photographs in-game.

- Comes in an oversized white cartridge with an ovular top-end.
- Comes with a segmented LCD screen capable of displaying a few digits for glucose levels, time, date, and other statuses.
- Has "M" and UP and DOWN buttons on the sides of the LCD screen, which should work similarly to other glucose meters.
- Has a slot for accepting blood testing strips at the very top, specifically Bayer's Contour brand test strips.
- Uses a coin cell battery (CR2032) to power the unit's glucose checking functions as well as an internal real-time clock.
- Has a USB Mini slot on the lower side of the unit for PC connection via the GLUCOFACTS DELUXE software.
- The PCB is split into two main sections: top for glucose checking hardware, bottom for internal flash memory.
- Top PCB contains a Panasonic MN101CB microcontroller, presumably used to handle glucose checking and managing the RTC.
- Has an LED at the top left corner that flashes during testing.
- Has an operating tempurature of 5C - 45C (41F - 113F).
- Stores 480 test results internally.

[Bayer Didget Glucose Meter] : 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 Didget:

    //Read individual bytes from GBA cart space
    if address AND 1
    	return 0xF3
    else
    	return ANY VALUE

[Bayer Didget Glucose Meter] : Accessing Didget Data

The Nintendo DS does not directly test glucose or blood samples. Rather, the Didget handles that on its own and allows the handheld to read back the data stored on the device. The Didget operates in much the same manner as the original Glucoboy with only minor differences. The Didget uses a single, multipurpose 1-byte register mapped to the address 0xA000000, named here as DIDGET_CNT for the purposes of this document. By reading and writing to DIDGET_CNT, data such as reward points, bonus points, short messages, and other miscellaneous hardware information can be extracted. The DS can also push data to the Didget by updating the player's high scores and total available points.

To access data on the Didget, an index must first be written to DIDGET_CNT. Different data — such as reward points earned today or bonus points — are stored at different indices. Once an index is set, the Didget triggers a Game Pak IRQ. Following this, 1-byte, 4-bytes, or 6-bytes, or 64-bytes must be read from/written to DIDGET_CNT, depending on the index. For example, in the case that an index returns 4-bytes of data, DIDGET_CNT must be read a total of 4 times, once per byte. 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 DIDGET_CNT. For integer values (primarily 4-byte and 6-byte indices) data is read/written MSB-first, therefore, software must also manually adjust LSB-first values on the DS. Other data such as the 64-byte indices for messages is written sequentially.

The Didget appears to have a sort of "idle" mode when no index is currently specified. These instances seem to happen after initially booting up the DS and the Didget, and it also occurs after the DS has finished reading from/writing to an index. In these instances where the Didget is "idle", reading from DIDGET_CNT twice returns the values 0xBD and 0xDA in that order. Knock'em Downs: World's Fair does this at times to verify that the Didget is ready for read or write operations. During idle mode, the Didget *DOES NOT* generate Game Pak IRQs.

Below is the typical proceedure used to read or write to an index on the Didget of XYZ length:

    -----------------------------------------------------------
    XYZ-byte Index Access
    -----------------------------------------------------------
    WRITE INDEX TO DIDGET_CNT
    	WAIT FOR GAMEPAK IRQ

    READ OR WRITE BYTE AT DIDGET_CNT
    	WAIT FOR GAMEPAK IRQ

    REPEAT READ OR WRITE AT DIDGET_CNT FOR XYZ LENGTH
    -----------------------------------------------------------

Indices on the Didget are typically read-only or write-only. After writing data to a write-only index, however, reading 1-byte from that same index returns the status of the previous write operation. Any non-zero outputs indicate an error. Once this status byte is read, the Didget presumably returns to idle mode.

[Bayer Didget Glucose Meter] : Index Overview

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

    -----------------------------------------------------------
    Index		| Size 	| Description
    -----------------------------------------------------------
    0x10 - 0x1F 	| 64	| Read Messages (Banks 0 - 15)
    0x20		| 4	| Read System Date
    0x21		| 4	| Read New Reward Points
    0x22		| 4	| Read New Bonus Points
    0x23		| 4	| Read Current Number of Bonus Days
    0x24		| 4	| Read Number of Days Until Next Bonus
    0x25		| 4	| Read Hardware Flags
    0x26		| 4	| Read LD Threshold
    0x27		| 4	| Read Serial Number
    0x28		| 4	| Unknown Index
    0x29		| 4	| Unknown Index
    0x2A		| 4	| Unknown Index
    0x2B		| 4	| Unknown Index
    0x2C		| 4	| Read Current Total Points
    0x2D		| 4	| Unknown Index
    0x31		| 1	| Read Unknown Flag
    0x32		| 1	| Read Unknown Flag
    0x6C		| 4	| Write Current Total Points
    0xE3		| 6	| Write High Scores (Banks 1 - 12)
    -----------------------------------------------------------

The Didget largely copies the Glucoboy for its indices. Many of the indices related to rewards and points are simply renamed while retaining the same purpose. One key difference is that while the Glucoboy stored the total amount of earned points inside the EEPROM inside its cartridge, the Didget dedicates a specific index for this. A number of hardware specific details (flags, serial number, LD threshold), are also read but seemingly unused by the Didget. Additionally, the Didget uses 1KB of its internal storage for short messages.

Any indices present on both the Glucoboy and Didget are assumed to work identically unless further testing reveals otherwise. This document, therefore, will only explore indices exclusively used by the Didget. Refer to documentation on the Glucoboy for further information if necessary.

Index 0x10 to 0x1F - Read Messages (Banks 0 - 15)

The Didget can store a total of 16 different 64-byte messages using extended ASCII encoding. NULL characters can terminate the message at any given point. If a message begins with a NULL character, Knock'em Downs: World's Fair ignore it as empty. The software will display any non-empty message it finds, however, the order of the messages is independent of the bank. The message in Bank 0 is always a "Daily Message", while any subsequent messages are numbered from 1 up to 15. That is to say, if a message bank is empty, it does not take up a number when listed. For example, if Banks 0, 1, 2, and 4 have messages, but Bank 3 is empty, Bank 0 will be the Daily Message, and Banks 1, 2, and 4 will be labeled "Message #1", "Message #2", and "Message #3".

The extended ASCII encoding is standard ASCII for the first 128-bytes with non-standard encodings for several accented characters. Encodings vary between the regular copies of Knock'em Downs: World's Fair and the DSi enhanced version. For whatever reason, on regular versions of the game, characters such as "à" (using a value of 0xA0) and "Ñ" have glitched renderings, with the former effectively being invisible.

    Regular Encodings
    ----------------------------------------------------------------------------------------------------------------------------------------------
         |	0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F
    ----------------------------------------------------------------------------------------------------------------------------------------------
    0x80 |	À 	Á	Â	Ä			È	É	Ê	Ë	Ì	Í	Î	Ï	Ñ	Ò
    0x90 |	Ó	Ô	Ö			Ù	Ú	Û	Ü
    0xA0 |		á	â	ä			è	é	ê	ë	ì	í	î	ï	ñ	ò
    0xB0 |	ó	ô	ö			ù	ú	û	ü	¡	¿
    ----------------------------------------------------------------------------------------------------------------------------------------------

    DSi Enhanced Encodings
    ----------------------------------------------------------------------------------------------------------------------------------------------
         |	0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F
    ----------------------------------------------------------------------------------------------------------------------------------------------
    0x80 |	À 	Á	Â	Ã	Ä	Å	Æ	Ç	È	É	Ê	Ë	Ì	Í	Î	Ï
    0x90 |	Ñ	Ò	Ó	Ô	Õ	Ö	Œ	Ø	Ù	Ú	Û	Ü
    0xA0 |	à	á	â	ã	ä	å	æ	ç	è	é	ê	ë	ì	í	î	ï
    0xB0 |	ñ	ò	ó	ô	õ	ö	œ	ø	ù	ú	û	ü	¡	¿	◌̇
    ----------------------------------------------------------------------------------------------------------------------------------------------

These messages were transferred from the Bayer Didget website when connecting the device via USB to a PC.

Index 0x20 - Read System Date

This index returns the current system date according to the Didget's RTC. The clock is used internally to decide if glucose testing has been performed on a consistent schedule in order to give out reward points. It is entirely independent from the DS' own clock. Knock'em Downs: World Fair does not seem to make use of this data, however. 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 New Reward Points

This represents the amount of reward points earned since the player last checked in with the game. Internally, this value is presumably added to the total amount of points in index 0x2C automatically. The exact amount is determined by factors such as whether the levels were healthy and whether the test was done in accordance to a regular schedule. The DS does not seem to have access to the components that calculate these points, so it only reads whatever the hardware reports.

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

Index 0x22 - Read New Bonus Points

This represents the amount of bonus points earned by maintaining healthy glucose levels over a specific number of days since the player last checked in with the game. The Didget likely updates this internally when the "Number of Good Days Until Bonus Rewarded" value reaches zero and reloads to a new value. At that time, these bonus points are also added to the total amount of points.

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

Index 0x23 - Read Current Number of Bonus Days

This index represents the number of continuous 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 a signed 32-bit integer. Only positive numbers are valid, so the maximum allowed value is therefore 2147483647.

Index 0x24 - Read Number of Days Until Next Bonus

This index represents the number of remaining days needed until the bonus points would be granted. This value likely decreases by one every 24-hours, so long as the player's glucose levels were kept in check regularly.

The 4 bytes returned by this index form a 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 Didget. It is assumed they carry over from the Glucoboy in function and meaning. Knock'em Downs: World's Fair reads this data but makes no use of it. 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 Didget 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 Didget's method of determining how it gives out points. 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, Knock'em Downs: World's Fair does not take any specific actions on them. For example, the player is not warned if any of these components stops working, although, it may affect retrieving reward points, 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 Didget. This appears to be a per-device serial number. Although is is read by Knock'em Downs: World's Fair, the game does not use it. It was, however, read via USB when connecting the Didget to a PC for the Bayer Didget website.

The 4 bytes returned by this index form an unsigned 27-bit integer. It is used to represent values ranging from 00000000 - 99999999.

Index 0x28 - Read Unknown Index

The exact purpose of this index is unknown. It does not seem to be actively used by Knock'em Downs: World's Fair.

Index 0x29 - Read Unknown Index

The exact purpose of this index is unknown. It does not seem to be actively used by Knock'em Downs: World's Fair.

Index 0x2A - Read Unknown Index

The exact purpose of this index is unknown. It does not seem to be actively used by Knock'em Downs: World's Fair.

Index 0x2B - Read Unknown Index

The exact purpose of this index is unknown. It does not seem to be actively used by Knock'em Downs: World's Fair.

Index 0x2C - Read Current Total Points

This represents the total amount of points earned. Realistically, it should not be lower than the sum of New Reward Points and Bonus Points, however, Knock'em Downs: World's Fair does not perform any checks or validation on this value. The index is responsible for telling the game how many points the player can spend to get in-game tickets.

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

Index 0x2D - Read Unknown Index

The exact purpose of this index is unknown. It does not seem to be actively used by Knock'em Downs: World's Fair.

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 Didget to register an error when retrieving points.

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 Didget to register an error when retrieving points.

Index 0x6C - Current Total Points

This index sets the total amount of points earned. It receives 4 bytes representing a signed 32-bit integer. This index is updated by Knock'em Downs: World's Fair after converting points from the Didget to in-game tickets.

Index 0xE3 - Write High Scores

This index is used to write the high scores on each minigame from Knock'em Downs: World's Fair. Although the DS cartridge contains the scores in its own save data, this information was presumably uploaded as part of the official online community surrounding the Didget. Each game has its own "bank" that can be addressed. The format of the 6 bytes written to this index is detailed below:

    -----------------------------------------------------------
    Bytes	| Description	| Value
    -----------------------------------------------------------
    0	| Bank High	| Always 0x02
    1	| Bank Low	| 0x01 - 0x0C
    2 - 5	| Score		| 32-bit signed integer
    -----------------------------------------------------------

The specific game is always determined by Byte 1 (Bank Low). The list of games is as follows:

    -----------------------------------------------------------
    Bank	| Game Name
    -----------------------------------------------------------
    0x01	| Carnival Chaos
    0x02	| Operation Maze
    0x03	| Flash Carb
    0x04	| Knock'em Down Launch
    0x05	| Hook Shot
    0x06	| Knock'em Down
    0x07	| Puzzle Monster
    0x08	| Anglin' Ventures
    0x09	| Arena Gladiator
    0x0A	| Russian Dolls
    0x0B	| Ace of Vase
    0x0C	| That's A Wrap
    -----------------------------------------------------------

[Bayer Didget Glucose Meter] : Point Calculation

The Bayer Didget's formula for calculating reward points is cleary documented in its manual. It uses a rolling average based on the amount of times tested within a 24-hour period and whether the player's glucose levels are below, above, or on target. The chart below shows the amount of points added to the average for any given amount of tests:

    ----------------------------------------------------------------------------------------------------------------------------------------------
    Current Test # 	| Below Target Points	| On Target Points	| Above Target Points
    ----------------------------------------------------------------------------------------------------------------------------------------------
    1		| 20			| 25			| 20
    2		| 40			| 50			| 40
    3		| 75			| 100			| 75
    4+		| 150			| 200			| 150
    ----------------------------------------------------------------------------------------------------------------------------------------------

For example, for the first test, the user would receive 20 points if below their target. For the second test, assuming they are on target, they would add 50 points to their average, resulting in (20 + 50) / 2 points (i.e. 35) as the final total. Assuming a third test was done and they were above target, they would add 150 points to their average, resulting in (20 + 50 + 150) / 3 points (i.e. 73 points) as the final total. The average seems to be rounded.

There must be a 6-hour gap between the first and second tests to register points. All subsequent tests require a 2-hour gap. A maximum of 9 tests can be performed in a single day. This averaging mechanism was designed to encourage children to more frequently test themselves. If the player tests 3 times or more in a 24-hour period, this counts towards a streak where bonus points are rewarded after a fixed amount of days:

    -----------------------------------------------------------
    # of Days	| Bonus Points Awarded
    -----------------------------------------------------------
    7		| 100
    14		| 300
    21		| 500
    30		| 1000
    90		| 5000
    -----------------------------------------------------------

After a 90-day streak, the bonus points restart by waiting for a 7-day streak.

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.

- The Mobile Adapter is a small device that essentially allows a Japanese phone to connect to the Game Boy's link port
- Model number is CGB-005
- Officially released with 3 different versions of the Mobile Adapter. Each featured distinct colors to work with different type of phones
- Each Mobile Adapter came packaged with a cartridge called the Mobile Trainer to help configure and setup the device
- Servers were formally hosted at gameboy.datacenter.ne.jp

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 Wars 3
- Hello Kitty: Happy House
- Mobile Golf
- Mobile Trainer
- Net de Get Minigames @ 100
- Pocket Monsters Crystal Version

Game Boy Advance : 16 Total

- All-Japan GT Championship
- Daisenryaku For Game Boy Advance
- Doraemon: Midori no Wakusei Doki Doki Daikyuushuutsu!
- Exciting Bass
- EX Monopoly
- JGTO Licensed: Golfmaster Mobile
- Kinniku Banzuke ~Kongou-kun no Daibouken!~
- Mail de Cute
- Mario Kart Advance
- Mobile Pro Baseball: Control Baton
- Monster Guardians
- Morita Shougi Advance
- Napoleon
- Play Novel: Silent Hill
- Starcom: Star Communicator
- Zero-Tours

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:

- http://gameboy.datacenter.ne.jp/cgb/download?name=/A7/AGB-AMOJ/information.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/A7/AGB-AMOJ/query_T.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/A7/AGB-AMOJ/query_M.cgb
- http://gameboy.datacenter.ne.jp/cgb/upload?name=/A7/AGB-AMOJ/0.regist.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/A7/AGB-AMOJ/10.temporary.cgb

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

- If the first byte is in the range 0x00-0xF0 (inclusive), the pair is written as a tile and the cursor moves one tile to the right.
- If the first byte is in the range 0xF1-0xFD (inclusive), nothing happens.
- If the first byte is 0xFE, the cursor moves to the next line's leftmost tile.
- If the first byte is 0xFF, the game stops reading the file immediately.

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

Note that, in the initial GET request to this file before authentication is complete, the game sends a "Content-Length: 24" header without sending any content.

[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	ブ	ベ	ボ	パ	ピ	プ	ペ	ポ	＄	０	１	２	３	４	５	６
    0xA0	７	８	９	　	ァ	ィ	ゥ	ェ	ォ	ッ	？	ヴ	っ	家	軒	抵
    0xB0	当	価	格	建	設	水	道	費	抖	鉄	会	社	電	力	地	中
    0xC0	海	公	井	通	ぁ	ぃ	ぅ	ぇ	ぉ	゛	゜	枚	倍	Ａ	Ｂ	Ｃ
    0xD0	Ｄ	Ｅ	Ｆ	Ｇ	Ｈ	Ｉ	Ｊ	Ｋ	Ｌ	Ｍ	Ｎ	Ｏ	Ｐ	Ｑ	Ｒ	Ｓ
    0xE0	Ｔ	Ｕ	Ｖ	Ｗ	Ｘ	Ｙ	Ｚ	％	：	⋯	♪	♥︎	～	男	女	位
    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):

- http://gameboy.datacenter.ne.jp/cgb/download?name=/18/CGB-BWWJ/0.map_menu.txt
- http://gameboy.datacenter.ne.jp/cgb/download?name=/18/CGB-BWWJ/map/map_****.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/18/CGB-BWWJ/charge/****.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/18/CGB-BWWJ/mbox/mbox_serial.txt
- http://gameboy.datacenter.ne.jp/cgb/download?name=/18/CGB-BWWJ/mbox/mbox_**.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/18/CGB-BWWJ/0.youhei_menu.txt

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

The 3-letter codes act as stand-ins for numbers (A = 0 ... Z = 25) in a weird mix of Base-10 and Base-26. The position of each letter multiplies its value by 10. As a result, some values can have multiple encodings that the game will accept. For example, the number "20" can be enocoded as "AAU" or "ABK" or "ACA".

    ---------------------------------------------------
    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 1
    AAU	ABK	ACA	Massage Chair 2
    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:

- http://gameboy.datacenter.ne.jp/cgb/download?name=/01/AGB-AMKJ/index.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/01/AGB-AMKJ/rule.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/01/AGB-AMKJ/*total.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/01/AGB-AMKJ/*query.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/01/AGB-AMKJ/*0.dlghost.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/01/AGB-AMKJ/*0.dlghost2.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/01/AGB-AMKJ/*0.dlghost3.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/01/AGB-AMKJ/*0.dlghostdr.cgb
- http://gameboy.datacenter.ne.jp/cgb/ranking?name=/01/AGB-AMKJ/*0.dlghostst.cgb
- http://gameboy.datacenter.ne.jp/cgb/upload?name=/01/AGB-AMKJ/*0.entry.cgb

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:

- Enable coins on track.
- Enable item boxes.
- Enable triple mushroom at start.
- Enable mushrooms-only mode.
- Enable COM opponents.
- Forced character (driver number plus one, 0 = any).
- Starting coin count divided by 5.
- Enable five-lap race.

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	０	１	２	３	４	５	６	７	８	９	：	；	＜	＝	＞	？
    0x20	＠	Ａ	Ｂ	Ｃ	Ｄ	Ｅ	Ｆ	Ｇ	Ｈ	Ｉ	Ｊ	Ｋ	Ｌ	Ｍ	Ｎ	Ｏ
    0x30	Ｐ	Ｑ	Ｒ	Ｓ	Ｔ	Ｕ	Ｖ	Ｗ	Ｘ	Ｙ	Ｚ	［	￥	］	＾	＿
    0x40	‘	ａ	ｂ	ｃ	ｄ	ｅ	ｆ	ｇ	ｈ	ｉ	ｊ	ｋ	ｌ	ｍ	ｎ	ｏ
    0x50	ｐ	ｑ	ｒ	ｓ	ｔ	ｕ	ｖ	ｗ	ｘ	ｙ	ｚ	｛	｜	｝	〜
    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:

- http://gameboy.datacenter.ne.jp/01/CGB-B9AJ/index.html

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:

- <a>
  Hyperlinking can be selected with d-pad and A button
- <b>
  This turns text red instead of black
- <br>
  New line
- <div>
  Starts a new line, can use the align="" attribute
- <center>
  Centers text. Needs to be inside <html></html> tags to render
- <html>
  Not necessary for most elements to render correctly
- <hr>
  Works
- <img>
  Only accepts 1BPP BMPs. If 404, displays a small "broken image" icon
- <title>
  Works
- <li>
  Works
- <ol>
  Works
- <ul>
  Works. Little tiny dot for bullet points

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:

- Maximum size is 144x96. While the BMP specification allows width and height to be defined as 32-bit integers, any image where the dimensions exceed 8-bit integers is rejected.
- The offset to pixel data in the BMP file header must be a 16-bit integer, despite being 32-bit in the specification.
- The 16-bit value for BPP in the BMP image header must be 0x1 (with the MSB being zero).
- The 16-bit value for planes in the BMP image header must be 0x1 (with the MSB being zero).
- The entire 32-bit integer for compression flags in the BMP image header must be zero.
- The entire 32-bit integer for the number of color maps in the BMP image header must be zero.

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.

Mobile Pro Yakyuu

General Information

Server Structure

counter.cgb

200.member.cgb

Player Data

All-Star Data

Team Data

Season Data

String Format

[Mobile Pro Yakyuu] : General Information

Mobile Pro Yakyuu - Kantoku no Saihai (also known simply as Mobile Professional Baseball) is a baseball game for the Game Boy Advance, published by Mobile21 in 2001. Though it initially released with data for the 2000 NPB season, arguably its most prominent feature was the ability to download updated player data.

[Mobile Pro Yakyuu] : Server Structure

Mobile Professional Baseball is known to access the following URLs:

- http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/AGB-AMBJ/counter.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/AGB-AMBJ/200.member.cgb

[Mobile Pro Yakyuu] : counter.cgb

This file is one byte simply indicating the current version number of 200.member.cgb, where zero is the version of the data built into the game. If the game sees that this file's byte matches the version number currently present, it will not redownload 200.member.cgb. The version numbers do not need to be sequential, though given the file's name it's very likely that they were.

[Mobile Pro Yakyuu] : 200.member.cgb

This file is saved directly to the game's save file and thus has a size limit of 0x6000 bytes (24 KiB). When the game first boots (and when new data is downloaded), the data is decompressed using SWI #0x13 (HuffUnComp), then that is itself decompressed using SWI #0x11 (LZ77UnCompWram), and the final data is copied to address 0x2000000. The intermediate and final decompressed data each have a size limit of 0x8000 bytes (32 KiB). The first 16 bytes of the final decompressed data are used as follows:

    ----------------------------------
    Initial Pointers
    ----------------------------------
    0x00 - 0x03			::	Pointer to player data, stored LSB first.
    0x04 - 0x07			::	Pointer to all-star data, stored LSB first.
    0x08 - 0x0B			::	Pointer to team data, stored LSB first.
    0x0C - 0x0F			::	Pointer to season data, stored LSB first.

Most of this data is stored in densely-packed bitfields. These bitfields are entirely little-endian; that is, if a field spans multiple bytes, its least-significant bit(s) are stored in the first byte, and its most-significant bit(s) are stored in the last byte; additionally, when multiple fields take a single byte, the first field takes the least-significant bit(s) of that byte, while the last field takes the most-significant bit(s) of that byte. Byte addresses are suffixed with .0 through .7 to indicate the least-significant bit through the most-significant bit, respectively.

[Mobile Pro Yakyuu] : Player Data

The player data is simply 12 pointers, each 4 bytes stored LSB first, to 25 player profiles, which are formatted as follows:

    ----------------------------------
    Player Profile
    ----------------------------------
    0x00.0 - 0x03.7			::	Pointer to player's long name (width limit: 6 characters).
    0x04.0 - 0x07.7			::	Pointer to player's short name (width limit: 3 characters).
    0x08.0 - 0x08.7			::	Player's squad number. Values 100-109 are used for numbers 00-09 with a leading zero.
    0x09.0 - 0x09.3			::	Player's position (0 = pitcher, 1 = catcher, 2-4 = 1st-3rd base, 5 = shortshop, 6 = left, 7 = center, 8 = right).
    0x09.4 - 0x09.5			::	Pitching hand (0 = right, 1 = left, 2 = both).
    0x09.6				::	0 means the player is an infielder, 1 means otherwise.
    0x09.7 - 0x0A.0			::	Batting hand (0 = right, 1 = left, 2 = both).
    0x0A.1 - 0x0B.0			::	Batting: runs batted in.
    0x0B.1 - 0x0B.7			::	Batting: stolen bases.
    0x0C.0 - 0x0C.7			::	Height (cm).
    0x0D.0 - 0x0D.7			::	Weight (kg).
    0x0E.0 - 0x0E.6			::	Birth year (without century).
    0x0E.7 - 0x0F.2			::	Birth month (1 = January).
    0x0F.3 - 0x0F.7			::	Birth day (1-31).
    0x10.0 - 0x10.7			::	Batting: games played.
    0x11.0 - 0x12.1			::	Batting: at-bats.
    0x12.2 - 0x13.1			::	Batting: runs scored.
    0x13.2 - 0x14.2			::	Batting: hits.
    0x14.3 - 0x15.1			::	Batting: double hits.
    0x15.2 - 0x15.6			::	Batting: triple hits.
    0x15.7 - 0x16.5			::	Batting: home runs.
    0x16.6 - 0x17.1			::	Pitching: shutouts.
    0x17.2 - 0x18.3			::	Batting: batting average times 1,000.
    0x18.4 - 0x19.2			::	Pitching: games played.
    0x19.3 - 0x19.7			::	Pitching: complete games.
    0x1A.0 - 0x1B.1			::	Pitching: innings pitched times 3.
    0x1B.2 - 0x1B.6			::	Pitching: wins.
    0x1B.7 - 0x1C.3			::	Pitching: losses.
    0x1C.4 - 0x1D.1			::	Pitching: saves.
    0x1D.2 - 0x1E.1			::	Pitching: walks granted.
    0x1E.2 - 0x1E.6			::	Pitching: times hit batter.
    0x1E.7 - 0x1F.7			::	Pitching: strikeouts.
    0x20.0 - 0x21.1			::	Pitching: earned-run average times 100.
    0x21.2 - 0x23.7			::	Always zero.
    0x24.0 - 0x25.1			::	"Bat distance" points.
    0x25.2 - 0x26.3			::	"Bat skill" points.
    0x26.4 - 0x27.5			::	"Bat accuracy" points.
    0x27.6 - 0x28.7			::	"Base running" points.
    0x29.0 - 0x2A.1			::	"Catch ball" points.
    0x2A.2 - 0x2B.3			::	"Throw distance" points.
    0x2B.4 - 0x2C.5			::	"Pitch judgement" points.
    0x2C.6 - 0x2D.7			::	"Movement" points.
    0x2E.0 - 0x2F.1			::	"Catcher" points.
    0x2F.2 - 0x30.3			::	"Pitch speed" points.
    0x30.4 - 0x31.5			::	"Ball speed" points.
    0x31.6 - 0x32.7			::	"Sharpness" points.
    0x33.0 - 0x34.1			::	"Control" points.
    0x34.2 - 0x35.3			::	"Endurance" points.
    0x35.4 - 0x36.1			::	Top-left corner of batting skill indicator, see below.
    0x36.2 - 0x36.4			::	Width of batting skill indicator, see below.
    0x36.5 - 0x36.7			::	Height of batting skill indicator, see below.
    0x37.0 - 0x37.5			::	Top-left corner of catching skill indicator, see below.
    0x37.6 - 0x38.0			::	Width of catching skill indicator, see below.
    0x38.1 - 0x38.3			::	Height of catching skill indicator, see below.
    0x38.4 - 0x38.6			::	Level (0 = S, 1-6 = A-F).
    0x38.7 - 0x3C.1			::	3-bit skill multipliers for each position, see below.
    0x3C.2 - 0x3C.7			::	Always zero.
    0x3D.0 - 0x3D.3			::	Unknown, treated as a pitch strength.
    0x3D.4 - 0x3D.7			::	Unknown, treated as a pitch strength.
    0x3E.0 - 0x3E.3			::	"Curve" pitch strength.
    0x3E.4 - 0x3E.7			::	"Change-up" pitch strength.
    0x3F.0 - 0x3F.3			::	"Slider" pitch strength.
    0x3F.4 - 0x3F.7			::	"Shoot" pitch strength.
    0x40.0 - 0x40.3			::	"Sinker" pitch strength.
    0x40.4 - 0x40.7			::	"Fork" pitch strength.
    0x41.0 - 0x41.3			::	Always zero.
    0x41.4 - 0x41.7			::	Unknown, treated as a pitch strength.
    0x42.0 - 0x43.7			::	Always zero.

The "skill indicators" are displayed in a 6x6 matrix. The "top-left corner" value is calculated as (row * 6) + column, where the corners of the matrix are (0, 0) and (5, 5). If the indicator is not to be displayed, all its values are set to zero. If both inidicators overlap, the catching skill indicator takes priority. The "skill multipliers" are values from 0-5, where 0 multiplies skill points by 0.5, 1 multiplies them by 0.6, and so forth. The first eight players on a team must take each non-pitcher position, and the ninth must be a pitcher.

[Mobile Pro Yakyuu] : All-Star Data

The all-star data is 2 pointers (first for the Central League, second for the Pacific League), each 4 bytes stored LSB first, to 25 all-star specifiers, which are formatted as follows:

    ----------------------------------
    All-Star Specifier
    ----------------------------------
    0x00.0 - 0x00.3			::	Team number.
    0x00.4 - 0x01.0			::	Player number.
    0x01.1 - 0x01.4			::	Position (see above).
    0x01.5 - 0x03.7			::	Always zero.

Similarly to player data, the first eight members of an all-star team must take each non-pitcher position, and the ninth must be a pitcher.

[Mobile Pro Yakyuu] : Team Data

The team data is not an array of pointers, but simply an array of 12 team profiles, which are formatted as follows:

    ----------------------------------
    Team Profile
    ----------------------------------
    0x00.0 - 0x03.7			::	Pointer to team's name (width limit: 8 characters).
    0x04.0 - 0x07.7			::	Pointer to manager's name (width limit: 8 characters).
    0x08.0 - 0x08.6			::	Founding year (without century).
    0x08.7 - 0x09.2			::	Founding month (1 = January).
    0x09.3 - 0x09.7			::	Founding day (1-31).
    0x0A.0 - 0x0B.4			::	Total wins.
    0x0B.5 - 0x0D.1			::	Total losses.
    0x0D.2 - 0x0D.7			::	League wins.
    0x0E.0 - 0x0F.0			::	Average game length? (minutes).
    0x0F.1 - 0x10.2			::	Win rate times 1,000.
    0x10.3 - 0x13.7			::	Always zero.

Teams are always in the following order:

    * Yomiuri Giants (Central)
    * Chunichi Dragons (Central)
    * Yokohama BayStars (Central)
    * Yakult Swallows (Central)
    * Hiroshima Toyo Carp (Central)
    * Hanshin Tigers (Central)
    * Fukuoka Daiei Hawks (Pacific)
    * Seibu Lions (Pacific)
    * Nippon-Ham Fighters (Pacific)
    * Orix BlueWave (Pacific)
    * Chiba Lotte Marines (Pacific)
    * Osaka Kintetsu Buffaloes (Pacific)

[Mobile Pro Yakyuu] : Season Data

The season data is simply a single byte in the range 0x00-0x03, indicating whether the rest of the data represents the 2000, 2001, 2002, or 2003 NPB season.

[Mobile Pro Yakyuu] : String Format

The byte 0x00 terminates a string, 0x5B (left bracket) switches to a half-width font, and 0x5D (right bracket) switches to the default full-width font. Any other byte in a string will be taken along with its next byte as a two-byte Shift-JIS sequence.

All characters from JIS X 0208 row 1 are supported except the following, which will appear as spaces:

    ゛゜´¨ヽヾゝゞ〃仝〆〇‐‖∥‥÷≠∴♂♀°′″℃¢£§

All characters from JIS X 0208 row 2 will appear as spaces except the following:

    ◆□■△▲▽▼※→←↑↓

All characters from JIS X 0208 rows 3-5 are supported, and all characters from rows 6-8 will appear as spaces. The circled digits ① through ⑩ from row 13 are supported only in the full-width font, as are all of the "level 1" kanji (rows 16-47).

Net de Get: Mini Game @ 100

General Information

Server Structure

h0000.cgb, h0*.cgb

h8*.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:

- http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/h0000.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/h0*.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/h8*.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/RomList.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/

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, h0*.cgb

Once one of the default minigames has been played, the "セーバ" or "Server" option in the main menu unlocks. After the user's password is given, h0000.cgb is then downloaded via HTTP GET. The purpose of these files is simply to display a selection menu.

    ----------------------------------
    Header - 5 bytes
    ----------------------------------
    0x00 - "M"			::	0x4D
    0x01 - "N"			::	0x4E
    0x02 - "G"			::	0x47
    0x03 - "L"			::	0x4C
    0x04				::	Number of menu items.

Following this is a five-byte file name for each menu item. If the file name begins with a digit "0" or "8", it is inserted into the URL http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/h*.cgb, then the file is downloaded via HTTP GET and its contents treated based on the first digit. In this case, the file name MUST end with a null byte (0x00), or the game will continue copying characters until it reaches one. If the file name does not begin with either of these digits, it is ignored and the menu selection downloads http://gameboy.datacenter.ne.jp/cgb/download?name=/A4/CGB-BMVJ/RomList.cgb instead.

After the file names come the null-terminated names of each menu item, using a custom encoding (see below). Additionally, the game is liable to crash and/or corrupt save data if this file does not end with the bytes 0x00, 0x00, 0x01.

As far as anyone knows, this file only had one menu item, and the "ミニゲームリスト" text itself did not change. Additionally, the game manual shows only one menu item in a screenshot.

[Net de Get] : h8*.cgb

This file contains a message to the player. Once it has been downloaded, the game disconnects from the internet and the message is displayed.

    ----------------------------------
    File format
    ----------------------------------
    0x00 - 0x17			::	Background palettes 0-2, used for text.
    0x18 - 0x37			::	Background palettes 3-6, unused.
    0x38 - 0x3F			::	Background palette 7, used for background and other elements.
    0x40 - 0x47			::	Object palette 0, used for blinking arrows.
    0x48 - 0x7F			::	Object palettes 1-7, unused.
    0x80				::	Number of pages. No known maximum, but page numbers above 10 use garbage tiles.
    0x81 - 0x82			::	Pointer to page 1 text.
    ...				::	Repeat pointers as needed.

Palettes are in GBC format (that is, four colors each in little-endian RGB555). For background palettes, color 0 is the foreground, color 1 is a shadow, and color 3 is the background. The file's contents are read from 0xB000, so the text pointers can be considered as file offsets with 0xB000 added to them.

[Net de Get] : 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			::	Minimum levels in each category to download this minigame. If all 3 are not met, the menu item is grayed out and cannot be selected.
    0x0C - 0x0D			::	If both are not zero, the menu item does not appear.
    0x0E				::	Minimum hidden level to download this minigame. If not met, the minigame's name does not appear and it cannot be selected.
    0x0F				::	If not zero, the menu item does not appear.
    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:

- 0x33 is supposed to be the multiplication sign (not X).
- 0x5B is supposed to be the GBC's d-pad.
- 0x7B and 0x7C are actually inverted color-wise (black circle with white "A" or "B" in the center). These are presumably the GBC's A and B buttons.
- 0xF8 is actually inverted color-wise (black outlines, white on the inside).
- 0xFB is a "smiley face" like 0xFA, but it's kind of lumpy and missing an eye.

Additionally, there are a few control codes:

- 0x00 terminates a string.
- 0x01 terminates a line.
- 0x02 takes a second byte and uses it to set the text color. The default color is 0x00.
- 0x03 takes a second byte and uses it as the parameter to an unknown function. It also causes 0x00 to return just after the second byte and continue printing text.
- 0x04 clears the text field.
- 0x0F causes the game to wait for the A button to be pressed, then continues printing text. However, this continuation is broken and probably shouldn't be used.

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

- Net de Get never appears to check the chip ID for Flash ROM. Instead of issuing the 0x90 command, it immediately accesses Flash. Given that the MX29F008TC-14 was likely a variant of other existing Macronix Flash chips but specialized exclusively for the Game Boy Color, it's entirely possible that Net de Get was all but gauranteed to use one Flash chip. In that sense, the developers had no need to identity other Flash hardware.
- Net de Get makes extensive use of the 0x30 command to erase sectors, particularly before a minigame is downloaded. After the 0x30 command is issued, Net de Get issues a 0xF0 command, which forcibly terminates the previous erase command. During this time (until another Flash command is issued), any reads to Flash return the current status of the previous erase command. The status is a single byte. Bit 7 determines if the erase command has indeed finished (1 = Done, 0 = In Progress). Bit 4 seems to indicate a timeout (1 = Timeout, 0 = OK). Net de Get actively checks both bits.
- Net de Get only writes to Flash ROM in portions of 128 bytes at a time. At the end of each 128 byte section (e.g. 0x407F, 0x40FF, etc), it writes a 0x00 at the very last byte. This seems to indicate that the Flash chip should return the status byte from any reads, much like the 0x30 commands. Again, Bit 7 and 4 are checked. Afterwards, the game will use the 0xF0 command to terminate writing.
- Net de Get actually saves the downloaded minigame to SRAM initially, then portions are copied to WRAM, and eventually Flash ROM. Net de Get also actively verifies whether the data written to Flash is correct by comparing current Flash memory to the original RAM data. Any discrepancy triggers an error message and aborts.
- The exact way in which the MBC6 handles flash ROM banking is not entirely understood, however, there is some evidence of how it should work. After issuing command 0x30 (sector erase), the current bank is taken from whatever bank ID was written to in 0x2000 (for flash ROM mapped to 0x4000 - 0x5FFF) or 0x3000 (for flash ROM mapped to 0x6000 - 0x7FFF). The flash bank used for all further IO operations is essentially "remembered" after the 0x30 command. Reads and writes to flash ROM will use that "remembered" bank instead of the one specified at 0x2000 or 0x3000 until another command is issued. The other 8KB area of flash memory can use the bank ID in 0x2000 or 0x3000 for reading normally.

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

Ghost Entry

Character Encoding

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

- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtconfig.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/100.gtexcrs***.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtgst00.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtgst01.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtgst02.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtgst03.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtgst04.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtgst05.cgb
- http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/gtgst06.cgb

Additionally, the following files are accessed with a URL prefix defined in gtconfig.cgb:

- gtrkconfig.cgb
- gtrk00.cgb
- gtrk01.cgb
- gtrk02.cgb
- gtrk03.cgb
- gtrk04.cgb
- gtrk05.cgb
- gtrk06.cgb

Finally, ghost data can have any file name prefixed with "http://gameboy.datacenter.ne.jp/cgb/download?name=/28/AGB-AGTJ/".

[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				::	Service status bitfield, see below.
    0x01				::	Enables Time Trial Ghost downloads for select race tracks.
    0x02				::	Downloadable course ID.
    0x03				::	Course ID for ghost uploads.
    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.

Byte 0x00 is a bitfield indicating the current service status. When Bit 1 is set, course downloads cannot be accessed, with an error message implying that the service will not return. When Bit 1 is clear but Bit 0 is set, course downloads cannot be accessed, with an error message implying that the outage is temporary. Only when both bits are clear can course downloads be accessed. Bits 5 and 4 apply in the same way to all other services.

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 game's programmers evidently tried to prevent ghost uploads for custom courses other than the one whose ID matches Byte 0x03, but in practice, the upload still goes through, rendering Byte 0x03 meaningless.

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.

[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				::	Enables ghost uploads for select race tracks.
    0x02 - 0x03 			::	Unused.
    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. Byte 0x01 is intended to apply in the same way to ghost uploads, but like Byte 0x03 of gtconfig.cgb, all uploads go through regardless of Byte 0x01.

[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				::	Course ID. Used to prevent purchasing the same course twice.
    0x0001				::	A value of 0x01 changes the scenery to promote the Famitsu magazine.
    0x0002 - 0x0003			::	Unused. Should be zero.
    0x0004 - 0x001B			::	11 character title. 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 - 0x0007			::	Local timestamp for last update.
    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 - 0x33			::	Mobile Rank Entry.
    0x34 - 0x53			::	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 URL must contain one or two dots. If it contains one dot, it is marked as free in the download menu. If it contains two dots, it must have a service fee of 0, 50, 100, 150, 200, 250, or 300 yen (which is shown in the download menu), or the entry will not be displayed.

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 is 99 minutes, 59 seconds, and 99 hundredths 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 - 0x33			::	Mobile Rank Entry.
    0x34 - EOF			::	Track Movement Data.

This is the only file where Byte 0x00 of the Mobile Rank Entry is used. 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, only adding a checksum every 4KB. No checksum is need for the file itself.

[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 - 0x0007			::	Local timestamp for last update.
    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				::	Race Track (see above).
    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				::	Gear Ratio (0 = Low, 1 = Medium, 2 = High).
    0x05				::	Steering (0 = Slow, 1 = Medium, 2 = Quick).
    0x06				::	Brake (0 = Soft, 1 = Medium, 2 = Hard).
    0x07				::	Tire (0 = Soft, 1 = Medium, 2 = Hard).
    0x08				::	Aerodynamics (0 = Low, 1 = Medium, 2 = High).
    0x09				::	Course ID (for custom courses).
    0x0A - 0x0B			::	Unused. Should be zero.
    0x0C - 0x0D			::	Handicap Weight in kilograms. 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			::	11 character player name. Uses a custom 16-bit character encoding.
    0x24 - 0x27			::	Course Completion Time. 32-bit value stored LSB first. Same format as Ghost Time, see notes above.
    0x28 - 0x2F			::	GMT timestamp for registration.
    0x30 - 0x33			::	Ghost ID. 32-bit value stored LSB first. Must not be zero.

    ----------------------------------
    Timestamp
    ----------------------------------
    0x00 - 0x01			::	Year. 16-bit value stored LSB first.
    0x02				::	Month.
    0x03				::	Day.
    0x04				::	Hour.
    0x05				::	Minute.
    0x06				::	Second.
    0x07				::	Unused. Should be zero.

[Zen Nihon GT Senshuken] : Ghost 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
    -----------------------
    【全日本ＧＴ選手権】でランキング登録が失敗している可能性があります。
    -----------------------
    ----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 message, encoded as ISO-2022-JP, translates to: "There is a possibility that ranking registration has failed in the [All Japan GT Championship]." "octec-stream" is not a typo.

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 in the following format:

    ----------------------------------
    Ghost Entry Format
    ----------------------------------
    0x0000 - 0x001F			::	Player's email address.
    0x0020 - 0x0053			::	Mobile Rank Entry.
    0x0054 - 0x2FAB			::	Track Movement Data.
    0x2FAC - 0x2FAF			::	Always zero.
    0x2FB0 - 0x2FB3			::	A 32-bit checksum for all bytes from 0x0000 - 0x2FAF. All bytes are added, one-by-one. Checksum stored LSB first.

The player name as uploaded is limited to 5 characters. The Ghost ID as uploaded is calculated by starting with 0x20031DC, adding the remaining bytes of the Mobile Rank Entry, then adding all bytes of the Track Movement Data, one-by-one.

[Zen Nihon GT Senshuken] : Character Encoding

    	0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F
    0x000	 	!	"	#	$	%	&	'	(	)	*	+	,	-	.	/
    0x010	0	1	2	3	4	5	6	7	8	9	:	;	<	=	>	?
    0x020	@	A	B	C	D	E	F	G	H	I	J	K	L	M	N	O
    0x030	P	Q	R	S	T	U	V	W	X	Y	Z	[	¥	]	^	_
    0x040	`	a	b	c	d	e	f	g	h	i	j	k	l	m	n	o
    0x050	p	q	r	s	t	u	v	w	x	y	z	{	|	}	~	〒
    0x060	☆	★	○	●	◎	◇	◆	□	■	△	▲	▽	▼	❤	♂	♀
    0x070	\	≠	＜	＞	±	✕	÷	‖	‘	’	“	”	〔	〕	《	》
    0x080	 	。	「	」	、	・	ヲ	ァ	ィ	ゥ	ェ	ォ	ャ	ュ	ョ	ッ
    0x090	ー	ア	イ	ウ	エ	オ	カ	キ	ク	ケ	コ	サ	シ	ス	セ	ソ
    0x0A0	タ	チ	ツ	テ	ト	ナ	ニ	ヌ	ネ	ノ	ハ	ヒ	フ	ヘ	ホ	マ
    0x0B0	ミ	ム	メ	モ	ヤ	ユ	ヨ	ラ	リ	ル	レ	ロ	ワ	ン	゛	゜
    0x0C0	‥	…	ヰ	ヴ	ヱ	 	ガ	ギ	グ	ゲ	ゴ	ザ	ジ	ズ	ゼ	ゾ
    0x0D0	ダ	ヂ	ヅ	デ	ド	パ	ピ	プ	ペ	ポ	バ	ビ	ブ	ベ	ボ	♪
    0x0E0	∞	【	】	℃	¢	£	§	＝	～	™	©	®	→	←	↑	↓
    0x0F0	 	。	『	』	、	・	を	ぁ	ぃ	ぅ	ぇ	ぉ	ゃ	ゅ	ょ	っ
    0x100	ー	あ	い	う	え	お	か	き	く	け	こ	さ	し	す	せ	そ
    0x110	た	ち	つ	て	と	な	に	ぬ	ね	の	は	ひ	ふ	へ	ほ	ま
    0x120	み	む	め	も	や	ゆ	よ	ら	り	る	れ	ろ	わ	ん	゛	゜
    0x130	‥	…	ゐ	 	ゑ	 	が	ぎ	ぐ	げ	ご	ざ	じ	ず	ぜ	ぞ
    0x140	だ	ぢ	づ	で	ど	ぱ	ぴ	ぷ	ぺ	ぽ	ば	び	ぶ	べ	ぼ

For user input, the game uses characters 0x000, 0x081, 0x084, 0x0F5, and 0x100. Characters 0x0BE and 0x0BF appear on the katakana keyboard, while characters 0x12E and 0x12F appear on the hiragana keyboard, though none are actual input characters, and they are unlikely to have been used in downloadable content. Characters 0x0C0, 0x0C1, 0x130, and 0x131 are not available for user input, so it is unknown which, if any, were used in downloadable content. Character 0x135, along with all characters starting at 0x14F, have garbage tile data and should not be used. Finally, character 0xFFFF is used as a terminator.

Vaus Controller

General Information

Operation

[Vaus Controller] : General Information

The Vaus Controller is a hypothetical accessory for the original Game Boy. In theory, it would have been released alongside the Game Boy in early 1989. Alleyway, a launch title for the system, still has leftover code that appears to communicate with an unknown device via the Link Cable. The data returned from the Link Cable controls the player's paddle and allows the game to pause/resume and start a new ball.

Given Alleyway's similarity to Arkanoid, the device may have been a "Vaus Controller" similar to those found on other platforms (such the one for the NES made by Taito). It would have comprised some sort of rotating control knob and a single button to fire the ball. If it had been released, the "Vaus Controller" would have been the earliest example of analog controls on the Game Boy.

The exact reason why the Vaus Controller was never realized is unknown. One suggestion is that, as a Link Cable accessory that likely required 2 hands, it may have been cumbersome to deal with on the Game Boy. Additionally, design-wise it may not have been suitable for the image of portability Nintendo wanted project for its new handheld.

[Vaus Controller] : Operation

The Vaus Controller returns a 16-bit value representing the ADC value of the control knob as well as input for a single button. The Game Boy acts on an internal clock when communicating with the Vaus Controller and must send 2 transfers to grab the 16-bit value. The Vaus Controller does not seem to care about the incoming values from the Game Boy. Data is transferred Least Significant Byte first. Its format is as follows:

    ---------------------------------------------------------
    Bit 0 - 7	| 8-bit ADC
    Bit 8 - 14	| N/A
    Bit 15		| Button Input
    ---------------------------------------------------------

The 8-bit ADC value should have a minimum range of 0x3F and a maximum range of 0x97. These values translate the paddle from left to right across the screen. An ADC value of 0x6B centers the paddle.

Button Input is a single bit. When Bit 15 is set to 1, a new ball is launched. Alternatively, this will pause/resume gameplay. In effect, Alleyway treats this as a substitute for the START button.

WorkBoy

General Information

Communication Protocol

Real-Time Clock

Keyboard Input

[WorkBoy] : General Information

The WorkBoy is a cancelled Game Boy accessory made by Fabtek. It would have been released in December 1992, but circumstances prevented the product from launching. The device itself is a small, handheld keyboard that connects to the Game Boy via the Link Cable. In conjunction with specialized software, the WorkBoy allows users to send keyboard input to the Game Boy in order to perform small office-related tasks. Previously, both the software and the hardware were believed to be lost to time but have since been found.

- Uses 2 coin-cell batteries for power.
- Features a miniature QWERTY keyboard.
- Has a built-in real-time clock.
- Has a built-in speaker for alarm functionality.
- Contains a small amount of DRAM to save some data.

[WorkBoy] : Communication Protocol

The WorkBoy communicates via the Link Cable using several commands. The Game Boy runs on an Internal Clock and is responsible for driving the protocol. The known commands are listed below:

    ---------------------------------------------------------
    Command	| Description
    ---------------------------------------------------------
    0x44	| Read RTC Data
    0x4F	| Poll Keyboard Input
    0x52	| WorkBoy Init
    0x57	| Write RTC Data
    ---------------------------------------------------------

When booting, software will issue the WorkBoy Init command. This is a single byte command with no parameters, however, the WorkBoy should eventually respond with a 0x44 byte to indicate that the RTC can be read. The following sections deal with RTC reading/writing and keyboard input in detail.

[WorkBoy] : Real-Time Clock

To read the RTC, the Game Boy must first send the command byte 0x44. The WorkBoy should immediately respond with a series of 42 bytes representing the current time and date as well as other data that is currently undocumented. After the command byte, the Game Boy continually transfers the value 0x00 while the WorkBoy is replying. Evidently, all data from the WorkBoy must be non-zero, otherwise it seems to indicate an error. The following bytes from the WorkBoy are the known data for the RTC:

    ---------------------------------------------------------
    Byte	| Description
    ---------------------------------------------------------
    0x04	| Seconds - First Digit
    0x05	| Seconds - Second Digit
    0x06	| Minutes - First Digit
    0x07	| Minutes - Second Digit
    0x08	| Hours - First Digit
    0x09	| Hours - Second Digit
    0x0A	| Day - First Digit
    0x0B	| Day - Second Digit
    0x0C	| Month - First Digit
    0x0D	| Month - Second Digit
    0x1E	| Year - MSB
    0x1F	| Year - LSB
    ---------------------------------------------------------

Every value except the year is expressed as ASCII values that represent a 2 digit number. That is to say, representing something like 37 seconds would use the ASCII values "3" and "7", or 0x33 and 0x37 in hexadecimal.

Years are slightly more elaborate. The lowest year possible is 1900, and this is used as a base. The current year is then an offset from that, calculated as such, using whole integers for division:

    ---------------------------------------------------------
    YEAR_DIFF = CURRENT_YEAR - 1900
    YEAR_DIV = (DIFF / 16)

    YEAR MSB = 0x30 + YEAR_DIV
    YEAR LSB = 0x30 + (CURRENT_YEAR - (YEAR_DIFF * 16))
    ---------------------------------------------------------

To write to the RTC, the Game Boy must first send the command byte 0x57. Afterwards, the Game Boy sends a stream of 23 bytes to set the time and date. The format of the data is as follows:

    ---------------------------------------------------------
    Byte	| Description
    ---------------------------------------------------------
    0x06	| Always 0x04
    0x08	| Seconds
    0x09	| Minutes
    0x0A	| Hours
    0x0B	| Days + Some Bits of Years
    0x0C	| Month + Some Bits of Years
    0x15	| Years
    0x16	| Years (Copy)
    ---------------------------------------------------------

For Seconds, Minutes, and Hours, the values written to the WorkBoy are binary coded decimals. This is also true of Bits 0-5 of Days value and Bits 0-4 of Month value. The upper-bits of both, however, store information about the Year value. The Year value is the current number of years since 1900 with the lower 2 bits masked off. Those same 2 bits, however, are the upper-bits of the Days value. The upper 3 bits of the Months value is incremented once for every year since 1900 *and* it is also incremented again every 4 years.

[WorkBoy] : Keyboard Input

The WorkBoy has a semi-standard QWERTY keyboard that can be used as input in addition to the Game Boy's buttons. Software can poll the WorkBoy to receive the latest key that was pressed. Only a single value from the keyboard will be read at any given time, so it is important to poll the keyboard frequently to catch user input. To read from the keyboard, the Game Boy simply sends the command byte 0x4F. The following values represent the key selected:

    ----------------------------------------------------------------------------------------------------------------------
    Byte	| CAPS Mode				| NUM Mode
    ----------------------------------------------------------------------------------------------------------------------
    0x00	| No Keyboard Input			|
    0x01	| App Key -> Clock			|
    0x02	| App Key -> Tempurature Conversion	|
    0x03	| App Key -> Currency and Checkbook	|
    0x04	| App Key -> Calculator			|
    0x05	| App Key -> Calendar and Appointments	|
    0x06	| App Key -> Unit Conversion		|
    0x07	| App Key -> Database and Phone Records	|
    0x08	| App Key -> Translator and World Map	|
    0x09	| App Key -> Phone Dialer		|
    0x0A	| Escape				|
    0x0B	| Delete / Backspace			|
    0x0C	| Insert				|
    0x10	| Left Arrow				|
    0x11	| Q					| 1
    0x12	| W					| 2
    0x13	| E					| 3
    0x14	| R					| M+ (for calculator only)
    0x15	| T					| M- (for calculator only)
    0x16	| Y					| MR (for calculator only)
    0x17	| U					| MC (for calculator only)
    0x18	| I					| !
    0x19	| O					| £
    0x1A	| P					| *
    0x1B	| $					| #
    0x1C	| A					| 4
    0x1D	| S					| 5
    0x1E	| D					| 6
    0x1F	| F					| +
    0x20	| G					| -
    0x21	| H					| × (for calculator only)
    0x22	| J					| ÷ (for calculator only)
    0x23	| K					| (
    0x24	| L					| )
    0x25	| ;					| :
    0x26	| Return / Enter			|
    0x27	| NUMS Mode				|
    0x28	| Z					| 7
    0x29	| X					| 8
    0x2A	| C					| 9
    0x2B	| V					| .
    0x2C	| B					| %
    0x2D	| N					| =
    0x2E	| M					| C (for calculator only)
    0x2F	| ,					| <
    0x30	| .					| >
    0x31	| /					| ?
    0x32	| CAPS Mode				|
    0x33	| "					| 0
    0x34	| Space					|
    0x35	| '					| @
    0x36	| Up Arrow 				|
    0x37	| Down Arrow				|
    0x38	| Right Arrow				|
    ----------------------------------------------------------------------------------------------------------------------

The WorkBoy's keyboard does not appear to have a dedicated shift key to modify values. Instead, it relies on the CAPS and NUM keys to swap between each mode. Unlike most PC keyboards, the WorkBoy does not have any built-in lighting to indicate which mode is active. Instead, the software typically puts a "C" or "N" character inside a colored block for the cursor. Note that some applications (such as the telephone dialer) can force CAPS or NUM mode.