24385-\[GBC]_Mapas:_Todo_lo_necesario_para_modificar_o_crear_una_región
#0
Crystal_ 28012
.
.

Contenidos



Introducción

Este tutorial esta pensado para proporcionar al lector toda la información necesaria a la hora de trabajar con mapas. El tutorial contiene información sobre como modificar mapas existentes y crear nuevos mapas, como modificar el aspecto de la región y la localización de los mapas en ésta, y como conexionar mapas adyacentes corréctamente.

Para editar la apariencia de los mapas se emplean editores de mapas como son JohtoMap y GoldMap para Pokemon Gold / Silver, y CrystalMap para Pokemon Crystal. Como la edición del aspecto de mapas es muy intuitivo mediante la utilización de estas tools, nos centraremos en otros aspectos mas complicados.

Cada mapa viene identificado por dos equivalentes númericos de tamaño de byte: un equivalente que identifica el grupo al que pertenece el mapa, y un equivalente que permite distinguir entre mapas dentro de un mismo grupo. Hay 0x1A grupos diferentes mientras que la cantidad de mapas dentro de un mismo grupo es variable.



Un mapa viene definido por su Map Header y su Secondary Map Header y debe tener una entrada en ambos para existir como tal.



Map Header

Gold (U) / Silver (U): 0x94121
Crystal (U): 0x94034
Longitud de cada entrada: 0x09 bytes

Estructura

[Tileset][Permiso][Pointer a Secondary Map Header (2 bytes)]
[Localización en el Town Map][Música][Tiempo del día][Grupo de pesca]

Bank del Secondary Map Header
ROM bank en la que se encuentra el Secondary Map Header del mapa.

Tileset
Tileset usada por el mapa.

Permiso
Permisos ofrecidos por el mapa, tales como si es posible volar o montar en bicicleta.


Pointer a Secondary Map Header
Puntero de 2 bytes al Secondary Map Header del mapa (dentro de la ROM bank indicada por Bank del Secondary Map Header).

Localización en el Town Map
Localización del mapa en el Town Map visible en el Pokegear (ver la sección Localización en el Town Map para mas información).

Música
Música que suena al estar dentro del mapa.


Tiempo del día
Paleta usada por el mapa según el tiempo del día.


Grupo de pesca
Indica que tabla de pesca tiene asignada el mapa (ver la sección Añadiendo Pokemon Salvajes para mas información).



Secondary Map Header

Gold (U) / Silver (U): 0x95B6D
Crystal (U): 0x94DD8
Longitud de cada entrada: 0x0C + (0x0C * Nº Conexiones) bytes

Estructura

[Altura][Anchura][Pointer a Block Data (3 bytes)]
[Pointer a Script Header (2 bytes)][Pointer a Event Header (2 bytes)]

Por cada conexión:

[Identificador de grupo del mapa destino][Identificador de mapa del mapa destino][Strip Pointer (2 bytes)]
[Strip destination (2 bytes)][Longitud del Strip][Anchura del mapa destino][Alineación vertical]
[Alineación horizontal][Ventana (2 bytes)]

Border Block
Bloque de relleno mostrado en pantalla por defecto cuando el mapa no cubre toda el área de visión de la ventana y no hay datos de otro mapa adyacente que mostrar. El bloque se toma del tileset utilizado por el mapa en que nos encontramos.

Altura
Numero de bloques que tiene mapa en el eje Y.

Anchura
Numero de bloques que tiene mapa en el eje X.

Pointer a Block Data (3 bytes)
Puntero de 3 bytes al Block Data del mapa.

Bank del Script Header y del Event Header
ROM bank en la que se encuentan el Script Header y el Event Header del mapa.

Pointer a Script Header (2 bytes)
Puntero de 2 bytes al Script Header del mapa (dentro de la ROM bank indicada por Bank del Script Header y del Event Header).

Pointer a Event Header (2 bytes)
Puntero de 2 bytes al Event Header del mapa (dentro de la ROM bank indicada por Bank del Script Header y del Event Header).

Byte de conexión
Indica la cantidad y tipo de conexiones del mapa.


Si hay mas de una conexión, estás deben ordenarse NORTE | SUR | OESTE | ESTE

(Ver la sección Conectando Mapas para mas información)

