Welcome to Data Crystal's new home! Data Crystal is now part of the TCRF family (sort of).
The wiki has recently moved; please report any issues in Discord. Pardon the dust.

Pokémon Red and Blue/Notes: Difference between revisions

From Data Crystal
Jump to navigation Jump to search
(1.5 - added more information about tilesets.)
m (Xkeeper moved page Pokémon Red and Blue:Notes to Pokémon Red and Blue/Notes: normalize subpages and titles)
 
(13 intermediate revisions by 7 users not shown)
Line 1: Line 1:
{{notes|game=Pokémon Red and Blue}}
==False 'level' addresses==
These are stored values that may change after switching a Pokémon up to a specific position in the party. The value for that process is updated after depositing and withdrawing the Pokémon into a box.
== Tileset headers ==
12 bytes per header, as follows :
<pre>
<pre>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1 byte  - Bank ID of blocks and tiles
2 bytes - Pointer to blocks
2 bytes - Pointer to tiles
2 bytes - Pointer to collision data
3 bytes - Up to 3 'talking-over tiles' tile numbers ("empty" slots are filled with $FF)
1 byte  - Grass tile ($FF if none)
1 byte  - Animation flag
</pre>
 
Since the player moves on a 2x2 tile grid, the game checks the bottom-left tile of such a group for its properties (grass, talking-over...)
 
