papermario/tools/msg/parse_compile.py
2021-02-10 14:26:58 +00:00

948 lines
34 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#! /usr/bin/python3
from sys import argv
from collections import OrderedDict
import re
import msgpack # way faster than pickle
class Message:
def __init__(self, name, section, index):
self.name = name
self.section = section
self.index = index
self.bytes = [] # XXX: bytearray would be better
def try_convert_int(s):
try:
return int(s, base=0)
except:
return s
def parse_command(source):
if source[0] != "[":
return None, [], source
source = source[1:] # "["
inside_brackets = ""
while source[0] != "]":
if source[0] == "\n":
return None, [], source
inside_brackets += source[0]
source = source[1:]
source = source[1:] # "]"
command, *raw_args = inside_brackets.split(":")
"""
args = []
named_args = {}
if "=" in command:
key, value = command.split("=", 1)
command = key
named_args[key] = try_convert_int(value)
for arg in args:
if "=" in arg:
key, value = arg.split("=", 1)
named_args[key.lower()] = try_convert_int(value.lower())
else:
args.append(try_convert_int(arg))
"""
args = []
for arg in raw_args:
args.append(try_convert_int(arg.lower()))
return command.lower(), args, source
def color_to_code(color, style):
"""
COLORS = {
"diary": {
"normal": 0x00,
"red": 0x07,
},
"inspect": {
"dark": 0x17,
},
"button": {
"blue": 0x10,
"green": 0x11,
"red": 0x12,
"yellow": 0x13,
"gray": 0x14,
"grey": 0x14,
},
"popup": {
"red": 0x28,
"pink": 0x29,
"purple": 0x2A,
"blue": 0x2B,
"teal": 0x2C,
"green": 0x2D,
"yellow": 0x2E,
"normal": 0x2F,
},
"sign": {
"normal": 0x18,
"red": 0x19,
"blue": 0x1A,
"green": 0x1B,
}
}
"""
COLORS = {}
if type(color) is int:
return color
return COLORS.get(ctx, {
# [style:left], [style:right]
"normal": 0x0A,
"red": 0x20,
"pink": 0x21,
"purple": 0x22,
"blue": 0x23,
"cyan": 0x24,
"green": 0x25,
"yellow": 0x26,
}).get(color)
def resolve_effect(fx):
if type(fx) is int:
return fx
FX = {
"jitter": 0x00,
"wavy": 0x01,
"noise": 0x02,
"fadednoise": 0x03, # 1 arg
"unknown": 0x04,
"fadedjitter": 0x05, # 1 arg
"rainbow": 0x06,
"faded": 0x07, # 1 arg
"wavyb": 0x08,
"rainbowb": 0x09,
"shrinking": 0x0a,
"growing": 0x0b,
"sizejitter": 0x0c,
"sizewave": 0x0d,
"dropshadow": 0x0e,
}
return FX.get(fx)
CHARSET = {
#"𝅘𝅥𝅮": 0x00,
"!": 0x01,
'"': 0x02,
"#": 0x03,
"$": 0x04,
"%": 0x05,
"&": 0x06,
"'": 0x07,
"(": 0x08,
")": 0x09,
"*": 0x0A,
"+": 0x0B,
",": 0x0C,
"-": 0x0D,
".": 0x0E,
"/": 0x0F,
"0": 0x10,
"1": 0x11,
"2": 0x12,
"3": 0x13,
"4": 0x14,
"5": 0x15,
"6": 0x16,
"7": 0x17,
"8": 0x18,
"9": 0x19,
":": 0x1A,
";": 0x1B,
"<": 0x1C,
"=": 0x1D,
">": 0x1E,
"?": 0x1F,
"@": 0x20,
"A": 0x21,
"B": 0x22,
"C": 0x23,
"D": 0x24,
"E": 0x25,
"F": 0x26,
"G": 0x27,
"H": 0x28,
"I": 0x29,
"J": 0x2A,
"K": 0x2B,
"L": 0x2C,
"M": 0x2D,
"N": 0x2E,
"O": 0x2F,
"P": 0x30,
"Q": 0x31,
"R": 0x32,
"S": 0x33,
"T": 0x34,
"U": 0x35,
"V": 0x36,
"W": 0x37,
"X": 0x38,
"Y": 0x39,
"Z": 0x3A,
"[": 0x3B,
"¥": 0x3C,
"]": 0x3D,
"^": 0x3E,
"_": 0x3F,
"`": 0x40,
"a": 0x41,
"b": 0x42,
"c": 0x43,
"d": 0x44,
"e": 0x45,
"f": 0x46,
"g": 0x47,
"h": 0x48,
"i": 0x49,
"j": 0x4A,
"k": 0x4B,
"l": 0x4C,
"m": 0x4D,
"n": 0x4E,
"o": 0x4F,
"p": 0x50,
"q": 0x51,
"r": 0x52,
"s": 0x53,
"t": 0x54,
"u": 0x55,
"v": 0x56,
"w": 0x57,
"x": 0x58,
"y": 0x59,
"z": 0x5A,
"{": 0x5B,
"|": 0x5C,
"}": 0x5D,
"~": 0x5E,
"°": 0x5F,
"À": 0x60,
"Á": 0x61,
"Â": 0x62,
"Ä": 0x63,
"Ç": 0x64,
"È": 0x65,
"É": 0x66,
"Ê": 0x67,
"Ë": 0x68,
"Ì": 0x69,
"Í": 0x6A,
"Î": 0x6B,
"Ï": 0x6C,
"Ñ": 0x6D,
"Ò": 0x6E,
"Ó": 0x6F,
"Ô": 0x70,
"Ö": 0x71,
"Ù": 0x72,
"Ú": 0x73,
"Û": 0x74,
"Ü": 0x75,
"ß": 0x76,
"à": 0x77,
"á": 0x78,
"â": 0x79,
"ä": 0x7A,
"ç": 0x7B,
"è": 0x7C,
"é": 0x7D,
"ê": 0x7E,
"ë": 0x7F,
"ì": 0x80,
"í": 0x81,
"î": 0x82,
"ï": 0x83,
"ñ": 0x84,
"ò": 0x85,
"ó": 0x86,
"ô": 0x87,
"ö": 0x88,
"ù": 0x89,
"ú": 0x8A,
"û": 0x8B,
"ü": 0x8C,
"¡": 0x8D,
"¿": 0x8E,
"ª": 0x8F,
# "♥": 0x90,
# "★": 0x91,
# "↑": 0x92,
# "↓": 0x93,
# "←": 0x94,
# "→": 0x95,
# "●": 0x96,
# "✖": 0x97,
"": 0xA2,
"": 0xA3,
"": 0xA4,
"": 0xA5,
" ": 0xF7,
# "Ⓐ": [0xFF, 0x24, 0xFF, 0x05, 0x10, 0x98, 0xFF, 0x25],
# "Ⓑ": [0xFF, 0x24, 0xFF, 0x05, 0x11, 0x99, 0xFF, 0x25],
# "Ⓢ": [0xFF, 0x24, 0xFF, 0x05, 0x12, 0xA1, 0xFF, 0x25],
# "▲": [0xFF, 0x24, 0xFF, 0x05, 0x13, 0x9D, 0xFF, 0x25],
# "▼": [0xFF, 0x24, 0xFF, 0x05, 0x13, 0x9E, 0xFF, 0x25],
# "◀": [0xFF, 0x24, 0xFF, 0x05, 0x13, 0x9F, 0xFF, 0x25],
# "▶": [0xFF, 0x24, 0xFF, 0x05, 0x13, 0xA0, 0xFF, 0x25],
# "Ⓛ": [0xFF, 0x24, 0xFF, 0x05, 0x14, 0x9A, 0xFF, 0x25],
# "Ⓡ": [0xFF, 0x24, 0xFF, 0x05, 0x14, 0x9B, 0xFF, 0x25],
# "Ⓩ": [0xFF, 0x24, 0xFF, 0x05, 0x14, 0x9C, 0xFF, 0x25],
}
CHARSET_CREDITS = {
"A": 0x00,
"B": 0x01,
"C": 0x02,
"D": 0x03,
"E": 0x04,
"F": 0x05,
"G": 0x06,
"H": 0x07,
"I": 0x08,
"J": 0x09,
"K": 0x0A,
"L": 0x0B,
"M": 0x0C,
"N": 0x0D,
"O": 0x0E,
"P": 0x0F,
"Q": 0x10,
"R": 0x11,
"S": 0x12,
"T": 0x13,
"U": 0x14,
"V": 0x15,
"W": 0x16,
"X": 0x17,
"Y": 0x18,
"Z": 0x19,
"'": 0x1A,
".": 0x1B,
",": 0x1C,
"0": 0x1D,
"1": 0x1E,
"2": 0x1F,
"3": 0x20,
"4": 0x21,
"5": 0x22,
"6": 0x23,
"7": 0x24,
"8": 0x25,
"9": 0x26,
"©": 0x27,
"&": 0x28,
" ": 0xF7,
}
def strip_c_comments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return " "
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
if __name__ == "__main__":
if len(argv) < 3:
print("usage: parse_compile.py [in.msg] [out.msgpack]")
exit(1)
_, filename, outfile = argv
messages = []
message = None
with open(filename, "r") as f:
source = strip_c_comments(f.read())
lineno = 1
directive = ""
indent_level = 0
charset = CHARSET
font_stack = [0]
sound_stack = [0]
color_stack = [0x0A]
style = None
explicit_end = False
while len(source) > 0:
if source[0] == "\r" or source[0] == "\t":
source = source[1:]
continue
if source[0] == "\n":
lineno += 1
source = source[1:]
for i in range(indent_level):
if source[0] == "\t":
source = source[1:]
else:
break
continue
if message is None:
directive = ""
while source[0] != " ":
if source[0] == "\n":
lineno += 1
elif source[0] == "\r":
pass
else:
directive += source[0]
source = source[1:]
directive = directive.split(":")
if directive[0] != "#message" or len(directive) != 3:
print(f"{filename}:{lineno}: expected #message:SECTION:INDEX directive")
exit(1)
section = int(directive[1], 16)
if directive[2].startswith("(") and directive[2].endswith(")"):
name = directive[2][1:-1]
index = None
else:
name = None
index = int(directive[2], 16)
directive = ""
message = Message(name, section, index)
messages.append(message)
while source[0] != "{":
source = source[1:]
if source[0] == "\n":
lineno += 1
elif source[0] == "\r":
pass
elif source[0] == "{":
break
elif source[0] != " " and source[0] != "\t":
print(f"{filename}:{lineno}: expected opening brace ('{{')")
exit(1)
source = source[1:] # {
# count indent level
indent_level = 0
"""
while source[0] == " " or source[0] == "\t" or source[0] == "\n" or source[0] == "\r":
if source[0] == " " or source[0] == "\t":
indent_level += 1
source = source[1:]
"""
else:
command, args, source = parse_command(source)
if command:
if command == "end":
message.bytes += [0xFD]
explicit_end = True
elif command == "raw":
message.bytes += [*args]
#elif command == "func":
# message.bytes += [0xFF, *args]
elif command == "br":
message.bytes += [0xF0]
elif command == "wait":
message.bytes += [0xF1]
elif command == "pause":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xF2, args[0]]
elif command == "next":
message.bytes += [0xFB]
elif command == "func_04":
message.bytes += [0xFF, 0x04]
elif command == "pushcolor":
message.bytes += [0xFF, 0x24]
elif command == "popcolor":
message.bytes += [0xFF, 0x25]
elif command == "color":
if len(args) != 1:
print(f"{filename}:{lineno}: color command requires 1 parameter")
exit(1)
color = color_to_code(args[0], style)
if color is None:
print(f"{filename}:{lineno}: unknown color")
exit(1)
message.bytes += [0xFF, 0x05, color]
color_stack.append(color)
#elif command == "/color":
# color_stack.pop()
# message.bytes += [0xFF, 0x05, color_stack[0]]
elif command == "style":
message.bytes += [0xFC]
style = args[0]
args = args[1:]
if type(style) is int:
message.bytes += [style, *args]
else:
if style == "right":
message.bytes += [0x01]
elif style == "left":
message.bytes += [0x02]
elif style == "center":
message.bytes += [0x03]
elif style == "tattle":
message.bytes += [0x04]
elif style == "choice":
if len(args) != 4:
print(f"{filename}:{lineno}: 'choice' style requires 4 parameters")
exit(1)
message.bytes += [0x05, *args]
elif style == "inspect":
message.bytes += [0x06]
elif style == "sign":
message.bytes += [0x07]
elif style == "lamppost":
if len(args) != 1:
print(f"{filename}:{lineno}: 'lamppost' style requires 1 parameter")
exit(1)
message.bytes += [0x08, args[0]]
elif style == "postcard":
if len(args) != 1:
print(f"{filename}:{lineno}: 'lamppost' style requires 1 parameter")
exit(1)
message.bytes += [0x09, args[0]]
elif style == "popup":
message.bytes += [0x0A]
elif style == "upgrade":
if len(args) != 4:
print(f"{filename}:{lineno}: 'upgrade' style requires 4 parameters")
exit(1)
message.bytes += [0x0C, *args]
elif style == "narrate":
message.bytes += [0x0D]
elif style == "epilogue":
message.bytes += [0x0E]
elif command == "font":
if len(args) != 1:
print(f"{filename}:{lineno}: font command requires 1 parameter")
exit(1)
font = args[0]
if font == "normal":
font = 0
elif font == "title":
font = 3
elif font == "subtitle":
font = 4
if type(font) is not int:
print(f"{filename}:{lineno}: unknown font '{font}'")
exit(1)
message.bytes += [0xFF, 0x00, font]
font_stack.append(font)
if font == 3 or font == 4:
charset = CHARSET_CREDITS
else:
charset = CHARSET
# elif command == "/font":
# font_stack.pop()
# message.bytes += [0xFF, 0x00, font_stack[0]]
# if font == 3 or font == 4:
# charset = CHARSET_CREDITS
# else:
# charset = CHARSET
elif command == "inputoff":
message.bytes += [0xFF, 0x07]
elif command == "inputon":
message.bytes += [0xFF, 0x08]
elif command == "delayoff":
message.bytes += [0xFF, 0x09]
elif command == "delayon":
message.bytes += [0xFF, 0x0A]
elif command == "kerning":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x0B, args[0]]
elif command == "scroll":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x0C, args[0]]
elif command == "size":
if len(args) != 2:
print(f"{filename}:{lineno}: {command} command requires 2 parameters")
exit(1)
message.bytes += [0xFF, 0x0D, *args]
elif command == "sizereset":
message.bytes += [0xFF, 0x0E]
elif command == "speed":
if len(args) != 2:
print(f"{filename}:{lineno}: {command} command requires 2 parameters")
exit(1)
message.bytes += [0xFF, 0x0F, *args]
# elif command == "pos":
# if "y" not in named_args:
# print(f"{filename}:{lineno}: pos command requires parameter: y (x is optional)")
# exit(1)
# if "x" in named_args:
# message.bytes += [0xFF, 0x10, named_args["x"], named_args["y"]]
# else:
# message.bytes += [0xFF, 0x11, named_args["y"]]
elif command == "setprintpos":
if len(args) != 2:
print(f"{filename}:{lineno}: {command} command requires 2 parameters")
exit(1)
message.bytes += [0xFF, 0x10, *args]
elif command == "setprinty":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x11, *args]
elif command == "indent":
if len(args) != 1:
print(f"{filename}:{lineno}: indent command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x12, args[0]]
# elif command == "image":
# if len(args) == 1:
# message.bytes += [0xFF, 0x15, args[0]]
# elif len(args) == 7:
# message.bytes += [0xFF, 0x18, *args]
# else:
# print(f"{filename}:{lineno}: image command requires 1 or 7 parameters")
# exit(1)
elif command == "image1":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameters")
exit(1)
message.bytes += [0xFF, 0x15, *args]
elif command == "image7":
if len(args) != 7:
print(f"{filename}:{lineno}: {command} command requires 7 parameters")
exit(1)
message.bytes += [0xFF, 0x18, *args]
elif command == "sprite":
if len(args) != 3:
print(f"{filename}:{lineno}: sprite command requires 3 parameters")
exit(1)
message.bytes += [0xFF, 0x16, *args]
elif command == "item":
if len(args) != 2:
print(f"{filename}:{lineno}: item command requires 2 parameters")
exit(1)
message.bytes += [0xFF, 0x17, *args]
elif command == "cursor":
if len(args) != 1:
print(f"{filename}:{lineno}: cursor command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x1E, *args]
elif command == "option":
if len(args) != 1:
print(f"{filename}:{lineno}: option command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x21, *args]
elif command == "endchoice":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x1F, args[0]]
elif command == "setcancel":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x20, args[0]]
elif command == "startfx":
message.bytes += [0xFF, 0x26, resolve_effect(args[0]), *args[1:]]
elif command == "endfx":
message.bytes += [0xFF, 0x27, resolve_effect(args[0]), *args[1:]]
# elif command == "shaky":
# message.bytes += [0xFF, 0x26, 0x00]
# elif command == "/shaky":
# message.bytes += [0xFF, 0x27, 0x00]
# elif command == "wavy":
# message.bytes += [0xFF, 0x26, 0x01]
# elif command == "/wavy":
# message.bytes += [0xFF, 0x27, 0x01]
# elif command == "shaky":
# if "opacity" in named_args:
# print(f"{filename}:{lineno}: shaky command doesn't accept parameter 'fade' (hint: did you mean 'faded-shaky'?)")
# exit(1)
# message.bytes += [0xFF, 0x26, 0x00]
# elif command == "/shaky":
# message.bytes += [0xFF, 0x27, 0x00]
# elif command == "noise":
# message.bytes += [0xFF, 0x26, 0x03, named_args.get("fade", 3)]
# elif command == "/noise":
# message.bytes += [0xFF, 0x27, 0x03]
# elif command == "faded-shaky":
# message.bytes += [0xFF, 0x26, 0x05, named_args.get("fade", 5)]
# elif command == "/faded-shaky":
# message.bytes += [0xFF, 0x27, 0x05]
# elif command == "fade":
# message.bytes += [0xFF, 0x26, 0x07, named_args.get("fade", 7)]
# elif command == "/fade":
# message.bytes += [0xFF, 0x27, 0x07]
# elif command == "shout" or command == "shrinking":
# message.bytes += [0xFF, 0x26, 0x0A]
# elif command == "/shout" or command == "/shrinking":
# message.bytes += [0xFF, 0x27, 0x0A]
# elif command == "whisper" or command == "growing":
# message.bytes += [0xFF, 0x26, 0x0B]
# elif command == "/whisper" or command == "/growing":
# message.bytes += [0xFF, 0x27, 0x0B]
# elif command == "scream" or command == "shaky-size":
# message.bytes += [0xFF, 0x26, 0x0C]
# elif command == "/scream" or command == "/shaky-size":
# message.bytes += [0xFF, 0x27, 0x0C]
# elif command == "chortle" or command == "wavy-size":
# message.bytes += [0xFF, 0x26, 0x0D]
# elif command == "/chortle" or command == "/wavy-size":
# message.bytes += [0xFF, 0x27, 0x0D]
# elif command == "shadow":
# message.bytes += [0xFF, 0x26, 0x0E]
# elif command == "/shadow":
# message.bytes += [0xFF, 0x27, 0x0E]
elif command == "var":
if len(args) != 1:
print(f"{filename}:{lineno}: var command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x28, *args]
elif command == "func_29":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x29, *args]
elif command == "volume":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x2E, *args]
elif command == "speechsound":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
sound = args[0]
# if sound == "normal":
# sound = 0
# elif sound == "bowser":
# sound = 1
# elif sound == "star":
# sound = 2
if type(sound) is not int:
print(f"{filename}:{lineno}: unknown sound '{sound}'")
exit(1)
message.bytes += [0xFF, 0x2F, sound]
sound_stack.append(sound)
# elif command == "/sound":
# sound_stack.pop()
# message.bytes += [0xFF, 0x2F, sound_stack[0]]
# elif command == "a":
# color_code = color_to_code(named_args.get("color", "blue"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x98, 0xFF, 0x25]
# elif command == "b":
# color_code = color_to_code(named_args.get("color", "green"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x99, 0xFF, 0x25]
# elif command == "l":
# color_code = color_to_code(named_args.get("color", "gray"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x9A, 0xFF, 0x25]
# elif command == "r":
# color_code = color_to_code(named_args.get("color", "gray"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x9B, 0xFF, 0x25]
# elif command == "z":
# color_code = color_to_code(named_args.get("color", "gray"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x9C, 0xFF, 0x25]
# elif command == "c-up":
# color_code = color_to_code(named_args.get("color", "yellow"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x9D, 0xFF, 0x25]
# elif command == "c-down":
# color_code = color_to_code(named_args.get("color", "yellow"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x9E, 0xFF, 0x25]
# elif command == "c-left":
# color_code = color_to_code(named_args.get("color", "yellow"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0x9F, 0xFF, 0x25]
# elif command == "c-right":
# color_code = color_to_code(named_args.get("color", "yellow"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0xA0, 0xFF, 0x25]
# elif command == "start":
# color_code = color_to_code(named_args.get("color", "red"), named_args.get("ctx", "button"))
# message.bytes += [0xFF, 0x24, 0xFF, 0x05, color_code, 0xA1, 0xFF, 0x25]
elif command == "a":
message.bytes += [0x98]
elif command == "b":
message.bytes += [0x99]
elif command == "l":
message.bytes += [0x9a]
elif command == "r":
message.bytes += [0x9b]
elif command == "z":
message.bytes += [0x9c]
elif command == "c-up":
message.bytes += [0x9d]
elif command == "c-down":
message.bytes += [0x9e]
elif command == "c-left":
message.bytes += [0x9f]
elif command == "c-right":
message.bytes += [0xa0]
elif command == "start":
message.bytes += [0xa1]
elif command == "note":
message.bytes += [0x00]
elif command == "heart":
message.bytes += [0x90]
elif command == "star":
message.bytes += [0x91]
elif command == "up":
if len(args) == 1:
message.bytes += [0xFF, 0x14, args[0]]
else:
message.bytes += [0x92]
elif command == "down":
if len(args) == 1:
message.bytes += [0xFF, 0x13, args[0]]
else:
message.bytes += [0x93]
elif command == "left":
message.bytes += [0x94]
elif command == "right":
message.bytes += [0x95]
elif command == "circle":
message.bytes += [0x96]
elif command == "cross":
message.bytes += [0x97]
# elif command == "wait":
# print(f"{filename}:{lineno}: unknown command 'wait' (hint: did you mean 'prompt'?)")
# exit(1)
# elif command == "pause":
# print(f"{filename}:{lineno}: unknown command 'pause' (hint: did you mean 'sleep'?)")
# exit(1)
elif command == "func_1a":
if len(args) != 3:
print(f"{filename}:{lineno}: {command} command requires 3 parameters")
exit(1)
message.bytes += [0xFF, 0x1A, *args]
elif command == "func_1b":
if len(args) != 2:
print(f"{filename}:{lineno}: {command} command requires 2 parameters")
exit(1)
message.bytes += [0xFF, 0x1B, *args]
elif command == "func_1c":
if len(args) != 1:
print(f"{filename}:{lineno}: {command} command requires 1 parameter")
exit(1)
message.bytes += [0xFF, 0x1C, *args]
elif command == "startanim":
message.bytes += [0xFF, 0x22]
elif command == "endanim":
message.bytes += [0xFF, 0x23]
elif command == "func_2b":
message.bytes += [0xFF, 0x2b]
else:
print(f"{filename}:{lineno}: unknown command '{command}'")
exit(1)
else:
if source[0] == "}":
if not explicit_end:
print(f"{filename}:{lineno}: warning: string lacks an [end] command")
#message.bytes += [0xFD]
explicit_end = False
# padding
while len(message.bytes) % 4 != 0:
message.bytes += [0x00]
message = None
source = source[1:] # }
indent_level = 0
continue
if source[0] == "\\":
source = source[1:]
if source[0] in charset:
data = charset[source[0]]
if type(data) is int:
message.bytes.append(data)
else:
message.bytes += data
source = source[1:]
else:
print(f"{filename}:{lineno}: unsupported character '{source[0]}' for current font")
exit(1)
if message != None:
print(f"{filename}: missing [/message]")
exit(1)
with open(outfile, "wb") as f:
msgpack.pack([{
"section": message.section,
"index": message.index,
"name": message.name,
"bytes": bytes(message.bytes),
} for message in messages], f)