Identificador de grupo del mapa destino
Identificador de grupo del mapa al cual el mapa en en que nos encontramos se conecta.

Identificador de mapa del mapa destino
Identificador de mapa del mapa al cual el mapa en en que nos encontramos se conecta.

Strip Pointer (2 bytes)
Puntero del Strip en la ROM.

Strip destination (2 bytes)
Destino del Strip en la RAM.

Longitud del Strip
Número de bloques que cubre el Strip a lo largo.

Anchura del mapa destino
Numero de bloques que tiene el mapa en el eje X.

Alineación vertical
Posición relativa en el eje Y tras entrar en el mapa destino (en bloques).

Alineación horizontal
Posición relativa en el eje X tras entrar en el mapa destino (en bloques).

Ventana
Parte del mapa que se visualiza en la pantalla tras entrar en el mapa destino.



Localización en el Town Map

Esta sección es una ampliación a la entrada del Map Header Localización en el Town Map.

La posición de cada mapa individual en el mapa global (Town Map) mostrado en el Pokegear viene determinado por una tabla con la siguiente estructura y localización:

[Coordenada X][Coordenada Y][Pointer al nombre del mapa (2 bytes)]

Gold (U) / Silver (U): 0x92383
Crystal (U): 0x1CA8C3
Longitud de cada entrada: 0x04 bytes

El orden de los mapas en la tabla, que coincide con el orden según el cual nos desplazamos en el Pokegear, es el siguiente:



La diferencia entre Gold / Silver y Crystal es que Crystal contiene una entrada adicional entre Lighthouse y Route 40: Battle Tower.

La primera entrada ("SPECIAL") nos es irrelevante, por lo que utilizaremos como ejemplo la siguiente, que se corresponde con "NEW BARK TOWN". Si utilizamos Pokemon Gold / Silver como ROM base, veremos lo siguiente:

[0x94][0x74][0xFE][0x64]

0x94: Coordenada X en el Town Map
0x74: Coordenada Y en el Town Map
0xFE 0x64: Puntero de 2 bytes al nombre asignado a dichas coordenadas (es decir, la string con el nombre esta localizada en 0x924FE).

(Nota: Para modificar el aspecto del Town Map se recomienda utilizar la tool GSC Town Map Editor.)



Flypoints y Blackout Points

Los flypoints (posiciones de vuelo) y blackout points (posiciones de blackout) vienen determinados por una tabla con la siguiente estructura:

[Identificador de grupo del mapa][Identificador de mapa del mapa][Coordenada X][Coordenada Y]

donde las coordenadas X e Y se miden en half-blocks.

Su localización es:

Gold (U) / Silver (U): 0x15319
Crystal (U): 0x152AB
Longitud de cada entrada: 0x04 bytes

Esta tabla indica los mapas a los que se puede volar mediante en uso de la HM02 (Fly) con las coordenadas correspondientes en las que apareceremos en cada mapa, además de determinar los mapas y posiciones de blackout. En este último caso, se tomará la entrada de la tabla que contenga el mapa cuyo PC (Pokemon Center) se visitó por última vez.

La primera entrada de la tabla coincide con la posición de inicio del juego, y será, ademas, la entrada utilizada si ocurre un blackout cuando no se ha visitado ningún PC aún. La segunda entrada apunta al PC de Viridian City, pero en realidad nunca se usa. A partir de aquí tendremos una entrada para cada mapa con PC.

Cada uno de los mapas con entrada en la tabla posee una flag que indica si es posible volar a dicho mapa o no. Estas flags de vuelo pertenecen a la BitTable2 y están localizadas en el rango [0034,004B] para Gold / Silver, y en el rango [0035,004C] para Crystal. Si la flag asociada a un determinado mapa está activada, será posible volar a dicho mapa. Estas flags se activan inmediatamente al entrar a cada mapa en cuestión, mediante un Callback y la instrucción SetBit2 cuya estructura es [0x34][Flag (2 bytes)]. En otras palabras, es posible volar a un mapa una vez que éste haya sido visitado.

A continuación se muestra una lista con el formato Nº entrada en la tabla - Flag asociada - Nombre del mapa



