inv_nds
Thread Id: 11015
Thread Name: Pokémon Black/White: Scripts
#0
Tsuka 15343
A ver, por si no había quedado claro, y para evitar futuros incidentes, lo resaltaré:

Cuento con el permiso del autor original de este tema, ~Arc, para postearlo aquí, en WaH, sin ningún tipo de edición porque todo lo que viene a continuación es fruto de su esfuerzo y no soy quién para tergiversar sus palabras. La primera persona en la cuál está escrita esta investigación hace referencia a su autor, ~Arc, y no a mí, Tsuka.


***


Bueno, llevo un tiempo investigando los scripts del Pokémon Negro español (aunque es extrapolable a las demás versiones) y quería compartir mis descubrimientos acerca de este tema. Sin embargo, antes de nada haré una pequeña introducción.


Estructura de los juegos de NDS:

(Léase en caso de no saber cómo es internamente un juego de NDS)

Una de las más notables diferencias entre los ROMs de NDS y los de GBA es su estructura. Internamente, los juegos de la portátil de doble pantalla están compuestos por diferentes archivos, que definen sus funcionalidades. Por una parte, están los archivos ejecutables (arm9.bin, arm7.bin y overlays) y los archivos que contienen los recursos del juego (los que se encuentran en la carpeta "data" cuando extraemos el ROM con dslazy, ndstool u otro programa. Estos últimos son los que nos interesan actualmente, pues ahí se encuentran las imágenes, datos de Pokémon, scripts y demás. Muchos de estos archivos (por no decir todos) son archivos NARC (Nitro ARChive), que son archivos que contienen otros archivos (algo como archivos .rar, pero sin comprimir), y que podemos descomprimir con el NDS Editor de kiwi.ds.

Pero en fin, a lo que nos incumbe, en el Blanco y Negro los scripts se encuentran en el archivo "data/a/0/5/7".


Estructura de los archivos de scripts:


Cabe mencionar que en el Blanco y Negro, no todos los archivos del narc "a/0/5/7" contienen archivos de scripts, sino que sólo los archivos pares contienen scripts (000, 002, 004, 006...) y cada uno corresponde a un mapa del juego. Todavía no sé qué contienen los archivos impares.

La estructura de los archivos de scripts, al igual que en el resto de juegos de Pokémon de NDS (D/P/Pt y HG/SS) es la siguiente:

<Offset relativo al inicio del script: 4 bytes> (se repite por cada script del mapa)
<13 FD>: Indica el final de la zona de offsets y el comienzo de los scripts en sí.
<Scripts (comandos)>: Aquí están los comandos de los scripts.

Tomando como ejemplo el archivo de scripts de la casa de Cheren (Planta baja, archivo 788):

06 00 00 00 44 00 00 00 13 FD 2E 00 A6 00 47 05 74 00 4C 00 00 10 00 62 09 08 00 01 00 11 00 01 00 1F 00 FF 10 00 00 00 3D 00 00 04 02 00 00 00 00 00 1E 00 0A 00 00 00 3D 00 00 04 00 00 00 00 00 00 32 00 3E 00 30 00 2F 00 02 00 2E 00 A6 00 47 05 74 00 4C 00 00 10 00 62 09 08 00 01 00 11 00 01 00 1F 00 FF 10 00 00 00 3D 00 00 04 03 00 00 00 00 00 1E 00 0A 00 00 00 3D 00 00 04 01 00 00 00 00 00 32 00 3E 00 30 00 2F 00 02 00 00 00

Rojo: Offsets de cada uno de los scripts (en este caso hay dos, puesto que cada offset son 4 bytes).
Verde: Separador entre los offsets y los comandos.
Morado: Comandos.



Comandos B/W:


Bueno, a lo que iba. Aquí está el verdadero fruto de la investigación, no es mucho, pero bueno, actualizaré cuando sepa algo más:

Nótese que tanto los comandos como los parámetros han de estar permutados dentro del ROM. Por ejemplo, un Faceplayer (0x0074) aparecerá como 74 00 en el editor hex.

0x0000 - Nop: Sin parámetros
No hace nada. Tan simple como eso.

0x0002 - End: Sin parámetros
Finaliza el script.

0x001C - Callstd: <2 bytes: Función estándar>
Llama a una función estándar. Algunas de las que he descubierto son:


0x001E - Goto: <4 bytes: Offset relativo al que saltar>
Salta a otra parte del archivo de script actual.

0x0023 - Setflag: <2 bytes: ID Flag>
Activa una flag.

0x002A - SetVar: <2 bytes: Variable> <2 bytes: Valor>
Almacena un valor en una variable. Las variables suelen ser del tipo 0x80XX.

0x002E - Lockall: Sin parámetros
Bloquea todos los overworlds del mapa hasta que Releaseall es llamado. Igual que en GBA.

0x002F - Releaseall: Sin parámetros
Libera todos los overworlds del mapa.

0x0032 - WaitButton?: Sin parámetros
Espera a que se pulse un botón (normalmente usado antes de un CloseMsgBox). No estoy muy seguro de este .

0x003C - Message: <2 bytes: Ni idea, parece ser siempre 0x400> <2 bytes: ID del texto> <2 bytes: ID del overworld que habla? (para que el bocadillo salga de la "boca" del overworld)> <2 bytes: Ni idea> <2 bytes: Ni idea>
Muestra un mensaje.

0x003D - Message2: Parece tener los mismos parámetros que el Message normal, quitando los 2 bytes del final.
Muestra un mensaje.

0x003E - CloseMsgBox: Sin parámetros
Cierra la caja de texto.

0x003F - CloseMsgOnKeyPress: Sin parámetros
Lo mismo que el anterior, pero espera a que se pulse un botón.

0x0047 - YesNoBox: <2 bytes: Variable donde se almacena el resultado>
Muestra una caja tipo "Sí/No". La opción escogida se guarda en la variable indicada (0x1 sí se escoge "Sí", 0x0 en caso contrario (si se escoge "No", vamos))

0x004B - WaitButton: Sin parámetros
Parece ser como el 0x0032... o no.

0x0064 - ApplyMovement: <2 bytes: ID del OW> <4 bytes: Offset relativo hacia la lista de movimientos>
El clásico ApplyMovement... Hace que un determinado overworld realice un movimiento. Más información acerca de los movimientos al final del post.

0x0065 - WaitMovement: Sin parámetros
Espera que el movimiento actual termine su ejecución antes de seguir ejecutando el resto del script.

0x006B - AddPeople: <2 bytes: ID del OW>
Hace aparecer a un overworld en el mapa (si no estaba en él ya).

0x006C - RemovePeople: <2 bytes: ID del OW>
Hace desaparecer a un overworld del mapa.

0x0074 - Faceplayer: Sin parámetros
El overworld actual mira hacia el personaje, como en GBA.

0x0085 - TrainerBattle: <2 bytes: Trainer ID> <2 bytes: Trainer ID #2> <2 bytes: Ni idea>
Inicia una batalla sencilla contra un entrenador (si el segundo parámetro es 00 00) o una doble contra dos (si el segundo parámetro es distinto de 00 00).

0x00A6 - Sound: <2 bytes: ID del sonido>
Reproduce un sonido. Normalmente utilizado al comienzo del script para que suene un "bip" inicial (no se me ocurre una mejor manera de explicarlo ).

0x00A9 - Fanfare: <2 bytes: ID de la fanfare>
Reproduce una fanfare. Lista de fanfares recopiladas.

0x00AA - WaitFanfare: Sin parámetros
Espera a que la fanfare deje de sonar antes de seguir con el resto del script.

0x00AB - PlayCry: <2 bytes: ID del Pokémon>
Reproduce el grito de un Pokémon.

0x00AC - WaitCry: Sin parámetros
Espera a que el grito reproducido con PlayCry deje de sonar antes de ejecutar el siguiente comando.

0x00B3 - FadeScreen: <2 bytes: Desconocido> <2 bytes: ??? (10 00 cuando se oscurece la pantalla)> <2 bytes: ??? (10 00 cuando se aclara la pantalla)> <2 bytes: 02 00>
Aclara u oscurece la pantalla (usado en los típicos scripts donde una persona cura a tus Pokémon y la pantalla se oscurece unos segundos mientras suena la fanfare )

0x00B4 - WaitFade: Sin parámetros
Espera a que la pantalla termine de aclararse u oscurecerse (evidentemente debido al comando anterior).

0x010C - GivePokémon: <2 bytes: Variable> <2 bytes: ID del Pokémon> <2 bytes: 00 00 (¿Objeto, quizás?)> <2 bytes: Nivel>
Añade un Pokémon al equipo. La variable indicada almacenará el valor 0x1 si ya se tienen 6 Pokémon en el equipo (por lo tanto no se puede dar el Pokémon), en caso contrario almacena 0x0.

0x010E - GivePokémon2: <2 bytes: Variable> <2 bytes: ID del Pokémon> <2 bytes: 00 00 (¿Objeto?)> <2 bytes: Nivel> + ??
Otra versión del comando anterior, y con más parámetros. Es el GivePokémon usado en el evento de Zorua.

0x010F - GiveEgg: <2 bytes: Variable> <2 bytes: ID del Pokémon> <2 bytes: 00 00>
Añade un huevo Pokémon al equipo. Al igual que con el GivePokémon, la variable tomará el valor 0x1 si ya tienes 6 Pokémon en el equipo.

0x0178 - WildBattle: <2 bytes: ID del Pokémon> <2 bytes: Nivel> <2 bytes: Variable (quizás almacena el resultado de la batalla)>
Inicia una batalla contra un Pokémon salvaje.


Movimientos


Las listas de movimientos se almacenan junto a los scripts y toman la siguiente estructura:

<ID del movimiento 1 (2 bytes)>
<Número de repeticiones del movimiento 1 (2 bytes)>
[<ID del movimiento 2 (2 bytes)>
<Número de repeticiones del movimiento 2 (2 bytes)>]

...

<FE 00 (marca el final de la lista de movimientos)>


Cada movimiento está compuesto de su ID (la lista más abajo) y del número de repeticiones (cuantas veces se va a ejecutar ese movimiento). Así, si un personaje da un paso hacia la izquierda y cinco hacia abajo (a velocidad normal), la lista sería:

0A 00 01 00 09 00 05 00 FE 00

Aquí una recopilación de IDs de movimiento que he ido sacando (hasta la 0x9A):




Lista de archivos de script (hasta Ciudad Teja):



Por supuesto, si alguien tiene algún dato más que aportar o simplemente aclarar algo, es libre de postear. ^^


***


Ahora hablo yo, Tsuka. Voy a aclarar, sí, por si acaso, que si tenéis cualquier duda, os dirijáis a ~Arc porque es quién mejor os puede responder. Por si no sabéis dónde encontrarle, es un usuario de la comunidad de hacking SpriHackNet [SHN] cuyo link podéis encontrar en el área de publicidad de WAH.
#1
Sephiroth 13677
A ver Tsuka, podrias haber modificado algo, porque es basicamente un copy&paste de SHN, cosa que no me agrada porque los de SHN se quejaran y nos diran de todo, plagiadores y cosas asi; por lo cual deberias haber cambiado algo, no se, queda como si nadie entendiese nada, pero que lo hubieras copiado por "hacer algo", no se.

Por ejemplo, poner "IDs de Movimiento que he ido sacando" es como decir que TÚ los sacaste cuando no es cierto, lo hizo Arc.

Por el resto, gracias, Arc.
#2
Tsuka 15343
¿De qué vas? En ningún momento he reclamado nada por estos descubrimientos.

En primer plano y bien clarito:
Cuento con el permiso del autor original de este tema, ~Arc, para postearlo aquí en WaH.


SHN no tiene derecho de quejarse puesto que el autor es ~Arc y él está de acuerdo con ésto. Por si no lo sabes, es co-autor de la investigación de la estructura de Platino y este tema es necesario porque la complementa.

Lo que hay que leer.
#3
Tsuka 15343
Ya basta.

Próximo mensaje que no aporte nada a la investigación o se desvíe del tema principal, será borrado sin previo aviso.