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

From Data Crystal
Jump to navigation Jump to search
(New page: <pre> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% RGBY Map Headers & Stuff That Goes With It By Hat (a.k.a. The Black Phantom) Version 1.0 ...)
 
No edit summary
 
(32 intermediate revisions by 15 users not shown)
Line 1: Line 1:
<pre>
{{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.


    RGBY Map Headers & Stuff That Goes With It
== Pokémon  ID==
    By Hat (a.k.a. The Black Phantom)
    Version 1.0
    -Feel free to distribute this document and/or edit it,
    -try and credit people you get info from and/or write how you updated...


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The RAM structure includes references Pokémon IDs. These do not match the Pokédex number in game. Instead, they correspond to the pokedex order listed in the ROM section, but with some numbers skipped:


Main Credits (Structure Information):
{|  class="wikitable" style="text-align: center;"
-------------------------------------
!Pokémon !! ID
  [Xeon]
|-
    Wrote some stuff about Map Headers and Object Data.
| Rhydon || 01
    Which this document expands upon, a bit.
|-
| Kangaskhan || 02
|-
| Nidoran M || 03
|-
| Clefairy || 04
|-
| Spearow || 05
|-
| Voltorb || 06
|-
| Nidoking || 07
|-
| Slowbro || 08
|-
| Ivysaur || 09
|-
| Exeggutor || 0A
|-
| Lickitung || 0B
|-
| Exeggcute || 0C
|-
| Grimer || 0D
|-
| Gengar || 0E
|-
| Nidoran F || 0F
|-
| Nidoqueen || 10
|-
| Cubone || 11
|-
| Rhyhorn || 12
|-
| Lapras || 13
|-
| Arcanine || 14
|-
| Mew || 15
|-
| Gyardos || 16
|-
| Shellder || 17
|-
| Tentacool || 18
|-
| Gastly || 19
|-
| Scyther || 1A
|-
| Staryu || 1B
|-
| Blastoise || 1C
|-
| Pinsir || 1D
|-
| Tangela || 1E
|-
| Growlithe || 21
|-
| Onix || 22
|-
| Fearow || 23
|-
| Pidgey || 24
|-
| Slowpoke || 25
|-
| Kadabra || 26
|-
| Graveler || 27
|-
| Chansey || 28
|-
| Machoke || 29
|-
| Mr. Mime || 2A
|-
| Hitmonlee || 2B
|-
| Hitmonchan || 2C
|-
| Arbok || 2D
|-
| Parasect || 2E
|-
| Psyduck || 2F
|-
| Drowzee || 30
|-
| Golem || 31
|-
| Magmar || 33
|-
| Electabuzz || 35
|-
| Magneton || 36
|-
| Koffing || 37
|-
| Mankey || 39
|-
| Seel || 3A
|-
| Diglett || 3B
|-
| Tauros || 3C
|-
| Farfetch || 40
|-
| Venonat || 41
|-
| Dragonite || 42
|-
| Doduo || 46
|-
| Poliwag || 47
|-
| Jynx || 48
|-
| Moltres || 49
|-
| Articuno || 4A
|-
| Zapdos || 4B
|-
| Ditto || 4C
|-
| Meowth || 4D
|-
| Krabby || 4E
|-
| Vulpix || 52
|-
| Ninetales || 53
|-
| Pikachu || 54
|-
| Raichu || 55
|-
| Dratini || 58
|-
| Dragonair || 59
|-
| Kabuto || 5A
|-
| Kabutops || 5B
|-
| Horsea || 5C
|-
| Seadra || 5D
|-
| Sandshrew || 60
|-
| Sandslash || 61
|-
| Omanyte || 62
|-
| Omastar || 63
|-
| Jigglypuff || 64
|-
| Wigglytuff || 65
|-
| Eevee || 66
|-
| Flareon || 67
|-
| Jolteon || 68
|-
| Vaporeon || 69
|-
| Machop || 6A
|-
| Zubat || 6B
|-
| Ekans || 6C
|-
| Paras || 6D
|-
| Poliwhirl || 6E
|-
| Poliwrath || 6F
|-
| Weedle || 70
|-
| Kakuna || 71
|-
| Beedrill || 72
|-
| Dodrio || 74
|-
| Primeape || 75
|-
| Dugtrio || 76
|-
| Venomoth || 77
|-
| Dewgong || 78
|-
| Caterpie || 7B
|-
| Metapod || 7C
|-
| Butterfree || 7D
|-
| Machamp || 7E
|-
| Golduck || 80
|-
| Hypno || 81
|-
| Golbat || 82
|-
| Mewtwo || 83
|-
| Snorlax || 84
|-
| Magikarp || 85
|-
| Muk || 88
|-
| Kingler || 8A
|-
| Cloyster || 8B
|-
| Electrode || 8D
|-
| Clefable || 8E
|-
| Weezing || 8F
|-
| Persian || 90
|-
| Marowak || 91
|-
| Haunter || 93
|-
| Abra || 94
|-
| Alakazam || 95
|-
| Pidgeotto || 96
|-
| Pidgeot || 97
|-
| Starmie || 98
|-
| Bulbasaur || 99
|-
| Venusaur || 9A
|-
| Tentacruel || 9B
|-
| Goldeen || 9D
|-
| Seaking || 9E
|-
| Ponyta || A3
|-
| Rapidash || A4
|-
| Rattata || A5
|-
| Raticate || A6
|-
| Nidorino || A7
|-
| Nidorina || A8
|-
| Geodude || A9
|-
| Porygon || AA
|-
| Aerodactyl || AB
|-
| Magnemite || AD
|-
| Charmander || B0
|-
| Squirtle || B1
|-
| Charmeleon || B2
|-
| Wartortle || B3
|-
| Charizard || B4
|-
| Oddish || B9
|-
| Gloom || BA
|-
| Vileplume || BB
|-
| Bellsprout || BC
|-
| Weepinbell || BD
|-
| Victreebel || BE
|}


  [F-Zero] & [Tauwasser]
== Move ID ==
    Wrote a document (in German) explaining how GSC connection data is stored.
{| class="wikitable"
    RGBY connection data is stored almost the same way, it turns out, so
! ID !! Move
    that helped a great deal. All that is really different is the values you
|-
    add the amount of blocks to.
| 01 || POUND
...............................................................................
|-
| 02 || KARATE CHOP
|-
| 03 || DOUBLESLAP
|-
| 04 || COMET PUNCH
|-
| 05 || MEGA PUNCH
|-
| 06 || PAY DAY
|-
| 07 || FIRE PUNCH
|-
| 08 || ICE PUNCH
|-
| 09 || THUNDERPUNCH
|-
| 0A || SCRATCH
|-
| 0B || VICEGRIP
|-
| 0C || GUILLOTINE
|-
| 0D || RAZOR WIND
|-
| 0E || SWORDS DANCE
|-
| 0F || CUT
|-
| 10 || GUST
|-
| 11 || WING ATTACK
|-
| 12 || WHIRLWIND
|-
| 13 || FLY
|-
| 14 || BIND
|-
| 15 || SLAM
|-
| 16 || VINE WHIP
|-
| 17 || STOMP
|-
| 18 || DOUBLE KICK
|-
| 19 || MEGA KICK
|-
| 1A || JUMP KICK
|-
| 1B || ROLLING KICK
|-
| 1C || SAND-ATTACK
|-
| 1D || HEADBUTT
|-
| 1E || HORN ATTACK
|-
| 1F || FURY ATTACK
|-
| 20 || HORN DRILL
|-
| 21 || TACKLE
|-
| 22 || BODY SLAM
|-
| 23 || WRAP
|-
| 24 || TAKE DOWN
|-
| 25 || THRASH
|-
| 26 || DOUBLE-EDGE
|-
| 27 || TAIL WHIP
|-
| 28 || POISON STING
|-
| 29 || TWINEEDLE
|-
| 2A || PIN MISSILE
|-
| 2B || LEER
|-
| 2C || BITE
|-
| 2D || GROWL
|-
| 2E || ROAR
|-
| 2F || SING
|-
| 30 || SUPERSONIC
|-
| 31 || SONICBOOM
|-
| 32 || DISABLE
|-
| 33 || ACID
|-
| 34 || EMBER
|-
| 35 || FLAMETHROWER
|-
| 36 || MIST
|-
| 37 || WATER GUN
|-
| 38 || HYDRO PUMP
|-
| 39 || SURF
|-
| 3A || ICE BEAM
|-
| 3B || BLIZZARD
|-
| 3C || PSYBEAM
|-
| 3D || BUBBLEBEAM
|-
| 3E || AURORA BEAM
|-
| 3F || HYPER BEAM
|-
| 40 || PECK
|-
| 41 || DRILL PECK
|-
| 42 || SUBMISSION
|-
| 43 || LOW KICK
|-
| 44 || COUNTER
|-
| 45 || SEISMIC TOSS
|-
| 46 || STRENGTH
|-
| 47 || ABSORB
|-
| 48 || MEGA DRAIN
|-
| 49 || LEECH SEED
|-
| 4A || GROWTH
|-
| 4B || RAZOR LEAF
|-
| 4C || SOLARBEAM
|-
| 4D || POISONPOWDER
|-
| 4E || STUN SPORE
|-
| 4F || SLEEP POWDER
|-
| 50 || PETAL DANCE
|-
| 51 || STRING SHOT
|-
| 52 || DRAGON RAGE
|-
| 53 || FIRE SPIN
|-
| 54 || THUNDERSHOCK
|-
| 55 || THUNDERBOLT
|-
| 56 || THUNDER WAVE
|-
| 57 || THUNDER
|-
| 58 || ROCK THROW
|-
| 59 || EARTHQUAKE
|-
| 5A || FISSURE
|-
| 5B || DIG
|-
| 5C || TOXIC
|-
| 5D || CONFUSION
|-
| 5E || PSYCHIC
|-
| 5F || HYPNOSIS
|-
| 60 || MEDITATE
|-
| 61 || AGILITY
|-
| 62 || QUICK ATTACK
|-
| 63 || RAGE
|-
| 64 || TELEPORT
|-
| 65 || NIGHT SHADE
|-
| 66 || MIMIC
|-
| 67 || SCREECH
|-
| 68 || DOUBLE TEAM
|-
| 69 || RECOVER
|-
| 6A || HARDEN
|-
| 6B || MINIMIZE
|-
| 6C || SMOKESCREEN
|-
| 6D || CONFUSE RAY
|-
| 6E || WITHDRAW
|-
| 6F || DEFENSE CURL
|-
| 70 || BARRIER
|-
| 71 || LIGHT SCREEN
|-
| 72 || HAZE
|-
| 73 || REFLECT
|-
| 74 || FOCUS ENERGY
|-
| 75 || BIDE
|-
| 76 || METRONOME
|-
| 77 || MIRROR MOVE
|-
| 78 || SELFDESTRUCT
|-
| 79 || EGG BOMB
|-
| 7A || LICK
|-
| 7B || SMOG
|-
| 7C || SLUDGE
|-
| 7D || BONE CLUB
|-
| 7E || FIRE BLAST
|-
| 7F || WATERFALL
|-
| 80 || CLAMP
|-
| 81 || SWIFT
|-
| 82 || SKULL BASH
|-
| 83 || SPIKE CANNON
|-
| 84 || CONSTRICT
|-
| 85 || AMNESIA
|-
| 86 || KENESIS
|-
| 87 || SOFTBOILED
|-
| 88 || HI JUMP KICK
|-
| 89 || GLARE
|-
| 8A || DREAM EATER
|-
| 8B || POISON GAS
|-
| 8C || BARRAGE
|-
| 8D || LEECH LIFE
|-
| 8E || LOVELY KISS
|-
| 8F || SKY ATTACK
|-
| 90 || TRANSFORM
|-
| 91 || BUBBLE
|-
| 92 || DIZZY PUNCH
|-
| 93 || SPORE
|-
| 94 || FLASH
|-
| 95 || PSYWAVE
|-
| 96 || SPLASH
|-
| 97 || ACID ARMOR
|-
| 98 || CRABHAMMER
|-
| 99 || EXPLOSION
|-
| 9A || FURY SWIPES
|-
| 9B || BONEMERANG
|-
| 9C || REST
|-
| 9D || ROCK SLIDE
|-
| 9E || HYPER FANG
|-
| 9F || SHARPEN
|-
| A0 || CONVERSION
|-
| A1 || TRI ATTACK
|-
| A2 || SUPER FANG
|-
| A3 || SLASH
|-
| A4 || SUBSTITUTE
|-
| A5 || STRUGGLE
|}




===============================================================================
== Tileset headers ==
12 bytes per header, as follows :
<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...)


    General Map Header Structure
(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?)


Explanation:
A tile is 8x8 pixels, so a block is 32x32 pixels.
~~~~~~~~~~~~
This contains all the data (pointers count as data) to build the map.


Format:
=== Tiles ===
~~~~~~~
Tiles are stored using the GB's format, and directly copied to VRAM.
  #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:
        00 = No Connections
        01 = North
        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]
  ?: [*11 Bytes per Connection*, No connections? Straight to "Object Data"!]
Last: [*2 Bytes*: Pointer to Object Data]


===============================================================================
=== Collision data ===
    1) Tileset Numbers
This is a pointer to a list of tile numbers over which the player can walk. Terminated with a FF byte.
===============================================================================


These are copied from a PDF by Cartmic, called "Pokemon Red Documents".
=== 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.


  00 = "Outside"
Each tileset can have up to 3 talking over tiles. Use FF to fill the unused slots.
  01 = "Ash's House"
  02 = "Pokemon Center"
  03 = "Viridian Forest"
  04 = "Ash's House -- Again"
  05 = "Gym"
  06 = "Pokemon Center -- Again"
  07 = "Gym -- Again"
  08 = "House"
  09 = "Museum"
  0A = "Museum -- Again"
  0B = "Underground Path"
  0C = "Museum -- Again #2"
  0D = "S.S. Anne"
  0E = "Vermilion Port"
  0F = "Pokemon Cemetary"
  10 = "Silph Co."
  11 = "Cave"
  12 = "Celadon Mart"
  13 = "Game Freak HQ"
  14 = "Lab"
  15 = "Bike Shop/Cable Center"
  16 = "Cinnabar Mansion/Power Plant etc"
  17 = "Indigo Plateau"
  18 = ???


===============================================================================
=== Grass tile ===
    2 & 3) Map Height (Y) & Width (X)
