Split charsets, matching load_font and load_font_data (#312)

Also use snake_case for splat_ext types
This commit is contained in:
alex 2021-07-16 10:28:37 +01:00 committed by GitHub
parent f02743e1cb
commit 7cf8bf0b88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 227 additions and 105 deletions

View File

@ -1,5 +1,7 @@
#include "common.h"
#include "ld_addrs.h"
// TODO consider symbol
#define MSG_ROM_START 0x1B83000
extern s16 gNextMessageBuffer;
@ -18,7 +20,8 @@ extern s32 D_802EE8D0;
extern s32 D_802F39D0;
extern s32 D_802F4560;
s32 _update_message(MessagePrintState*);
void load_font(s32 font);
s32 _update_message(MessagePrintState* printer);
void clear_character_set(void) {
D_80155C98 = -1;
@ -43,37 +46,24 @@ void clear_printers(void) {
load_font(0);
}
// needs rom split around 0x10F1B0
void load_font_data(s32 start, u16 size, s32* dest);
#ifdef NON_MATCHING
void load_font_data(s32 start, u16 size, s32* dest) {
u8* temp_a0;
void load_font_data(Addr offset, u16 size, void* dest) {
u8* base = charset_ROM_START + (s32) offset;
temp_a0 = start + 0x10F1B0;
dma_copy(temp_a0, temp_a0 + size, dest);
dma_copy(base, base + size, dest);
}
#else
INCLUDE_ASM(void, "msg", load_font_data, s32 start, u16 size, s32* dest);
#endif
// Needs symbols for font offsets
#ifdef NON_MATCHING
void load_font(s32 font) {
if (font != D_80155C98) {
if (font == 0) {
load_font_data(0, 0x5100, &D_802EE8D0);
load_font_data(0x5300, 0x500, &D_802F4560);
load_font_data(charset_standard_OFFSET, 0x5100, &D_802EE8D0);
load_font_data(charset_standard_pal_OFFSET, 0x500, &D_802F4560);
} else if (font == 1) {
load_font_data(0x5800, 0xF60, &D_802ED970);
load_font_data(0x6760, 0xB88, &D_802F39D0);
load_font_data(0x72E8, 0x80, &D_802F4560);
load_font_data(charset_title_OFFSET, 0xF60, &D_802ED970);
load_font_data(charset_subtitle_OFFSET, 0xB88, &D_802F39D0);
load_font_data(charset_credits_pal_OFFSET, 0x80, &D_802F4560);
}
}
}
#else
INCLUDE_ASM(void, "msg", load_font, s32 font);
#endif
void load_font(s32 font);
void update_messages(void) {
s32 i;

View File

@ -175,6 +175,10 @@ def write_ninja_rules(ninja: ninja_syntax.Writer, cpp: str):
ninja.rule("map_header", command=f"$python {BUILD_TOOLS}/mapfs/map_header.py $in > $out")
ninja.rule("pm_charset", command=f"$python {BUILD_TOOLS}/pm_charset.py $out $in")
ninja.rule("pm_charset_palettes", command=f"$python {BUILD_TOOLS}/pm_charset_palettes.py $out $in")
def write_ninja_for_tools(ninja: ninja_syntax.Writer):
ninja.rule("cc_tool",
description="cc_tool $in",
@ -195,7 +199,7 @@ class Configure:
modes = ["ld"]
if assets:
modes.extend(["bin", "Yay0", "img", "PaperMarioMapFS", "PaperMarioMessages", "PaperMarioNpcSprites"])
modes.extend(["bin", "Yay0", "img", "pm_map_data", "pm_msg", "pm_npc_sprites", "pm_charset", "pm_charset_palettes"])
if code:
modes.extend(["code", "c", "data", "rodata"])
@ -385,7 +389,7 @@ class Configure:
"img_flags": "",
})
build(entry.object_path, [bin_path], "bin")
elif seg.type == "PaperMarioNpcSprites":
elif seg.type == "pm_npc_sprites":
sprite_yay0s = []
for sprite_id, sprite_dir in enumerate(entry.src_paths, 1):
@ -412,7 +416,7 @@ class Configure:
build(entry.object_path.with_suffix(".bin"), sprite_yay0s, "sprite_combine")
build(entry.object_path, [entry.object_path.with_suffix(".bin")], "bin")
elif seg.type == "PaperMarioMessages":
elif seg.type == "pm_msg":
msg_bins = []
for section_idx, msg_path in enumerate(entry.src_paths):
@ -425,7 +429,7 @@ class Configure:
self.build_path() / "include" / "message_ids.h",
], msg_bins, "msg_combine")
build(entry.object_path, [entry.object_path.with_suffix(".bin")], "bin")
elif seg.type == "PaperMarioMapFS":
elif seg.type == "pm_map_data":
bin_yay0s: List[Path] = [] # flat list of (uncompressed path, compressed? path) pairs
src_dir = Path("assets/x") / seg.name
@ -511,6 +515,34 @@ class Configure:
# combine
build(entry.object_path.with_suffix(""), bin_yay0s, "mapfs")
build(entry.object_path, [entry.object_path.with_suffix("")], "bin")
elif seg.type == "pm_charset":
rasters = []
for src_path in entry.src_paths:
out_path = self.build_path() / seg.dir / seg.name / (src_path.stem + ".bin")
build(out_path, [src_path], "img", variables={
"img_type": "ci4",
"img_flags": "",
})
rasters.append(out_path)
build(entry.object_path.with_suffix(""), rasters, "pm_charset")
build(entry.object_path, [entry.object_path.with_suffix("")], "bin")
elif seg.type == "pm_charset_palettes":
palettes = []
for src_path in entry.src_paths:
out_path = self.build_path() / seg.dir / seg.name / "palette" / (src_path.stem + ".bin")
build(out_path, [src_path], "img", variables={
"img_type": "palette",
"img_flags": "",
})
palettes.append(out_path)
build(entry.object_path.with_suffix(""), palettes, "pm_charset_palettes")
build(entry.object_path, [entry.object_path.with_suffix("")], "bin")
elif seg.type == "linker" or seg.type == "linker_offset":
pass
else:
raise Exception(f"don't know how to build {seg.__class__.__name__} '{seg.name}'")

14
tools/build/pm_charset.py Normal file
View File

@ -0,0 +1,14 @@
#! /usr/bin/python3
from sys import argv
if __name__ == "__main__":
argv.pop(0) # python3
out = argv.pop(0)
with open(out, "wb") as f:
for path in argv:
with open(path, "rb") as j:
f.write(j.read())
while f.tell() % 8 != 0:
f.write(b'\0')

View File

@ -0,0 +1,12 @@
#! /usr/bin/python3
from sys import argv
if __name__ == "__main__":
argv.pop(0) # python3
out = argv.pop(0)
with open(out, "wb") as f:
for path in argv:
with open(path, "rb") as j:
f.write(j.read())

View File

@ -4,7 +4,7 @@ from sys import argv, path
from pathlib import Path
path.append(str(Path(__file__).parent.parent.parent / "splat"))
path.append(str(Path(__file__).parent.parent.parent / "splat_ext"))
from PaperMarioNpcSprites import Sprite
from pm_npc_sprites import Sprite
if __name__ == "__main__":
if len(argv) < 4:

View File

@ -5,7 +5,7 @@ from sys import argv, path
from pathlib import Path
path.append(str(Path(__file__).parent.parent.parent / "splat"))
path.append(str(Path(__file__).parent.parent.parent / "splat_ext"))
from PaperMarioNpcSprites import Sprite
from pm_npc_sprites import Sprite
def pack_color(r, g, b, a):
r = floor(31 * (r / 255))

View File

@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/ethteck/splat.git
branch = master
commit = cc58f64954e8b7b2369b03db1152b161e6ccb78b
parent = c4e441d9ab91a2f63d7563c034772150934b48a1
commit = 8588eaae7b57f6eab91e3aa5df2bce4affa84308
parent = 00d93ef991911893fadc245169fc8b8f1dfddd68
method = merge
cmdver = 0.4.3

View File

@ -5,7 +5,7 @@ default: all
all: Yay0decompress
Yay0decompress:
gcc $(UTIL_DIR)/n64/Yay0decompress.c -fPIC -shared -O3 -o $(UTIL_DIR)/n64/Yay0decompress
gcc $(UTIL_DIR)/n64/Yay0decompress.c -fPIC -shared -O3 -Wall -Wextra -o $(UTIL_DIR)/n64/Yay0decompress
clean:
rm -f $(UTIL_DIR)/n64/Yay0decompress

View File

@ -42,7 +42,7 @@ class LinkerEntry:
self.segment = segment
self.src_paths = [clean_up_path(p) for p in src_paths]
self.section = section
if self.section == "linker":
if self.section == "linker" or self.section == "linker_offset":
self.object_path = None
else:
self.object_path = path_to_object_path(object_path)
@ -84,6 +84,9 @@ class LinkerWriter():
self._end_block()
self._begin_segment(entry.segment)
continue
elif cur_section == "linker_offset":
self._write_symbol(f"{get_segment_cname(entry.segment)}_OFFSET", f". - {get_segment_cname(segment)}_ROM_START")
continue
# text/data/bss START/END labels
if not data_started and ("data" in cur_section or "rodata" in cur_section):

View File

@ -29,7 +29,7 @@ class N64SegData(N64SegCodeSubsegment, N64SegGroup):
def split(self, rom_bytes: bytes):
N64SegGroup.split(self, rom_bytes)
if self.file_text:
if not self.type.startswith(".") and self.file_text:
path = self.out_path()
if path:

View File

@ -0,0 +1,8 @@
from segtypes.n64.segment import N64Segment
class N64SegLinker_offset(N64Segment):
def get_linker_entries(self):
from segtypes.linker_entry import LinkerEntry
return [LinkerEntry(self, [], self.name, "linker_offset")]

View File

@ -36,7 +36,8 @@ void decompress(Yay0Header* hdr, uint8_t* srcPtr, uint8_t* dstPtr, bool isBigEnd
written += copy = (op >> 12) ? (2 + (op >> 12)) : (18 + *data++);
while (copy--) {
*dstPtr++ = dstPtr[-(op & 0xfff) - 1];
*dstPtr = dstPtr[-(op & 0xfff) - 1];
dstPtr++;
}
}
}

