Lunes, 10 de noviembre de 2025

¿Quién se acuerda del Krakout? Ese clon horizontal del Breakout que publicó Gremlin Graphics en 1987 para varios ordenadores, incluyendo el MSX. ¿Ahora sí? Bueno, pues a mi me encantaba jugar con él. Recuerdo haberme pasado muchas tardes moviendo el bate arriba y abajo, intentando eliminar todos los ladrillos de la pantalla... de las 100 pantallas que vienen con el juego original.

Esta historia comienza comentando que entre las opciones hay una que permite cargar más niveles de cinta, pero nunca aparecieron cintas con niveles adicionales al estilo del Deeper Dungeons para el Gauntlet. También hay que hacer notar que en otras plataformas como el Commodore 64, hubo gente que hizo modificaciones del juego e incluyó más niveles. Incluso hicieron un editor de niveles llamado Krakout Construction Set cuyo autor animaba a la gente a diseñar niveles y enviárselos, con la intención de sacar versiones del juego con nuevos y desafiantes niveles.


Lamentablemente este editor no es compatible con la estructura de niveles del juego para MSX, porque tienen un tamaño diferente. Eso significa que para MSX no existe un editor de niveles... ¡hasta ahora!

Este fin de semana ha tenido lugar la Reunión de Usuarios del Norte RUN QuesadaSX Fall 2025, a la que asistí. Allí presenté el editor de niveles del Krakout en el que he estado trabajando muy a ratos durante bastante tiempo. Mediante este editor se pueden crear packs de 100 niveles para el juego y grabarlos en un fichero KLP (Krakout LevelPack) que luego puede ser vuelto a cargar para seguir editando. Además, permite parchear un fichero de imagen de cinta tanto de MSX (TSX o CAS) como de Spectrum (TZX o TAP) con los niveles editados.

El editor carga inicialmente los niveles originales del juego, por lo que podemos ver los entresijos de los mismos. Así, el primer nivel se ve como sigue:


Aquí podemos ver que algunos de los ladrillos planos amarillos contienen power-ups. Estos power-ups tienen una probabilidad de aparecer, es decir, no siempre van a salir, pero si aparece, el ladrillo se gira y revela el power-up y si le damos nuevamente, lo conseguiremos (perdiendo el que ya teníamos). Si activamos los tooltips en la paleta de ladrillos disponibles (a la izquierda) podremos saber qué hace cada power-up.

Para editar un nivel, simplemente hay que ir seleccionando los ladrillos que queremos poner e irlos situando en alguna de las casillas del nivel, que tiene un tamaño de 9x9. Es posible desplazar todo el contenido del nivel en las cuatro direcciones o borrarlo. También podemos seleccionar el nivel visible y un nivel secundario para copiar el nivel visible en él o intercambiar ambos, así como grabar o cargar un pack de niveles. Por último, los botones de la derecha nos permiten restaurar los niveles originales o parchear un fichero de cinta de MSX o de Spectrum.

Además, cualquier acción que no pueda ser deshecha fácilmente (como borrar todo un nivel o cargar un fichero KLP) está progegida y deberá ser confirmada.

Gracias a este editor, he podido averiguar unas cuantas curiosidades sobre el juego, ¿me acompañáis en el viaje?

El nivel 34

Cuando el editor ya podía visualizar todos los niveles del juego, me desplacé por todos ellos para comprobar que todo se veía bien y me topé con el nivel 34, el cual se veía así:


Esto significaba que algunos ladrillos que se usaban en el juego no estaban contemplados en mi editor. Sin embargo, al jugar este nivel, todos los ladrillos aparentemente son iguales: un simple rectángulo blanco, sin ningún tipo de bonus especial. ¿Entonces? Pues comprobando, resulta que hay dos sets de ladrillos planos totalmente idénticos. Uno, que es el que se usa normalmente, tiene los identificadores 4A a 50 (en hexadecimal), mientras que el otro tiene los identificadores del 43 al 49 (nuevamente en hexadecimal). El nivel 34 es el único nivel (de los que vienen con el juego) que usa un ladrillo de este set, concretamente el 49.

¿Por qué existen dos sets con un aspecto totalmente idéntico. Bueno, en un principio la respuesta parecía estar en que el set "oculto" (con los identificadores del 43 al 49) se utilizaba para la animación del giro cuando el ladrillo ocultaba un power-up, pero indagando un poco más no es así. Parcheando un poco aquí y allá, es posible diseñar un nuevo set de ladrillos usando dicho set (ya lo he probado con éxito en MSX). Por lo que en una futura versión del editor se podrá incluir en el propio fichero KLP la información gráfica necesaria.

El nivel vacío