This is both a tile that will be rendered above sprites, and one where random "grass" encounters are possible.
===============================================================================


Exactly that, the amount of blocks high and wide the map data is.
=== 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.
    4 & 5) Map Data Pointer
===============================================================================


You can use Pokemap/GoldMap for hacking all this quite easily.
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.


The map you walk around on and stuff is stored as block indexes.
A single block consists of 4*4 tiles, so... somewhere else (the Block Data),
the block is stored as 16 bytes...


...the same amount of bytes as a 2bpp tile.
== Map headers ==
Read stuff on Romhacking.net for information on bits per plane/pixel (bpp).
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>


===============================================================================
=== Tileset numbers ===
    6 & 7) Pointer to Maps Text Pointers
===============================================================================


2 byte pointers to text that is used on that map.
The tileset descriptions are copied from a document compiled by Cartmic, called "Pokémon Red Documents", which may help you with other stuff too.


===============================================================================
{|  class="wikitable" style="text-align: center;"
    8 & 9) Pointer to Maps "Script"
!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
|}


Not entirely sure what/when/where/why/how.
NOTE: As you can see there's multiple copies of some tileset headers. They are literally copies.
But it contains unique things to the map at a guess, as I've found such things
as "what Pokemon is inside a Pokeball on the desk data"(Eevee) living there.