La tabla que vamos a ver a continuación relaciona las entradas correspondientes de la tabla vista en la sección Localización del Town Map (G/S: 0x92383 / C: 0x1CA8C3), con las entradas de la tabla vista recientemente en esta sección (G/S: 0x15319 / C: 0x152AB). Por tanto, es importante tener esta tabla en cuenta para que el Town Map mostrado al usar Fly se muestre consecuentemente a los cambios realizados en los flypoints.

Estructura:

[Nº entrada tabla 0x92383 / 0x1CA8C3][Nº entrada tabla 0x15319 / 0x152AB]

Localización:

Gold (U) / Silver (U): 0x91BCC
Crystal (U): 0x91C5E
Longitud de cada entrada: 0x02 bytes

Por ejemplo, la primera entrada de esta tabla es [0x01][0x0E]. Esta entrada implica que, en efecto, la posición en el Town Map correspondiente a New Bark Town (ver tabla G/S: 0x92383 / C: 0x1CA8C3) se corresponde con el flypoint de New Bark Town (ver tabla G/S: 0x15319 / C: 0x152AB). Del mismo modo, la segunda entrada de esta tabla, [0x03][0x0F], está relacionando las dos instancias de Cherrygrove City.

Ejemplo

Para este ejemplo tomaremos Pokemon Crystal como ROM base. Nótese que para aplicarlo a las versiones Gold / Silver tan solo tendríamos que ajustar el orden de las diferentes entradas de dichas tablas, y, por supuesto, usar los offsets indicados para Gold / Silver.

Vamos a suponer que queremos situar el flypoint / blackout point correspondiente a Cherrygrove City en Route 43. A primera vista esto no tiene mucho sentido, pero en caso de haber cambiado el aspecto de la región (o de haber creado una nueva región), es posible que hayamos convertido lo que originalmente era Route 43 en una ciudad o pueblo con PC.

Lo primero que debemos hacer es localizar la entrada de Cherrygrove City en la tabla 0x152AB. Para ello no tenemos mas que tener en cuenta la longitud de cada entrada. Como Cherrygrove City se encuentra en la entrada 0x0F y la primera entrada la hemos identificado como 0x00:

0x152AB + (0x0F - 0x00) * 0x04 = 0x152AB + 0x0F * 0x04 = 0x152E7

Esta entrada muestra lo siguiente:

[0x1A][0x03][0x1D][0x04]

Lo primero que hacemos es ajustar los bytes identificadores de mapa. Tomamos los identificadores correspondientes a Route 43, de manera que nos queda:

[0x09][0x05][0x1D][0x04]

También deberiamos ajustar las coordenadas X e Y a nuestro nuevo mapa. Si quisiesemos seguir con la tendencia del juego original, ajustaríamos las coordenadas al half-block situado delante de la puerta del PC. Un ejemplo podría ser:

[0x09][0x05][0x11][0x0B]

Por último debemos modificar la entrada correspondiente de la tabla 0x91C5E para que el Town Map se muestre acorde a los cambios realizados al usar Fly. Como ya hemos visto, la entrada correspondiente a Cherrygrove City se encuentra en la segunda posición de dicha tabla. Si tuviesemos que encontar una entrada N cualquiera, tan solo tendríamos que aplicar la misma lógica que usamos para la tabla anterior. Es decir, si tomamos como referencia que la primera entrada se corresponde con 0x01:

0x91C5E + (N - 0x01) * 0x02

Nuestro caso es muy sencillo:

0x91C5E + (0x02 - 0x01) * 0x02 = 0x91C60

Esta entrada contiene los siguientes bytes:

[0x03][0x0F]

El segundo byte no lo modificamos ya que hace referencia a la entrada 0x0F de la tabla 0x152AB que acabamos de ajustar.

Sin embargo, debemos modificar el primero para que haga referencia a Route 43 en vez de a Cherrygrove City. Para ello, no tenemos mas que buscar la posición de Route 43 en la tabla 0x1CA8C3 vista en Localización en el Town Map. Como su posición es 0x25, la entrada de la tabla 0x91C5E modificada quedaría de la siguiente manera:

[0x25][0x0F]



Conectando Mapas

A la hora de conectar dos mapas adyacentes debemos establecer una conexión en ambos mapas y debemos tener en cuenta, para las dos conexiones, los siguientes parámetros:

En el caso de que los dos mapas esten conectados mediante un Warp, los siguientes parámetros son irrelevantes:

Si además el mapa destino no es visible desde ningún punto del mapa origen, todos los parámetros son irrelevantes y no es necesario definir la conexión en esa dirección.

(Nota: en esta subsección, todas las medidas de longitud se toman en bloques, y todos los calculos están realizados en numeración hexadecimal.)

Identificando el Strip

El Strip es una tira que cubre todo el rango de visión del mapa destino desde cualquier punto del mapa origen. Debido al tamaño de la ventana mostrada en pantalla, se tiene que tomas un margen de 3 bloques tanto a lo largo como a lo ancho siempre que sea necesario.

Strip Pointer

Puntero al bloque de menor offset del Strip.

Strip Destination

Se calcula de la siguiente manera, dependiendo del tipo de conexión:

Donde:

Alineación vertical

Se calcula de la siguiente manera, dependiendo del tipo de conexión:

Donde:

Alineación horizontal

Se calcula de la siguiente manera, dependiendo del tipo de conexión:

Donde:

Ventana

Se calcula de la siguiente manera, dependiendo del tipo de conexión:

Donde:

Ejemplo

Vamos a ver un ejemplo para cada tipo de conexión, tomando Pokemon Crystal como ROM base:

Se recomienda tomar esta imagen como referencia:



Origen: Cherrygrove City - Destino: Este a Route 29 (1)


Origen: Route 29 - Destino: Oeste a Cherrygrove City (2)




Origen: Cherrygrove City - Destino: Norte a Route 30 (3)



Origen: Route 30 - Destino: Sur a Cherrygrove City (4)




En este caso se van a detallar tan solo las diferencias significativas con respecto a los ejemplos anteriores.

A la hora de determinar el Strip, debemos tener en cuenta que estamos pasando verticalmente hacia un mapa mas ancho. Por tanto el Strip no solo debe cubrir el margen de 3 bloques vertical, sino que se deben añadir 3 bloques horizontalmente a ambos lados para cubrir todo el posible área de visión (ver imagen). Es facil de ver que la longitud del Strip sera entonces la anchura de Route 30 + 6, es decir, 0x10.

Para calcular el offset horizontal, al igual que en el ejemplo anterior, tomamos el extremo izquierdo del mapa origen y el extremo izquierdo del Strip en el mapa destino, y contamos la cantidad de bloques que el segundo esta desplazado respecto del primero (ver imagen). En este caso, el Strip del mapa destino (Cherrygrove City) comienza tres bloques mas a la izquierda ("antes") que el mapa origen (Route 30), lo que significa que tenemos que manejar un offset en X de -3.

Este offset de valor -3 nos sirve para calcular el Strip Destination, pero para calcular la alineacion horizontal, alineación vertical y ventana (parámetros que no están relacionados con el Strip), el offset horizontal es diferente. En este caso, no debemos tomar el extremo izquierdo del Strip, sino el extremo izquierdo del mapa completo, lo que nos da un offset de -5 (ver imagen). En el ejemplo (3) no existía diferencia entre el offset para el Strip Destination y el offset para los parámetros posteriores, ya que la posición en la que empezaba el Strip coincidía con la posición en la que empezaba el mapa (ver imagen).




Añadiendo Pokemon Salvajes

Pokemon salvajes "de suelo"

Aunque resulta muy sencillo editar este tipo Pokemon salvajes mediante una tool como el GSC Wild Pokemon Editor, resulta útil tener conocimientos sobre este tema para poder asignar datos de Pokemon salvajes a diferentes mapas.

(Nota: A partir de ahora en esta subsección se concreta el termino Pokemon Salvajes a tan solo los Pokemon "de suelo", es decir, Pokemon que aparecen en la hierba alta o en cuevas o torres.)

La estructura que siguen los datos de los Pokemon salvajes es la siguiente:

[Identificador de grupo][Identificador de mapa][Prob. encuentro mañana][Prob. encuentro día][Prob. encuentro noche][Datos de Pokemon]