(Note : there's an inconsistency with this, the game uses the bottom-right tile to determine water, hence the Old Man Glitch)


    RGBY Map Headers & Stuff That Goes With It
=== Blocks ===
    Version 1.5
Maps are made up of 4x4 tile blocks, stored (how?)
    -Feel free to distribute this document and/or edit it.
    -Try and credit people you get info from and/or write how you updated.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A tile is 8x8 pixels, so a block is 32x32 pixels.


Things that need adding:
=== Tiles ===
------------------------
Tiles are stored using the GB's format, and directly copied to VRAM.
More information about tilesets, and info about what sprites get loaded for
which maps.


Updates:
=== Collision data ===
--------
This is a pointer to a list of tile numbers over which the player can walk. Terminated with a FF byte.
v1.5 By phire: Completed Tileset Header, except for that last byte. (It's not number of animated tiles, and as far as I can tell, its not even used)
v1.4 Complete object data info with details about picture id.
v1.3 Edit by Cartmic to include almost completed tileset header information
    and Hat's further clarification on what the X/Y Movement of the Connection means.
v1.2: By ubitux: Add some information about connections and distinction between entities (People/Trainers/Items)
v1.11: Typo fixed by Hat: "01 = North" changed to "01 = East". Thanks to IIMarckus for pointing that out.
v1.1: By Hat, minor improvements.
v1.0: Original version typed up by Hat.


Main Credits (Structure Information):
=== Talking-over tiles ===
-------------------------------------
These are tiles which allow the player to talk to a person on the other side, such as the counters in the Pokémon Centers or Pokémarts.
  [Xeon]
    Wrote some stuff about Map Headers and Object Data.
    Which this document expands upon, a bit.


  [F-Zero] & [Tauwasser]
Each tileset can have up to 3 talking over tiles. Use FF to fill the unused slots.
    Wrote a document (in German) explaining how GSC connection data is stored.
    RGBY connection data is stored almost the same way, it turns out, so
    that helped a great deal. All that is really different is the values you
    add the amount of blocks to.
...............................................................................


Notes:
=== Grass tile ===
R/B Pointers to Map Headers: 0x01AE
This is both a tile that will be rendered above sprites, and one where random "grass" encounters are possible.
R/B Map Header Banks: 0xC23D
R/B Pointer to Tileset Headers: 0xC767


Maximum tileset size in VRAM: 6 rows of 16 tiles (9000-95FF)
=== Animation flag ===
This byte defines whether the tileset has animated tiles.


...............................................................................
If the byte is zero, no animations take place. Otherwise, the water animation will be in effect, and if bit 0 is reset, the flower animation also will.


===============================================================================
The water animation is done by rotating tile $14's pixels left and right. The flower animation, however, overwrites tile $03 with images stored in the ROM, at addresses $1F29, $1F29 and $1F39.


    Tileset Header Structure (Almost complete)


===============================================================================
== Map headers ==
This contains all the data (pointers count as data) to build the map.
<pre>
1 byte  - Tileset ID
1 byte  - (Y Size) Map height
1 byte  - (X Size) Map width
2 bytes - Pointer to map data
2 bytes - Pointer to text pointers
2 bytes - Pointer to script
1 byte  - Connection Byte
11 bytes per connection - Connection data (No connections? Straight to object data!)
2 bytes - Pointer to object data
</pre>


12 bytes per header...
=== Tileset numbers ===


Format:
The tileset descriptions are copied from a document compiled by Cartmic, called "Pokémon Red Documents", which may help you with other stuff too.
~~~~~~~
[1 BYTE: Bank No. of Blocks/Tiles]
[2 BYTES: Pointer to Blocks (-10 for some reason)]
[2 BYTES: Pointer to Tiles]
[2 BYTES: Pointer to Collision Data]
[3 BYTES: Upto 3 'talking over tiles' tile numbers, FF if unused.]
[1 BYTE:  Grass Tile or FF if unused]
[1 BYTE:  Unknown byte]


Blocks:
{|  class="wikitable" style="text-align: center;"
~~~~~~~
!Tileset No. !! Location in US R/B ROM !! Description
Maps are made up of 4x4 tile blocks.
|-
|00||C7BE||Outside
|-
|01||C7CA||Red's House
|-
|02||C7D6||Pokémon Center
|-
|03||C7E2||Viridian Forest
|-
|04||C7EE||Red's House (copy)
|-
|05||C7FA||Gym
|-
|06||C806||Pokémon Center
|-
|07||C812||Gym (copy)
|-
|08||C81E||House
|-
|09||C82A||Museum
|-
|0A||C836||Museum (copy)
|-
|0B||C842||Underground Path
|-
|0C||C84E||Museum (second copy)
|-
|0D||C85A||S.S. Anne
|-
|0E||C866||Vermilion Port
|-
|0F||C872||Pokémon Cemetery
|-
|10||C87E||Silph Co.
|-
|11||C88A||Cave
|-
|12||C896||Celadon Mart
|-
|13||C8A2||Game Freak HQ
|-
|14||C8AE||Lab
|-
|15||C8BA||Bike Shop/Cable Center
|-
|16||C8C6||Cinnabar Mansion/Power Plant etc
|-
|17||C8D2||Indigo Plateau
|}


Collision Data:
NOTE: As you can see there's multiple copies of some tileset headers. They are literally copies.
~~~~~~~~~~~~~~~
This is a pointer to a list of tile numbers which the player can walk over, Terminated with a FF byte.


Talking over tiles:
If you're ROM hacking the game and want to add custom tilesets, you can delete copies to make room. However make sure that all maps that used the copy now use the original.
~~~~~~~~~~~~~~~~~~~
These are tiles which allow the player to talk to a person on the other side, such as the counters in the Pokemon Centers or Pokemarts.  
Since the player snaps to a 2x2 tile grid you only need list the tile number of the lower left tile of the group of 4 tiles in front of the player.


Each tileset can have upto 3 talking over tiles. Use FF instead if they aren't used.
=== Map height (Y axis) & width (X axis) ===
Exactly that, the amount of blocks high and wide the map data is.


=== Map data pointer ===
You can use the GoldMap engine for hacking map data quite easily.


===============================================================================
The map you walk around on and stuff is stored as block indexes. A single block consists of 4x4 tiles.


    Map Header Structure
=== Pointer to text pointers ===
This points to a list of pointers. When the game attempts to display textbox #3, it will fetch the 3rd pointer in this list.


===============================================================================
(Note : textbox #0 is hardwired to the START menu)


Explanation:
=== Pointer to script ===
~~~~~~~~~~~~
Points to a function ran on each frame spent in this overworld (for example, not ran while a textbox is active)
This contains all the data (pointers count as data) to build the map.


Format:
If a map has a functionality you can't implement otherwise, check this out. You can sometimes find things like XY positions of Poké Balls and 1-time only Pokémon.
~~~~~~~
  #1: [Tileset Number]
  #2: [(Y Size) Map Height]
  #3: [(X Size) Map Width]
#4-5: [*2 Bytes*: Pointer to Map]
#6-7: [*2 Bytes*: Pointer to Maps Text Pointers]
#8-9: [*2 Bytes*: Pointer to Maps "Script"]
#10: [Connection Byte]
  ?: [*11 Bytes per Connection*, No connections? Straight to "Object Data"!]
Last: [*2 Bytes*: Pointer to Object Data]


===============================================================================
=== Connection mask ===
    1) Tileset Numbers
===============================================================================


The tileset descriptions are copied from a document compiled by Cartmic,
Note: If this value is $00 it is immediately followed by the object data pointer, no gap.
called "Pokemon Red Documents", which may help you with other stuff too.


Unchanged R/B Locations/Tileset No./Tileset Descriptions
Connections can be obtained with binary masks:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<pre>
C7BE; 00: "Outside"
connect_byte & (1 << 3) -> North
C7CA; 01: "Ash's House (#1)"
connect_byte & (1 << 2) -> South
C7D6; 02: "Pokemon Center (#1)"
connect_byte & (1 << 1) -> West
C7E2; 03: "Viridian Forest"
connect_byte & (1 << 0) -> East
C7EE; 04: "Ash's House (#2)"
</pre>
C7FA; 05: "Gym (#1)"
C806; 06: "Pokemon Center (#2)"
C812; 07: "Gym (#2)"
C81E; 08: "House"
C82A; 09: "Museum (#1)"
C836; 0A: "Museum (#2)"
C842; 0B: "Underground Path"
C84E; 0C: "Museum (#3)"
C85A; 0D: "S.S. Anne"
C866; 0E: "Vermilion Port"
C872; 0F: "Pokemon Cemetery"
C87E; 10: "Silph Co."
C88A; 11: "Cave"
C896; 12: "Celadon Mart"
C8A2; 13: "Game Freak HQ"
C8AE; 14: "Lab"
C8BA; 15: "Bike Shop/Cable Center"
C8C6; 16: "Cinnabar Mansion/Power Plant etc"
C8D2; 17: "Indigo Plateau"


NOTE: As you can see there's multiple copies of some tileset headers. They are
List of values:
literally copies, you only need 1 copy, but you will need to make sure all maps
<pre>
using that tileset are set to using that tileset number, then you can use the
00 = No Connections
free space for more tilesets.
01 = East
02 = West
03 = West + East
04 = South
05 = South + East
06 = South + West
07 = South + West + East
08 = North
09 = North + East
0A = North + West
0B = North + West + East
0C = North + South
0D = North + South + East
0E = North + South + West
0F = North + South + West + East
</pre>


===============================================================================
=== Connection Data ===
    2 & 3) Map Height (Y) & Width (X)
Size can range from 0 to 44 bytes.
===============================================================================


Exactly that, the amount of blocks high and wide the map data is.
Probably the toughest thing to manipulate. This will certainly require planning, with no background distractions. (Unless an editor gets built that can hack the connections for RGBY.)


===============================================================================
==== X/Y movement of connection ====
    4 & 5) Map Data Pointer
A X movement is how many map blocks there are to the left of one of your north/south connections.
===============================================================================


You can use the GoldMap engine for hacking map data quite easily.
A Y movement is how many map blocks there are above your west/east connection.