===============================================================================
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.
    10) Connection Byte
===============================================================================


Note:
=== Map height (Y axis) & width (X axis) ===
~~~~~
Exactly that, the amount of blocks high and wide the map data is.
I think I wrote the directions in the order connection data is stored...?
By the way if this value is 00h it is immediately followed by the Object Data
Pointer, no gap. Repeated list...


Connection Byte:
=== Map data pointer ===
    00 = No Connections
You can use the GoldMap engine for hacking map data quite easily.
    01 = North
    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


===============================================================================
The map you walk around on and stuff is stored as block indexes. A single block consists of 4x4 tiles.
    ?) Connection Data (0-44 bytes, explained in more depth: further down)
===============================================================================


===============================================================================
=== Pointer to text pointers ===
    Last) Object Data Pointer
This points to a list of pointers. When the game attempts to display textbox #3, it will fetch the 3rd pointer in this list.
===============================================================================


The last thing in the Map Header. It points to a bunch of certain stuff that
(Note : textbox #0 is hardwired to the START menu)
is stored in certain structures, because they are so overly used on maps.


Object Data is discussed at the end of this document.
=== 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 ===


    *** Hacking Connections ***
Note: If this value is $00 it is immediately followed by the object data pointer, no gap.
    This might take a bit of "practise hacking" to fully understand what the
    hell is being said here.


===============================================================================
Connections can be obtained with binary masks:
<pre>
connect_byte & (1 << 3) -> North
connect_byte & (1 << 2) -> South
connect_byte & (1 << 1) -> West
connect_byte & (1 << 0) -> East
</pre>


Explanation:
List of values:
~~~~~~~~~~~~
<pre>
The "Connection Byte" determines how many connections are in this space,
00 = No Connections
including none at all.
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>


Structure:
=== Connection Data ===
~~~~~~~~~~
Size can range from 0 to 44 bytes.
    #1: [Map Index of Connected Map]
  #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]


Connection Strip Example:
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.)
-------------------------
Connection Byte 0D...
the C rectangles are the connection strips for the current map...


                &&&      \