Esto, más que una curiosidad del juego en sí, fue un experimento en base a una pregunta de mi hija: "¿qué pasaría si dejamos un nivel vacío sin ningún ladrillo?". ¡Pues está previsto! Si un nivel es vacío, el juego lo detecta y antes de que la bola comience a moverse, el nivel se acaba y pasamos al siguiente. Esto también sucede si, en lugar de ser un nivel totalmente vacío, contiene únicamente ladrillos indestructibles.

Krakout II de Spectrum

Al igual que en Commodore 64, alguien hizo una modificación del juego de Spectrum y sacó una versión llamada Krakout II en 1988. Si miramos el mapa del juego, veremos que hay 100 niveles totalmente diferentes a los que venían con el juego original. Pues bien, es posible extraerlos e incluirlos en un fichero KLP. Como nota curiosa dentro de la curiosidad, la cinta del juego está "encriptada" y los niveles no se ven a simple vista. Al parecer los autores ocultaron el contenido de los niveles (y puede que más) mediante un XOR 64 (en hexadecimal). Además, hay un byte extra entre el nivel 20 y el 21, lo que provocaba que los niveles del 21 en adelante estuvieran desplazados un ladrillo.

Pero todo eso está totalmente arreglado y pude extraer todos los niveles del juego. ¡Ahora podremos disfrutarlos también en MSX!

Set de ladrillos nuevo

Vamos a echar un segundo vistazo al mapa del Krakout II... concretamente al nivel 8.


¡Espera, espera! ¿Qué son esos ladrillos blancos y verdes que parecen una cara mirando hacia la derecha? ¡Esos ladrillos no aparecen en el juego original! Pues no, pero al inspeccionar los niveles con el editor, sucedió exactamente lo mismo que en el nivel 34 del set de niveles originales: ¡había imágenes de ladrillos que no se cargaban! Probé este nivel en el MSX... y resulta que sale exactamente igual a como viene en el mapa. Estos ladrillos (con identificadores del 66 al 6C en hexadecimal) están presentes en el juego, pero ninguno de los niveles originales los usaba. Quienes hicieron la modificación del juego en 1988 se dieron cuenta de ello y los aprovecharon. Ahora también están incluidos en el editor.

Esto me hizo pensar si existían más ladrillos que no se usaban en los niveles... Veamos, los tiles que representan ladrillos van del 0 (vacío) al 115 (el último que se ve en la paleta del editor). ¿Qué sucede si pongo ladrillos más allá del 115 en una pantalla? Pues pasan cosas raras, como que aparecen ladrillos invisibles e indestructibles que no permiten que se termine el nivel. En conclusión, parece que ahora sí tenemos todos los posibles ladrillos del juego.

Krakout 3, 4 y 5

¿Cómo? ¿Que una modificación del juego os sabe a poco? Pues hubo tres más, que podríamos denominar Krakout 3, Krakout 4 y Krakout 5 respectivamente, aunque algunas páginas los nombran a los tres como Krakout 3. Estas tres modificaciones se realizaron en 1993, 1994 y 1996 respectivamente e incluyen niveles totalmente nuevos y algunas de ellas también presentan modificaciones gráficas de los ladrillos. Al igual que con el Krakout II, he extraído los niveles de las cintas de estos tres juegos (dato curioso: en los tres casos los niveles estaban situados exactamente en la misma posición de la cinta y sin ningún tipo de "encriptación").

A continuación os dejo los enlaces de descarga de los niveles extraídos de las cuatro modificaciones del Krakout para Spectrum, junto a sus mapas.


Editor de niveles para ZX Spectrum

También hubo un editor de niveles para ZX Spectrum realizado en 1996 o 1999 (según consultes) por un grupo de usuarios de Rusia. Este programa solo lo he encontrado en formato disco SCL/TRD (formato utilizado por las versiones rusas del Spectrum, como el Scorpion o el Pentagon) y por lo que he podido ver contiene dos sets de 100 niveles, cada uno de ellos totalmente idéntico a los niveles originales, salvo el primero. No merece la pena crear dos ficheros KLP para solo un nivel nuevo en cada uno, así que aquí os dejo los mapas de los dos niveles tal y como aparecen en el editor por si a alguien le apetece editarlos:


Cargador de cinta MSX

Por último, quería comentar mi pelea contra el cargador de cinta en su versión MSX. Aunque inicialmente lo estuve probando sobre TSX, esto también sucede en la versión CAS, por lo que no es debido al formato TSX, sino a algo que está presente en el contenido del juego en sí.