The map you walk around on and stuff is stored as block indexes.
==== Structure ====
A single block consists of 4*4 tiles.
<pre>
1 byte  - Map ID of connected map
2 bytes - Pointer to "connection strip"s upper-left block (Connected map)
2 bytes - Pointer to "connection strip"s upper-left block (Current map)
1 byte  - "Bigness"
1 byte  - Map Width
1 byte  - Y alignment
1 byte  - X alignment
2 bytes - Window
</pre>


TODO : convert this block to wiki format.
<pre>
===============================================================================
===============================================================================
     6 & 7) Pointer to Maps Text Pointers
     #1 : Map Indexes
===============================================================================
===============================================================================


2 byte pointers to text that is used on that map.
Not included! Download UltraMap, the text file known as "RedEnglish.ini"
contains all the Map Indexes in decimal for R/B, which you'll obviously need
to convert to hex.


===============================================================================
===============================================================================
    8 & 9) Pointer to Maps "Script"
#2-#3 : "Connection Strip" Location
===============================================================================
===============================================================================


ASM used on that map, chances are if there's something on a map you can't find
The "connection strip" pointer -- points to the area of the connected map that
elsewhere you might easily be able to find it here, using a hex search
is visible when standing before you even enter it. Points to the upperleft
function. You can find things like XY positions of Poke Balls and 1-time
block of the "connection strip".
only Pokemon.
      * connection strip is always 3 blocks wide (E/W connection)
                                  3 blocks high (N/S connection)


===============================================================================
===============================================================================
    10) Connection Byte
#4-#5 : Current Map Position
===============================================================================
===============================================================================


Note:
This points to the part of the current map (further up in RAM)
~~~~~
that the connection strips upperleft block is placed on the current map.
If this value is 00h it is immediately followed by the Object Data
Pointer, no gap. Repeated list:


Connection Byte:
____________________
    00 = No Connections
Connection |
    01 = East
Direction  | Formula
    02 = West
___________|_______
    03 = West + East
    04 = South
    05 = South + East
    06 = South + West
    07 = South + West + East
    08 = North
    09 = North + East
    0A = North + West
    0B = North + West + East
    0C = North + South
    0D = North + South + East
    0E = North + South + West
    0F = North + South + West + East


Connections can be obtained with binary masks:
    North: C6EB + X_Movement_of_Connection Strip


    1. connect_byte & (1 << 3) -> North
    South: C6EB + (Height of Map + 3) * (Width of Map + 6) +
    2. connect_byte & (1 << 2) -> South
                  X_Movement_of_Connection Strip
    3. connect_byte & (1 << 1) -> West
    4. connect_byte & (1 << 0) -> East


You have to respect this order to get the correct list.
      West: C6E8 + (Width of Map + 6) * (Y_Movement_of_"Connection Strip" + 3)
 
      East: C6E5 + (Width of Map + 6) * (Y_Movement_of_"Connection Strip" + 4)


===============================================================================
===============================================================================
     ?) Connection Data (0-44 bytes, explained in more depth: further down)
     #6 : Map "Bigness"
===============================================================================
===============================================================================
North/South Connection = Connected Maps Width
East/West Connection = Connected Maps Height


===============================================================================
===============================================================================
     Last) Object Data Pointer
     #7 : Map Width
===============================================================================
===============================================================================


The last thing in the Map Header. It points to a bunch of certain stuff that
The width of the connected map.
is stored in similar structures.


Object Data is discussed at the end of this document.
===============================================================================
...............................................................................
    #8 : Y alignment
===============================================================================


Relative Y-position of player after entering connected map.
____________________
Connection |
Direction  | Formula
___________|_______
    North: (Height_of_connected_map * 2) - 1
    South: 0
West/East: (Y_movement_of_connection_strip_in_blocks * -2)


===============================================================================
    #9 : X alignment
===============================================================================
===============================================================================


    *** Hacking Connections ***
Relative X-Position of player after entering connected map.
    This will certainly require planning, with no background distractions.
    Unless a editor gets built that can hack the connections for RGBY.


____________________
Connection |
Direction  | Formula
___________|_______
North/South: (X_movement_of_connection_strip_in_blocks * -2)
      West: (Width_of_connected_map * 2) - 1
      East: 0
===============================================================================
#10-#11 : Window
===============================================================================
===============================================================================


Explanation:
Position of the upper left block after entering the Map.
~~~~~~~~~~~~
The "Connection Byte" determines how many connections are in this space,
including none at all.


X/Y_Movement_Of_Connection
____________________
~~~~~~~~~~~~~~~~~~~~~~~~~~
Connection |
 
Direction  | Formula
A X movement is how many map blocks there are to the left of one of your north/south connections.
___________|_______
A Y movement is how many map blocks there are above your west/east connection.
    Above: C6E9h + Height_of_connected_map * (Width_of_connected_map + 6)
 
South/East: C6EFh + Width_of_connected_map
Structure:
      West: C6EEh + 2 * Width_of_connected_map
~~~~~~~~~~
...............................................................................
    #1: [Map Index of Connected Map]
</pre>
  #2-3: [Pointer to "Connection Strip"s Upperleft Block (Connected Map)]
  #4-5: [Pointer to "Connection Strip"s Upperleft Block (Current Map)]
    #6: ["Bigness"]
    #7: [Map Width]
    #8: [Y alignment]
    #9: [X alignment]
#10-11: [Window]


==== Example ====
<pre>
PKMN Red Example -- Saffron City (Header: 0x509A4) Diagram:
PKMN Red Example -- Saffron City (Header: 0x509A4) Diagram:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Line 339: Line 380:
     X alignment: 00
     X alignment: 00
           Window: C70D (C6EF + 1E)
           Window: C70D (C6EF + 1E)
