♥ lp-engine

Chapter 9

Text

LovePlus+ has about fifty thousand messages, and it draws every character itself, one glyph at a time, into tiles of video memory, sideways. Putting English in meant learning every place words live, and one place where the game was quietly reading them.

Where the words live

wherewhathow much
scriptsdialogue: every scene's lines, inside its script (chapter 3)50,272 messages
text banksmenus, system messages, mail, descriptions, in eight banks of groups and lines22,413 lines
graphicswords drawn as pixel art: buttons, tabs, the date header, stat labels, place nameshundreds of images
codea few strings built into the program: the default player name, family names, the speech recognition vocabularya handful

The text banks are read by TextRes_GetCurrentEntry: a bank holds groups, a group holds subgroups, a subgroup holds lines. Lines can carry placeholders the game fills in, such as your name, and scripts have their own string variables for the same purpose.

Drawn sideways

You hold LovePlus+ like a book, so the screens are turned a quarter turn, and the game draws everything turned to match. Its fonts are stored already rotated: the two main ones are bitmap fonts of 10 and 12 pixels, in Nintendo's font format. The game draws text one glyph at a time into tiles in video memory (Text_DrawString, LetterChar, DrawGlyphLine), then shows those tiles as a background layer. Because the font is turned, a glyph's "left side bearing" runs across the line, not along it, which is easy to get wrong and was.

The message window

Dialogue appears in a window of three lines per page, typed out at your chosen text speed (one character every 10, 8, 4, 2 or 1 frames). Lines are broken by Japanese rules: certain characters, such as 。、!?, must never start a line, so the game moves them back onto the line before.

Putting English in

The translation covers every message: 48,242 of 48,422 worded messages. The other 180 are kept in Japanese on purpose. They're questions from the game's Japanese-language quiz, which can't be translated without giving the answers away. Fitting English into a game written for Japanese took more than replacing strings:

The game was reading the names

One bug showed what a translation can break. After the dialogue was translated, the heroines stopped moving their lips. The cause: when a message is shown, the game compares the speaker's displayed name against a list of seven Japanese names (Char_LookupIdByName) to decide who is talking, and lip-sync only runs if it finds a heroine. "Manaka" wasn't on the list. lp-engine now maps each translated speaker name back to the Japanese name the game expects before the game looks. The lesson applies to any translation: game logic that tests displayed strings breaks silently when the strings change.

How the translation ships

The translated files can't be shared as they are, because they're modified copies of the game's own files. So the translation ships as a delta: a list of operations that rebuilds each translated file from the player's own copy, either "copy these bytes from your file" or "insert these new bytes". Everything copied comes from the player's cartridge; everything inserted is the translation's own work. On first run, lp-engine applies the delta to the files it read from your cartridge, checks every result against its expected hash, and keeps the result in its own folder. Game > English Translation switches it off.

Still open. Some minigame graphics (name tags, stage names, the pause menu) and a few rarely seen images still show Japanese. The translation tools are in tools/; the translated text itself is published only as the delta.