==== 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.
                & &      |
                & &      |
                & &      |
                & &      |- Connected Map (North)
                & &      |
  +++++++++++++CCC+++++ |
  +++++++++++++CCC+++++ |
  +++++++++++++CCC+++++ /
  +++###############+++
  +++#            #+++<------------- '+'s = current maps border
  +++#            #+++
  +++#  Current  #CCC&&&&&&&&&&&&
  +++#            #CCC          &
  +++#    Map    #CCC          &
  +++#            #CCC          &
  +++#            #CCC&&&&&&&&&&&&
  +++#            #+++
  +++###############+++
/ +++CCCCCCCCCCCCCCC+++
| +++CCCCCCCCCCCCCCC+++
| +++CCCCCCCCCCCCCCC+++
|    &            &\_____________/
|    &            &            \
|    &            &            Connected Map (East)
/|    &            &
|\    &&&&&&&&&&&&&&&
|
\_ Connected Map (South)


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


==== Structure ====
<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>
===============================================================================
===============================================================================
     #1 : Map Indexes
     #1 : Map Indexes
===============================================================================
===============================================================================


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


===============================================================================
===============================================================================
Line 254: Line 863:
===============================================================================
===============================================================================


This points to the part of the current map (in RAM somwhere or something)
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.
that the connection strips upperleft block is placed on the current map.


Line 294: Line 903:
Direction  | Formula
Direction  | Formula
___________|_______
___________|_______
     North: (Heigt_of_connected_map * 2) - 1
     North: (Height_of_connected_map * 2) - 1
     South: 0
     South: 0
  West/East: (Y_movement_of_connection_strip_in_blocks * -2)
  West/East: (Y_movement_of_connection_strip_in_blocks * -2)
Line 313: Line 922:


===============================================================================
===============================================================================
#10-#11 : X alignment
#10-#11 : Window
===============================================================================
===============================================================================


Line 326: Line 935:
       West: C6EEh + 2 * Width_of_connected_map
       West: C6EEh + 2 * Width_of_connected_map
...............................................................................
...............................................................................
</pre>
==== Example ====
<pre>
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)
</pre>


=== Object Data ===
<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>


===============================================================================
==== Warps ====
<pre>
1 byte  - Y position
1 byte  - X position
1 byte  - Destination warp-to's ID (within target map)
1 byte  - Destination map
</pre>
 
==== Signposts ====
<pre>
1 byte  - Y position
1 byte  - X position
1 byte  - Text string ID
</pre>
 
==== 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 =====
<pre>
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>
 
===== 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>
 
===== Items =====
<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>
 
==== Warp-To Points ====
<pre>
2 bytes - Event Displacement
1 byte  - Y position
1 byte  - X position
</pre>
 
 
== 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 :
<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.
 
===== 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
  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
</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 ...
 
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
.    ... .  .  .  .  .  .  ... .  .  .  .  .  .  .  .  .  .  .  .  .  ...
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 ===
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:
<pre>
2 bytes - Tile address
1 byte  - Total size of tile data
1 byte  - Bank ID
</pre>
 
So then, address = bankID * 0x4000 + tileAddr % 0x4000


    Object Data: General Structure
=== 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


