Wordwrapping working
This commit is contained in:
parent
38a6819722
commit
c5fd435aef
1 changed files with 44 additions and 2 deletions
|
|
@ -355,11 +355,13 @@ def extract_dialogue(raw):
|
|||
|
||||
# ── pack ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
def patch_ystb(raw, translations):
|
||||
def patch_ystb(raw, translations, wrap_nl_bytes=b'\x0a'):
|
||||
"""
|
||||
Patch translated text into a YSTB binary.
|
||||
|
||||
translations : {src_text: tl_text}
|
||||
wrap_nl_bytes : bytes to insert as line-break separator (default b'\x0a').
|
||||
YU-RIS native newline is b'\xef\xf0' (two-byte control code).
|
||||
Returns patched bytes, or None if nothing changed (no matches found).
|
||||
|
||||
Strategy:
|
||||
|
|
@ -411,6 +413,9 @@ def patch_ystb(raw, translations):
|
|||
new_bytes = tl.encode('cp932')
|
||||
except Exception:
|
||||
new_bytes = tl.encode('utf-8')
|
||||
# Replace sentinel 0x01 with the requested newline bytes
|
||||
if wrap_nl_bytes != b'\x0a':
|
||||
new_bytes = new_bytes.replace(b'\x01', wrap_nl_bytes)
|
||||
attr_replacements[attr_idx] = new_bytes
|
||||
|
||||
elif a_type == 3:
|
||||
|
|
@ -824,6 +829,25 @@ def patch_font_sizes(raw, style_sizes):
|
|||
return bytes(new_header) + instr_enc + new_attrs_enc + new_vals_enc + tail
|
||||
|
||||
|
||||
# ── word-wrap helper ────────────────────────────────────────────────────────────
|
||||
|
||||
def _wrap_text(text, width):
|
||||
"""
|
||||
Word-wrap `text` to at most `width` characters per line.
|
||||
Returns the wrapped string with '\n' (0x0a) as the line separator.
|
||||
Preserves any manual '\n' already present in the text.
|
||||
"""
|
||||
import textwrap
|
||||
paragraphs = text.split('\n')
|
||||
lines = []
|
||||
for para in paragraphs:
|
||||
if len(para) <= width:
|
||||
lines.append(para)
|
||||
else:
|
||||
lines.extend(textwrap.wrap(para, width=width) or [''])
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
# ── CLI commands ──────────────────────────────────────────────────────────────
|
||||
|
||||
def cmd_extract(args):
|
||||
|
|
@ -882,6 +906,12 @@ def cmd_extract(args):
|
|||
def cmd_pack(args):
|
||||
json_dir = args.json_dir
|
||||
ysbin_dir = args.ysbin_dir
|
||||
wrap_width = getattr(args, 'wrap', 0) or 0
|
||||
wrap_nl_str = getattr(args, 'wrap_newline', 'eff0') or 'eff0'
|
||||
try:
|
||||
wrap_nl_bytes = bytes.fromhex(wrap_nl_str.replace(' ', '').replace('0x', ''))
|
||||
except ValueError:
|
||||
wrap_nl_bytes = b'\xef\xf0'
|
||||
patched = 0
|
||||
skipped = 0
|
||||
|
||||
|
|
@ -948,6 +978,14 @@ def cmd_pack(args):
|
|||
if not e.get('src') or not e.get('tl') or e['tl'] == e['src']:
|
||||
continue
|
||||
tl = e['tl']
|
||||
# Word-wrap English speech text if requested.
|
||||
# Only wrap if the translation looks like English (no CJK).
|
||||
if wrap_width and tl and not any(0x3000 <= ord(c) <= 0x9fff for c in tl):
|
||||
tl = _wrap_text(tl, wrap_width)
|
||||
# If a non-default newline byte is requested, store a sentinel
|
||||
# that will be replaced after cp932 encoding below.
|
||||
if wrap_nl_bytes != b'\x0a':
|
||||
tl = tl.replace('\n', '\x01') # temp sentinel (0x01 unused in text)
|
||||
key = e.get('_raw', e['src'])
|
||||
# Re-attach the ORIGINAL speaker prefix from _raw so the engine
|
||||
# continues to recognise the name in its es.CHAR.NAME registry.
|
||||
|
|
@ -974,7 +1012,7 @@ def cmd_pack(args):
|
|||
with open(ybn_path, 'rb') as f:
|
||||
raw = f.read()
|
||||
|
||||
result = patch_ystb(raw, translations)
|
||||
result = patch_ystb(raw, translations, wrap_nl_bytes=wrap_nl_bytes)
|
||||
if result is None:
|
||||
print(f' SKIP {fname}: no matching strings found in binary')
|
||||
skipped += 1
|
||||
|
|
@ -1375,6 +1413,10 @@ def main():
|
|||
p_pack = sub.add_parser('pack', help='JSON → .ybn (patch in-place)')
|
||||
p_pack.add_argument('--ysbin-dir', default='data/ysbin')
|
||||
p_pack.add_argument('--json-dir', default='json')
|
||||
p_pack.add_argument('--wrap', type=int, default=0, metavar='N',
|
||||
help='Auto word-wrap English lines to N chars (0 = off, try 50)')
|
||||
p_pack.add_argument('--wrap-newline', default='eff0', metavar='HEX',
|
||||
help='Hex bytes for line separator (default: eff0 = YU-RIS native newline 0xEF 0xF0)')
|
||||
|
||||
# repack-ypf
|
||||
p_ypf = sub.add_parser('repack-ypf', help='data/ysbin/*.ybn → patched .ypf')
|
||||
|
|
|
|||
Loading…
Reference in a new issue