Parche de español para la Máquina-Z de Infocom

El programa en SuperBASIC zipfix_bas parchea el intérprete de la Máquina-Z de aventuras de Infocom para el Sinclair QL llamado `zip` (Z-machine Interpreter Program, no confundir con el compresor de ficheros). El parche permite que se muestren correctamente los caracteres acentuados, la ñ y otros signos de puntuación al leer los ficheros de aventuras conversacionales que soporta.
El programa `zip` es un port de ZIP 2.0 de Mark Howell a QDOS realizado por Luke Roberts en noviembre de 1994, que entiende las versiones .z1 a .z5 de estas aventuras.
En esta entrada conocerás los pasos llevados a cabo para su adaptación al idioma español.
Puedes descargar el fichero comprimido original con el programa zip y algunas utilidades desde la página de Dilwyn Jones.
El problema
El intérprete para QL no reconoce los caracteres y símbolos propios del idioma español, ya que sólo usa caracteres del inglés, por ello, las aventuras creadas en nuestro idioma muestran esos caracteres con símbolos extraños o con una interrogación. Lamentablemente, el código fuente del programa no está disponible, y se distribuye compilado.
Al usarlo con aventuras en castellano aparecían tres problemas:
- La ñ salía como `+` y las vocales acentuadas, la `¡` y la `¿` como `?`.
- Los mensajes del propio intérprete estaban en inglés (`Game file not found`, `[MORE]`…).
- Aunque el teclado del QL permitía escribir acentos, el juego no entendía palabras como «pirámide» o «peldaño».
Para poder obtener un resultado correcto en pantalla es necesario modificar el programa, y para ello, existen varias vías. Descastada la posibilidad de contactar con el autor, tras consultarlo en la comunidad de QL, el programa se podría desensamblar, no obstante se optó por encontrar alguna solución intermedia mediante el uso de la IA.
El problema a salvar comprende tres pasos: mostrar los mensajes del programa en castellano, mostrar los caracteres especiales correctamente y entender los caracteres especiales que se introducen por el teclado durante la ejecución del juego.
La solución: zipfix_bas
El programa zipfix_bas toma el ejecutable del intérprete, lo copia, y lleva a cabo las modificaciones necesarias sobre esta copia, realizando algunas comprobaciones. Ha sido creado con la ayuda de la IA Claude de Antrophic en su versión gratuita.
Para su elaboración, a la IA se le ha facilitado:
- El fichero aventuras.zip disponible aquí, que es un compendio de aventuras .z5 en español (aventura, faro, libro, luna, navidad, olvido) que contiene también un menú de arranque, el interprete original renombrado a zip_exe e información sobre los seis juegos que incluye.
- La tabla de conversión chr.csv que fue generada mediante la utilidad Tabla de caracteres del QL creada por Juanjo Ruiz. Esta tabla ayuda a la IA a buscar las equivalencias del juego de caracteres del QL con la tabla ZSCII de la Máquina-Z que usan los juegos.
La IA ha realizado numerosas pruebas y versiones previas, incluyendo la aventura chrtest_z5 que se incluye en este repositorio, y que espera que se introduzcan caracteres especiales y entonces devuelve su código equivalente en la tabla de caracteres ZSCII para comprobar que la conversión de los caracteres del QL es correcta. Ver el fichero ZSCII.md.
Qué hace el programa
| Parte | Resultado |
| Salida | Los acentos la ñ y los caracteres especiales se ven bien en pantalla. |
| Entrada | Lo que se teclea llega al juego con los códigos correctos, y las mayúsculas con acento pasan a minúscula. |
| Mensajes | 30 mensajes del intérprete en castellano, más el cambio de la tecla S en el aviso de confirmación. |
| Ejecutable | El tamaño no cambia, y el programa verifica cada paso antes de escribir. |
Qué no hace el programa
- Á, Í, Ó y Ú mayúsculas salen sin acento, porque el juego de caracteres del QL no tiene esas letras.
- Las teclas sueltas (los «pulsa una tecla») no se convierten. No hace falta.
Sobre el ejecutable
La cabecera. Un ejecutable de QDOS lleva 64 bytes de cabecera. Si se descomprime fuera del QL se pierde (el zip la guarda en un campo extra). Por eso el programa trabaja sobre una copia hecha en el QL, conservando la cabecera, y todas las posiciones se cuentan desde el inicio del fichero, sin cabecera.
La reubicación. El ejecutable está compilado con C68 y usa direcciones absolutas. Al final del fichero hay una tabla con unas 1.800 posiciones que el arranque corrige al cargar el programa. Eso impone tres reglas:
- El tamaño no puede cambiar.
- El código nuevo debe usar direcciones relativas al contador de programa.
- Si se elimina una instrucción con dirección absoluta, su entrada de la tabla seguiría aplicándose y corrompería los bytes que se pongan en su lugar. Hay que conservarla o dejarla sobre bytes que no se usen.
Problemas que hubo que salvar durante el desarrollo
Alterar el tamaño del fichero: Modificaba la longitud añadiendo código al final, y esto rompía el bloque que el auto-reubicador de C68 copiaba a la RAM, ignorando el añadido.
Ignorar las referencias absolutas: Al tocar código que dependía de la tabla de reubicación de C68, cualquier cambio sin respetar las direcciones o dejar intactas las instrucciones desplazadas corrompía la ejecución.
Averiguaciones
Cómo codifican los acentos las aventuras
Decodificamos los textos de las aventuras. Usan la tabla por defecto del Z-machine: los códigos ZSCII 155 a 223 representan 69 caracteres acentuados. Por ejemplo: á = 169, é = 170, í = 171, ó = 172, ú = 173, ñ = 206, ¡ = 222, ¿ = 223.
La rutina de salida del intérprete (en la posición $5234) solo sabía hacer tres cosas con esos códigos: escribir `ae`, `oe`, `ue`… para unos pocos; dibujar símbolos de caja (`| # – = +`) para los códigos 179 a 219; y escribir `?` para el resto. Por eso la ñ (206) salía como `+`.
Cómo llega lo que se teclea
La línea la lee el propio QL, que se encarga del teclado y del eco. El buffer del juego recibe los códigos del QL (ñ = 137), pero el diccionario del juego guarda esa letra como 206. El codificador de palabras del intérprete no traduce nada, así que esas palabras nunca coincidían.
Había además un problema añadido: antes de analizar la línea, ZIP pone en minúsculas lo tecleado con `tolower`, que usa un código con signo como índice de una tabla. Los códigos ≥ 128 salen negativos y leen fuera de la tabla, de modo que algunos se alteran: ñ se convierte en Ñ, ú en `»`, É en 195, ¡ en 211.
En cada juego hay entre 2 y 6 palabras que solo existen con acento (`pirámide`, `peldaño`, `muñeco`, `señora`, `acompaña`…). Sin conversión de entrada, un jugador que las escribiera bien no sería entendido.
Los mensajes
Los mensajes están como cadenas dentro del código, apuntadas desde la tabla de reubicación. Localizando esas referencias encontramos 30 cadenas traducibles. Los mensajes se escriben directamente en la consola, así que los acentos van con el código del QL (por ejemplo, 150 para ó), sin pasar por la tabla ZSCII.
Hay un detalle: el aviso `Proceed? (Y/N)` compara la tecla pulsada con `Y`. Al traducirlo a «(S/N)» hay que cambiar también esa comparación.
Cómo funcionan los parches
1. Salida: una tabla de 69 bytes
Sustituimos la lógica de rangos por una tabla: la entrada i contiene el código del QL del ZSCII 155+i. Las letras que el QL no tiene (Á, Í, Ó, Ú…) se escriben sin acento.
move.w d3,d0 ; d0 = código ZSCIIsubi.w #155,d0 ; índice en la tablacmpi.w #68,d0bhi.w imprimir ; fuera de 155..223: se queda como está ('?')lea TABLA,a0move.b 0(a0,d0.w),(a2) ; carácter del QL al buffer de impresión
La instrucción lea conserva la reubicación que ya había en esa posición, y solo cambia la dirección a la que apunta.
2. Entrada: la misma tabla, al revés
En el bucle que pone en minúsculas lo tecleado colocamos un gancho de 4 bytes que salta a 48 bytes de código nuevo. Para liberar ese espacio reorganizamos el parche de salida. El código nuevo, resumido:
move.b 0(a4,a3.l),d0 ; carácter tecleadotst.b d0bpl.w original ; ASCII: sigue el camino original (tolower)cmpi.b #$ac,d0bcc.s buscabclr #5,d0 ; mayúscula del QL (160-171) -> minúsculabusca:lea TABLA(pc),a0 ; relativo al pc: sin reubicación nuevamoveq #68,d1bucle:cmp.b 0(a0,d1.w),d0 ; busca el código QL en la tabladbeq d1,buclebne.s fin ; no está: se deja como estáaddi.w #155,d1 ; índice + 155 = ZSCIImove.b d1,0(a4,a3.l) ; el juego recibe ZSCIIfin: bra.w siguiente
Los caracteres ASCII siguen igual que antes. Los demás no pasan por `tolower`, con lo que se acaba el problema de los códigos alterados.
3. Mensajes: una tabla de datos
Cada mensaje es una línea DATA en el programa zipfix_bas con la posición, el texto original, la longitud y la traducción, que debe medir exactamente lo mismo:
DATA 3244,"Game file not found",19,"Juego no encontrado"DATA 19500,"[MORE]",6,"[M"&CHR$(140)&"s] "
El programa escribe solo en esas posiciones, sin recorrer el fichero. El mismo mecanismo cambia el byte de la tecla `Y` por `S`.
4. El programa SuperBASIC
- Comprueba que el origen es un ejecutable (tipo 1).
- Copia el fichero conservando la cabecera.
- Comprueba que la copia mantiene tipo, dataspace y longitud.
- Comprueba 6 puntos del fichero para confirmar que es la versión esperada.
- Escribe el parche de salida con `BPUT`.
- Relee lo escrito y lo compara.
- Aplica el parche de entrada (opcional).
- Traduce los mensajes (opcional): primero valida longitudes y textos originales de todos, y solo entonces escribe.
Los pasos 7 y 8 se desactivan poniendo `REMark` al principio de su línea.
Límites y adaptación
- Los parches valen para esta versión de `zip_exe` (49.322 bytes). El programa lo comprueba antes de escribir.
- Á, Í, Ó y Ú mayúsculas salen sin acento, porque el QL no tiene esas letras.
- Para otro idioma bastaría con cambiar la tabla de 69 bytes y los textos.
¿Por qué este parche?
Un parche de pocas decenas de bytes de código, una tabla y unas líneas de `DATA` bastan para que un intérprete de 1990 hable castellano. Lo más laborioso no fue escribirlo, sino averiguar qué hacía el ejecutable y comprobar cada paso.
En 2008 realicé una recopilación de aventuras z5. Cuando estaba todo listo, menú, selección, nos percatamos de que el intérprete no mostraba bien los acentos. Era complicado esensamblar el programa, entender cómo funcionaba y recompilarlo. Aquello me dejó una espinita que hoy me he sacado gracias a la IA con este parche y la redistribución de esa recopilación, ahora sí, con el intérprete zip correcto.
Espero que la información relativa a este parche pueda ser usada también por otros usuarios de distintos países cuyos idiomas no están soportados por este intérprete para Sinclair QL.
Descargas
- Imagen de disquete para QL con el programa ejecutable ya parcheado: aventuras_es.img
- Fichero comprimido para QL con el programa ejecutable ya parcheado: aventuras_es_zip
- Fichero SuperBASIC usado para aplicar el parche: zipfix_bas
- Repositorio del parche


























































































