Gaudí: Winds of Barcelona — the technical chronicle of an impossible localization
How a 1989 Japanese graphic adventure about Barcelona — one Barcelona itself never got to play — was rescued, taken apart piece by piece, and translated into Spanish, Catalan and English.
Romhack & reverse engineering: Pedro Pablo Fernández Moya «ArcanBytes» · License and Translation: Shinyuden
Versión en español disponible: Lee la crónica técnica en castellano aquí
A Japanese game about Barcelona that Barcelona never got to play
In 1989, the Japanese studio Wolf Team — which years later would give rise to the Tales of saga — published a most unusual graphic adventure: Gaudí: Barcelona no Kaze (Gaudí: The Wind of Barcelona). The game dropped the player into the July 1992 of a Barcelona buzzing with pre-Olympic excitement, in the shoes of Henry Howard, a former Scotland Yard detective turned private investigator who uncovers an international terrorist plot among the streets of the Gothic Quarter, the Sagrada Família and Park Güell, all recreated in lovingly detailed pixel art.
It was a game ahead of its time: it featured a context-sensitive cursor over the scene (the OPS system, Object Pointing System) and a story “rewind” mechanism (HRS, History Repeat System) that let the player undo decisions. It was released for MSX2, NEC PC-8801, PC-9801 and Sharp X68000 — exclusively in Japanese and exclusively in Japan. It never left. For more than 35 years, the most elaborate videogame homage ever paid to the city of Barcelona was unreadable to anyone who didn’t master Japanese.
This project has changed that: today the game can be played in Spanish, Catalan and English, on the most technically powerful version of them all — the Sharp X68000 release (three 5.25″ high-density floppy disks) — and it arrives in the West through the publisher Shinyuden. It is also, in all likelihood, one of the first Japanese computer games of the 80s ever officially translated into Catalan.
What follows is the chronicle of everything that had to be touched to make it happen. Because — spoiler — it was never going to be as simple as “changing the text”.

Why “changing the text” was never going to be enough
A 1989 game doesn’t separate “program” from “text” the way a modern game does with its tidy localization files. In Gaudí, the text lives embedded inside the code of each scene, interleaved with instructions that control pauses, line breaks, image changes, story branches — even the loading of the backgrounds. Moving a single byte out of place can hang the game.
On top of that, three fundamental obstacles:
- The engine only knows how to draw Japanese. Every Japanese character occupies a 16×16-pixel cell (“full-width”). The engine has no concept of narrow Latin letters: type “Barcelona” as-is and every letter hogs the slot of an entire kanji, leaving room for pitifully few words per line.
- There is no room. Three 1.2 MB floppies packed to the brim. The translated text has to fit where the Japanese fit, and files can’t simply grow at will, because the floppy’s file system already has its cluster chains assigned.
- There are three languages. All of the above, in triplicate — and with characters the game never dreamed of drawing:
á é í ó ú ñ ¿ ¡for Spanish, andà è ò ï ü ç ·for Catalan (including the punt volat, the raised dot in “col·legi”!).
The project’s philosophy fits in one sentence: if a line hasn’t been translated, the game must produce exactly the same bytes as the 1989 original. Every modification is surgical, reversible and verifiable. That obsession, as we’ll see, ended up saving the project more than once.
The anatomy of the patient
Before operating, we had to understand what lived inside those three floppies:
- GAU1.X — the main executable: the “brain” that interprets the scripts, draws the text and manages menus, saving and disk swapping. Written in Motorola 68000 assembly.
- GS001–GS0xx (.DAT and .OPS) — 62 scene scripts, holding some 1,660 unique text blocks of dialogue and narration. The
.DATcontains the scene; its companion.OPScarries the strings for the cursor system. - TABLE.DAT — the index that wires up the jumps between scenes.
- DEMO.TXT and ENDING.TXT (disk 2) — the game’s intro and finale. And here comes one of the project’s big surprises: they aren’t data, they are source code that the game interprets live, with commands like
GLOAD,SCROLLandMOJI. We’ll come back to them. - SAVEDATA — the save file, whose internal format turned out to be far more interesting than expected.

