Gaudí: El Viento de Barcelona — crónica técnica de una localización imposible
Cómo se rescató, se desmontó pieza a pieza y se tradujo al castellano, catalán e inglés una aventura gráfica japonesa de 1989 que hablaba de Barcelona… y que Barcelona nunca pudo jugar.
Romhack e ingeniería inversa: Pedro Pablo Fernández Moya «ArcanBytes» · Licencia y Traducción: Shinyuden
English version available: Read the technical article in English here
Un juego japonés sobre Barcelona que Barcelona nunca pudo jugar
En 1989, el estudio japonés Wolf Team —que años más tarde daría origen a la saga Tales of— publicó una aventura gráfica insólita: Gaudí: Barcelona no Kaze (Gaudí: El Viento de Barcelona). El juego trasladaba al jugador al julio de 1992 de una Barcelona en plena efervescencia preolímpica, en la piel de Henry Howard, un exdetective de Scotland Yard reconvertido en investigador privado que destapa una trama de terrorismo internacional entre las calles del Barrio Gótico, la Sagrada Família y el Park Güell, recreados en detallado pixel art.
Era un juego adelantado a su tiempo: incorporaba un cursor contextual sobre la escena (el sistema OPS, Object Pointing System) y un mecanismo de «rebobinado» de la historia (HRS, History Repeat System) que permitía deshacer decisiones. Se publicó para MSX2, NEC PC-8801, PC-9801 y Sharp X68000, exclusivamente en japonés y exclusivamente en Japón. Nunca salió de allí. Durante más de 35 años, el homenaje en forma de videojuego más elaborado que se le ha hecho a la ciudad de Barcelona fue ilegible para cualquiera que no dominara el japonés.
Este proyecto ha cambiado eso: hoy el juego puede jugarse en castellano, en catalán y en inglés, sobre la versión técnicamente más potente de todas, la de Sharp X68000 (tres disquetes de 5,25″ de alta densidad), y llega a Occidente de la mano de la editorial Shinyuden. Es, además, con toda probabilidad, uno de los primeros juegos japoneses de ordenador de los 80 traducidos oficialmente al catalán.
Lo que sigue es la crónica de todo lo que hubo que tocar para conseguirlo. Porque —spoiler— no bastaba con «cambiar el texto».

Por qué no bastaba con «cambiar el texto»
Un juego de 1989 no separa «programa» y «texto» como lo haría un juego moderno con sus limpios archivos de localización. En Gaudí, el texto vive incrustado dentro del código de las escenas, entrelazado con instrucciones que controlan pausas, saltos de línea, cambios de imagen, ramificaciones de la historia y hasta la carga de los fondos. Mover un solo byte de sitio puede colgar el juego.
A eso se suman tres obstáculos de fondo:
- El motor solo sabe dibujar japonés. Cada carácter japonés ocupa una celda de 16×16 píxeles («ancho completo» o full-width). El motor no contempla letras latinas estrechas: si escribes «Barcelona» tal cual, cada letra ocupa el hueco de un kanji entero y en pantalla caben poquísimas palabras por línea.
- No hay espacio. Tres disquetes de 1,2 MB llenos hasta los topes. El texto traducido tiene que caber donde cabía el japonés, y los ficheros no pueden crecer alegremente porque el sistema de archivos del disquete tiene sus cadenas de clusters ya asignadas.
- Hay tres idiomas. Todo lo anterior, por triplicado, y con caracteres que el juego jamás soñó con dibujar:
á é í ó ú ñ ¿ ¡para el castellano, yà è ò ï ü ç ·(¡incluido el punt volat de «col·legi»!) para el catalán.
La filosofía del proyecto se puede resumir en una frase: si una línea no se ha traducido, el juego debe generar exactamente los mismos bytes que el original de 1989. Cada modificación es quirúrgica, reversible y verificable. Esa obsesión, como veremos, acabó salvando el proyecto varias veces.
La anatomía del paciente
Antes de operar hubo que entender qué había dentro de esos tres disquetes:
- GAU1.X — el ejecutable principal: el «cerebro» que interpreta los guiones, dibuja el texto y gestiona menús, guardado y cambio de disco. Está escrito en ensamblador del Motorola 68000.
- GS001–GS0xx (.DAT y .OPS) — 62 guiones de escena, con unos 1.660 bloques de texto únicos entre diálogos y narración. El
.DATcontiene la escena; el.OPSacompaña con las cadenas del sistema de cursor. - TABLE.DAT — el índice que conecta los saltos entre escenas.
- DEMO.TXT y ENDING.TXT (disco 2) — la intro y el final del juego. Y aquí llega una de las sorpresas del proyecto: no son datos, son código fuente que el juego interpreta en vivo, con comandos como
GLOAD,SCROLLoMOJI. Volveremos a ellos. - SAVEDATA — el archivo de partidas guardadas, cuyo formato interno resultó ser mucho más interesante de lo esperado.

