Cabecera interna de las ROMS de Super Nintendo (SNES)

En Desarrollo, Tutoriales y Guías por

Animado por un artículo en inglés y visto que apenas existe información sobre la cabecera interna de las ROMs de Super Nintendo en español, he decidido publicar este pequeño documento. No soy ningún gurú de la SNES, por lo que toda la información es fruto de varios meses de lectura.

Cabecera interna de las ROMS de Super Nintendo (SNES)

Para llegar a entender el documento hay que tener unos conocimientos básicos de informática, aunque trataré de explicar cada apartado con el mayor detalle posible. Como resultado de este documento y a modo de práctica, he ido programando en C# una pequeña herramienta que permite extraer la información de las cabeceras de las ROMs y presentarla de forma legible. Sobre esta pequeña utilidad hablaremos al final del artículo.

¿Qué es la cabecera interna de una ROM de SNES?

Toda ROM de Super Nintendo contiene una cabecera de 64 bytes. A esta cabecera se le llama cabecera interna y es donde se almacena información sobre el cartucho. No debemos confundir esta cabecera interna con la llamada cabecera SMC.

¿Qué es la cabecera SMC?

La cabecera SMC es una cabecera que agregan las copiadoras de cartuchos. El hardware destinado a volcar los datos del cartucho en un archivo de datos, a veces agrega esta cabecera SMC con información extra.

La existencia o no de la cabecera SMC en una ROM de SNES es importante, ya que dependiendo de una posibilidad u otra, el mapeado de la cabecera interna será diferente (más adelante explicaré esto con más detalle).

La cabecera SMC se localiza al inicio de la ROM y tiene un tamaño de 512 bytes. En función de si tienen o no esta cabecera SMC las ROMs de SNES se denominan:

  • Headered ROM: tiene cabecera SMC.
  • Headerless ROM: no tiene cabecera SMC.

Existen programas que se encargan de eliminar la cabecera SMC, ya que en los emuladores de SNES actuales no tiene ningún uso. Este documento tratará sobre la cabecera interna, que es la que realmente nos interesa, pero es necesario saber que nos podemos encontrar con esta cabecera SMC.

Localización de la cabecera interna en la ROM SNES.

El primer objetivo será localizar la cabecera interna para poder leerla e interpretar la información.

¿Cómo detectar si una ROM tiene o no la cabecera SMC?

En este proceso vamos a detectar si una ROM es headered o si es headerless. La forma más sencilla de averiguar si una ROM tiene o no la cabecera SMC es dividir el tamaño de la ROM en bytes entre 1024. Según sea el resto de esta división se pueden dar tres posibilidades:

  • Si el resto es cero, no hay cabecera SMC (ROM haderless).
  • Si el resto es 512, existe una cabecera SMC (ROM hadered).
  • Si el resto es cualquier otro número diferente de los dos anteriores, puede ser que tengamos una ROM inválida.

Localizando la cabecera interna de la ROM (LoROM y HiROM).

Ahora que ya sabemos si la ROM tiene o no cabecera SMC podemos tratar de localizar la cabecera interna. Recordemos una vez más que la cabecera interna y la cabecera SMC son cosas diferentes.

Esta cabecera interna se puede localizar en dos offsets diferentes según se trate de una ROM LoROM o HiROM. Por esto, antes de determinar el offset de la cabecera interna, debemos determinar si se trata de una ROM LoRom o HiROM.

Los offsets por defecto para la cabecera son:

  • LoROM: 0x7FC0
  • HiROM: 0xFFC0

Estos offsets se ven desplazados si el ROM contiene la cabecera SMC, porque recordemos que eran 512 bytes al inicio del archivo. En el caso de existir cabecera SMC, los offsets son:

  • LoROM: 0x81C0
  • HiROM: 0x101C0

Para determinar si es HiROM o LoROM tenemos que calcular el Checksum y el ChecksumCompliment. Calculamos el Checksum y el ChecksumCompliment como si fuese LoROM (con el offset 0x7FC0). Si al comparar ambos checksum con el operador ^ (bitwise exclusive-OR) el resultado es 0xFFFF, entonces estamos en ante una ROM LoROM.

Si el resultado de la comparación anterior no es 0xFFFF, tendremos que repetir el proceso pero esta vez calculando el Checksum y el ChecksumCompliment como si fuese HiROM (con el offset 0xFFC0).

Con este paso ya sabemos si una ROM es HiROM o LoROM y por lo tanto el offset donde localizar la cabecera interna.

Extraer información de la cabecera de una ROM SNES.

Ahora que ya tenemos localizada la cabecera, tenemos que ir procesando la información para extraer los datos de forma legible.

Es bastante la información que podemos extraer de la cabecera interna de una ROM de SNES. A continuación iremos viendo cada sección con detalle, pero empezaremos enumerando las diferentes secciones de información que podemos extraer:

  • Nombre del cartucho.
  • ROM Makeup Byte (también llamado ROM Layout).
  • Tipo de ROM (también llamado ROM Type).
  • Tamaño de ROM (también llamado ROM Size).
  • Tamaño de SRAM (también llamado SRAM Size).
  • Código de país (también llamado Country Code).
  • License Code.
  • Versión del cartucho (también llamado Version Number).

Nombre del cartucho.