View File

@ -0,0 +1,61 @@
from segtypes.n64.segment import N64Segment
from util import options
import png
def parse_ci4(data, width, height):
raster = bytearray()
for i in range(width * height // 2):
raster.append(data[i] >> 4)
raster.append(data[i] & 0xF)
return raster
def next_8(n):
if n % 8 != 0:
return next_8(n + 1)
else:
return n
class N64SegPm_charset(N64Segment):
def scan(self, rom_bytes):
data = rom_bytes[self.rom_start:self.rom_end]
# start, type, name, WIDTH, HEIGHT, NUM_RASTERS
self.width = self.yaml[3]
self.height = self.yaml[4]
# pm_charset_palettes sibling
self.sibling = next(filter(lambda s: s.type == "pm_charset_palettes" and s.name == self.name, self.parent.subsegments))
self.rasters = []
for i in range(0, self.size, next_8(self.width * self.height // 2)):
raster = parse_ci4(data[i:], self.width, self.height)
self.rasters.append(raster)
def split(self, rom_bytes):
fs_dir = options.get_asset_path() / self.dir / self.name
fs_dir.mkdir(parents=True, exist_ok=True)
for i, raster in enumerate(self.rasters):
palette = self.sibling.palettes[0]
w = png.Writer(self.width, self.height, palette=palette)
with open(fs_dir / f"{i:02X}.png", "wb") as f:
w.write_array(f, raster)
def get_linker_entries(self):
from segtypes.linker_entry import LinkerEntry
# start, type, name, WIDTH, HEIGHT
self.width = self.yaml[3]
self.height = self.yaml[4]
fs_dir = options.get_asset_path() / self.dir / self.name
return [LinkerEntry(
self,
[fs_dir / f"{i:02X}.png" for i in range(self.yaml[5])],
fs_dir.with_suffix(".dat"), ".data"),
]

View File

@ -0,0 +1,50 @@
from segtypes.n64.segment import N64Segment
from util.color import unpack_color
from util.iter import iter_in_groups
from util import options
import png
def parse_palette(data):
palette = []
for a, b in iter_in_groups(data, 2):
palette.append(unpack_color([a, b]))
return palette
class N64SegPm_charset_palettes(N64Segment):
require_unique_name = False
def scan(self, rom_bytes):
data = rom_bytes[self.rom_start:self.rom_end]
# pm_charset sibling
self.sibling = next(filter(lambda s: s.type == "pm_charset" and s.name == self.name, self.parent.subsegments))
self.palettes = []
for i in range(0, self.size, 0x10):
palette = parse_palette(data[i : i + 0x10])
self.palettes.append(palette)
def split(self, rom_bytes):
fs_dir = options.get_asset_path() / self.dir / self.name / "palette"
fs_dir.mkdir(parents=True, exist_ok=True)
for i, palette in enumerate(self.palettes):
raster = self.sibling.rasters[0]
w = png.Writer(self.sibling.width, self.sibling.height, palette=palette)
with open(fs_dir / f"{i:02X}.png", "wb") as f:
w.write_array(f, raster)
def get_linker_entries(self):
from segtypes.linker_entry import LinkerEntry
fs_dir = options.get_asset_path() / self.dir / self.name / "palette"
return [LinkerEntry(
self,
[fs_dir / f"{i:02X}.png" for i in range(self.yaml[3])],
fs_dir.with_suffix(".dat"), ".data"),
]

View File

@ -36,7 +36,7 @@ def add_file_ext(name: str) -> str:
else:
return name + ".bin"
class N64SegPaperMarioMapFS(N64Segment):
class N64SegPm_map_data(N64Segment):
def __init__(self, rom_start, rom_end, type, name, vram_start, extract, given_subalign, given_is_overlay, given_dir, args, yaml):
super().__init__(rom_start, rom_end, type, name, vram_start, extract, given_subalign, given_is_overlay, given_dir, args, yaml)

View File

@ -366,7 +366,7 @@ CHARSET_CREDITS = {
0xF7: " ",
}
class N64SegPaperMarioMessages(N64Segment):
class N64SegPm_msg(N64Segment):
def __init__(self, rom_start, rom_end, type, name, vram_start, extract, given_subalign, given_is_overlay, given_dir, args, yml):
super().__init__(rom_start, rom_end, type, name, vram_start, extract, given_subalign, given_is_overlay, given_dir, args, yml)

View File

@ -250,7 +250,7 @@ class Component:
return self
class N64SegPaperMarioNpcSprites(N64Segment):
class N64SegPm_npc_sprites(N64Segment):
DEFAULT_SPRITE_NAMES = [f"{i:02X}" for i in range(0xEA)]
def __init__(self, rom_start, rom_end, type, name, vram_start, extract, given_subalign, given_is_overlay, given_dir, args, yml):

View File

@ -1,48 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel load_font
/* B9E34 80123734 3C028015 */ lui $v0, %hi(D_80155C98)
/* B9E38 80123738 84425C98 */ lh $v0, %lo(D_80155C98)($v0)
/* B9E3C 8012373C 27BDFFE8 */ addiu $sp, $sp, -0x18
/* B9E40 80123740 10820022 */ beq $a0, $v0, .L801237CC
/* B9E44 80123744 AFBF0010 */ sw $ra, 0x10($sp)
/* B9E48 80123748 1480000B */ bnez $a0, .L80123778
/* B9E4C 8012374C 24020001 */ addiu $v0, $zero, 1
/* B9E50 80123750 3C040000 */ lui $a0, 0
/* B9E54 80123754 24840000 */ addiu $a0, $a0, 0
/* B9E58 80123758 3C06802F */ lui $a2, %hi(D_802EE8D0)
/* B9E5C 8012375C 24C6E8D0 */ addiu $a2, $a2, %lo(D_802EE8D0)
/* B9E60 80123760 0C048DC2 */ jal load_font_data
/* B9E64 80123764 24055100 */ addiu $a1, $zero, 0x5100
/* B9E68 80123768 3C040000 */ lui $a0, 0
/* B9E6C 8012376C 24845300 */ addiu $a0, $a0, 0x5300
/* B9E70 80123770 08048DEF */ j .L801237BC
/* B9E74 80123774 24050500 */ addiu $a1, $zero, 0x500
.L80123778:
/* B9E78 80123778 14820014 */ bne $a0, $v0, .L801237CC
/* B9E7C 8012377C 00000000 */ nop
/* B9E80 80123780 3C040000 */ lui $a0, 0
/* B9E84 80123784 24845800 */ addiu $a0, $a0, 0x5800
/* B9E88 80123788 3C06802F */ lui $a2, %hi(D_802ED970)
/* B9E8C 8012378C 24C6D970 */ addiu $a2, $a2, %lo(D_802ED970)
/* B9E90 80123790 0C048DC2 */ jal load_font_data
/* B9E94 80123794 24050F60 */ addiu $a1, $zero, 0xf60
/* B9E98 80123798 3C040000 */ lui $a0, 0
/* B9E9C 8012379C 24846760 */ addiu $a0, $a0, 0x6760
/* B9EA0 801237A0 3C06802F */ lui $a2, %hi(D_802F39D0)
/* B9EA4 801237A4 24C639D0 */ addiu $a2, $a2, %lo(D_802F39D0)
/* B9EA8 801237A8 0C048DC2 */ jal load_font_data
/* B9EAC 801237AC 24050B88 */ addiu $a1, $zero, 0xb88
/* B9EB0 801237B0 3C040000 */ lui $a0, 0
/* B9EB4 801237B4 248472E8 */ addiu $a0, $a0, 0x72e8
/* B9EB8 801237B8 24050080 */ addiu $a1, $zero, 0x80
.L801237BC:
/* B9EBC 801237BC 3C06802F */ lui $a2, %hi(D_802F4560)
/* B9EC0 801237C0 24C64560 */ addiu $a2, $a2, %lo(D_802F4560)
/* B9EC4 801237C4 0C048DC2 */ jal load_font_data
/* B9EC8 801237C8 00000000 */ nop
.L801237CC:
/* B9ECC 801237CC 8FBF0010 */ lw $ra, 0x10($sp)
/* B9ED0 801237D0 03E00008 */ jr $ra
/* B9ED4 801237D4 27BD0018 */ addiu $sp, $sp, 0x18

View File

@ -1,15 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel load_font_data
/* B9E08 80123708 27BDFFE8 */ addiu $sp, $sp, -0x18
/* B9E0C 8012370C 3C020011 */ lui $v0, 0x11
/* B9E10 80123710 2442F1B0 */ addiu $v0, $v0, -0xe50
/* B9E14 80123714 00822021 */ addu $a0, $a0, $v0
/* B9E18 80123718 30A5FFFF */ andi $a1, $a1, 0xffff
/* B9E1C 8012371C AFBF0010 */ sw $ra, 0x10($sp)
/* B9E20 80123720 0C00A5CF */ jal dma_copy
/* B9E24 80123724 00852821 */ addu $a1, $a0, $a1
/* B9E28 80123728 8FBF0010 */ lw $ra, 0x10($sp)
/* B9E2C 8012372C 03E00008 */ jr $ra
/* B9E30 80123730 27BD0018 */ addiu $sp, $sp, 0x18

View File

@ -458,8 +458,22 @@ segments:
start: 0x10CC10
vram: 0x802EB3D0
subsegments:
- [0x10CC10, data]
- [0x10F1B0, bin]
- [0x10CC10, data] # font width data
- type: group
dir: charset
start: 0x10F1B0
subsegments:
- [0x10F1B0, linker_offset, standard]
- [0x10F1B0, pm_charset, standard, 16, 16, 0xA6]
- [0x1144B0, linker_offset, standard_pal]
- [0x1144B0, pm_charset_palettes, standard, 0x50]
- [0x1149B0, linker_offset, title]
- [0x1149B0, pm_charset, title, 12, 15, 0x29]
- [0x115910, linker_offset, subtitle]
- [0x115910, pm_charset, subtitle, 12, 12, 0x29]
- [0x116498, linker_offset, credits_pal]
- [0x116498, pm_charset_palettes, subtitle, 1]
- [0x1164A8, pm_charset_palettes, title, 1]
- [0x1164B8, ci8, peach_letter, 150, 105]
- [0x11A240, palette, peach_letter]
- [0x11A440, bin]
@ -10376,7 +10390,7 @@ segments:
- [0x19E5950, Yay0]
- [0x19E62A0, Yay0]
- start: 0x19E67B8
type: PaperMarioNpcSprites
type: pm_npc_sprites
dir: sprite
name: npc
files:
@ -10615,7 +10629,7 @@ segments:
- leaf
- [0x1B82208, bin]
- start: 0x1B83000
type: PaperMarioMessages
type: pm_msg
files:
- 00_introduction
- 01_postgame_celebration
@ -10667,7 +10681,7 @@ segments:
- [0x1C84D30, bin] # junk(?)
- [0x1E00000, bin] # junk (player sprite data; can be zeroed out with no effect)
- name: mapfs
type: PaperMarioMapFS
type: pm_map_data
start: 0x1E40000
files:
- dro_01_shape