</pre>


===============================================================================
=== Object Data ===
    #1 : Map Indexes
<pre>
===============================================================================
1 byte  - Border block ID
1 byte  - Number of warps
4 bytes per warp - Warp data
1 byte  - Number of signs
3 bytes per sign - Sign data
1 byte  - Number of NPCs (total)
6/8/7 bytes per NPC - NPC data
4 bytes per warp-to - Warp-To data
</pre>


Not included! Download UltraMap, the text file known as "RedEnglish.ini"
==== Warps ====
contains all the Map Indexes in decimal for R/B, which you'll obviously need
<pre>
to convert to hex.
1 byte  - Y position
1 byte  - X position
1 byte  - Destination warp-to's ID (within target map)
1 byte  - Destination map
</pre>


===============================================================================
==== Signposts ====
  #2-#3 : "Connection Strip" Location
<pre>
===============================================================================
1 byte  - Y position
1 byte  - X position
1 byte - Text string ID
</pre>


The "connection strip" pointer -- points to the area of the connected map that
==== NPCs ====
is visible when standing before you even enter it. Points to the upperleft
In order to distinguish People, Trainers and Items, you must check the text string ID:
block of the "connection strip".
      * connection strip is always 3 blocks wide (E/W connection)
                                  3 blocks high (N/S connection)


===============================================================================
strID & (1 << 6) != 0 : Trainer (2 extra bytes, the trainer class and roster IDs)
#4-#5 : Current Map Position
===============================================================================


This points to the part of the current map (further up in RAM)
strID & (1 << 7) != 0 -> Item (1 extra byte, the item ID)
that the connection strips upperleft block is placed on the current map.


____________________
===== Normal people =====
Connection |
<pre>
Direction | Formula
1 byte - Picture number
___________|_______
1 byte  - Y position + 4
1 byte  - X position + 4
1 byte  - Movement byte 1
1 byte  - Movement byte 2
1 byte  - Text string ID
</pre>


    North: C6EB + X_Movement_of_Connection Strip
===== Trainers / One-time Pokémon =====
One-time Pokémon and Trainers are essentially the same thing, separated by their species ID. If it's under 200, it's a Pokémon. Over or equal to 200, it's a Trainer.
<pre>
1 byte  - Picture number
1 byte  - Y position + 4
1 byte  - X position + 4
1 byte  - Movement 1
1 byte  - Movement 2
1 byte  - Text string ID
1 byte  - Pokémon species ID / Trainer class
1 byte  - Pokemon level / Trainer's roster ID
</pre>


    South: C6EB + (Height of Map + 3) * (Width of Map + 6) +
===== Items =====
                  X_Movement_of_Connection Strip
<pre>
1 byte  - Picture number
1 byte  - Y position + 4
1 byte  - X position + 4
1 byte  - Movement 1
1 byte  - Movement 2
1 byte  - Text string ID
1 byte  - Item ID
</pre>


      West: C6E8 + (Width of Map + 6) * (Y_Movement_of_"Connection Strip" + 3)
==== Warp-To Points ====
<pre>
2 bytes - Event Displacement
1 byte  - Y position
1 byte  - X position
</pre>


      East: C6E5 + (Width of Map + 6) * (Y_Movement_of_"Connection Strip" + 4)


===============================================================================
== Sprites ==
    #6 : Map "Bigness"
Sprites are loaded when changing maps. However, there is a little subtlety : when traversing a map connection, the game assumes the correct sprite set is loaded, and doesn't reload sprites. (Hence glitchy sprites sometimes observed with Walk Through Walls).
===============================================================================


North/South Connection = Connected Maps Width
The other occasion where sprites are loaded is when a text display is closed ; the game reloads sprites because the "walking" sprites are overwritten by font tiles.
East/West Connection = Connected Maps Height


===============================================================================
Also, if there are no sprites (NPCs) the game doesn't reload sprite graphics.
    #7 : Map Width
===============================================================================


The width of the connected map.
How the game reloads sprites differs for "exterior" and "interior" maps.


===============================================================================
=== Exterior maps ===
    #8 : Y alignment
The game reads an entry from the table at 17A64, MapSpriteSets. If the entry is < $F0, the game uses the corresponding sprite set. Otherwise, it uses the corresponding split sprite set (see dedicated section).
===============================================================================


Relative Y-position of player after entering connected map.
==== Split sprite sets ====
Some exterior maps have two sprite sets, which depend on position.


____________________
Consider the entry read from MapSpriteSets. If the entry is $F8, that's Route 20 - a special case with a complex splitting. See its dedicated section.
Connection |
Direction  | Formula
___________|_______
    North: (Height_of_connected_map * 2) - 1
    South: 0
West/East: (Y_movement_of_connection_strip_in_blocks * -2)


===============================================================================
The table maintains a table at 17A89, SplitMapSpriteSets, structured like so :
    #9 : X alignment
<pre>
===============================================================================
1 byte  - Split type (1 = East/West division, 2 = North/South division)
1 byte  - Split coordinate
1 byte  - Sprite set ID if coordinate <  split coordinate
1 byte  - Sprite set ID if coordinate >= split coordinate
</pre>
The game reads an entry, indexed using (the byte read from MapSpriteSets AND $0F), and uses this sprite set.


Relative X-Position of player after entering connected map.
===== Sea Route 20 =====
Sea Route 20 has two sprite sets, $01 (West) and $0A (East). The only thing that differs from above is that the splitting is more complex.
<pre>
If X coordinate < $2B
  Use set $01
End


____________________
If X coordinate >= $3E
Connection |
  Use set $0A
Direction  | Formula
End
___________|_______
North/South: (X_movement_of_connection_strip_in_blocks * -2)
      West: (Width_of_connected_map * 2) - 1
      East: 0


