Historial de reemplazo de un solo byte
Cartoon Cartoon Summer Resort
Era el verano de 2000. Cumplí seis años, acabo de terminar el primer grado y comenzaron las vacaciones. Esto significaba que podía jugar durante mucho tiempo en la calle, ver dibujos animados y encender la computadora de mi padre con Windows 98 para buscar juegos en una tierra completamente nueva e inexplorada llamada Internet. Uno de mis favoritos fue el sitio web de Cartoon Network. En él encontré muchos juegos flash fascinantes basados en dibujos animados de televisión. Ese verano lanzaron una serie de juegos llamados Cartoon Cartoon Summer Resort.
Jugabilidad del primer episodio de Cartoon Cartoon Summer ResortEste juego fue un RPG / aventura bidimensional con una vista superior desde el costado, que consta de cuatro episodios. El jugador controlaba un personaje de dibujos animados de vacaciones en el resort con otros personajes de dibujos animados. En cada episodio, apareció un problema en el complejo que debía resolverse. El jugador tenía que resolverlo interactuando con los personajes y encontrando objetos o intercambiándolos.
Regresando 18 años
Durante uno de los recientes ataques de nostalgia, recordé este juego y me di cuenta de que lo volvería a jugar. Tenía casi dos décadas de edad, por lo que era difícil encontrar un vínculo de trabajo.
Además, ningún navegador moderno lanzaría el antiguo y vulnerable reproductor Shockwave ... excepto Internet Explorer. Probablemente fui la primera persona en encontrar una razón legítima para usar Internet Explorer en 2018.
Después de jugar un poco, noté momentos que no podían ser ignorados. Por ejemplo, música de fondo monótona que se reproduce en un bucle sin fin y un reconocimiento deficiente de las colisiones.
El mismo error
Después de un tiempo, encontré un error en el juego:
Al moverse por áreas donde no debería pasar nada, a veces aparece un cuadro de diálogo.Como se puede ver en la animación, en el juego puedes alquilar un bote para moverte por el agua. Cuando intenta alquilar otro barco, aparece el mensaje "¡Hoy no hay más barcos alquilados!". Si navegas hacia el norte y caminas por el borde derecho de la isla, pero se abre el mismo texto que debería aparecer en el muelle del barco.
En esta etapa, cualquier persona sensata que respete su tiempo y energía consideraría el error como una molestia menor, recordándose a sí mismo que era un juego web mediocre para niños, creado hace dos décadas, y que continuaría jugando. Pero yo no.
Ya poseyendo todo mi conocimiento de programación y mirando el juego, percibí este error como extrañamente atractivo. Me pareció que había desenterrado una tumba antigua y encontré en ella un rompecabezas intacto que podría haber desaparecido y que nunca fue resuelto por nadie. Para mí, este error fue una oportunidad para aprender y descubrir algo nuevo. Curiosamente, fueron precisamente estas oportunidades las que me dio el
proceso del juego en la infancia. Hay algo casi poético en cómo algo puede, sin darse cuenta, plantear nuevos desafíos si lo miras desde un ángulo diferente.
Juego de deconstruccion
Para solucionar el error, necesitaba comprender el funcionamiento interno del juego. Después de examinar el problema, descubrí que el juego fue creado en Shockwave en la aplicación
Director . Cuando se trabaja con Director, los proyectos se guardan como un
.dir
(Director). Este archivo es similar al archivo PSD para Photoshop. Al igual que un archivo PSD contiene información no destructiva sobre capas y texto, un proyecto
.dir
guarda todos los recursos, el código fuente sin
.dir
y otra información que ayuda en el proceso de desarrollo. Director utilizó el lenguaje de secuencias de comandos patentado
Lingo para animar escenas.
Si el juego se
.dir
en un archivo
.dir
, podría abrirlo en Director y aprender fácilmente cómo funciona el juego. Sin embargo, el juego se publica como un archivo
.dcr
. El archivo
.dcr
es una versión compilada del proyecto Director. Es decir, todo el código fuente se compila en bytecode que se ejecuta en la plataforma Shockwave. Este proceso es similar a cómo se simplifica un archivo PSD y se convierte en una imagen PNG. La imagen PNG (en nuestro caso, el archivo DCR) es de menor tamaño, pero no contiene información sobre capas y ediciones, y está destinada solo a la distribución.
Esto significaba que estaba sosteniendo un objeto binario de 500 KB sin documentación de su estructura. Incluso si descubrí cómo encontrar bytecode de bajo nivel, parece que nadie ha realizado ingeniería inversa del bytecode de Lingo y documentado el principio de la plataforma Shockwave. Toda esta información es de propiedad exclusiva, es propiedad de Adobe, que no tiene ningún motivo para publicarla. Las posibilidades de entender el juego parecían bastante sombrías.
Descompresión
Sintiéndome derrotado porque lo más probable es que no pudiera eliminar este error, decidí averiguar si los recursos se podrían extraer de alguna manera del juego. Pensé que probablemente encontraría una sección de datos comprimidos o algo similar. Después de buscar, encontré un par de programas llamados
offzip y packzip . Estas herramientas pueden buscar datos zlib en archivos binarios arbitrarios, mostrar desplazamientos y extraerlos en archivos separados.
Me salí de la cremallera con un archivo DCR y para mi sorpresa, ¡realmente encontró los archivos! 249 piezas, para ser más precisos.
$ ./offzip.exe -a 1.dcr
- open input file: 1.dcr
- zip data to check: 32 bytes
- zip windowBits: 15
- seek offset: 0x00000000 (0)
+------------+-----+----------------------------+----------------------+
| hex_offset | ... | zip -> unzip size / offset | spaces before | info |
+------------+-----+----------------------------+----------------------+
0x00000026 . 164 -> 214 / 0x000000ca _ 38 8:7:26:0:1:7b6349f6
0x000000d3 .. 3932 -> 9169 / 0x0000102f _ 9 8:7:26:0:1:c1079d84
...
0x00080490 . 265 -> 472 / 0x00080599 _ 0 8:7:26:0:1:04d6b43f
0x00080599 . 209 -> 366 / 0x0008066a _ 0 8:7:26:0:1:7da3ba08
- 249 valid compressed streams found
- 0x0004040d -> 0x001565c8 bytes covering the 50% of the file
Extraje todos estos archivos en una carpeta y comencé a estudiar los resultados. Había 206 archivos
.dat
, 38 archivos
.fff
, 4
.atn
y un solo archivo
.ini
.
Descubrimientos
Comencé con el archivo INI, pero fue inútil. Era una simple tabla de conversión de fuentes del Directorio 7.0 entre Windows y Mac. Luego pasé a los archivos DAT. La mayoría de ellos eran 1 KB, así que comencé con un enorme 144 KB. Lo abrí en un editor hexadecimal y estudié. Principalmente eran datos ilegibles. Sin embargo, con el tiempo, encontré algunas palabras en ellos que parecían ser identificadores de Lingo.
El análisis de los grandes archivos DAT me dio algunas pistas, mantuvieron algunos mensajes interesantes. Descubrí que Photoshop 3.0 probablemente se usaba para gráficos. También aprendí que el juego tenía una herramienta de edición de mapas interna llamada
Map-O-Matic v1
. Me gustaría ver cómo se veía y cómo se creó.
También encontré el nombre de la compañía que desarrolla el juego:
Funny Garbage . El nombre del desarrollador principal también estaba en el archivo, pero no lo nombraré. Fue genial descubrir al autor del juego, que tercamente intenté arreglar después de casi 20 años, y finalmente ver la cara de la persona que se convirtió en la causa probable de esta agonía. Todas estas migajas de información fueron, por supuesto, interesantes, pero no ayudaron mucho.
Avance
Luego comencé a estudiar archivos
.fff
en un editor hexadecimal. Para mi gran sorpresa, todos los datos en estos archivos eran legibles y parecían datos de mapas:
Extraje manualmente algunos de estos datos y los limpié en un editor de texto. Lo que hice fue muy parecido a una matriz JSON:
[
#member: "block.104",
#type: #FLOR,
#location: [16, 9],
#width: 64,
#WSHIFT: 0,
#height: 32,
#HSHIFT: 0,
#data: [
#item: [
#name: "",
#type: #WALL,
#visi: [
#visiObj: "",
#visiAct: "",
#inviObj: "",
#inviAct: ""
],
#COND: [[#hasObj: "", #hasAct: "", #giveObj: "sunscreen", #giveAct: "gotscreen"], #none, #none, #none]
],
#move: [#U: 0, #d: 0, #L: 0, #R: 0, #COND: 1, #TIMEA: 0, #TIMEB: 0],
#message: [
[#text: "You bought the sun screen.", #plrObj: "", #plrAct: ""],
[#text: "No more sunscreen today!", #plrObj: "", #plrAct: "gotscreen"]
]
]
]
Fue muy importante, porque logré aprender mucho sobre cómo funcionaba el juego.
- El juego espera que los datos de mapa, texto y eventos estén en objetos Lingo similares a JSON
- Cada entrada de
#member
es un mosaico, bloque o personaje que se puede #member
. - Las
#member
coordenadas y tamaños #member
se pueden editar.
Sabiendo que los diálogos del juego se guardaron en estos archivos, escribí una línea corta para exportar solo un diálogo a un archivo:
grep -a -o '#text: "[^"]*' Uncompressed/*.fff | awk '{print $0,"\r"}' > Dialogue.txt
Al usar este archivo, puedo encontrar rápidamente el texto erróneo y ver en qué archivo estaba:
El texto erróneo está en
0004eda0.fff
o en
0004f396.fff
. En nuestro caso, el texto del error apareció en el primer archivo. Sabemos esto porque justo después es un mensaje que recibimos cuando interactuamos con Og, que es un personaje en el mismo mapa que el mosaico con el error.
Corrección de errores
Ahora podría abrir
0004eda0.fff
y encontrar la línea sobre el barco en el editor hexadecimal. Una vez encontrado, pude encontrar el objeto
#member
asociado con él. Luego cambie sus propiedades y guarde el archivo. Luego lo comprimí nuevamente y lo
packzip
archivo fuente del juego DCR usando
packzip
.
$ ./packzip -o 0x0004EDA0 Uncompressed/0004eda0.fff test.dcr
Cuando cambio el tipo de bloque de
block.11
a
block.13
y parcheo el juego, puedo ver claramente el esquema del mosaico de error:
Al cambiar la ID del mosaico, puede ver los límites del área problemáticaLa corrección de errores en sí es ridículamente simple. Todo lo que tenía que hacer era cambiar el identificador
#message
para este
#message
error a
#fessage
:
Ahora, si corregimos los cambios y volvemos a esta área, ¡los mensajes no volverán a aparecer!
Se corrigió un error en el juego, literalmente cambiando 1 byte¿Por qué es posible corregir el error?
Solo puedo suponer que es probable que el motor del juego verifique el mosaico en el que se encuentra cuando el jugador se mueve. Si se cumple alguna condición, muestra el mensaje correspondiente a este mosaico de la matriz
#message
. Después de cambiar
#message
a
#fessage
enlace a la matriz
#message
que busca el código ya no se encuentra. Él lo considera un objeto vacío (¿o indefinido?) Y no muestra nada.
Considere un ejemplo en JS:
function foo(bar) { if (bar["message"] !== undefined) {
Supongamos que no podemos cambiar la función
foo()
, pero necesitamos cambiar el resultado. Tenemos acceso a los datos que se le transmiten. Puede cambiar el nombre de la propiedad del
message
del objeto pasado y la función pensará que no estaba allí.
¿Cómo apareció este error?
Supongo que debido a la pereza. Los desarrolladores utilizaron un editor de mapas para crear esta área. Lo más probable es que copiaron tarjetas antiguas en nuevas áreas y luego las cambiaron. Esto es más fácil que crear todo desde cero. Pero dado que el evento y los datos de texto son mixtos, lo más probable es que pasaron por alto en algunos lugares y olvidaron eliminarlos o reemplazarlos. Esto parece lo más lógico, porque el diálogo erróneo a menudo se tomó de una tarjeta vecina, donde se usó correctamente.
¿Por qué gastar tanto trabajo en algo tan insignificante?
No lo se Tal vez debido a la nostalgia?