Texto que también es programa: los opcodes
Si abrimos un guion de escena, el texto japonés aparece salpicado de secuencias de control — los opcodes — que son como las acotaciones de una obra de teatro, pero ejecutables:
j— salto de línea.vj— dibuja el triangulito ▼, espera el clic del jugador y avanza. El «pasa página» clásico.js— doble salto: deja un margen entre párrafos.j@5— pausa cronometrada (el texto «respira» cinco tics antes de continuar).q=— un if en toda regla: comprueba una bandera de la historia y, según su valor, muestra un bloque de texto u otro. Es el mecanismo de las ramificaciones.z— salta a otra escena.i@,g@— cargan una imagen en pantalla (un retrato, un objeto).(— sí, un simple paréntesis: es el opcode que pinta el fondo de la escena.
Parte de esta semántica no estaba documentada en ningún sitio: hubo que desensamblar el intérprete de GAU1.X para confirmar, por ejemplo, que j y s producen exactamente un salto de línea, que js produce el margen de párrafo, o que vjs combina el ▼ con ese margen. Sin ese conocimiento, es imposible que el texto traducido conserve el ritmo del original: dónde respira, dónde espera, dónde pasa página.
Y esta es la trampa mortal del proyecto: el traductor no puede limitarse a escribir bonito. Si al traducir se pierde un q=, la escena deja de ramificar. Si se pierde un (, la escena se queda sin fondo (y a veces, sin fondo que pintar, el juego se queda esperando para siempre: un softlock). Si un vj cambia de sitio, el jugador hace clic donde no toca y el diálogo se desincroniza.
Los punteros de la cabecera: un mes de lápiz y papel
El primer gran muro del proyecto no fue la fuente: fue un mecanismo cuya existencia ni siquiera se sospechaba. Las primeras reinserciones de prueba funcionaban… hasta que el jugador entraba en el modo de interacción (el cursor OPS sobre la escena) y todo se rompía: respuestas corruptas, textos cambiados, cuelgues. El texto estaba bien. Los opcodes estaban bien. ¿Entonces?
La respuesta estaba escondida en la cabecera de cada .DAT: una tabla de punteros de 16 bits que mapea las interacciones de la escena — las respuestas a «mirar», «hablar», «entrar»… El número varía según la escena: en la que sirvió de piedra Rosetta eran nueve; otras manejan más. Cuando el jugador hace clic en un hotspot, el motor no busca el texto: va directo a donde el puntero dice que está. Y al traducir, el texto se desplaza, así que la tabla entera queda apuntando al sitio equivocado — a menudo al medio de una palabra. Basta un byte de desvío para que la respuesta salga cortada o corrupta.
Lo retorcido es que esos punteros no son posiciones del fichero: son direcciones «lógicas» del segmento tal y como queda cargado en memoria, desplazadas por una base que tampoco está escrita en ninguna parte. Descifrar la regla — puntero = constante de banco, menos el inicio del bloque de guion, más la posición real del texto — supuso un parón de más de un mes al comienzo del proyecto: volcados hexadecimales, lápiz y papel, restando direcciones a mano hasta que los números cuadraron en todas las interacciones de una escena… y después en todas las demás.
La recompensa justificó el mes: entendida la aritmética, se implementó en el reinsertor un generador de cabeceras dinámicas que detecta cuántos punteros usa cada escena y los recalcula todos en cada reconstrucción. Es una de las piezas más críticas de todo el pipeline: el retoque más mínimo de una traducción desplaza el texto e invalida la cabecera entera. Sin regeneración automática, cada iteración habría exigido recalcular todas esas direcciones a mano — por escena, por idioma, por versión.

Un pipeline reproducible en vez de un editor hexadecimal
La tentación clásica del romhacking es abrir el fichero con un editor hexadecimal e ir machacando bytes. Con 62 escenas, tres idiomas y meses de revisiones por delante, eso es suicida. En su lugar se construyó una cadena de herramientas en Python que convierte el problema en un flujo industrial:
- Extracción — cada
.DAT/.OPSse convierte en un fichero JSON legible por humanos. Cada bloque de texto conserva el original japonés intacto (jp_raw), una versión limpia para leer, el nombre del personaje que habla, y una plantilla de ritmo (tpl) donde los opcodes aparecen como etiquetas comprensibles:[P:5](pausa),[N](avance con ▼),[W](margen),[C:...](control crítico que no se puede perder). - Traducción — los traductores trabajan sobre exportaciones limpias de esos JSON, con los tres idiomas conviviendo en el mismo archivo. Los nombres de los hablantes se localizan mediante diccionarios por idioma (que «Anna» sea «Anna» en los tres, pero que 運転手 sea «Taxista», «Taxista» y «Driver»).
- Fusión y mantenimiento — herramientas de merge reincorporan las traducciones a los maestros sin pisar jamás trabajo previo, y un colocador automático de etiquetas (smarttags) reparte los opcodes sobre el texto traducido respetando fronteras de palabra: la pausa que en japonés caía tras una coma debe caer tras la coma equivalente en castellano.
- Reinserción — el reinsertor reconstruye cada
.DAT/.OPSbyte a byte: cabecera de narración o diálogo, texto en la codificación original (Shift-JIS), opcodes en su posición, y el ajuste de línea calculado para el ancho real de la ventana del juego: 60 unidades de medio ancho, es decir, 30 celdas de kanji por línea. - Validación — de esto hablamos en detalle más abajo, porque es la mitad del proyecto.
La prueba de fuego del pipeline es elegante: si se reinserta el propio texto japonés sin traducir, el fichero resultante debe ser idéntico bit a bit al original. Cualquier desviación delata un error en las herramientas antes de que llegue al juego.
El gran hack: letras latinas en un motor que solo habla japonés
Este es el corazón técnico del proyecto. El motor de Gaudí dibuja cada carácter en una celda de 16×16 píxeles. Con letras latinas a ese tamaño, «El detective Howard» ocupa media pantalla. La solución: enseñar al motor a dibujar dos letras latinas en el espacio de un solo kanji (half-width, 8×16 por letra). Suena simple. No lo es, porque el motor no tiene ni una sola rutina pensada para ello.
El parche —bautizado internamente patch_gau1_shiftjis_latin, hoy en su versión 27.8 tras meses de iteración— opera directamente sobre el ejecutable GAU1.X, y funciona así:
1. La cantera de glifos. El script lee la ROM de caracteres del propio X68000 (CGROM), extrae las letras A–Z y a–z, las corta en mitades de 8×16 y guarda copias alineadas a izquierda y derecha. Todo ese material se inyecta en una code cave: una zona vacía del ejecutable original donde cabe código y datos nuevos sin desplazar nada de lo existente.
2. Dos ganchos (hooks) en el motor. Un hook es un desvío quirúrgico: se sustituyen unas pocas instrucciones del código original por un salto a nuestra rutina, que hace su trabajo y devuelve el control como si nada.
- El hook de la interfaz intercepta la llamada de dibujo a bajo nivel que usan la intro y los menús. Cuando detecta dos letras latinas consecutivas, las fusiona en una sola celda (combinando las dos mitades con una operación OR de bits), vuelca el resultado directamente en la memoria de vídeo y avanza el cursor dos caracteres de golpe.
- El hook de los diálogos intercepta el lector de guiones
.DATy monta una pequeña máquina de estados: la primera letra no se dibuja, se guarda en secreto en la RAM; cuando llega la segunda, se fusionan ambas y el bloque combinado se entrega al motor a través de un carácter «prestado» (un glifo japonés poco conflictivo que actúa de proxy y cuyo dibujo hemos sustituido al vuelo).
Para curiosos: el hook de diálogos tuvo un enemigo inesperado: el motor reciclaba para ese búfer la máscara de sombra de otro carácter, y las letras salían con un «tupé» negro y fondo sólido. La solución fue escribir
0xFFFFFFFFen la zona de máscara, que en el hardware gráfico del X68000 significa transparencia total. Un misterio visual de semanas, resuelto con cuatro bytes.
3. El alfabeto que faltaba. Las letras base salen de la ROM del sistema, pero á é í ó ú à è ò ï ü ñ ç (y sus mayúsculas), el apóstrofe, el punt volat ·, y los signos ¿ ¡ no existen en ningún sitio: se dibujaron a mano y se alojaron en un juego de caracteres especial de 33 huecos, mapeados sobre códigos Shift-JIS técnicamente válidos pero sin glifo asignado (dos ventanas: 0x8740–0x875D y 0x8760–0x8762, esquivando 0x875E, que es un código ilegal en la codificación y habría reventado cualquier conversión de texto).
Para curiosos:
¿y¡merecieron un tratamiento de lujo. En vez de encogerlos a medio ancho, se implementaron como pares compuestos (mitad izquierda + mitad derecha) que se comportan métricamente igual que los? !japoneses de ancho completo, incluida la regla de paridad: si la línea va «a media celda», se inserta un espacio de ajuste antes del signo, exactamente como haría el motor original con su puntuación.

Hacer sitio: el guion traducido no cabía en la RAM
Quedaba otra pared invisible. El motor carga el guion completo de cada escena en un búfer de RAM de unos 8 KB: de sobra para el japonés, que es densísimo (una frase entera cabe en un puñado de kanji), pero no para las lenguas latinas, que lo «deletrean» todo. Varias escenas traducidas superan los 8 KB, y al cargarlas el guion desbordaba el búfer y pisaba lo que hubiera al lado en memoria.
El parche redirige ese búfer a un espacio de trabajo de 16 KB en otra zona de la RAM. El desvío en sí son tres retoques quirúrgicos en GAU1.X (la instrucción que escribe el puntero del búfer y las dos que lo leen). Lo verdaderamente difícil fue encontrar 16 KB realmente libres en una máquina sin protección de memoria, donde el motor va reclamando RAM a medida que avanza la partida. Hicieron falta tres intentos:
- El primer emplazamiento parecía vacío al arrancar el juego… pero en partidas avanzadas el motor escribía justo ahí: softlock en la catedral.
- El segundo se eligió cruzando cuatro savestates de fases avanzadas con una herramienta construida a propósito para buscar «zonas muertas» de memoria… y cayó en la estación de trenes: un búfer dinámico del motor crece con el progreso de la historia y acabó invadiéndolo.
- El tercero, elegido tras cruzar ocho savestates que cubrían todas las etapas de la trama (asesinatos incluidos), deja 24 KB de margen sobre ese búfer dinámico… y aguantó.
La moraleja es muy de 1989: en un ordenador sin protección de memoria, «memoria libre» no es algo que se comprueba mirando un momento — es una afirmación sobre el transcurso entero de la partida.
Maquetar, no solo traducir: el wrapping y los opcodes automáticos
Reinsertar el texto es la mitad del trabajo; la otra mitad es que quede bien puesto en pantalla. La maquetación original venía hecha a mano por los desarrolladores: sus saltos de línea, sangrías y pausas estaban pensados para frases de kanji compactas. Volcar encima frases en castellano reutilizando esa maquetación produce basura visual: líneas que desbordan, sangrías heredadas que descuadran, triángulos ▼ de «pasa página» caídos a media frase.
Por eso el reinsertor incorpora una capa de maquetación automática que compone cada bloque como lo haría un maquetista humano:
- Ajuste de línea a la medida real del motor. La caja de diálogo mide 30 celdas (60 unidades de medio ancho); las letras latinas miden media celda y todo lo demás una entera. El wrapper mide cada palabra en esas unidades y corta solo en fronteras de palabra, reiniciando la cuenta en cada salto de línea y en cada frontera de bloque condicional.
- Sangrías japonesas, fuera. La sangría francesa del original, natural en japonés, descuadra el texto latino: se elimina de serie.
- Las pausas, a fin de frase. El ensamblado reinyecta cada ▼ en su posición japonesa original, que en castellano suele caer a media frase. Un pase posterior lo recoloca en el siguiente final de frase, colapsa pausas dobles y cierra la media celda pendiente.
- Frases partidas, avisadas. Si una frase continúa en el bloque siguiente (cosa del scroll), se le añaden puntos suspensivos.
- El ▼ elige sitio según el contexto. Si cabe en la última línea y la frase acaba en puntuación, se dibuja en línea; si no, salta a línea nueva; y el margen entre párrafos se conserva o se suprime según quién hable a continuación. Todo verificado in-game caso a caso.
Y como toda esta cosmética podría, en teoría, romper algo importante, la capa lleva su propia red de seguridad: un modo estricto que comprueba que los tokens de flujo de escena (condiciones, banderas, saltos) del fichero resultante coinciden exactamente con los del original. 186 reinserciones (62 escenas × 3 idiomas): cero desviaciones.
El resultado se nota sin saber por qué: el texto respira al ritmo del original japonés, pero está compuesto como si el juego se hubiera escrito en tu idioma.

Los bugs fantasma del renderizado
Dibujar de dos en dos tiene un precio: el motor pasa a tener estado (esa primera letra guardada «en secreto») y el estado, cuando sobrevive más de la cuenta, produce fenómenos paranormales.
El más célebre fue el bug de la letra arrastrada. En algunas líneas, la última letra de una línea aparecía pegada al principio de la siguiente, comiéndose un espacio: «spea» → «kwith». Se sospechó del ancho de línea, del ajuste de palabras, de los datos… y tras semanas de investigación la culpa resultó ser del propio parche en combinación con una peculiaridad del motor: la ventana de diálogo tiene un margen izquierdo impar, así que cada línea de continuación arranca «a media celda»; si una línea terminaba con una letra pendiente de pareja en el momento del salto, esa letra sobrevivía al salto de línea y se fusionaba con la primera letra de la línea siguiente.
La cura fue otro microparche de motor: un gancho de 90 bytes en el manejador de salto de línea que, antes de cada salto, vacía la media celda pendiente dibujándola donde corresponde. Se verificó primero en una simulación offline que reproducía el fallo al 100% sobre los bytes reales de una escena, y después in-game. Un solo fix curó el artefacto en todas las escenas del juego a la vez.
Su primo hermano fue la línea fantasma: párrafos que aparecían con interlineado doble sin motivo. Aquí la lección fue la contraria: tras descartar el motor con varios parches que resultaron inertes, la causa estaba en el reinsertor, que calculaba el ajuste de línea con un ancho distinto del que el texto japonés original ocupaba de facto. Dos bugs gemelos en apariencia; uno era del motor, el otro de las herramientas. En romhacking, saber dónde no está el bug es tan valioso como saber dónde está.
Cinemáticas: cuando los créditos son código fuente
La intro y el final del juego (disco 2) esconden la anécdota más deliciosa del proyecto. Sus ficheros, DEMO.TXT y ENDING.TXT, parecen simples archivos de texto, pero son programas: código fuente de un pequeño lenguaje de script que GAU1.X interpreta en tiempo real, con comandos de carga de imágenes, scroll y bucles. El texto en pantalla se declara así:
MOJI(col,fila,color,página) *"私はヘンリー・ハワード"Ese *"..." tiene toda la pinta de ser un comentario del programador. No lo es: es el propio texto que el comando MOJI pinta en pantalla. El «comentario» es la carga útil. Descubrirlo llevó su tiempo (el texto no existía en ningún otro fichero del disco).
Traducir las cinemáticas exigió extender el hack de medio ancho al renderizador MOJI, y aquí la filosofía conservadora del proyecto brilló: el modo de dos-letras-por-celda es opt-in. Solo las líneas traducidas llevan un marcador invisible al principio de la cadena que activa el modo half-width; cualquier línea sin marcador (los créditos japoneses, texto sin tocar) recorre el camino de código original, byte a byte idéntico al de 1989. Los espacios entre palabras usan otro marcador-proxy que el motor convierte al espacio nativo del sistema. Y los créditos del equipo original, escritos en silabario japonés, se romanizaron con cuidado para que los nombres de aquellos desarrolladores de Wolf Team sean por fin legibles fuera de Japón.
La llave del Amiga: abrir los gráficos de Wolf Team
Las cinemáticas guardaban una última trampa: parte de lo que se lee en pantalla no es texto, son rótulos pintados dentro de las imágenes. Para traducirlos no basta el pipeline de guiones: hay que abrir los gráficos. Y los gráficos de Gaudí viven en formatos sin documentación alguna: bitmaps .XGD de 16 colores con su paleta .XPA en el formato de color del X68000, y ficheros .A68/.B68 comprimidos con una variante de LZSS propia de la casa.
La llave llegó de la plataforma más inesperada: el Amiga. En Aminet, el archivo histórico de software amiguero, vive x68k2amiga, una utilidad de Franck Charlet pensada para convertir ejecutables de X68000 al formato del Amiga y poder así destriparlos con los desensambladores de Commodore — un puente posible porque ambas máquinas comparten corazón: el mismo Motorola 68000. Y entre sus despaquetadores había uno muy especial: el del formato .A68 de Mugen Senshi Valis II — un título de la misma familia Telenet/Wolf Team que Gaudí, con el mismo linaje de empaquetador.
Estudiando ese despaquetador (escrito en ensamblador de 68000) se reimplementó la variante exacta de LZSS en Python: depack_valis2.py, bautizada en honor al juego que prestó la llave. El ADN compartido de los motores de Wolf Team hizo el resto: una herramienta hecha para llevar otros juegos de la casa al Amiga acabó abriendo los gráficos de Gaudí 35 años después.
El resto de la cadena la cubre un conversor propio: XGD+paleta ↔ PNG, con exportación de paletas en formatos que entienden los editores de imagen y reimportación que cuantiza de vuelta a los 16 colores exactos del original. Incluye un detalle muy de la época: en ese modo de pantalla el píxel del X68000 no es cuadrado, así que las imágenes se exportan estiradas ×1,5 en vertical — para retocar viendo lo que veía el monitor — y se desescalan al importar.
Estado honesto: la cadena está montada y verificada ida y vuelta — imagen extraída, convertida y reimportada sin pérdida — y el retoque en sí es el siguiente hito: traducir los rótulos bitmap del opening y el ending (y, aún en deliberación, el subtítulo rotulado del título, que acompaña al jugador durante toda la partida). Un golpe de suerte lo facilita: el motor lee XGD sin comprimir directamente, así que no hizo falta escribir el compresor — los gráficos traducidos pueden volver al disco «en plano», y el disco 2, donde viven, todavía tiene espacio de sobra.

Ramas, banderas y el secreto de las partidas guardadas
Las decisiones del jugador viven en una tabla de banderas en RAM. El opcode condicional q= las consulta para decidir qué versión de una escena mostrar: si ayudaste a cierto personaje, si examinaste tres veces el coche sospechoso, si llegaste a la reunión por la ruta de Anna o por la directa. Hubo que mapear este sistema entero —qué bandera activa qué escena, qué evento activa qué bandera— para poder probar todas las ramas de la historia traducida.
Y al diseccionar el archivo de guardado apareció una joya: SAVEDATA no contiene «4 partidas guardadas», sino un anillo de 160 instantáneas consecutivas de la tabla de banderas. Es la implementación física del History Repeat System: cada paso de la historia queda fotografiado, y «rebobinar» es simplemente retroceder por el anillo. Ingeniería de 1989 sorprendentemente moderna — a su manera, Gaudí ya tenía save states.
Para curiosos: para depurar las ramificaciones se construyó un lector forense de los savestates del emulador. Tuvo su propia curva de aprendizaje: la RAM del 68000 aparece volcada con los bytes intercambiados por parejas (una consecuencia del bus de 16 bits), y hasta corregir el mapeo, las banderas impares se leían desplazadas. La herramienta acabó siendo capaz incluso de «leer» el texto visible en pantalla analizando el perfil de tinta de la memoria de vídeo volcada — una forma de comprobar automáticamente qué estaba mostrando el juego sin mirar la pantalla.
Cacería de softlocks: tres culpables y un inocente
Con texto que es programa, los errores no producen erratas: producen cuelgues. Tres casos ilustran la variedad del enemigo:
La estación de Renfe. El juego se colgaba en la estación de tren, solo en las versiones traducidas. La autopsia reveló que una entrada del JSON había perdido su «cola»: el fragmento de código de dispatcher que remataba el bloque y decidía a dónde saltar. El fix restauró la cola desde el original japonés — y, fiel al espíritu del proyecto, se añadió una red de seguridad al pipeline: esa cola quedó protegida contra futuras fusiones, y el auditor ganó un detector específico para que ningún dispatcher vuelva a perderse en silencio.
El amuleto que no cargaba. Otra escena se colgaba al mostrar un objeto. Causa: los opcodes de imagen usan el carácter @ como operando (el índice de la imagen a cargar)… y una rutina de limpieza del reinsertor, pensada para eliminar sangrías de texto (que también usan @), se estaba comiendo el operando. La imagen no sabía qué imagen ser, y el juego esperaba eternamente. El fix: distinguir el @ de sangría (siempre seguido de dígito) del @ operando. Un solo carácter, dos significados, un cuelgue.
El fondo desaparecido. En una de las rutas hacia cierta reunión, la escena llegaba viva pero sin gráficos, y de ahí no pasaba. El culpable era el humilde opcode ( que pinta el fondo: al segmentar el texto para traducirlo había quedado fuera de la etiqueta de control protegida, y se perdía por el camino. Se corrigió la segmentación en la raíz, arreglando de una tacada todas las escenas que pintan el fondo por script.
Y el inocente: durante las pruebas se descubrió que cancelar la carga de partida nada más arrancar cuelga el juego… también en el original japonés intacto. Es un bug de Wolf Team de 1989, verificado sobre una copia japonesa pura, y se documentó y se dejó estar: el proyecto traduce, no reescribe la historia. Los bugs del original también son patrimonio.

Menús, disquetes y los pequeños detalles
Alrededor de los diálogos orbita un enjambre de textos menores que también hubo que cazar uno a uno: los menús del sistema, y 13 cadenas sueltas incrustadas en el ejecutable (mensajes de error, avisos de cambio de disco…). Estas últimas tienen presupuesto de bytes cerrado: la traducción debe caber exactamente en el hueco de la original. Y esconden trampas deliciosas: el mensaje «Inserte el disco X en la unidad Y» reserva posiciones exactas de byte donde el motor escribe en caliente el número de disco y de unidad — la frase traducida debe dejar esos huecos precisamente donde el motor espera encontrarlos.
Y todo el conjunto —guiones, ejecutable parcheado, cinemáticas, gráficos— se ensambla con un inyector que fabrica imágenes de disquete completas por idioma (ES/EN/CA) a partir de las originales. Hasta hubo que hacer sitio: se eliminan un par de ficheros de respaldo que el propio desarrollador dejó olvidados en los disquetes en 1989, y ningún fichero puede superar los 16 KB de su hueco original salvo los que ya lo hacían (el final del juego, con sus 32 KB, cabe justo en su propia cadena de clusters original).
La paranoia como método: verificación
Si la mitad del proyecto fue traducir y parchear, la otra mitad fue demostrar que nada más había cambiado. El arsenal:
- Roundtrip byte-idéntico: reinsertar el japonés sin traducir debe reproducir el fichero original bit a bit, en las 62 escenas. Es el canario en la mina de las herramientas.
- Diff estructural: un comparador verifica que la «estructura dura» de cada fichero traducido (cabeceras, tablas de offsets, bloques) coincide con la del original.
- Cuatro auditorías que barren los JSON maestros a la caza de opcodes perdidos, ecos de opcode filtrados al texto visible, mojibake, comillas descolgadas que desplazan el flujo de la escena, e incongruencias entre idiomas.
- Barridos por juego de caracteres: en vez de buscar basura conocida, se lista todo carácter que aparece en las traducciones y se justifica su existencia. Cazó más morralla que todas las firmas específicas juntas.
- Guardias de tamaño y sombra que vigilan que ningún fichero crezca más de la cuenta y que cada regeneración produzca exactamente lo esperado.
- Y el juego, claro. Partidas completas en emulador, todas las rutas de la historia, en los tres idiomas, con instantáneas forenses en cada rama. Hasta el cambio de disco se instrumentó: se localizaron las marcas en RAM que delatan cuándo el juego pide el disco 2 o 3 y en qué unidad, para poder automatizarlo y que el jugador no tenga que hacer nada.
El resultado: el juego es completable al 100% en los tres idiomas, con el ritmo, las pausas y las ramificaciones del original intactos.
Epílogo: lo que pesa una letra
Vista desde fuera, una traducción parece un problema de palabras. Esta lo fue de bytes: de un motor al que hubo que enseñarle un alfabeto entero con ganchos de 90 bytes y máscaras de transparencia; de una tabla de punteros descifrada con lápiz y papel; de opcodes camuflados de paréntesis; de comentarios que resultaron ser el texto; de un archivo de guardado que escondía 160 fotografías de la historia; de un bug de 1989 al que se le respetó la vida por ser parte del original.
Gaudí: Barcelona no Kaze fue el homenaje de un puñado de desarrolladores japoneses a una ciudad que les fascinaba, publicado tres años antes de las Olimpiadas que imaginaron. Treinta y cinco años después, ese viento vuelve a soplar — y por fin se entiende lo que dice, en las dos lenguas de la ciudad que lo inspiró, y en la lengua franca que le abrirá el resto del mundo.
Puedes comprar la edición física de Gaudí en la web de Shinyuden:
https://shinyuden.com/en/product/gaudi-winds-of-barcelona/

El romhack y toda la ingeniería inversa descrita en este artículo son obra de Pedro Pablo Fernández Moya, alias ArcanBytes. La traducción de los textos corre a cargo de Jaume y Eric, traductores de Shinyuden. El pipeline completo de extracción, auditoría y reinserción está escrito en Python y documentado para su reproducibilidad; las herramientas se liberarán públicamente más adelante. Textos originales y marcas, © de sus titulares.