===============================================================================
If X coordinate >= $37
#10-#11 : Window
  If Y coordinate < $08
===============================================================================
    Use set $0A
  Else
    Use set $01
  End
Else
  If Y coordinate < $0D
    Use set $0A
  Else
    Use set $01
  End
End
</pre>
More visually :
<pre>
Y X  ... 28 29 2A 2B 2C 2D ... 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 ...


Position of the upper left block after entering the Map.
.   ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
05  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ...
06  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ...
07  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ...
08  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
09  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0A  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0B  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0C  ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0D  ... 01 01 01 01 01 01 ... 01 01 01 01 01 01 01 01 01 01 0A 0A 0A ...
0E  ... 01 01 01 01 01 01 ... 01 01 01 01 01 01 01 01 01 01 0A 0A 0A ...
0F  ... 01 01 01 01 01 01 ... 01 01 01 01 01 01 01 01 01 01 0A 0A 0A ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
</pre>


____________________
=== Interior maps ===
Connection |
The game loads sprites by request, ie. the sprite tiles will be loaded as required by NPCs present on the loaded map.
Direction  | Formula
___________|_______
    Above: C6E9h + Height_of_connected_map * (Width_of_connected_map + 6)
South/East: C6EFh + Width_of_connected_map
      West: C6EEh + 2 * Width_of_connected_map
...............................................................................




===============================================================================
== Useful notes ==
=== Picture numbers ===
In order to get the ROM address of the tile relative to an entity
(people/trainers/items), here is the formula to focus on the entity information:


    Object Data: General Structure
  5 * $4000 + ($7b27 + 4 * (picture_id - 1)) % $4000


===============================================================================
Then the entity information is stored according to this:
<pre>
2 bytes - Tile address
1 byte  - Total size of tile data
1 byte  - Bank ID
</pre>


Object Data
So then, address = bankID * 0x4000 + tileAddr % 0x4000
===========
[Maps Border Tile]
[Number of Warps][Warp Data]
[Number of Signs][Sign Data]
[Number of People/Trainers/Items]
[People Data]
[Trainer Data]
[Item Data]
[Warp-To Data]


Warps:
=== Event displacement formula ===
------
$C6EF + (Map width) + (Map width + 6) * (Y offset) + (X offset)
[Y position][X position][Warp-To Point][Warp-To Map]


Signposts:
=== Pointers ===
----------
R/B Pointers to Map Headers: 0x01AE
[Y position][X position][Text String Number]
R/B Map Header Banks: 0xC23D
R/B Pointer to Tileset Headers: 0xC767


Normal People:
=== Misc. ===
--------------
Maximum tileset size in VRAM: 6 rows of 16 tiles (9000-95FF)
[Picture Number][Y position + 4][X position + 4]
[Movement 1][Movement 2][Text String Number]


Trainers:
---------
[Picture Number][Y position + 4][X position + 4]
[Movement 1][Movement 2][Text String Number]
[Trainer Type][Pokemon Set]


Items:
== Credits ==
---------------------
<pre>
[Picture Number][Y position + 4][X position + 4]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[Movement 1][Movement 2][Text String Number]
[Item Number]


Warp-To Points
    RGBY Map Headers & Stuff That Goes With It
--------------
    Version 1.6
[*2 Bytes*: Event Displacement][Y position][X position]
    -Feel free to distribute this document and/or edit it.
    -Try and credit people you get info from and/or write how you updated.


In order to distinguish People, Trainers and Items, you must use the Text String Number:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


text_str_n & (1 << 6) -> Trainer (2 more byte to read, the trainer type and the pokémon set)
Things that need adding:
text_str_n & (1 << 7) -> Item (just one more byte to read, the item id)
------------------------
More information about tilesets, and info about what sprites get loaded for
which maps.


Picture Numbers
Updates:
~~~~~~~~~~~~~~~
--------
v1.6 by ISSOtm: Re-formatted the document, less ASCII and more wiki.
v1.5.1 by Sawakita: Fixed Tileset Header, completely (including last byte: Animation Flag)
v1.5 by phire: Completed Tileset Header, except for that last byte.
v1.4 Complete object data info with details about picture id.
v1.3 Edit by Cartmic to include almost completed tileset header information
    and Hat's further clarification on what the X/Y Movement of the Connection means.
v1.2: By ubitux: Add some information about connections and distinction between entities (People/Trainers/Items)
v1.11: Typo fixed by Hat: "01 = North" changed to "01 = East". Thanks to IIMarckus for pointing that out.
v1.1: By Hat, minor improvements.
v1.0: Original version typed up by Hat.


In order to get the ROM address of the tile relative to an entity
Main Credits (Structure Information):
(people/trainers/items), here is the formula to focus on the entity information:
-------------------------------------
  [Xeon]
    Wrote some stuff about Map Headers and Object Data.
    Which this document expands upon, a bit.


5 * 0x4000 + (0x7b27 + 4 * (picture_id - 1)) % 0x4000
  [F-Zero] & [Tauwasser]
 
    Wrote a document (in German) explaining how GSC connection data is stored.
Then the entity information is stored according to this:
    RGBY connection data is stored almost the same way, it turns out, so
 
    that helped a great deal. All that is really different is the values you
[*2 Bytes*: Tile address][Unknown][Bank id]
    add the amount of blocks to.
 
...............................................................................
So then, address = bank_id * 0x4000 + tile_addr % 0x4000
 
Event Displacement Formula:
~~~~~~~~~~~~~~~~~~~~~~~~~~~
C6E3 +  ((Map width + 8) * (rows above + 1))  + (X movement + 4)
 
###############################################################################
</pre>
</pre>
{{Internal Data|game=Pokémon Red and Blue}}

Latest revision as of 02:42, 24 January 2024

