awakening

Todos nosotros conocemos la saga de Zelda que Nintendo sacó para GameBoy. El primer capítulo fue una revolución, tanto en gráficos como en sonido, historia, complejidad, tiempo de juego… Con una rom de 512 kB habían conseguido un juego que perduraría en las memorias de todos sus jugadores. Si recordáis, se sacó una version del “Zelda: Link´s awakenning” para gameboy color, que incluía mejoras gráficas y una nueva mazmorra, pero se les escapó un pequeño detalle: El código fuente.

Como se puede leer en el blog pagetable, hay zonas de la rom en las que aparecen trozos de código fuente, tanto en “C” como en ensamblador, e incluso una lista de los ficheros que compondrían el proyecto. Por lo visto, se debió a un fallo a la hora de crear la rom. El juego final, pesaría algo más de 1 Mb, pero para crear la ROM sería necesario un chip de 2Mb. ¿Cómo se solucionaría el problema? Simplemente llenando el espacio sobrante con basura. Posiblemente usaran la función malloc() para reservar la memoria, y en los sistemas operativos de la época (posiblemente usaran MSDos, el juego era de 1998, y windows 98 seguía corriendo sobre MSDOS), esta función no era muy segura. Aunque actualmente al llamar a esa función nos devuelve un bloque de memoria en blanco (bueno, eso depende del compilador y del sistema operativo), en aquella época se podía acceder a datos “sucios” en memoria que pertenecían a ejecuciones anteriores de otras aplicaciones.

Como resultado, en la rom “Legend of Zelda, Link’s awakenning DX” se pueden encontrar grandes trozos de código fuente del editor de Borland Turbo C y de trazas del editor “QBasic” de MSDos. No se sabe que IDE usaron, aunque es bastante probable que en algún momento usaran el “Turbo C”, dado que se encontró estre trozo completo de código fuente:

#include
#include
   int main(void) {
   FILE *fp,*f1;
   int a=0xcd;
   int b=0xc6;
   int c=0×29;
   int ch;
   unsigned long i=0;
   if((fp=fopen(”zeldag.gb”,”rb”))==NULL) {
      printf(”can’t open the file”); return 0; 
   }
   if((f1=fopen(”ttmp.asm”,”wt”))==NULL) {
      printf(”can’t new file ttmp.asm”); return 0; 
   }
   while((ch=fgetc(fp))!=EOF) {
     if(a==ch) {
        i++;
        ch=fgetc(fp);
        if(b==ch) {
           i++;
           ch=fgetc(fp);
           if(c==ch)
              fprintf(f1,”%lXH, ” , i);
        }
    }
    i++;
  }
  fclose(fp);
  fclose(f1);

Este trozo de código intentaría escribir la instrución “CALL 0×29C6″ en la rom, aunque no está muy claro para qué se haría así. También apareció una lista con los nombres de ficheros del proyecto, que estaría en el directorio D:\GAMEBOY (qué originales) :
BANK37.ASM, CLEARKU.ASM, DAMA1.ASM, DAMA2.ASM, END.CPP, ENDEND.ASM, ENDEND.LST, ENDEND1.ASM, FEND1.ASM, FEND2.ASM, FEND3.ASM, FIND.ASM, FIND.CPP, IFCHAENL.ASM, INTWCHA.ASM,TEST.ASM,TTMP.ASM,TTMP.TXT,ZIPUTP.CPP

Y algunos ficheros extra que aparecen nombrados en la rom:

ADDPLAG.ASM, ADDPLAGF.ASM, CH64TBL.ASM, FEND.ASM, G.ASM, H.ASM, INSERTKU.ASM, INTWIN.ASM, KKKKKK.ASM, L.ASM, NOPLAY1.ASM, TAB.ASM, Y.ASM, ZXHPDM.ASM

Y por fin, código fuente en ensamblador del propio juego (no hay mucho, pero algo hay):

JoyPort_1:
                 AND $02 ;LEFT
                 JR  NZ, JoyPort_2
                 CALL LEFTScroll
                 RET
JoyPort_2:
                 AND $04 ;UP
                 JR  NZ, JoyPort_3
                 CALL UPScroll
                 RET
JoyPort_3:
                 AND $08 ;DOWN
                 JR  NZ, JoyPort_4
                 CALL DOWNScroll

También se encontró trozos de ensamblador ofuscado, lo que daría a entender que no usaron el código fuente original para hacer el remake, sino que lo desensamblaron desde la rom original, y se dedicaron a modificarla.

Fuentes: Pagetable

Por Marcos

5 comentarios en «Código fuente en algunas roms de «Zelda: Link´s awakening DX»»
  1. Mi hipótesis es que esta cagada no fue por usar malloc, sino por crear un fichero dummy del siguiente modo:
    1.- Crear el fichero con permiso de escritura usando fopen().
    2.- Hacer un fseek() hasta la posición final y escribir un caracter cualquiera (p.e. un 0).
    3.- Cerrar el fichero.

    Yo hace tiempo escribí un programa que creaba dummys de cualquier tamaño a toda pastilla con este método. Lo probé en Windows (no recuerdo la versión, sería un 98 o un XP) y en Linux con los siguientes resultados:
    1.- Windows: Pasa exactamente lo que se comenta con esta ROM: el fichero contiene toda clase de basura perteneciente a sectores del disco que no estaban reclamados pero contenían información de ficheros borrados/modificados.
    2.- Linux: El fichero se crea igual, pero como los sistemas de ficheros usados en Linux soportan «agujeros», al leer el fichero, en lugar de basura se lee totalmente como ceros. Además como sólo se reserva el espacio ocupado por los inodos, ficheros enormes ocupan un espacio real muy pequeño. Por ejemplo un fichero de varios terabytes creado por este método, se puede leer por entero (obteniéndose ceros) y ocupará únicamente unos 12 KiB en disco

    Conclusión: Niños, no uséis Windows que es una patata y nunca se sabe dónde pueden acabar datos privados como estos.

    1. Muy curioso, no se me había ocurrido eso. ¿Has probado lo mismo pero con el driver de ext3 para windows, o ntfs en linux? Me molaría saber si es una característica propia del sistema de ficheros, desde linux se accede a ntfs o fat y estas cosas de seguridad afectan a ambos. Si lo probaste con fat entonces no me extraña para nada, pero creo recordar que las últimas versiones de ntfs hacían algo similar a los inodos de linux.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *