add message naming to splat.yaml

This commit is contained in:
Alex Bates 2021-02-10 01:36:01 +00:00
parent 46d7a144e7
commit 87652e8abb
8 changed files with 76 additions and 63 deletions

View File

@ -315,9 +315,8 @@ async def main():
description="ld_addrs_h $in")
n.newline()
# $msg_combine_headers
n.rule("msg_combine",
command="$python tools/msg/combine.py $out $in --headers $msg_combine_headers",
command="$python tools/msg/combine.py $out $in",
description="combine messages")
n.rule("msg",
command="$python tools/msg/parse_compile.py $in $out",
@ -386,10 +385,11 @@ async def main():
n.build(add_generated_header("$builddir/include/ld_addrs.h"), "ld_addrs_h", "$builddir/$target.ld")
# messages
msg_files = []
msg_files = set()
for d in ASSET_DIRS:
msg_files.extend(glob(d + "/**/*.msg", recursive=True))
msg_files = list(set(msg_files)) # dedup
for f in glob(d + "/**/*.msg", recursive=True):
msg_files.add(find_asset(f[len(d)+1:]))
msg_files = list(msg_files)
for msg_file in msg_files:
n.build(
f"$builddir/{msg_file.split('/', 1)[1]}.bin",
@ -397,15 +397,13 @@ async def main():
msg_file,
implicit="tools/msg/parse_compile.py",
)
msg_headers = [add_generated_header(f"$builddir/include/{msg_file.split('/', 1)[1]}.h") for msg_file in msg_files]
#msg_headers = [add_generated_header(f"$builddir/include/{msg_file.split('/', 1)[1]}.h") for msg_file in msg_files]
msg_bins = [f"$builddir/{msg_file.split('/', 1)[1]}.bin" for msg_file in msg_files]
n.build(
"$builddir/msg.bin",
["$builddir/msg.bin", add_generated_header(f"$builddir/include/message_ids.h")],
"msg_combine",
msg_bins,
implicit="tools/msg/combine.py",
implicit_outputs=msg_headers,
variables={ "msg_combine_headers": msg_headers }
)
n.build("$builddir/msg.o", "bin", "$builddir/msg.bin")

View File

@ -5,12 +5,7 @@
typedef s32 MessageID;
// Prefer editing splat.yaml's msg ids section than using this directly!
#define MESSAGE_ID(section, index) (((section << 0x10) + index))
#define MessageID_TATTLE_KMR_03 MESSAGE_ID(0x19, 0x3B)
#define MessageID_TATTLE_KMR_12 MESSAGE_ID(0x19, 0x40)
#define MessageID_SIGN_MUSHROOM_GOOMBA_TRAP MESSAGE_ID(0x1D, 0x167)
#define MessageID_SIGN_GOOMBA_KINGS_FORTRESS_AHEAD MESSAGE_ID(0x1D, 0x168)
#endif

View File

@ -1,4 +1,5 @@
#include "kmr_03.h"
#include "message_ids.h"
#include "../../partners.h"
Script N(Main);
@ -61,7 +62,7 @@ MapConfig N(config) = {
.entryList = N(entryList),
.entryCount = ENTRY_COUNT(N(entryList)),
.background = &gBackgroundImage,
.tattle = MessageID_TATTLE_KMR_03,
.tattle = MSG_kmr_03_tattle,
};
Script N(Script_802406C0) = SCRIPT({

View File

@ -1,4 +1,5 @@
#include "kmr_12.h"
#include "message_ids.h"
#include "sprite/npc/goomba.h"
Script N(ExitWest) = EXIT_WALK_SCRIPT(60, 0, "kmr_07", 1);
@ -59,7 +60,7 @@ Script N(ReadWestSign) = SCRIPT({
// "Eat a Mushroom to regain your energy!"
suspend group 1;
DisablePlayerInput(TRUE);
ShowMessageAtScreenPos(MessageID_SIGN_MUSHROOM_GOOMBA_TRAP, 160, 40);
ShowMessageAtScreenPos(MSG_kmr_12_sign_trap, 160, 40);
resume group 1;
SI_FLAG(0) = FALSE;
@ -201,7 +202,7 @@ Script N(ReadEastSign) = SCRIPT({
func_802D5830(1);
DisablePlayerInput(1);
ShowMessageAtScreenPos(MessageID_SIGN_GOOMBA_KINGS_FORTRESS_AHEAD, 160, 40);
ShowMessageAtScreenPos(MSG_kmr_12_sign_to_fortress, 160, 40);
DisablePlayerInput(0);
func_802D5830(0);
});

View File

@ -1,4 +1,5 @@
#include "kmr_12.h"
#include "message_ids.h"
Vec4f N(entryList)[] = {
{ -126.0f, 0.0f, 12.0f, 90.0f }, // west, towards Red/Blue Goomba miniboss room
@ -10,7 +11,7 @@ MapConfig N(config) = {
.entryList = N(entryList),
.entryCount = ENTRY_COUNT(N(entryList)),
.background = &gBackgroundImage,
.tattle = MessageID_TATTLE_KMR_12,
.tattle = MSG_kmr_12_tattle,
};
Script N(PlayMusic) = SCRIPT({

View File

@ -16,30 +16,38 @@ class Message:
if __name__ == "__main__":
if len(argv) < 3:
print("usage: combine.py [out.bin] [compiled...] --headers [out.h]")
print("usage: combine.py [out.bin] [out.h] [compiled...]")
exit(1)
_, outfile, *infiles = argv
_, outfile, header_file, *infiles = argv
messages = []
header_files = []
#header_files = []
for i, infile in enumerate(infiles):
if infile == "--headers":
header_files = infiles[i+1:]
break
# if infile == "--headers":
# header_files = infiles[i+1:]
# break
with open(infile, "rb") as f:
messages.extend(Message(msg, i) for msg in msgpack.unpack(f))
with open(outfile, "wb") as f:
# sectioned+indexed, followed by just sectioned, followed by just indexed, followed by named (unsectioned & unindexed)
messages.sort(key=lambda msg: bool(msg.section)<<2 + bool(msg.index))
#messages.sort(key=lambda msg: bool(msg.section)<<2 + bool(msg.index))
names = set()
sections = [] * 0x2E
messages_by_file = {}
sections = []
#messages_by_file = {}
# this logic could probably be a bit better (i.e. read ahead, so no overwriting happens)
def section_get_unused_id(section):
max_index = 0
for index in section:
if index > max_index:
max_index = index
return max_index + 1
for message in messages:
if message.section is None:
@ -47,35 +55,45 @@ if __name__ == "__main__":
for section_idx, section in enumerate(sections):
if len(section) < 0xFFF:
break
message.section = section_idx
else:
section_idx = message.section
while len(sections) <= section_idx:
sections.append([])
sections.append({})
section = sections[section_idx]
message.index = index = message.index if message.index is not None else len(section)
if message.index is None:
message.index = section_get_unused_id(section)
if message.name:
if message.name in names:
print(f"warning: multiple messages with name '{message.name}'")
print(f"error: multiple messages with name '{message.name}'")
exit(1)
else:
names.add(message.name)
if message.header_file_index in messages_by_file:
messages_by_file[message.header_file_index].add(message)
else:
messages_by_file[message.header_file_index] = set([message])
# if message.header_file_index in messages_by_file:
# messages_by_file[message.header_file_index].add(message)
# else:
# messages_by_file[message.header_file_index] = set([message])
section.append(message.bytes)
if message.index in section:
print(f"error: multiple messages allocated to id {section_idx:02X}:{message.index:03X}")
exit(1)
section[message.index] = message
f.seek((len(sections) + 1) * 4) # skip past table of contents
section_offsets = []
for section in sections:
# convert dict into sorted list
section = [msg for idx, msg in sorted(section.items(), key=lambda ele: ele[0])]
message_offsets = []
for message in section:
message_offsets.append(f.tell())
f.write(message)
f.write(message.bytes)
section_offset = f.tell()
section_offsets.append(section_offset)
@ -92,34 +110,17 @@ if __name__ == "__main__":
f.write(offset.to_bytes(4, byteorder="big"))
f.write(b'\0\0\0\0')
for i, header_file in enumerate(header_files):
messages = messages_by_file.get(i, [])
h = (
f"#ifndef _MESSAGE_IDS_{i}_H_\n"
f"#define _MESSAGE_IDS_{i}_H_\n"
with open(header_file, "w") as f:
f.write(
f"#ifndef _MESSAGE_IDS_H_\n"
f"#define _MESSAGE_IDS_H_\n"
"\n"
'#include "messages.h"\n'
"\n"
)
for message in messages:
h += f"#define MSG_{message.name} MESSAGE_ID({message.section}, {message.index})\n"
if message.name:
f.write(f"#define MSG_{message.name} MESSAGE_ID(0x{message.section:02X}, 0x{message.index:03X})\n")
h += "\n#endif\n"
h_lines = h.splitlines()
# this doesnt work properly with ninja. the build is fast enough anyway
"""
# only rewrite the header file if its content changed
with open(header_file, "r") as f:
cur_h_lines = f.read().splitlines()
is_different = cur_h_lines != h_lines
if is_different:
with open(header_file, "w") as f:
f.write(h)
"""
with open(header_file, "w") as f:
f.write(h)
f.write("\n#endif\n")

View File

@ -9467,7 +9467,7 @@ segments:
- 20_party_letters_luigi_diary
- 21_advice_fortunes
- 22_treasure_fortunes
- 23_item_descriptions # TODO: difference between 23,24,25
- 23_item_descriptions # TODO: difference between 23,24,25 (shops, menus, pickups?)
- 24_item_descriptions
- 25_item_descriptions
- 26_item_names
@ -9479,6 +9479,11 @@ segments:
- 2C_quiz_questions
- 2D_quiz_options
- 2E_credits
ids:
- [0x19, 0x03B, kmr_03_tattle]
- [0x19, 0x040, kmr_12_tattle]
- [0x1D, 0x167, kmr_12_sign_trap]
- [0x1D, 0x168, kmr_12_sign_to_fortress]
- [0x1C84D30, bin] # junk(?)
- [0x1E00000, bin] # junk (player sprite data; can be zeroed out with no effect)
- [0x1E40000, PaperMarioMapFS]

View File

@ -356,6 +356,7 @@ class N64SegPaperMarioMessages(N64Segment):
def __init__(self, segment, next_segment, options):
super().__init__(segment, next_segment, options)
self.files = segment.get("files", []) if type(segment) is dict else []
self.ids = segment["ids"]
def split(self, rom_bytes, base_path):
data = rom_bytes[self.rom_start: self.rom_end]
@ -401,7 +402,17 @@ class N64SegPaperMarioMessages(N64Segment):
for j, msg_offset in enumerate(msg_offsets):
if j != 0:
self.f.write("\n")
self.f.write(f"#message:{i:02X}:{j:03X} {{\n ")
msg_name = None
for section, index, goodname in self.ids:
if i == section and j == index:
msg_name = goodname
break
if msg_name is None:
self.f.write(f"#message:{i:02X}:{j:03X} {{\n ")
else:
self.f.write(f"#message:{i:02X}:({msg_name}) {{\n ")
self.write_message_markup(data[msg_offset:])
self.f.write("\n}\n")