Para parchear las imágenes de cinta de Spectrum con los nuevos niveles solo hay que localizar la posición de los niveles originales y sobreescribir los 8100 bytes que ocupan con los datos de los niveles del editor. ¡Listo! Esto funciona correctamente en un Spectrum sin problema alguno. La primera prueba se realizó cargando un fichero TZX en un Next y este fin de semana, en la RUN, hemos cargado packs modificados en un ESPectrum y en un TK95, que es un clon brasileño del Spectrum. Lo divertido es que el juego se cargaba en el ESPectrum y su salida de audio se conectó al TK95 para cargarlo en los dos ordenadores al mismo tiempo. ¡Y funcionó a la perfección!


Cargando Krakout en el TK95 desde el ESPectrum.

Nivel de prueba en homenaje a la RUN.

Sin embargo, este sencillo proceso no funciona en MSX. Si hay cualquier tipo de modificación en los datos de los niveles, el juego sigue cargando, pero al llegar al final se cuelga irremisiblemente, llenando toda la memoria de basura. ¿Qué estaba sucediendo? Como la modificación se hace sobre el bloque de la cinta que contiene los datos, el problema debe estar ahí... ¡vamos a buscarlo!

La cinta original incluye varios bloques de datos en formato Spectrum, lo primero que se carga es un bloque MSX con un cargador especial que lee bloques de Spectrum, algo muy habitual en las cintas de la época y seguro que recordáis esas cargas con los colorines bailando en el fondo. Cada bloque de datos se encuentra codificado en la cinta como dos bloques estándar de Spectrum: el primero con la cabecera, que contiene la dirección donde hay que cargar el bloque de datos y su longitud (lo que hace un total de 4 bytes), mientras que el segundo bloque es el bloque de datos propiamente dicho. Veamos el código encargado de realizar la carga de un bloque de cabecera y un bloque de datos:

