Zack Buhman e4ff1b4c5a generate/text: added
Of the "trivial" texts that the current parser can handle, these are
now being inserted in obj_events.
2023-07-30 08:52:46 +00:00

146 lines
3.4 KiB
Python

"""
const uint8_t string[] = "foo" "\x0a" "abc";
"""
from itertools import chain
from parse import parse
from generate.generate import renderer
_control_encode = {
'text_end': None,
'text_ram': None,
'text_start': None,
'text_decimal': None,
'text_bcd': None,
'text' : 0x80,
'next' : 0x81,
'line' : 0x82,
'para' : 0x83,
'cont' : 0x84,
'done' : 0x85,
'prompt' : 0x86,
'page' : 0x87,
}
_bracketed_encode = {
'PKMN' : '\\x96',
'COLON' : '\\xa6',
# fixme hacks
'PLAYER': 'PLAYER',
'RIVAL' : 'RIVAL',
'TARGET': 'TARGET',
'USER' : 'USER',
'SCROLL': 'SCROLL', # _ContTextNoPause
'_CONT' : '_CONT', # _ContText
}
def encode_bracketed(bracketed):
# see control.hpp
assert bracketed in _bracketed_encode, bracketed
return _bracketed_encode[bracketed]
def parse_bracketed(string):
chars = []
in_bracket = False
for c in string:
if c == '<':
assert in_bracket is False
in_bracket = True
if chars:
yield ''.join(chars)
chars = []
elif c == '>':
assert in_bracket is True
in_bracket = False
yield encode_bracketed(''.join(chars))
chars = []
elif ord(c) == 165:
if chars:
yield ''.join(chars)
chars = []
yield '\\xa5'
else:
chars.append(c)
if chars:
yield ''.join(chars)
def encode_control(control):
assert control in _control_encode, control
encode = _control_encode[control]
if encode is not None:
return f'\\x{encode:x}'
else:
return None
def quote(s):
return f'"{s}"'
def generate_literals(text):
for control__value in text:
if len(control__value) == 1:
control, = control__value
ec = encode_control(control)
if ec is not None:
yield ec
elif len(control__value) == 2:
control, value = control__value
ec = encode_control(control)
if ec is None:
continue
yield ec
yield from parse_bracketed(value)
else:
assert False, control__value
def generate_text(name, text):
yield f"const uint8_t {name}[] = ("
for literal in generate_literals(text):
yield quote(literal)
yield ");"
def calculate_length(text):
return sum(
1 if literal[0:2] == '\\x' else len(literal)
for literal in generate_literals(text)
)
def texts_header():
text_list = chain.from_iterable(
d.items() for d in parse.text_list())
for name, text in text_list:
length = calculate_length(text) + 1
yield f"extern const uint8_t {name}[{length}];"
def includes_header():
yield "#pragma once"
yield ""
yield "#include <cstdint>"
yield ""
def texts_source():
text_list = chain.from_iterable(
d.items() for d in parse.text_list())
for name, text in text_list:
yield from generate_text(name, text)
yield ""
def generate_header():
render, out = renderer()
render(includes_header());
render(texts_header())
return out
def includes_source():
yield "#include <cstdint>"
yield ""
yield '#include "text.hpp"'
yield ""
def generate_source():
render, out = renderer()
render(includes_source());
render(texts_source())
return out