donde la probabilidad de encuentro se calcula sobre 256. Los datos de Pokemon se organizan de la forma [Nivel][Pokemon], habiendo un total de 21 Pokemon (7 por cada tiempo del día). Por tanto, los datos de Pokemon salvajes de un mapa ocupan un total de 47 bytes de la memoria ROM. Las probabilidades de aparición de cada uno de los siete Pokemon en particular dependen del orden el que estén colocados, y son, aproximadamente las siguientes:


Los datos de Pokemon salvajes son muy extensos y en gran medida no es necesario tener una tabla con las localizaciones de los Pokemon salvajes de cada mapa. Hay maneras sencillas de localizar los Pokemon salvajes de un determinado mapa en la ROM; conociendo los porcentajes de encuentro del mapa, no habría mas que buscar los 5 primeros bytes de la estructura dentro de la bank 0x0A. Por otra parte, el propio GSC Wild Pokemon Editor nos muestra los offsets donde se encuentran los Pokemon salvajes de un mapa sin mas que guardar cambios en ese mapa. Una vez localizada la entrada buscada, no hay mas que modificar los identificadores de mapa si quisiéramos asignar los datos de Pokemon salvajes de un mapa a otro.

Pokemon de Surf

Los Pokemon salvajes que se pueden encontrar al usar Surf siguen unas característican similares, pero ocupan mucho menos espacio:

[Identificador de grupo][Identificador de mapa][Prob. encuentro][Datos de Pokemon]

En este caso no se distingue en en función del tiempo del día, y, ademas solo hay 3 Pokemon asignados a cada mapa para un total de 9 bytes por entrada.
Los dos primeros Pokemon que introduzcamos aparecerán en el rango de niveles [L,L+4] y el tercer Pokemon podrá aparecer en el rango [L,L+1], donde L es el nivel introducido. Las doce posibilidades resultantes tienen una probabilidad similar de darse en un encuentro con un Pokemon salvaje de Surf.

La busqueda de los datos de Pokemon de Surf puede ser algo mas complicada, pero la tool GSC Wild Pokemon Editor también nos puede mostrar sus localizaciones si fuese necesario.

Pokemon de Headbutt y Rock Smash

Existen 12 tablas diferentes que contienen datos de Pokemon que aparecen al utilizar la TM Headbutt en uno de los árboles permitidos. Adicionalmente, existe una decimotercera tabla situada en la última posición que contiene los datos de Pokemon encontrados al usar Rock Smash en las rocas correspondientes. La localización de la primera tabla es:

Gold (U) / Silver (U): 0xBA47C
Crystal (U): 0xB82FA
Longitud de cada tabla: 0x13 bytes

Los punteros a cada una de las tablas se encuentran situadas justo antes de éstas.



La tabla que asigna una tabla de Headbutt a cada mapa está localizada en el offset 0xBA3E6 en Pokemon Gold / Silver y en el offset 0xB825E en Pokemon Crystal. Para cada entrada, los dos primeros bytes identifican al mapa, y el tercero determina la tabla de Headbutt asignada a dicho mapa. Al final de esta tabla se puede encontrar una nueva tabla que, del mismo modo, indica que mapas tienen asignada la tabla correspondiente a los Pokemon de Rock Smash.

Dependiendo del tiempo del día determinados Pokemon caerán dormidos del árbol al usar Headbutt. La tabla que determina que Pokemon y cuando lo harán está situada en el offset 0x3E9F3 en las versiones Gold / Silver y en el offset 0x3EBB5 en la versión Crystal. La tabla posee la siguiente estructura:

[Pokemon dormidos noche][0xFF][Pokemon dormidos día][0xFF][Pokemon dormidos mañana][0xFF]

Pokemon de pesca

Como vimos al principio del tutorial, los Pokemon salvajes que aparecen al pescar dependen de la tabla que tenga asignada cada mapa en su Map Header. Existen un total de 12 tablas o grupos de pesca, e incluyen datos correspondientes a las tres cañas de pescar (Old Rod, Good Rod, y Super Rod).

La localización de la primera tabla es la siguiente:

Gold (U) / Silver (U): 0x92A52
Crystal (U): 0x924E3

Además de las 12 tablas de pesca existe una tabla adicional (TimeFishGroups) que contiene datos de Pokemon que tan solo aparecen en un determinado tiempo del día.





.
.
.