Chip tiny.png The following article is a Notes Page for Pokémon Red and Blue.

False 'level' addresses

These are stored values that may change after switching a Pokémon up to a specific position in the party. The value for that process is updated after depositing and withdrawing the Pokémon into a box.


Tileset headers

12 bytes per header, as follows :

1 byte  - Bank ID of blocks and tiles
2 bytes - Pointer to blocks
2 bytes - Pointer to tiles
2 bytes - Pointer to collision data
3 bytes - Up to 3 'talking-over tiles' tile numbers ("empty" slots are filled with $FF)
1 byte  - Grass tile ($FF if none)
1 byte  - Animation flag

Since the player moves on a 2x2 tile grid, the game checks the bottom-left tile of such a group for its properties (grass, talking-over...)

(Note : there's an inconsistency with this, the game uses the bottom-right tile to determine water, hence the Old Man Glitch)

Blocks

Maps are made up of 4x4 tile blocks, stored (how?)

A tile is 8x8 pixels, so a block is 32x32 pixels.

Tiles

Tiles are stored using the GB's format, and directly copied to VRAM.

Collision data

This is a pointer to a list of tile numbers over which the player can walk. Terminated with a FF byte.

Talking-over tiles

These are tiles which allow the player to talk to a person on the other side, such as the counters in the Pokémon Centers or Pokémarts.

Each tileset can have up to 3 talking over tiles. Use FF to fill the unused slots.

Grass tile

This is both a tile that will be rendered above sprites, and one where random "grass" encounters are possible.

Animation flag

This byte defines whether the tileset has animated tiles.

If the byte is zero, no animations take place. Otherwise, the water animation will be in effect, and if bit 0 is reset, the flower animation also will.

The water animation is done by rotating tile $14's pixels left and right. The flower animation, however, overwrites tile $03 with images stored in the ROM, at addresses $1F29, $1F29 and $1F39.


Map headers

This contains all the data (pointers count as data) to build the map.

1 byte  - Tileset ID
1 byte  - (Y Size) Map height
1 byte  - (X Size) Map width
2 bytes - Pointer to map data
2 bytes - Pointer to text pointers
2 bytes - Pointer to script
1 byte  - Connection Byte
11 bytes per connection - Connection data (No connections? Straight to object data!)
2 bytes - Pointer to object data

Tileset numbers

The tileset descriptions are copied from a document compiled by Cartmic, called "Pokémon Red Documents", which may help you with other stuff too.

Tileset No. Location in US R/B ROM Description
00 C7BE Outside
01 C7CA Red's House
02 C7D6 Pokémon Center
03 C7E2 Viridian Forest
04 C7EE Red's House (copy)
05 C7FA Gym
06 C806 Pokémon Center
07 C812 Gym (copy)
08 C81E House
09 C82A Museum
0A C836 Museum (copy)
0B C842 Underground Path
0C C84E Museum (second copy)
0D C85A S.S. Anne
0E C866 Vermilion Port
0F C872 Pokémon Cemetery
10 C87E Silph Co.
11 C88A Cave
12 C896 Celadon Mart
13 C8A2 Game Freak HQ
14 C8AE Lab
15 C8BA Bike Shop/Cable Center
16 C8C6 Cinnabar Mansion/Power Plant etc
17 C8D2 Indigo Plateau

NOTE: As you can see there's multiple copies of some tileset headers. They are literally copies.

If you're ROM hacking the game and want to add custom tilesets, you can delete copies to make room. However make sure that all maps that used the copy now use the original.

Map height (Y axis) & width (X axis)

Exactly that, the amount of blocks high and wide the map data is.

Map data pointer

You can use the GoldMap engine for hacking map data quite easily.

The map you walk around on and stuff is stored as block indexes. A single block consists of 4x4 tiles.

Pointer to text pointers

This points to a list of pointers. When the game attempts to display textbox #3, it will fetch the 3rd pointer in this list.

(Note : textbox #0 is hardwired to the START menu)

Pointer to script

Points to a function ran on each frame spent in this overworld (for example, not ran while a textbox is active)

If a map has a functionality you can't implement otherwise, check this out. You can sometimes find things like XY positions of Poké Balls and 1-time only Pokémon.

Connection mask

Note: If this value is $00 it is immediately followed by the object data pointer, no gap.

Connections can be obtained with binary masks:

connect_byte & (1 << 3) -> North
connect_byte & (1 << 2) -> South
connect_byte & (1 << 1) -> West
connect_byte & (1 << 0) -> East

List of values:

00 = No Connections
01 = East
02 = West
03 = West + East
04 = South
05 = South + East
06 = South + West
07 = South + West + East
08 = North
09 = North + East
0A = North + West
0B = North + West + East
0C = North + South
0D = North + South + East
0E = North + South + West
0F = North + South + West + East

Connection Data

Size can range from 0 to 44 bytes.

Probably the toughest thing to manipulate. This will certainly require planning, with no background distractions. (Unless an editor gets built that can hack the connections for RGBY.)

X/Y movement of connection

A X movement is how many map blocks there are to the left of one of your north/south connections.

A Y movement is how many map blocks there are above your west/east connection.

Structure

1 byte  - Map ID of connected map
2 bytes - Pointer to "connection strip"s upper-left block (Connected map)
2 bytes - Pointer to "connection strip"s upper-left block (Current map)
1 byte  - "Bigness"
1 byte  - Map Width
1 byte  - Y alignment
1 byte  - X alignment
2 bytes - Window

TODO : convert this block to wiki format.

===============================================================================
    #1 : Map Indexes
===============================================================================

Not included! Download UltraMap, the text file known as "RedEnglish.ini"
contains all the Map Indexes in decimal for R/B, which you'll obviously need
to convert to hex.

===============================================================================
 #2-#3 : "Connection Strip" Location
===============================================================================

The "connection strip" pointer -- points to the area of the connected map that
is visible when standing before you even enter it. Points to the upperleft
block of the "connection strip".
      * connection strip is always 3 blocks wide (E/W connection)
                                   3 blocks high (N/S connection)

===============================================================================
 #4-#5 : Current Map Position
===============================================================================

This points to the part of the current map (further up in RAM)
that the connection strips upperleft block is placed on the current map.

____________________
Connection |
Direction  | Formula
___________|_______

     North: C6EB + X_Movement_of_Connection Strip

     South: C6EB + (Height of Map + 3) * (Width of Map + 6) +
                   X_Movement_of_Connection Strip

      West: C6E8 + (Width of Map + 6) * (Y_Movement_of_"Connection Strip" + 3)

      East: C6E5 + (Width of Map + 6) * (Y_Movement_of_"Connection Strip" + 4)

===============================================================================
    #6 : Map "Bigness"
===============================================================================

North/South Connection = Connected Maps Width
East/West Connection = Connected Maps Height

===============================================================================
    #7 : Map Width
===============================================================================

The width of the connected map.

===============================================================================
    #8 : Y alignment
===============================================================================

Relative Y-position of player after entering connected map.

____________________
Connection |
Direction  | Formula
___________|_______
     North: (Height_of_connected_map * 2) - 1
     South: 0
 West/East: (Y_movement_of_connection_strip_in_blocks * -2)

===============================================================================
    #9 : X alignment
===============================================================================

Relative X-Position of player after entering connected map.

____________________
Connection |
Direction  | Formula
___________|_______
North/South: (X_movement_of_connection_strip_in_blocks * -2)
       West: (Width_of_connected_map * 2) - 1
       East: 0

===============================================================================
#10-#11 : Window
===============================================================================

Position of the upper left block after entering the Map.

____________________
Connection |
Direction  | Formula
___________|_______
     Above: C6E9h + Height_of_connected_map * (Width_of_connected_map + 6)
South/East: C6EFh + Width_of_connected_map
      West: C6EEh + 2 * Width_of_connected_map
...............................................................................

Example

PKMN Red Example -- Saffron City (Header: 0x509A4) Diagram:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Saffrons need-to-know stats:

Block Height (Y): 12
 Block Width (X): 14
 Connection Byte: 0F (North + South + West + East)
                      -       -       -      -
 + = current maps border blocks

++++++++NNNNNNNNNN++++++++
++++++++NNNNNNNNNN++++++++
++++++++NNNNNNNNNN++++++++
+++####################+++
+++####################+++
+++####### My #########+++
+++####################+++
WWW####### Name's #####EEE
WWW####################EEE
WWW###### Saffron #####EEE
WWW####################EEE
WWW###### City! #######EEE
WWW####################EEE
WWW####################EEE
WWW####################EEE
WWW####################EEE
+++####################+++
+++####################+++
+++####################+++
+++####################+++
+++####################+++
++++++++SSSSSSSSSS++++++++
++++++++SSSSSSSSSS++++++++
++++++++SSSSSSSSSS++++++++

Connection to Route 5 (to the North)
              *Y: 12
              *X: 0A
              *X_Movement_of_Connection Strip = 5
       Map Index: 10
Connection Strip: 4668
 Where Connected: C6F0 (C6EB + 5)
       "Bigness": 0A
           Width: 0A
     Y alignment: 23 (12 * 2 - 1)
     X alignment: F6 (5 * -2)
          Window: C809 (C6E9 + (12 * (0A + 6)))

Connection to Route 6 (to the South)
              *Y: 12
              *X: 0A
              *X_Movement_of_Connection Strip = 5
       Map Index: 11
Connection Strip: 4079
 Where Connected: C912 (C6EB + ((12 + 3) * (14 + 6)) + 5)
       "Bigness": 0A
           Width: 0A
     Y alignment: 00
     X alignment: F6 (5 * -2)
          Window: C6F9 (C6EF + 0A)

Connection to Route 7 (to the West)
              *Y: 09
              *X: 0A
              *Y_Movement_of_Connection Strip = 4
       Map Index: 12
Connection Strip: 4058
 Where Connected: C79E (C6E8 + (14 + 6) * (4 + 3))
       "Bigness": 09
           Width: 0A
     Y alignment: F8 (4 * -2)
     X alignment: 13 ((0A * 2) - 1)
          Window: C702 (C6EE + (0A * 2))

Connection to Route 8 (to the East)
              *Y: 09
              *X: 1E
              *Y_Movement_of_Connection Strip = 4
       Map Index: 13
Connection Strip: 41C6
 Where Connected: C7B5 (C6E5 + (14 + 6) * (4 + 4))
       "Bigness": 09
           Width: 1E
     Y alignment: F8 (4 * -2)
     X alignment: 00
          Window: C70D (C6EF + 1E)

Object Data

1 byte  - Border block ID
1 byte  - Number of warps
4 bytes per warp - Warp data
1 byte  - Number of signs
3 bytes per sign - Sign data
1 byte  - Number of NPCs (total)
6/8/7 bytes per NPC - NPC data
4 bytes per warp-to - Warp-To data

Warps

1 byte  - Y position
1 byte  - X position
1 byte  - Destination warp-to's ID (within target map)
1 byte  - Destination map

Signposts

1 byte  - Y position
1 byte  - X position
1 byte  - Text string ID

NPCs

In order to distinguish People, Trainers and Items, you must check the text string ID:

strID & (1 << 6) != 0 : Trainer (2 extra bytes, the trainer class and roster IDs)

strID & (1 << 7) != 0 -> Item (1 extra byte, the item ID)

Normal people
1 byte  - Picture number
1 byte  - Y position + 4
1 byte  - X position + 4
1 byte  - Movement byte 1
1 byte  - Movement byte 2
1 byte  - Text string ID
Trainers / One-time Pokémon

One-time Pokémon and Trainers are essentially the same thing, separated by their species ID. If it's under 200, it's a Pokémon. Over or equal to 200, it's a Trainer.

1 byte  - Picture number
1 byte  - Y position + 4
1 byte  - X position + 4
1 byte  - Movement 1
1 byte  - Movement 2
1 byte  - Text string ID
1 byte  - Pokémon species ID / Trainer class
1 byte  - Pokemon level / Trainer's roster ID
Items
1 byte  - Picture number
1 byte  - Y position + 4
1 byte  - X position + 4
1 byte  - Movement 1
1 byte  - Movement 2
1 byte  - Text string ID
1 byte  - Item ID

Warp-To Points

2 bytes - Event Displacement
1 byte  - Y position
1 byte  - X position


Sprites

Sprites are loaded when changing maps. However, there is a little subtlety : when traversing a map connection, the game assumes the correct sprite set is loaded, and doesn't reload sprites. (Hence glitchy sprites sometimes observed with Walk Through Walls).

The other occasion where sprites are loaded is when a text display is closed ; the game reloads sprites because the "walking" sprites are overwritten by font tiles.

Also, if there are no sprites (NPCs) the game doesn't reload sprite graphics.

How the game reloads sprites differs for "exterior" and "interior" maps.

Exterior maps

The game reads an entry from the table at 17A64, MapSpriteSets. If the entry is < $F0, the game uses the corresponding sprite set. Otherwise, it uses the corresponding split sprite set (see dedicated section).

Split sprite sets

Some exterior maps have two sprite sets, which depend on position.

Consider the entry read from MapSpriteSets. If the entry is $F8, that's Route 20 - a special case with a complex splitting. See its dedicated section.

The table maintains a table at 17A89, SplitMapSpriteSets, structured like so :

1 byte  - Split type (1 = East/West division, 2 = North/South division)
1 byte  - Split coordinate
1 byte  - Sprite set ID if coordinate <  split coordinate
1 byte  - Sprite set ID if coordinate >= split coordinate

The game reads an entry, indexed using (the byte read from MapSpriteSets AND $0F), and uses this sprite set.

Sea Route 20

Sea Route 20 has two sprite sets, $01 (West) and $0A (East). The only thing that differs from above is that the splitting is more complex.

If X coordinate < $2B
  Use set $01
End

If X coordinate >= $3E
  Use set $0A
End

If X coordinate >= $37
  If Y coordinate < $08
    Use set $0A
  Else
    Use set $01
  End
Else
  If Y coordinate < $0D
    Use set $0A
  Else
    Use set $01
  End
End

More visually :

Y X  ... 28 29 2A 2B 2C 2D ... 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 ...

.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
05   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ...
06   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ...
07   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ...
08   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
09   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0A   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0B   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0C   ... 01 01 01 0A 0A 0A ... 0A 0A 0A 01 01 01 01 01 01 01 0A 0A 0A ...
0D   ... 01 01 01 01 01 01 ... 01 01 01 01 01 01 01 01 01 01 0A 0A 0A ...
0E   ... 01 01 01 01 01 01 ... 01 01 01 01 01 01 01 01 01 01 0A 0A 0A ...
0F   ... 01 01 01 01 01 01 ... 01 01 01 01 01 01 01 01 01 01 0A 0A 0A ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...

Interior maps

The game loads sprites by request, ie. the sprite tiles will be loaded as required by NPCs present on the loaded map.


Useful notes

Picture numbers

In order to get the ROM address of the tile relative to an entity (people/trainers/items), here is the formula to focus on the entity information:

 5 * $4000 + ($7b27 + 4 * (picture_id - 1)) % $4000

Then the entity information is stored according to this:

2 bytes - Tile address
1 byte  - Total size of tile data
1 byte  - Bank ID

So then, address = bankID * 0x4000 + tileAddr % 0x4000

Event displacement formula

$C6EF + (Map width) + (Map width + 6) * (Y offset) + (X offset)

Pointers

R/B Pointers to Map Headers: 0x01AE R/B Map Header Banks: 0xC23D R/B Pointer to Tileset Headers: 0xC767

Misc.

Maximum tileset size in VRAM: 6 rows of 16 tiles (9000-95FF)


Credits

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    RGBY Map Headers & Stuff That Goes With It
    Version 1.6
    -Feel free to distribute this document and/or edit it.
    -Try and credit people you get info from and/or write how you updated.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Things that need adding:
------------------------
More information about tilesets, and info about what sprites get loaded for
which maps.

Updates:
--------
v1.6 by ISSOtm: Re-formatted the document, less ASCII and more wiki.
v1.5.1 by Sawakita: Fixed Tileset Header, completely (including last byte: Animation Flag)
v1.5 by phire: Completed Tileset Header, except for that last byte.
v1.4 Complete object data info with details about picture id.
v1.3 Edit by Cartmic to include almost completed tileset header information
     and Hat's further clarification on what the X/Y Movement of the Connection means.
v1.2: By ubitux: Add some information about connections and distinction between entities (People/Trainers/Items)
v1.11: Typo fixed by Hat: "01 = North" changed to "01 = East". Thanks to IIMarckus for pointing that out.
v1.1: By Hat, minor improvements.
v1.0: Original version typed up by Hat.

Main Credits (Structure Information):
-------------------------------------
  [Xeon]
    Wrote some stuff about Map Headers and Object Data.
    Which this document expands upon, a bit.

  [F-Zero] & [Tauwasser]
    Wrote a document (in German) explaining how GSC connection data is stored.
    RGBY connection data is stored almost the same way, it turns out, so
    that helped a great deal. All that is really different is the values you
    add the amount of blocks to.
...............................................................................