Text that is also a program: the opcodes
Open any scene script and the Japanese text appears peppered with control sequences — the opcodes — which work like the stage directions of a play, except executable:
j— line break.vj— draws the little ▼ triangle, waits for the player’s click, then advances. The classic “next page”.js— double break: leaves a margin between paragraphs.j@5— a timed pause (the text “breathes” for five ticks before continuing).q=— a full-blown if: it checks a story flag and, depending on its value, shows one block of text or another. This is the branching mechanism.z— jumps to another scene.i@,g@— load an image on screen (a portrait, an object).(— yes, a plain parenthesis: it’s the opcode that paints the scene’s background.
Part of this semantics wasn’t documented anywhere: the interpreter inside GAU1.X had to be disassembled to confirm, for instance, that j and s produce exactly one line break, that js produces the paragraph margin, or that vjs combines the ▼ with that margin. Without that knowledge it’s impossible for the translated text to preserve the original’s rhythm: where it breathes, where it waits, where it turns the page.
And this is the project’s deadly trap: the translator cannot simply write well. Lose a q= in translation and the scene stops branching. Lose a ( and the scene loses its background (and sometimes, with no background to paint, the game waits forever: a softlock). Move a vj and the player clicks in the wrong place and the dialogue falls out of sync.
The header pointer table: a month of pencil and paper
The project’s first great wall wasn’t the font: it was a mechanism whose very existence wasn’t even suspected. The first test reinsertions worked… until the player entered interaction mode (the OPS cursor over the scene) and everything fell apart: corrupted responses, swapped texts, hangs. The text was fine. The opcodes were fine. So what was it?
The answer was hiding in the header of every .DAT: a table of 16-bit pointers mapping the scene’s interactions — the responses to “look”, “talk”, “enter”… The count varies per scene: the one that served as Rosetta stone had nine; others handle more. When the player clicks a hotspot, the engine doesn’t search for the text: it goes straight to wherever the pointer says it is. And translation shifts the text, so the whole table ends up aiming at the wrong place — often the middle of a word. One byte of drift is enough for the response to come out truncated or corrupted.
The twisted part is that those pointers are not file positions: they are “logical” addresses of the segment as it sits loaded in memory, displaced by a base that isn’t written down anywhere either. Deciphering the rule — pointer = bank constant, minus the start of the script block, plus the text’s real position — meant a stall of over a month at the start of the project: hex dumps, pencil and paper, subtracting addresses by hand until the numbers lined up across every interaction of one scene… and then across every other scene.
The reward justified the month: once the arithmetic was understood, a dynamic header generator was implemented in the reinserter, detecting how many pointers each scene uses and recalculating them all on every rebuild. It is one of the most critical pieces of the whole pipeline: the slightest tweak to a translation shifts the text and invalidates the entire header. Without automatic regeneration, every iteration would have meant recalculating all those addresses by hand — per scene, per language, per revision.

A reproducible pipeline instead of a hex editor
The classic romhacking temptation is to open the file in a hex editor and start hammering bytes. With 62 scenes, three languages and months of revisions ahead, that’s suicide. Instead, a Python toolchain was built to turn the problem into an industrial workflow:
- Extraction — every
.DAT/.OPSis converted into a human-readable JSON file. Each text block keeps the untouched Japanese original (jp_raw), a clean version for reading, the name of the speaking character, and a rhythm template (tpl) where the opcodes appear as understandable tags:[P:5](pause),[N](advance with ▼),[W](margin),[C:...](critical control that must never be lost). - Translation — translators work on clean exports of those JSON files, with all three languages living side by side in the same file. Speaker names are localized through per-language dictionaries (so that “Anna” stays “Anna” in all three, but 運転手 becomes “Taxista”, “Taxista” and “Driver”).
- Merging and maintenance — merge tools fold the translations back into the master files without ever trampling previous work, and an automatic tag placer (smarttags) distributes the opcodes across the translated text respecting word boundaries: the pause that fell after a comma in Japanese must fall after the equivalent comma in English.
- Reinsertion — the reinserter rebuilds every
.DAT/.OPSbyte by byte: narration or dialogue header, text in the original encoding (Shift-JIS), opcodes in position, and line wrapping computed for the game window’s real width: 60 half-width units — that is, 30 kanji cells per line. - Validation — covered in detail below, because it is half the project.
The pipeline’s acid test is elegant: reinsert the untranslated Japanese text itself and the resulting file must be bit-for-bit identical to the original. Any deviation exposes a bug in the tools before it ever reaches the game.
The big hack: Latin letters in an engine that only speaks Japanese
This is the technical heart of the project. Gaudí‘s engine draws every character in a 16×16 cell. With Latin letters at that size, “Detective Howard” takes up half the screen. The solution: teach the engine to draw two Latin letters in the space of a single kanji (half-width, 8×16 per letter). Sounds simple. It isn’t, because the engine doesn’t contain a single routine designed for it.
The patch — internally christened patch_gau1_shiftjis_latin, now at version 27.8 after months of iteration — operates directly on the GAU1.X executable, and works like this:
1. The glyph quarry. The script reads the X68000’s own character ROM (CGROM), extracts the letters A–Z and a–z, slices them into 8×16 halves and stores left-aligned and right-aligned copies. All that material is injected into a code cave: an empty region of the original executable with room for new code and data without displacing anything that already exists.
2. Two hooks into the engine. A hook is a surgical detour: a few instructions of the original code are replaced with a jump to our routine, which does its job and hands control back as if nothing happened.
- The interface hook intercepts the low-level drawing call used by the intro and the menus. When it detects two consecutive Latin letters, it fuses them into a single cell (combining the two halves with a bitwise OR), pours the result straight into video memory and advances the cursor two characters at once.
- The dialogue hook intercepts the
.DATscript reader and sets up a small state machine: the first letter isn’t drawn — it’s secretly stashed in RAM; when the second arrives, the two are merged and the combined block is handed to the engine through a “borrowed” character (an innocuous Japanese glyph acting as a proxy, whose artwork we’ve replaced on the fly).
For the curious: the dialogue hook faced an unexpected enemy: the engine recycled the shadow mask of another character for that buffer, so the letters came out with a black “quiff” and a solid background. The fix was to write
0xFFFFFFFFinto the mask area — which, on the X68000’s graphics hardware, means full transparency. A weeks-long visual mystery, solved with four bytes.
3. The missing alphabet. The base letters come from the system ROM, but á é í ó ú à è ò ï ü ñ ç (and their capitals), the apostrophe, the raised dot ·, and the ¿ ¡ marks exist nowhere: they were drawn by hand and housed in a special character set of 33 slots, mapped onto Shift-JIS codes that are technically valid but have no glyph assigned (two windows: 0x8740–0x875D and 0x8760–0x8762, carefully dodging 0x875E, an illegal code in the encoding that would have blown up any text conversion).
For the curious:
¿and¡got the deluxe treatment. Rather than shrinking them to half width, they were implemented as composite pairs (left half + right half) that behave metrically exactly like the full-width Japanese? !— including the parity rule: if the line is sitting “on a half cell”, a padding space is inserted before the mark, precisely as the original engine would do with its own punctuation.

Making room: the translated script didn’t fit in RAM
One more invisible wall was waiting. The engine loads each scene’s entire script into a RAM buffer of about 8 KB: plenty for Japanese, which is extraordinarily dense (a whole sentence fits in a handful of kanji), but not for Latin languages, which spell everything out. Several translated scenes exceed 8 KB, and on loading, the script overflowed the buffer and trampled whatever lived next to it in memory.
The patch redirects that buffer to a 16 KB workspace elsewhere in RAM. The detour itself is three surgical touches to GAU1.X (the instruction that writes the buffer pointer and the two that read it). The genuinely hard part was finding 16 KB of truly free memory on a machine with no memory protection, where the engine keeps claiming RAM as the adventure progresses. It took three attempts:
- The first location looked empty at boot… but in advanced playthroughs the engine wrote right there: softlock at the cathedral.
- The second was chosen by cross-referencing four late-game savestates with a purpose-built “dead space” finder… and fell at the train station: a dynamic engine buffer grows with story progress and ended up invading it.
- The third, picked after cross-referencing eight savestates covering every stage of the plot (murders included), leaves a 24 KB margin above that dynamic buffer… and held.
The moral is very 1989: on a computer with no memory protection, “free memory” isn’t something you check by glancing once — it’s a claim about the entire course of a playthrough.
Typesetting, not just translating: automatic wrapping and formatting opcodes
Reinserting the text is half the job; the other half is making it sit well on screen. The original layout was hand-crafted by the developers: its line breaks, indents and pauses were designed for compact kanji sentences. Pouring English sentences on top while reusing that layout produces visual garbage: overflowing lines, inherited indents that misalign everything, ▼ “next page” triangles stranded mid-sentence.
That’s why the reinserter carries an automatic typesetting layer that composes each block the way a human typesetter would:
- Line wrapping to the engine’s real metrics. The dialogue box measures 30 cells (60 half-width units); Latin letters measure half a cell and everything else a full one. The wrapper measures every word in those units and breaks only at word boundaries, resetting the count at every line break and at every conditional block boundary.
- Japanese indents, out. The original’s hanging indent, natural in Japanese, misaligns Latin text: it’s removed by default.
- Pauses go to the end of the sentence. Assembly reinjects each ▼ at its original Japanese position, which in English usually lands mid-sentence. A later pass relocates it to the next sentence end, collapses double pauses and flushes the pending half cell.
- Split sentences get a warning. If a sentence continues in the next block (a scrolling matter), an ellipsis is appended.
- The ▼ picks its spot in context. If it fits on the last line and the sentence ends in punctuation, it’s drawn inline; otherwise it jumps to a new line; and the margin between paragraphs is kept or dropped depending on who speaks next. All verified in-game, case by case.
And since all this cosmetics could, in theory, break something important, the layer carries its own safety net: a strict mode that checks that the scene-flow tokens (conditions, flags, jumps) of the resulting file match the original’s exactly. 186 reinsertions (62 scenes × 3 languages): zero deviations.
The result is felt without knowing why: the text breathes to the rhythm of the Japanese original, but it’s typeset as if the game had been written in your language.

The ghost bugs of the renderer
Drawing two-by-two has a price: the engine now has state (that first letter stashed “in secret”), and state, when it outlives its welcome, produces paranormal phenomena.
The most famous was the dragged-letter bug. On some lines, the last letter of a line appeared glued to the start of the next one, eating a space along the way: “spea” → “kwith”. The line width was suspected, then the word wrapping, then the data… and after weeks of investigation the culprit turned out to be the patch itself combined with a quirk of the engine: the dialogue window has an odd left margin, so every continuation line starts “on a half cell”; if a line ended with a letter still waiting for its partner at the moment of the break, that letter survived the line break and got fused with the first letter of the following line.
The cure was another engine micro-patch: a 90-byte hook in the newline handler that, before every break, flushes the pending half cell, drawing it where it belongs. It was verified first in an offline simulation that reproduced the bug 100% on the real bytes of a scene, and then in-game. A single fix cured the artifact in every scene of the game at once.
Its close cousin was the phantom line: paragraphs that showed up double-spaced for no reason. Here the lesson was the opposite one: after ruling out the engine with several patches that turned out to be inert, the cause lay in the reinserter, which was computing the line wrap with a width different from the one the original Japanese text effectively occupied. Two seemingly twin bugs; one lived in the engine, the other in the tools. In romhacking, knowing where the bug isn’t is as valuable as knowing where it is.
Cinematics: when the credits are source code
The game’s intro and finale (disk 2) hide the project’s most delicious anecdote. Their files, DEMO.TXT and ENDING.TXT, look like plain text files, but they are programs: source code for a small scripting language that GAU1.X interprets in real time, with commands for image loading, scrolling and loops. On-screen text is declared like this:
MOJI(col,row,color,page) *"私はヘンリー・ハワード"That *"..." looks for all the world like a programmer’s comment. It isn’t: it is the very text that the MOJI command paints on screen. The “comment” is the payload. Figuring that out took a while (the text existed in no other file on the disk).
Translating the cinematics meant extending the half-width hack to the MOJI renderer, and here the project’s conservative philosophy shone: the two-letters-per-cell mode is opt-in. Only translated lines carry an invisible marker at the start of the string that switches on half-width mode; any line without the marker (the Japanese credits, untouched text) runs through the original code path, byte-for-byte identical to 1989’s. Spaces between words use another proxy marker that the engine converts into the system’s native space. And the original team’s credits, written in Japanese syllabary, were carefully romanized so that the names of those Wolf Team developers are at last readable outside Japan.
The Amiga key: unlocking Wolf Team’s graphics
The cinematics held one last trap: part of what you read on screen isn’t text at all — it’s lettering painted inside the images. To translate it, the script pipeline isn’t enough: you have to crack open the graphics. And Gaudí‘s graphics live in formats with no documentation whatsoever: 16-color .XGD bitmaps with their .XPA palette in the X68000’s color format, plus .A68/.B68 files compressed with the studio’s own LZSS variant.
The key arrived from the most unexpected platform: the Amiga. On Aminet, the historic archive of Amiga software, lives x68k2amiga, a utility by Franck Charlet designed to convert X68000 executables into Amiga format so they could be dissected with Commodore’s disassemblers — a bridge made possible because both machines share the same heart: the Motorola 68000. And among its depackers there was a very special one: for the .A68 format of Mugen Senshi Valis II — a title from the same Telenet/Wolf Team family as Gaudí, with the same packer lineage.
By studying that depacker (written in 68000 assembly), the exact LZSS variant was reimplemented in Python: depack_valis2.py, christened in honor of the game that lent the key. Wolf Team’s shared engine DNA did the rest: a tool built to carry the studio’s other games to the Amiga ended up unlocking Gaudí‘s graphics 35 years later.
The rest of the chain is covered by a purpose-built converter: XGD+palette ↔ PNG, exporting palettes in formats image editors understand and reimporting with quantization back to the original’s exact 16 colors. It includes a very period-appropriate detail: in that screen mode the X68000’s pixel is not square, so images are exported stretched ×1.5 vertically — to retouch seeing what the monitor actually showed — and unscaled back on import.
Honest status: the chain is built and verified round-trip — image extracted, converted and reimported losslessly — and the retouching itself is the next milestone: translating the bitmap lettering of the opening and the ending (and, still under deliberation, the painted subtitle of the title, which accompanies the player through the whole game). One stroke of luck makes it easier: the engine reads uncompressed XGD directly, so no compressor had to be written — the translated graphics can go back to the disk “flat”, and disk 2, where they live, still has room to spare.

Branches, flags and the secret of the save files
The player’s decisions live in a flag table in RAM. The conditional opcode q= consults it to decide which version of a scene to show: whether you helped a certain character, whether you examined the suspicious car three times, whether you reached the meeting via Anna’s route or the direct one. This whole system had to be mapped — which flag activates which scene, which event sets which flag — in order to test every branch of the translated story.
And dissecting the save file revealed a gem: SAVEDATA doesn’t contain “4 save slots” — it holds a ring of 160 consecutive snapshots of the flag table. It is the physical implementation of the History Repeat System: every step of the story gets photographed, and “rewinding” is simply walking back through the ring. Surprisingly modern engineering for 1989 — in its own way, Gaudí already had save states.
For the curious: to debug the branching, a forensic reader for the emulator’s savestates was built. It had its own learning curve: the 68000’s RAM appears in the dump with its bytes swapped in pairs (a consequence of the 16-bit bus), and until the mapping was corrected, odd-numbered flags read out of place. The tool ended up being able to “read” the text visible on screen by analyzing the ink profile of the dumped video memory — a way of automatically checking what the game was displaying without looking at the screen.
Softlock hunting: three culprits and one innocent
When text is a program, mistakes don’t produce typos: they produce hangs. Three cases illustrate the variety of the enemy:
The Renfe train station. The game hung at the train station — only in the translated versions. The autopsy revealed that one JSON entry had lost its “tail”: the dispatcher code fragment that closed off the block and decided where to jump next. The fix restored the tail from the Japanese original — and, true to the project’s spirit, a safety net was added to the pipeline: that tail is now protected against future merges, and the auditor gained a dedicated detector so that no dispatcher can ever silently go missing again.
The amulet that wouldn’t load. Another scene hung when displaying an object. Cause: the image opcodes use the @ character as an operand (the index of the image to load)… and a cleanup routine in the reinserter, designed to strip text indentation (which also uses @), was eating the operand. The image didn’t know which image to be, and the game waited forever. The fix: distinguish the indentation @ (always followed by a digit) from the operand @. One character, two meanings, one hang.
The vanished background. On one of the routes to a certain meeting, the scene arrived alive but with no graphics, and went no further. The culprit was the humble ( opcode that paints the background: when the text was segmented for translation it had been left outside the protected control tag, and got lost along the way. The segmentation was fixed at the root, repairing in one stroke every scene that paints its background from the script.
And the innocent: during testing it was discovered that cancelling the load-game prompt right after booting hangs the game… on the untouched Japanese original too. It’s a 1989 Wolf Team bug, verified on a pristine Japanese copy, and it was documented and left alone: this project translates, it doesn’t rewrite history. The original’s bugs are heritage too.

Menus, floppies and the small details
Around the dialogue orbits a swarm of minor texts that also had to be hunted down one by one: the system menus, and 13 loose strings embedded in the executable (error messages, disk-change prompts…). The latter have a hard byte budget: the translation must fit exactly in the original’s slot. And they hide delightful traps: the “Insert disk X into drive Y” message reserves exact byte positions where the engine writes the disk and drive numbers at runtime — the translated sentence must leave those gaps precisely where the engine expects to find them.
And the whole package — scripts, patched executable, cinematics, graphics — is assembled by an injector that builds complete per-language floppy images (ES/EN/CA) from the originals. Room even had to be made: a couple of backup files that the original developer left forgotten on the floppies in 1989 get deleted, and no file may exceed the 16 KB of its original slot except those that already did (the game’s ending, at 32 KB, fits exactly within its own original cluster chain).
Paranoia as a method: verification
If half the project was translating and patching, the other half was proving that nothing else had changed. The arsenal:
- Byte-identical roundtrip: reinserting the untranslated Japanese must reproduce the original file bit for bit, across all 62 scenes. It’s the canary in the tools’ coal mine.
- Structural diff: a comparator verifies that the “hard structure” of every translated file (headers, offset tables, blocks) matches the original’s.
- Four audits that sweep the master JSONs hunting for lost opcodes, opcode echoes leaked into visible text, mojibake, stray quotes that shift the scene’s flow, and cross-language inconsistencies.
- Character-set sweeps: instead of searching for known junk, every character that appears in the translations is listed and its existence justified. It caught more debris than all the specific signatures combined.
- Size and shadow guards that watch that no file grows beyond its budget and that every regeneration produces exactly what’s expected.
- And the game itself, of course. Full playthroughs in the emulator, every route of the story, in all three languages, with forensic snapshots at every branch. Even the disk swap was instrumented: the RAM marks that betray when the game requests disk 2 or 3 — and in which drive — were located, so that long test sessions could be automated.
The result: the game is 100% completable in all three languages, with the original’s rhythm, pauses and branching intact.
Epilogue: the weight of a letter
Seen from the outside, a translation looks like a problem of words. This one was a problem of bytes: of an engine that had to be taught an entire alphabet with 90-byte hooks and transparency masks; of a pointer table deciphered with pencil and paper; of opcodes disguised as parentheses; of comments that turned out to be the text; of a save file hiding 160 photographs of the story; of a 1989 bug whose life was spared because it was part of the original.
Gaudí: Barcelona no Kaze was the homage of a handful of Japanese developers to a city that fascinated them, published three years before the Olympics they imagined. Thirty-five years later, that wind blows again — and at last we understand what it says, in the two languages of the city that inspired it, and in the lingua franca that carries it to the rest of the world.
You can purchase the physical game edition, La Edición Física, at Shinyuden:
https://shinyuden.com/producto/gaudi-el-viento-de-barcelona/

The romhack and all the reverse engineering described in this article are the work of Pedro Pablo Fernández Moya, a.k.a. ArcanBytes. The translation of the texts is by Jaume and Eric, translators at Shinyuden. The complete extraction, audit and reinsertion pipeline is written in Python and documented for reproducibility; the tools will be released publicly at a later date. Original texts and trademarks © their respective owners.