Object Data
=== Misc. ===
===========
Maximum tileset size in VRAM: 6 rows of 16 tiles (9000-95FF)
[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:
------
[Y position][X position][Warp-To Point][Warp-To Map]


Signposts:
== Credits ==
----------
<pre>
[Y position][X position][Text String Number]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


Normal People:
    RGBY Map Headers & Stuff That Goes With It
--------------
    Version 1.6
[Picture Number][Y position + 4][X position + 4]
    -Feel free to distribute this document and/or edit it.
[Movement 1][Movement 2][Text String Number]
    -Try and credit people you get info from and/or write how you updated.


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


Items:
Things that need adding:
---------------------
------------------------
[Picture Number][Y position + 4][X position + 4]
More information about tilesets, and info about what sprites get loaded for
[Movement 1][Movement 2][Text String Number]
which maps.
[Item Number]


Warp-To Points
Updates:
--------------
--------
[*2 Bytes*: Event Displacement???][Y position][X position]
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.


Event Displacement Formula:
Main Credits (Structure Information):
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------------
C6E3 +  ((Map width + 8) * (rows above + 1))  + (X movement + 4)
  [Xeon]
Just set it to C6E3 if you're not using it I think.
    Wrote some stuff about Map Headers and Object Data.
    Which this document expands upon, a bit.


############################################################### THE END FOR NOW
  [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.
...............................................................................
</pre>
</pre>
{{Internal Data|game=Pokémon Red and Blue}}

Latest revision as of 18:54, 3 October 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.

Pokémon ID

The RAM structure includes references Pokémon IDs. These do not match the Pokédex number in game. Instead, they correspond to the pokedex order listed in the ROM section, but with some numbers skipped:

Pokémon ID
Rhydon 01
Kangaskhan 02
Nidoran M 03
Clefairy 04
Spearow 05
Voltorb 06
Nidoking 07
Slowbro 08
Ivysaur 09
Exeggutor 0A
Lickitung 0B
Exeggcute 0C
Grimer 0D
Gengar 0E
Nidoran F 0F
Nidoqueen 10
Cubone 11
Rhyhorn 12
Lapras 13
Arcanine 14
Mew 15
Gyardos 16
Shellder 17
Tentacool 18
Gastly 19
Scyther 1A
Staryu 1B
Blastoise 1C
Pinsir 1D
Tangela 1E
Growlithe 21
Onix 22
Fearow 23
Pidgey 24
Slowpoke 25
Kadabra 26
Graveler 27
Chansey 28
Machoke 29
Mr. Mime 2A
Hitmonlee 2B
Hitmonchan 2C
Arbok 2D
Parasect 2E
Psyduck 2F
Drowzee 30
Golem 31
Magmar 33
Electabuzz 35
Magneton 36
Koffing 37
Mankey 39
Seel 3A
Diglett 3B
Tauros 3C
Farfetch 40
Venonat 41
Dragonite 42
Doduo 46
Poliwag 47
Jynx 48
Moltres 49
Articuno 4A
Zapdos 4B
Ditto 4C
Meowth 4D
Krabby 4E
Vulpix 52
Ninetales 53
Pikachu 54
Raichu 55
Dratini 58
Dragonair 59
Kabuto 5A
Kabutops 5B
Horsea 5C
Seadra 5D
Sandshrew 60
Sandslash 61
Omanyte 62
Omastar 63
Jigglypuff 64
Wigglytuff 65
Eevee 66
Flareon 67
Jolteon 68
Vaporeon 69
Machop 6A
Zubat 6B
Ekans 6C
Paras 6D
Poliwhirl 6E
Poliwrath 6F
Weedle 70
Kakuna 71
Beedrill 72
Dodrio 74
Primeape 75
Dugtrio 76
Venomoth 77
Dewgong 78
Caterpie 7B
Metapod 7C
Butterfree 7D
Machamp 7E
Golduck 80
Hypno 81
Golbat 82
Mewtwo 83
Snorlax 84
Magikarp 85
Muk 88
Kingler 8A
Cloyster 8B
Electrode 8D
Clefable 8E
Weezing 8F
Persian 90
Marowak 91
Haunter 93
Abra 94
Alakazam 95
Pidgeotto 96
Pidgeot 97
Starmie 98
Bulbasaur 99
Venusaur 9A
Tentacruel 9B
Goldeen 9D
Seaking 9E
Ponyta A3
Rapidash A4
Rattata A5
Raticate A6
Nidorino A7
Nidorina A8
Geodude A9
Porygon AA
Aerodactyl AB
Magnemite AD
Charmander B0
Squirtle B1
Charmeleon B2
Wartortle B3
Charizard B4
Oddish B9
Gloom BA
Vileplume BB
Bellsprout BC
Weepinbell BD
Victreebel BE

Move ID

ID Move
01 POUND
02 KARATE CHOP
03 DOUBLESLAP
04 COMET PUNCH
05 MEGA PUNCH
06 PAY DAY
07 FIRE PUNCH
08 ICE PUNCH
09 THUNDERPUNCH
0A SCRATCH
0B VICEGRIP
0C GUILLOTINE
0D RAZOR WIND
0E SWORDS DANCE
0F CUT
10 GUST
11 WING ATTACK
12 WHIRLWIND
13 FLY
14 BIND
15 SLAM
16 VINE WHIP
17 STOMP
18 DOUBLE KICK
19 MEGA KICK
1A JUMP KICK
1B ROLLING KICK
1C SAND-ATTACK
1D HEADBUTT
1E HORN ATTACK
1F FURY ATTACK
20 HORN DRILL
21 TACKLE
22 BODY SLAM
23 WRAP
24 TAKE DOWN
25 THRASH
26 DOUBLE-EDGE
27 TAIL WHIP
28 POISON STING
29 TWINEEDLE
2A PIN MISSILE
2B LEER
2C BITE
2D GROWL
2E ROAR
2F SING
30 SUPERSONIC
31 SONICBOOM
32 DISABLE
33 ACID
34 EMBER
35 FLAMETHROWER
36 MIST
37 WATER GUN
38 HYDRO PUMP
39 SURF
3A ICE BEAM
3B BLIZZARD
3C PSYBEAM
3D BUBBLEBEAM
3E AURORA BEAM
3F HYPER BEAM
40 PECK
41 DRILL PECK
42 SUBMISSION
43 LOW KICK
44 COUNTER
45 SEISMIC TOSS
46 STRENGTH
47 ABSORB
48 MEGA DRAIN
49 LEECH SEED
4A GROWTH
4B RAZOR LEAF
4C SOLARBEAM
4D POISONPOWDER
4E STUN SPORE
4F SLEEP POWDER
50 PETAL DANCE
51 STRING SHOT
52 DRAGON RAGE
53 FIRE SPIN
54 THUNDERSHOCK
55 THUNDERBOLT
56 THUNDER WAVE
57 THUNDER
58 ROCK THROW
59 EARTHQUAKE
5A FISSURE
5B DIG
5C TOXIC
5D CONFUSION
5E PSYCHIC
5F HYPNOSIS
60 MEDITATE
61 AGILITY
62 QUICK ATTACK
63 RAGE
64 TELEPORT
65 NIGHT SHADE
66 MIMIC
67 SCREECH
68 DOUBLE TEAM
69 RECOVER
6A HARDEN
6B MINIMIZE
6C SMOKESCREEN
6D CONFUSE RAY
6E WITHDRAW
6F DEFENSE CURL
70 BARRIER
71 LIGHT SCREEN
72 HAZE
73 REFLECT
74 FOCUS ENERGY
75 BIDE
76 METRONOME
77 MIRROR MOVE
78 SELFDESTRUCT
79 EGG BOMB
7A LICK
7B SMOG
7C SLUDGE
7D BONE CLUB
7E FIRE BLAST
7F WATERFALL
80 CLAMP
81 SWIFT
82 SKULL BASH
83 SPIKE CANNON
84 CONSTRICT
85 AMNESIA
86 KENESIS
87 SOFTBOILED
88 HI JUMP KICK
89 GLARE
8A DREAM EATER
8B POISON GAS
8C BARRAGE
8D LEECH LIFE
8E LOVELY KISS
8F SKY ATTACK
90 TRANSFORM
91 BUBBLE
92 DIZZY PUNCH
93 SPORE
94 FLASH
95 PSYWAVE
96 SPLASH
97 ACID ARMOR
98 CRABHAMMER
99 EXPLOSION
9A FURY SWIPES
9B BONEMERANG
9C REST
9D ROCK SLIDE
9E HYPER FANG
9F SHARPEN
A0 CONVERSION
A1 TRI ATTACK
A2 SUPER FANG
A3 SLASH
A4 SUBSTITUTE
A5 STRUGGLE


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