Skip to content

feat(gametext): decode UTF-8 in plain-text .str files - #3676

Open
dogefly233 wants to merge 1 commit into
TheSuperHackers:mainfrom
dogefly233:feat/gametext-utf8-str
Open

dogefly233 wants to merge 1 commit into
TheSuperHackers:mainfrom
dogefly233:feat/gametext-utf8-str

Conversation

@dogefly233

Copy link
Copy Markdown

Problem

In release builds the game prefers the plain-text Data\Generals.str over the compiled generals.csf (m_useStringFile = TRUE, g_strFile = "data/Generals.str"). That path is the most convenient one for translators and modders because it is plain text, but its conversion to wide characters, GameTextManager::translateCopy, copies exactly one byte per character:

*outbuf++ = *inbuf & 0x00FF;

Anything outside Latin-1 therefore cannot survive it. A UTF-8 Chinese .str, for example, renders as åä°æ... in the UI. This has been worked around for years by a runtime hook shipped as a Miles proxy DLL (mss32.dll); that workaround only works while the engine loads Miles, and it cannot apply to builds or ports that do not.

Change

  • Validate the whole string once: every non-ASCII byte must form a well-formed UTF-8 sequence, and at least one multi-byte sequence must be present.
  • When valid, decode the multi-byte sequences in translateCopy; otherwise keep the exact legacy byte copy, so existing ANSI strings keep their current output.
  • Non-BMP code points are written as a surrogate pair when WideChar is 16-bit.
  • No new includes or dependencies, and the code is VC6-compatible.

parseMapStringFile calls the same function, so map .str files benefit as well.

Compatibility

  • ASCII-only strings: identical output; the decoder is never entered.
  • ANSI/Latin-1 strings that are not valid UTF-8: identical output; validation fails and the legacy path runs.
  • A Latin-1 string that happens to be valid UTF-8 (for example ä) is now decoded as UTF-8. That is the intended reading for .str text, and distinguishing the two would require an explicit encoding setting; I can add one if you prefer.

Testing

  • Windows build with Data\Generals.str saved as UTF-8 (Chinese text): menu and label text render correctly.
  • The same file saved as ANSI/Western: text output is unchanged from before.
  • Existing English .str files still parse and display identically.

@coderabbitai

coderabbitai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

translateCopy now validates multibyte UTF-8 input and decodes valid sequences into WideChar values. Invalid UTF-8 and strings without multibyte sequences retain byte-copy behavior.

Changes

UTF-8 text conversion

Layer / File(s) Summary
UTF-8 validation and decoding
Core/GameEngine/Source/GameClient/GameText.cpp
Adds validation for well-formed UTF-8 sequences and decoding to WideChar. Out-of-BMP values use surrogate pairs when WideChar is 16-bit.
translateCopy integration
Core/GameEngine/Source/GameClient/GameText.cpp
translateCopy checks for valid multibyte UTF-8 once. It decodes valid sequences, including non-ASCII characters after an escape, and retains byte-by-byte copying otherwise.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Possibly related PRs

Suggested labels: Gen, ZH, Mod

Suggested reviewers: xezon, bobtista

Merge Risk: Minimal · up to e9acf

No demonstrated issue blocks merging; run the listed Windows text checks as part of normal validation.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title clearly identifies the change: decoding UTF-8 in plain-text .str files.
Description check Passed The description explains the UTF-8 decoding change, compatibility behavior, affected files, and planned tests.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ec9351cd-a454-4ffa-bdea-b9594f4b8e35
Commits

Reviewing files that changed from the base of the PR and between 781859c and e9acf8d.

Files selected for processing: 1

  • Core/GameEngine/Source/GameClient/GameText.cpp

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

@greptile-apps

greptile-apps Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; both previous findings are fixed and no new actionable issues remain.

Summary

Adds UTF-8 decoding for plain-text game and map strings while keeping the legacy byte copy for ASCII and invalid UTF-8.

  • Plain-text game and map strings can display valid UTF-8 text.

Reviews (2) · Last reviewed commit: "feat(gametext): decode UTF-8 in plain-te..." · Reviewed by Greptile

@dogefly233
dogefly233 force-pushed the feat/gametext-utf8-str branch from 781859c to e9acf8d Compare November 10, 2026 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant