Net de Get GB Mobile Adapter Server Technical Documentation 0.3
July 24, 2024
Shonumi aka D.S. Baxter, Winter1760

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

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. 


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


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

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

***************************************************
5. 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.
0x02 - 0x05			::	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"
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 + 2 + String Length 1 & 2	::	The price of the minigame download in yen. 4 digits max.
0x11 + 6 + String Length 1 & 2	::	Unique ID for download. 8 characters max.


The offset to the data structure is technically (ADDRESS - 0x4). If the data structure is located at 0x44, the offset is written as 0x40.

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.


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


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


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


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

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