El nombre del cartucho nos muestra el nombre del videojuego o a veces una abreviatura porque está limitado a 21 bytes (21 caracteres). El nombre suele estar en mayúsculas aunque no es algo obligatorio. Se podría decir que es el nombre interno de la ROM.

ROM Makeup Byte (también llamado ROM Layout).

Es un byte que nos muestra información muy interesante a cerca de la ROM. Partiendo de que un byte son 8 bits, estos 8 bits podríamos decir que siguen el patrón 001A0BCD, donde:

  • Si D=0 es LoROM y si D =1 es HiROM.
  • Si C=1 es ExLoROM.
  • Si B=1 es ExHiROM.
  • Si A=1 es FastROM y si A=0 se podría decir que es SlowROM aunque el nombre de SlowROM no se usa.

Tipo de ROM (también llamado ROM Type).

Es un byte que nos determina si la ROM usa RAM, SRAM o Enhancement Chips. Tenemos que evaluar este byte en formato hexadecimal y según su valor, sabemos qué tipo de ROM es en cuanto al uso de RAM, SRAM o chip.

Para los casos en los que no se usa ningún Enhancement Chip podemos tener los siguientes valores hexadecimales:

  • 0x00: Sólo ROM
  • 0x01: ROM + RAM
  • 0x02: ROM + RAM + SRAM

Para los casos en los que la ROM dispone de un Enhancement Chip, debemos fijarnos en ambos caracteres del valor hexadecimal. El primer carácter nos indica el tipo de Enhancement Chip que usa el cartucho de Super Nintendo, siendo las diferentes posibilidades las siguientes:

  • 0x0*: DSP
  • 0x1*: SuperFX
  • 0x2*: OBC1
  • 0x3*: SA-1
  • 0x4*: S-DD1
  • 0xE*: Otros
  • 0xF*: Chip personalizado

El segundo carácter nos indica si usar ROM, RAM o SRAM. Las posibilidades en este caso son:

  • 0x*0: ROM
  • 0x*1: ROM + RAM
  • 0x*2: ROM + RAM + SRAM
  • 0x*3: ROM + Enhancement Chip
  • 0x*4: ROM + Enhancement Chip + RAM
  • 0x*5: ROM + Enhancement Chip + RAM + SRAM
  • 0x*6: ROM + Enhancement Chip + SRAM

Por ejemplo si el tipo de ROM es 0x14, estaríamos ante: ROM + Enhancement Chip (SuperFX) + RAM.

Otro ejemplo para 0x42, estaríamos ante: ROM + Enhancement Chip (S-DD1) + RAM + SRAM.

Tamaño de ROM (también llamado ROM Size).

El tamaño en bits de la ROM. Es un byte que debemos evaluar en modo hexadecimal y podemos averiguar el tamaño interno de la ROM según los valores:

  • 0x08: 2Mbit
  • 0x09: 4Mbit
  • 0x0A: 8Mbit
  • 0x0B: 16Mbit
  • 0x0C: 32Mbit
  • 0x0D: 48Mbit

Tamaño de SRAM (también llamado SRAM Size).

El tamaño en bits de la SRAM que usa el cartucho. Es un byte que al evaluar su valor hexadecimal obtenemos el tamaño interno de la SRAM:

  • 0x00: El cartucho no usa SRAM
  • 0x01: 16 Kbits
  • 0x02: 32 Kbits
  • 0x03: 64 Kbits
  • 0x04: 128 Kbits
  • 0x05: 256 Kbits

Código de país (también llamado Country Code).

Este byte determina la región donde se comercializará el cartucho. No es un dato muy relevante, pero los códigos de regiones que he encontrado son:

  • 0x00: Japan
  • 0x01: USA
  • 0x02: Europe
  • 0x03: Swenden
  • 0x04: Finland
  • 0x05: Denmark
  • 0x06: France
  • 0x07: Netherlands
  • 0x08: Spain
  • 0x09: Germany
  • 0x10: Italy
  • 0x11: China
  • 0x12: indonesia
  • 0x13: Korea

License Code.

Es un byte que nos dice el nombre de la compañía dueña de la licencia del videojuego. Estos códigos de licencia no son relevantes y puede que algunos hasta sean incorrectos ya que la información al respecto es escasa.

Este byte se evalúa en formato hexadecimal y a modo de ejemplo, el valor 0x01 se corresponde con la compañía Nintendo.

Versión del cartucho (también llamado Version Number).

Es un byte que nos muestra el número de versión interna del cartucho. Este dato carece de total importancia ya que la mayoría de las ocasiones no se emplea.

Aplicación SNES ROM HEADER ANALYSIS.

Es una pequeña aplicación para poner en práctica todo lo aprendido. Está totalmente programada con fines didácticos y no tiene mayor utilidad que representar los datos contenidos en las cabeceras internas de las ROMS de SNES de una forma legible.

Está programado en C# con el .Net Framework 4 (es necesario tener instalado este Framework en vuestro sistema operativo Windows para que funcione el programa). La aplicación la podéis descargar desde este enlace.

Consideraciones finales.

Este documento ha sido redactado con el propósito de acercar a los usuarios nóveles la programación relacionada con la videoconsola Super Nintendo (SNES). La mayoría de la información ha sido recopilada de diferentes fuentes y puesta en práctica con la programación de la aplicación. Espero que sea de ayuda a todos los fans de la Super Nintendo.