d805: di
d806: ld ix,#d8ed
d80a: ld de,#0004
d80d: ld a,#fe
d80f: scf
d810: call #d837
d813: jr nc,#d805
d815: ld ix,(#d8ed)
d819: ld de,(#d8ef)
d81d: ld a,#ff
d820: call #d837
d823: jr nc,#d805
d825: ld hl,(#d8ed)
d828: call #d836
...
d836: jp (hl)

Todo comienza en #d805: se desactivan las interrupciones y se asigna el valor #d8ed al registro ix, que es donde va a almacenar el contenido de la cabecera, que recordemos contiene la dirección donde cargar el bloque y su longitud. A continuación, se asigna el valor 4 al registro de, que va a ser el encargado de contabilizar cuántos bytes se han de leer (lógico, pues queremos leer una cabecera). Se asigna el valor FE al acumulador, se activa el flag de acarreo y se llama a la rutina situada en #d836 que lee un bloque de cinta y deja el contenido (cuya longitud se especifica en el registro de) en la dirección apuntada por el registro ix.

Cuando vuelve de la rutina de lectura, tenemos en #d8ed la dirección donde se ha de cargar el siguiente bloque de datos y en #d8ef su longitud. Saltándonos, por el momento, la instrucción situada en la dirección #d813, a continuación el código hace algo similar: asigna a ix la dirección donde se ha de cargar el bloque y también asigna la longitud del bloque en el registro de. Asigna el valor FF al acumulador y vuelve a llamar a la rutina que lee un bloque.

Al volver, tenemos el bloque de datos cargado en su sitio y lo suyo sería ejecutarlo, realizando una llamada a la dirección contenida en #d8ed. Esto es lo que hacen, precisamente, las instrucciones a partir de #d825: cargan en hl la dirección a la que saltar y hacen un "call (hl)", sin más que hacer un call a una dirección de memoria (#d836) que contiene la instrucción jp (hl). Después hay un código que solo consume tiempo y vuelve a #d805 para seguir leyendo bloques.

Si hacemos un cambio, por pequeño que sea, en el bloque de datos, esta llamada nunca se produce. El código que se debería ejecutar en este bloque copia parte de lo que se ha cargado en la dirección #0380 de la RAM, pero, al no ejecutarse, no se realiza esta copia. Al terminar de cargar el juego, el último bloque salta, precisamente, a la dirección #0380 de la RAM, pero al no encontrar ahí lo que espera, el MSX se cuelga. La explicación está en las dos instrucciones que nos hemos saltado: jr nc,#d805. Su propósito es detectar si la rutina que lee un bloque indica que algo ha ido mal durante la lectura, en cuyo caso devuelve el flag de acarreo desactivado. Así, en el caso de ejecutarse el salto de la instrucción de la dirección #d813 nos saltamos la lectura del bloque de datos. Si se ejecuta el salto de la instrucción de la dirección #d823, nos saltamos la ejecución del código del bloque.

Así que el cargador realiza algún tipo de comprobación de la integridad de los datos leídos, por lo que tenemos que ver qué hace la rutina de lectura de un bloque. Para explicarlo vamos a analizar como ejemplo el bloque de cabecera correspondiente al bloque de datos que contiene los niveles. El contenido hexadecimal de este bloque, extraído de la imagen TSX de la cinta, es el siguiente: 10 91 00 06 00 FE 00 87 00 26 5F. ¿Qué significa cada byte?

El byte inicial 10 nos indica que es un bloque TZX tipo 10, que es un bloque de velocidad estándar de Spectrum. Según la especificación de este bloque de TZX, los cinco primeros bytes están perfectamente explicados: identificador del bloque, duración del silencio tras el mismo (#0091, o, lo que es lo mismo, 145 milésimas de segundo) y longitud, que nos indica que el contenido de este bloque (que es lo que va a llegar al MSX) contiene 6 bytes. Pero el cargador solo parece estar interesado en cuatro de ellos, concretamente en los cuatro interiores: Entonces, ¿para qué se usan el primero y el último? Un momento... el primero es FE, que es el valor con el que el cargador inicializa el acumulador. ¿Será FF el valor del primer byte de datos del bloque de datos? Vamos a verlo: 10 14 19 02 26 FF ... ¡Sí!

Según lo que vemos, el bloque de datos se trata de (nuevamente) un bloque TZX tipo 10, tras el cual la cinta tiene un silencio de #1914 (6420) milésimas de segundo y tiene una longitud de #2602 bytes. ¡Exactamente dos más de los que se esperan! Los datos que se cargan son, una vez más, los que están entre el primer byte y el último, cuyos valores son FF y EC respectivamente.

Al trazar la ejecución del cargador, vemos que se compara el primer byte con el valor que tenía a al llamar a la rutina de lectura. Esto permite que no se lea, erróneamente, una cabecera como bloque de datos o vicecersa. Es decir: si es una cabecera el primer byte es FE y si es un bloque de datos, el primer byte es FF. Después vemos que tras leer cada byte se hace un XOR de un valor acumulado con el byte leído y se vuelve a guardar en el mismo sitio. ¡Bingo! Este es el método de comprobación: inicializamos el valor con FE para una cabecera y con FF para un bloque y vamos haciendo XOR con todos los bytes leídos hasta que leemos el byte extra y lo comparamos con el resultado de todos los XOR. Si no son iguales, desactivamos el flag de acarreo antes de volver.

Esto se puede comprobar incluso a mano en el caso de una cabecera. Siguiendo con el ejemplo anterior, inicializamos con FE y luego haremos XOR con los bytes 00 87 00 26. Probadlo con una calculadora que son solo cuatro operaciones XOR (menos incluso, porque dos de ellas son XOR 0, que no hacen nada) y veréis que el resultado es 5F, que es, precisamente, el último byte.

En este punto, extraje el contenido del bloque con los datos de los niveles sin el byte inicial y el final y con un sencillo programa comprobé que inicializando con el valor FF y haciendo XOR de todos los bytes, da exactamente EC. ¡Misterio resuelto!

Por lo tanto, la solución pasa por recalcular el byte final del bloque. Gracias a que XOR es su propia inversa, solo hay que obtener el valor de ese byte y hacer XOR con el valor obtenido al hacer XOR de todos los bytes de los niveles originales y el valor obtenido al hacer XOR de todos los bytes de los nuevos niveles. Así pues, cuando parcheamos un TSX o un CAS con los nuevos niveles, se realiza un sencillo cálculo para obtener el nuevo valor correcto y se parchea el último byte del bloque que contiene los datos de los niveles. De esta forma, el cargador comprobará que son correctos y ejecutará el bloque sin problemas, permitiendo que el juego funcione correctamente.





Pues eso es todo, la verdad es que ha sido un trabajo bastante interesante que me ha llevado a descubrir unas cuantas curiosidades sobre el juego y a aprender sobre el formato TSX y cómo funcionaba el cargador de bloques de Spectrum usado en el juego y, presumiblemente, en otros juegos de Gremlin Graphics. Desde aquí quiero agradecer a Fénix por probar el TZX parcheado en su Next, a NatyPC por su labor de preservación con los TSX y a Tonike por sugerirme probar a parchear también una imagen CAS del juego. También dar las gracias especialmente a Tiburoncio por echarme una mano para comprender el debugger del OpenMSX y ayudarme a comenzar el trazado de la ejecución del cargador. Espero que las curiosidades sobre el juego os hayan parecido interesantes y, sobre todo, que le deis caña al editor a ver si aparecen nuevos niveles que todos podamos disfrutar. Si queréis, podéis enviármelos y los iré publicando en la sección de descargas.