diff --git a/configure.py b/configure.py index 55ca69a90a..f0925b9da9 100755 --- a/configure.py +++ b/configure.py @@ -263,7 +263,7 @@ async def main(): # KMC gcc doesn't support input on stdin, so a temp file has to be made for the preprocessor output n.rule("cc_kmc", command=f"bash -o pipefail -c '{cpp} -Iver/$version/build/include -Iinclude -Iinclude/PR -Isrc -D _LANGUAGE_C -D _FINALROM -D VERSION=$version -ffreestanding -DF3DEX_GBI_2 -D_MIPS_SZLONG=32 {args.cflags} -MD -MF $out.d $in -o $out.i && export WINEPATH=tools/kmc/BIN && wine exew32 gcc -O3 -c -G0 -mgp32 -mfp32 -mips3 $out.i -o $out' && {cross}strip $out -N $in", - description="dsl $in", + description="kmc $in", depfile="$out.d", deps="gcc") n.newline() diff --git a/tools/splat/.gitrepo b/tools/splat/.gitrepo index 3e510e041d..c286b3bc36 100644 --- a/tools/splat/.gitrepo +++ b/tools/splat/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/ethteck/splat.git branch = master - commit = db0b6f0cba3e07edac25fdb38ae30d2bd52044ca - parent = b97c4c139cd95cda596c9ee5097ccd1efa37185a + commit = 90fae1a8294eb42912717db587ff070474a307f8 + parent = 886a779bdb282646459e9f58c65454fbf6a6dfda method = merge cmdver = 0.4.3 diff --git a/tools/splat/segtypes/n64/ci4.py b/tools/splat/segtypes/n64/ci4.py index 349423c506..dba33b1fec 100644 --- a/tools/splat/segtypes/n64/ci4.py +++ b/tools/splat/segtypes/n64/ci4.py @@ -2,7 +2,7 @@ from segtypes.n64.ci8 import N64SegCi8 class N64SegCi4(N64SegCi8): @staticmethod - def parse_image(data, width, height): + def parse_image(data, width, height, flip_h=False, flip_v=False): img_data = bytearray() for i in range(width * height // 2): diff --git a/tools/splat/segtypes/n64/ci8.py b/tools/splat/segtypes/n64/ci8.py index 87572ab9a8..236244c837 100644 --- a/tools/splat/segtypes/n64/ci8.py +++ b/tools/splat/segtypes/n64/ci8.py @@ -16,7 +16,7 @@ class N64SegCi8(N64SegRgba16): data = rom_bytes[self.rom_start: self.rom_end] - self.image = self.parse_image(data, self.width, self.height) + self.image = self.__class__.parse_image(data, self.width, self.height, self.flip_horizontal, self.flip_vertical) def postsplit(self, segments): palettes = [seg for seg in segments if seg.type == @@ -51,7 +51,7 @@ class N64SegCi8(N64SegRgba16): f"No unnamed palette for {self.name}; wrote image data to {self.path}") @staticmethod - def parse_image(data, width, height): + def parse_image(data, width, height, flip_h=False, flip_v=False): return data def max_length(self): diff --git a/tools/splat/segtypes/n64/code.py b/tools/splat/segtypes/n64/code.py index 9a547ea418..24e7f5edbf 100644 --- a/tools/splat/segtypes/n64/code.py +++ b/tools/splat/segtypes/n64/code.py @@ -1,5 +1,6 @@ import os import re +from segtypes.n64.rgba16 import N64SegRgba16 import sys from collections import OrderedDict from pathlib import Path, PurePath @@ -8,6 +9,12 @@ import png from capstone import * from capstone.mips import * from segtypes.n64.ci4 import N64SegCi4 +from segtypes.n64.ci8 import N64SegCi8 +from segtypes.n64.i4 import N64SegI4 +from segtypes.n64.i8 import N64SegI8 +from segtypes.n64.ia4 import N64SegIa4 +from segtypes.n64.ia8 import N64SegIa8 +from segtypes.n64.ia16 import N64SegIa16 from segtypes.n64.palette import N64SegPalette from segtypes.n64.segment import N64Segment from segtypes.segment import Segment @@ -126,6 +133,18 @@ class Subsegment(): return PaletteSubsegment elif typ == "rgba32": return RGBA32Subsegment + elif typ == "rgba16": + return RGBA16Subsegment + elif typ == "i4": + return I4Subsegment + elif typ == "i8": + return I8Subsegment + elif typ == "ia4": + return Ia4Subsegment + elif typ == "ia8": + return Ia8Subsegment + elif typ == "ia16": + return Ia16Subsegment elif typ == "linker": return LinkerSubsegment else: @@ -295,6 +314,96 @@ class RGBA32Subsegment(Subsegment): with open(generic_out_path, "wb") as f: w.write_array(f, image) +class RGBA16Subsegment(Subsegment): + def should_run(self): + return super().should_run() or options.mode_active("img") + + def split_inner(self, segment, rom_bytes, base_path, generic_out_path): + img_bytes = rom_bytes[self.rom_start : self.rom_end] + width, height = self.args + image = N64SegRgba16.parse_image(img_bytes, width, height) + + w = png.Writer(width, height, greyscale=False, alpha=True) + + Path(generic_out_path).parent.mkdir(parents=True, exist_ok=True) + with open(generic_out_path, "wb") as f: + w.write_array(f, image) + +class I4Subsegment(Subsegment): + def should_run(self): + return super().should_run() or options.mode_active("img") + + def split_inner(self, segment, rom_bytes, base_path, generic_out_path): + img_bytes = rom_bytes[self.rom_start : self.rom_end] + width, height = self.args + image = N64SegI4.parse_image(img_bytes, width, height) + + w = png.Writer(width, height, greyscale=True, alpha=False) + + Path(generic_out_path).parent.mkdir(parents=True, exist_ok=True) + with open(generic_out_path, "wb") as f: + w.write_array(f, image) + +class I8Subsegment(Subsegment): + def should_run(self): + return super().should_run() or options.mode_active("img") + + def split_inner(self, segment, rom_bytes, base_path, generic_out_path): + img_bytes = rom_bytes[self.rom_start : self.rom_end] + width, height = self.args + image = N64SegI8.parse_image(img_bytes, width, height) + + w = png.Writer(width, height, greyscale=True, alpha=False) + + Path(generic_out_path).parent.mkdir(parents=True, exist_ok=True) + with open(generic_out_path, "wb") as f: + w.write_array(f, image) + +class Ia4Subsegment(Subsegment): + def should_run(self): + return super().should_run() or options.mode_active("img") + + def split_inner(self, segment, rom_bytes, base_path, generic_out_path): + img_bytes = rom_bytes[self.rom_start : self.rom_end] + width, height = self.args + image = N64SegIa4.parse_image(img_bytes, width, height) + + w = png.Writer(width, height, greyscale=True, alpha=True) + + Path(generic_out_path).parent.mkdir(parents=True, exist_ok=True) + with open(generic_out_path, "wb") as f: + w.write_array(f, image) + +class Ia8Subsegment(Subsegment): + def should_run(self): + return super().should_run() or options.mode_active("img") + + def split_inner(self, segment, rom_bytes, base_path, generic_out_path): + img_bytes = rom_bytes[self.rom_start : self.rom_end] + width, height = self.args + image = N64SegIa8.parse_image(img_bytes, width, height) + + w = png.Writer(width, height, greyscale=True, alpha=True) + + Path(generic_out_path).parent.mkdir(parents=True, exist_ok=True) + with open(generic_out_path, "wb") as f: + w.write_array(f, image) + +class Ia16Subsegment(Subsegment): + def should_run(self): + return super().should_run() or options.mode_active("img") + + def split_inner(self, segment, rom_bytes, base_path, generic_out_path): + img_bytes = rom_bytes[self.rom_start : self.rom_end] + width, height = self.args + image = N64SegIa16.parse_image(img_bytes, width, height) + + w = png.Writer(width, height, greyscale=True, alpha=True) + + Path(generic_out_path).parent.mkdir(parents=True, exist_ok=True) + with open(generic_out_path, "wb") as f: + w.write_array(f, image) + class N64SegCode(N64Segment): palettes = {} @@ -1050,7 +1159,10 @@ class N64SegCode(N64Segment): width, height = sub.args for palette in self.palettes[sub.name]: - image = N64SegCi4.parse_image(img_bytes, width, height) + if sub.type == "ci4": + image = N64SegCi4.parse_image(img_bytes, width, height) + elif sub.type == "ci8": + image = N64SegCi8.parse_image(img_bytes, width, height) w = png.Writer(width, height, palette=palette.palette) diff --git a/tools/splat/segtypes/n64/i4.py b/tools/splat/segtypes/n64/i4.py index 4b597f10f6..3da22262fa 100644 --- a/tools/splat/segtypes/n64/i4.py +++ b/tools/splat/segtypes/n64/i4.py @@ -4,12 +4,13 @@ from math import ceil class N64SegI4(N64SegRgba16): def png_writer(self): - return png.Writer(self.width, self.height, greyscale = True) + return png.Writer(self.width, self.height, greyscale=True) - def parse_image(self, data): + @staticmethod + def parse_image(data, width, height, flip_h=False, flip_v=False): img = bytearray() - for x, y, i in self.iter_image_indexes(0.5, 1): + for x, y, i in N64SegRgba16.iter_image_indexes(width, height, 0.5, 1, flip_h, flip_v): b = data[i] i1 = (b >> 4) & 0xF diff --git a/tools/splat/segtypes/n64/i8.py b/tools/splat/segtypes/n64/i8.py index adbeca3924..1496331863 100644 --- a/tools/splat/segtypes/n64/i8.py +++ b/tools/splat/segtypes/n64/i8.py @@ -2,7 +2,8 @@ from segtypes.n64.i4 import N64SegI4 from math import ceil class N64SegI8(N64SegI4): - def parse_image(self, data): + @staticmethod + def parse_image(data, width, height, flip_h=False, flip_v=False): return data def max_length(self): diff --git a/tools/splat/segtypes/n64/ia16.py b/tools/splat/segtypes/n64/ia16.py index 07d957165d..08baa8bea7 100644 --- a/tools/splat/segtypes/n64/ia16.py +++ b/tools/splat/segtypes/n64/ia16.py @@ -1,6 +1,6 @@ from segtypes.n64.ia4 import N64SegIa4 -class N64SegIa8(N64SegIa4): +class N64SegIa16(N64SegIa4): def parse_image(self, data): return data diff --git a/tools/splat/segtypes/n64/ia4.py b/tools/splat/segtypes/n64/ia4.py index ca285abb14..a7c9a9be85 100644 --- a/tools/splat/segtypes/n64/ia4.py +++ b/tools/splat/segtypes/n64/ia4.py @@ -4,12 +4,13 @@ from math import ceil class N64SegIa4(N64SegRgba16): def png_writer(self): - return png.Writer(self.width, self.height, greyscale = True, alpha = True) + return png.Writer(self.width, self.height, greyscale=True, alpha=True) - def parse_image(self, data): + @staticmethod + def parse_image(data, width, height, flip_h=False, flip_v=False): img = bytearray() - for x, y, i in self.iter_image_indexes(0.5, 1): + for x, y, i in N64SegRgba16.iter_image_indexes(width, height, 0.5, 1, flip_h, flip_v): b = data[i] h = (b >> 4) & 0xF diff --git a/tools/splat/segtypes/n64/ia8.py b/tools/splat/segtypes/n64/ia8.py index 0005abbca7..2cc7d89c5f 100644 --- a/tools/splat/segtypes/n64/ia8.py +++ b/tools/splat/segtypes/n64/ia8.py @@ -1,11 +1,13 @@ from segtypes.n64.ia4 import N64SegIa4 +from segtypes.n64.rgba16 import N64SegRgba16 from math import ceil class N64SegIa8(N64SegIa4): - def parse_image(self, data): + @staticmethod + def parse_image(data, width, height, flip_h=False, flip_v=False): img = bytearray() - for x, y, i in self.iter_image_indexes(): + for x, y, i in N64SegRgba16.iter_image_indexes(width, height, flip_h=flip_h, flip_v=flip_v): b = data[i] i = (b >> 4) & 0xF diff --git a/tools/splat/segtypes/n64/rgba16.py b/tools/splat/segtypes/n64/rgba16.py index 784c92097a..0303273ef7 100644 --- a/tools/splat/segtypes/n64/rgba16.py +++ b/tools/splat/segtypes/n64/rgba16.py @@ -37,14 +37,15 @@ class N64SegRgba16(N64Segment): def flip_horizontal(self): return self.flip == "both" or self.flip.startswith("h") or self.flip == "x" - def iter_image_indexes(self, bytes_per_x=1, bytes_per_y=1): - w = int(self.width * bytes_per_x) - h = int(self.height * bytes_per_y) + @staticmethod + def iter_image_indexes(width, height, bytes_per_x=1, bytes_per_y=1, flip_h=False, flip_v=False): + w = int(width * bytes_per_x) + h = int(height * bytes_per_y) xrange = range(w - ceil(bytes_per_x), -1, -ceil(bytes_per_x) - ) if self.flip_horizontal else range(0, w, ceil(bytes_per_x)) + ) if flip_h else range(0, w, ceil(bytes_per_x)) yrange = range(h - ceil(bytes_per_y), -1, -ceil(bytes_per_y) - ) if self.flip_vertical else range(0, h, ceil(bytes_per_y)) + ) if flip_v else range(0, h, ceil(bytes_per_y)) for y in yrange: for x in xrange: @@ -61,17 +62,18 @@ class N64SegRgba16(N64Segment): w = self.png_writer() with open(path, "wb") as f: - w.write_array(f, self.parse_image(data)) + w.write_array(f, self.parse_image(data, self.width, self.height, self.flip_horizontal, self.flip_vertical)) self.log(f"Wrote {self.name} to {path}") def png_writer(self): return png.Writer(self.width, self.height, greyscale=False, alpha=True) - def parse_image(self, data): + @staticmethod + def parse_image(data, width, height, flip_h=False, flip_v=False): img = bytearray() - for x, y, i in self.iter_image_indexes(2, 1): + for x, y, i in N64SegRgba16.iter_image_indexes(width, height, 2, 1, flip_h, flip_v): img += bytes(unpack_color(data[i:])) return img diff --git a/tools/splat/segtypes/n64/rgba32.py b/tools/splat/segtypes/n64/rgba32.py index 7a885d69d7..a101a668cb 100644 --- a/tools/splat/segtypes/n64/rgba32.py +++ b/tools/splat/segtypes/n64/rgba32.py @@ -1,7 +1,8 @@ from segtypes.n64.rgba16 import N64SegRgba16 class N64SegRgba32(N64SegRgba16): - def parse_image(self, data): + @staticmethod + def parse_image(data, width, height, flip_h=False, flip_v=False): return data def max_length(self): diff --git a/ver/us/splat.yaml b/ver/us/splat.yaml index c28749f859..f1c4301132 100644 --- a/ver/us/splat.yaml +++ b/ver/us/splat.yaml @@ -470,36 +470,36 @@ segments: - [0x140C70, c] - [0x1421C0, c] - [0x1422A0, data] - - [0x1443F0, ci8, pause/world_map, 320, 320] - - [0x15D3F0, palette, pause/world_map] - - [0x15D5F0, ci4, pause/spirits_bg, 128, 110] - - [0x15F170, palette, pause/spirits_bg] - - [0x15F370, rgba16, pause/filled_pip, 8, 8] - - [0x15F3F0, rgba16, pause/empty_pip, 8, 8] - - [0x15F470, rgba16, pause/red_pip, 8, 8] - - [0x15F4F0, bin] - - [0x15F570, ia8, pause/image_15F570, 16, 16] - - [0x15F670, ia8, pause/image_15F670, 16, 16] - - [0x15F770, ia8, pause/arrows, 16, 32] - - [0x15F970, ci4, pause/banner_hp, 64, 16] - - [0x15FB70, palette, pause/banner_hp] - - [0x15FD70, ci4, pause/banner_fp, 64, 16] - - [0x15FF70, palette, pause/banner_fp] - - [0x160170, ci4, pause/banner_bp, 64, 16] - - [0x160370, palette, pause/banner_bp] - - [0x160570, ci4, pause/banner_boots, 48, 16] - - [0x1606F0, palette, pause/banner_boots] - - [0x1608F0, ci4, pause/banner_hammer, 48, 16] - - [0x160A70, palette, pause/banner_hammer] - - [0x160C70, ci4, pause/banner_star_energy, 48, 16] - - [0x160DF0, palette, pause/banner_star_energy] - - [0x160FF0, ci4, pause/available, 64, 16] - - [0x1611F0, palette, pause/available] - - [0x1613F0, ci4, pause/prompt_check_abilities, 128, 16] - - [0x1617F0, palette, pause/prompt_check_abilities] - - [0x1619F0, ci4, pause/stats_bar, 160, 8] - - [0x161C70, palette, pause/stats_bar] - - [0x161E70, bin] + - [0x1443F0, ci8, pause/world_map, 320, 320] + - [0x15D3F0, palette, pause/world_map] + - [0x15D5F0, ci4, pause/spirits_bg, 128, 110] + - [0x15F170, palette, pause/spirits_bg] + - [0x15F370, rgba16, pause/filled_pip, 8, 8] + - [0x15F3F0, rgba16, pause/empty_pip, 8, 8] + - [0x15F470, rgba16, pause/red_pip, 8, 8] + - [0x15F4F0, bin] + - [0x15F570, ia8, pause/image_15F570, 16, 16] + - [0x15F670, ia8, pause/image_15F670, 16, 16] + - [0x15F770, ia8, pause/arrows, 16, 32] + - [0x15F970, ci4, pause/banner_hp, 64, 16] + - [0x15FB70, palette, pause/banner_hp] + - [0x15FD70, ci4, pause/banner_fp, 64, 16] + - [0x15FF70, palette, pause/banner_fp] + - [0x160170, ci4, pause/banner_bp, 64, 16] + - [0x160370, palette, pause/banner_bp] + - [0x160570, ci4, pause/banner_boots, 48, 16] + - [0x1606F0, palette, pause/banner_boots] + - [0x1608F0, ci4, pause/banner_hammer, 48, 16] + - [0x160A70, palette, pause/banner_hammer] + - [0x160C70, ci4, pause/banner_star_energy, 48, 16] + - [0x160DF0, palette, pause/banner_star_energy] + - [0x160FF0, ci4, pause/available, 64, 16] + - [0x1611F0, palette, pause/available] + - [0x1613F0, ci4, pause/prompt_check_abilities, 128, 16] + - [0x1617F0, palette, pause/prompt_check_abilities] + - [0x1619F0, ci4, pause/stats_bar, 160, 8] + - [0x161C70, palette, pause/stats_bar] + - [0x161E70, bin] - type: code start: 0x163400 vram: 0x80242BA0