mirror of
https://github.com/pmret/papermario.git
synced 2024-11-08 12:02:30 +01:00
More image splits (#272)
* A number of new image splits * Address comments. * git subrepo pull --force --branch=imgflip tools/splat subrepo: subdir: "tools/splat" merged: "9caaa45df9" upstream: origin: "https://github.com/ethteck/splat.git" branch: "imgflip" commit: "9caaa45df9" git-subrepo: version: "0.4.3" origin: "???" commit: "???" * use flip_y over flip * git subrepo pull --force --branch=imgflip tools/splat subrepo: subdir: "tools/splat" merged: "ef663ec0d5" upstream: origin: "https://github.com/ethteck/splat.git" branch: "imgflip" commit: "ef663ec0d5" git-subrepo: version: "0.4.3" origin: "???" commit: "???" * use flip_y * git subrepo pull --force --branch=imgflip tools/splat subrepo: subdir: "tools/splat" merged: "3144dc17f6" upstream: origin: "https://github.com/ethteck/splat.git" branch: "imgflip" commit: "3144dc17f6" git-subrepo: version: "0.4.3" origin: "???" commit: "???" Co-authored-by: JoshDuMan <Joshua.Shoup.1996@gmail.com>
This commit is contained in:
parent
a3e4140101
commit
9900e9a2b8
@ -50,8 +50,14 @@ class Converter():
|
|||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.infile = infile
|
self.infile = infile
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
|
self.flip_x = "--flip-x" in argv
|
||||||
self.flip_y = "--flip-y" in argv
|
self.flip_y = "--flip-y" in argv
|
||||||
|
|
||||||
|
if self.flip_y:
|
||||||
|
print(self.infile)
|
||||||
|
|
||||||
|
assert self.flip_x == False, "flip_x is not supported"
|
||||||
|
|
||||||
self.warned = False
|
self.warned = False
|
||||||
|
|
||||||
def warn(self, msg):
|
def warn(self, msg):
|
||||||
@ -250,7 +256,7 @@ class Converter():
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(argv) < 4:
|
if len(argv) < 4:
|
||||||
print("usage: build.py MODE INFILE OUTFILE [--flip-y]")
|
print("usage: build.py MODE INFILE OUTFILE [--flip-x] [--flip-y]")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
Converter(*argv[1:]).convert()
|
Converter(*argv[1:]).convert()
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
;
|
;
|
||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/ethteck/splat.git
|
remote = https://github.com/ethteck/splat.git
|
||||||
branch = master
|
branch = imgflip
|
||||||
commit = 5e36c4555865e8192653217ca75afe0da661651a
|
commit = 3144dc17f6fd77211e016cfbbc6a705f59b838e0
|
||||||
parent = e7de26b831ba89b66285a4847c8c28e562f19ca2
|
parent = 70e14bea15b1374095da723425d9b59a2ffb5915
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.3
|
cmdver = 0.4.3
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
# splat Release Notes
|
# splat Release Notes
|
||||||
|
|
||||||
## 0.7: The Path Update
|
## 0.7.1
|
||||||
|
|
||||||
|
* Image segment changes:
|
||||||
|
* Added `flip_x` and `flip_y` boolean parameters to replace `flip`.
|
||||||
|
* `flip` is deprecated and will produce a warning when used.
|
||||||
|
* Fixed flipping of `ci4` and `ci8` images.
|
||||||
|
* Fixed `extract: false` (and `start: auto`) behaviour.
|
||||||
|
|
||||||
|
## 0.7.0: The Path Update
|
||||||
|
|
||||||
* Significantly better performance, especially when using the cache feature (`--use-cache` CLI arg).
|
* Significantly better performance, especially when using the cache feature (`--use-cache` CLI arg).
|
||||||
* BREAKING: Some cli args for splat have been renamed. Please consult the usage output (-h or no args) for more information.
|
* BREAKING: Some cli args for splat have been renamed. Please consult the usage output (-h or no args) for more information.
|
||||||
|
@ -35,11 +35,8 @@ class LinkerEntry:
|
|||||||
def __init__(self, segment: Segment, src_paths: List[Path], object_path: Path, section: str):
|
def __init__(self, segment: Segment, src_paths: List[Path], object_path: Path, section: str):
|
||||||
self.segment = segment
|
self.segment = segment
|
||||||
self.src_paths = [clean_up_path(p) for p in src_paths]
|
self.src_paths = [clean_up_path(p) for p in src_paths]
|
||||||
|
self.object_path = path_to_object_path(object_path)
|
||||||
self.section = section
|
self.section = section
|
||||||
if self.section == "linker":
|
|
||||||
self.object_path = None
|
|
||||||
else:
|
|
||||||
self.object_path = path_to_object_path(object_path)
|
|
||||||
|
|
||||||
class LinkerWriter():
|
class LinkerWriter():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -65,7 +62,6 @@ class LinkerWriter():
|
|||||||
if entry.section == "linker": # TODO: isinstance is preferable
|
if entry.section == "linker": # TODO: isinstance is preferable
|
||||||
self._end_block()
|
self._end_block()
|
||||||
self._begin_segment(entry.segment)
|
self._begin_segment(entry.segment)
|
||||||
continue
|
|
||||||
|
|
||||||
start = entry.segment.rom_start
|
start = entry.segment.rom_start
|
||||||
if isinstance(start, int):
|
if isinstance(start, int):
|
||||||
|
@ -27,7 +27,7 @@ class N64SegAsm(N64SegCodeSubsegment):
|
|||||||
|
|
||||||
def scan(self, rom_bytes: bytes):
|
def scan(self, rom_bytes: bytes):
|
||||||
if self.rom_start != "auto" and self.rom_end != "auto" and self.rom_start != self.rom_end:
|
if self.rom_start != "auto" and self.rom_end != "auto" and self.rom_start != self.rom_end:
|
||||||
self.funcs_text = self.disassemble_code(rom_bytes, options.get("asm_endlabels", False))
|
self.funcs_text = self.disassemble_code(rom_bytes)
|
||||||
|
|
||||||
def split(self, rom_bytes: bytes):
|
def split(self, rom_bytes: bytes):
|
||||||
if not self.rom_start == self.rom_end:
|
if not self.rom_start == self.rom_end:
|
||||||
|
@ -135,7 +135,7 @@ class N64SegC(N64SegCodeSubsegment):
|
|||||||
c_lines = self.get_c_preamble()
|
c_lines = self.get_c_preamble()
|
||||||
|
|
||||||
for func in funcs_text:
|
for func in funcs_text:
|
||||||
func_name = self.parent.get_symbol(func, type="func", local_only=True).name
|
func_name = self.get_symbol(func, type="func", local_only=True).name
|
||||||
if options.get_compiler() == "GCC":
|
if options.get_compiler() == "GCC":
|
||||||
c_lines.append("INCLUDE_ASM(s32, \"{}\", {});".format(self.name, func_name))
|
c_lines.append("INCLUDE_ASM(s32, \"{}\", {});".format(self.name, func_name))
|
||||||
else:
|
else:
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
from segtypes.n64.ci8 import N64SegCi8
|
from segtypes.n64.ci8 import N64SegCi8
|
||||||
|
from util import iter
|
||||||
|
|
||||||
class N64SegCi4(N64SegCi8):
|
class N64SegCi4(N64SegCi8):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_image(data, width, height, flip_h=False, flip_v=False):
|
def parse_image(data, width, height, flip_h=False, flip_v=False):
|
||||||
img_data = bytearray()
|
img_data = bytearray()
|
||||||
|
|
||||||
for i in range(width * height // 2):
|
for x, y, i in iter.iter_image_indexes(width, height, 0.5, 1, flip_h, flip_v):
|
||||||
img_data.append(data[i] >> 4)
|
img_data.append(data[i] >> 4)
|
||||||
img_data.append(data[i] & 0xF)
|
img_data.append(data[i] & 0xF)
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ from segtypes.n64.rgba16 import N64SegRgba16
|
|||||||
import png
|
import png
|
||||||
from util import log
|
from util import log
|
||||||
from util import options
|
from util import options
|
||||||
|
from util import iter
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from segtypes.n64.palette import N64SegPalette as Palette
|
from segtypes.n64.palette import N64SegPalette as Palette
|
||||||
@ -35,7 +36,19 @@ class N64SegCi8(N64SegRgba16):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_image(data, width, height, flip_h=False, flip_v=False):
|
def parse_image(data, width, height, flip_h=False, flip_v=False):
|
||||||
return data
|
# hot path
|
||||||
|
if not flip_h and not flip_v:
|
||||||
|
return data
|
||||||
|
|
||||||
|
flipped_data = bytearray()
|
||||||
|
|
||||||
|
for x, y, i in iter.iter_image_indexes(width, height, 1, 1, flip_h, flip_v):
|
||||||
|
flipped_data.append(data[i])
|
||||||
|
|
||||||
|
return flipped_data
|
||||||
|
|
||||||
def max_length(self):
|
def max_length(self):
|
||||||
return self.width * self.height
|
return self.width * self.height
|
||||||
|
|
||||||
|
def cache(self):
|
||||||
|
return (self.config, self.rom_end, 1)
|
||||||
|
@ -39,7 +39,7 @@ class N64SegCodeSubsegment(Segment):
|
|||||||
def is_branch_insn(mnemonic):
|
def is_branch_insn(mnemonic):
|
||||||
return (mnemonic.startswith("b") and not mnemonic.startswith("binsl") and not mnemonic == "break") or mnemonic == "j"
|
return (mnemonic.startswith("b") and not mnemonic.startswith("binsl") and not mnemonic == "break") or mnemonic == "j"
|
||||||
|
|
||||||
def disassemble_code(self, rom_bytes, addsuffix=False):
|
def disassemble_code(self, rom_bytes):
|
||||||
insns = [insn for insn in N64SegCodeSubsegment.md.disasm(rom_bytes[self.rom_start : self.rom_end], self.vram_start)]
|
insns = [insn for insn in N64SegCodeSubsegment.md.disasm(rom_bytes[self.rom_start : self.rom_end], self.vram_start)]
|
||||||
|
|
||||||
funcs = self.process_insns(insns, self.rom_start)
|
funcs = self.process_insns(insns, self.rom_start)
|
||||||
@ -50,7 +50,7 @@ class N64SegCodeSubsegment(Segment):
|
|||||||
|
|
||||||
funcs = self.determine_symbols(funcs)
|
funcs = self.determine_symbols(funcs)
|
||||||
self.gather_jumptable_labels(rom_bytes)
|
self.gather_jumptable_labels(rom_bytes)
|
||||||
return self.add_labels(funcs, addsuffix)
|
return self.add_labels(funcs)
|
||||||
|
|
||||||
def process_insns(self, insns, rom_addr):
|
def process_insns(self, insns, rom_addr):
|
||||||
assert(isinstance(self.parent, N64SegCode))
|
assert(isinstance(self.parent, N64SegCode))
|
||||||
@ -243,6 +243,7 @@ class N64SegCodeSubsegment(Segment):
|
|||||||
if offset != 0:
|
if offset != 0:
|
||||||
offset_str = f"+0x{offset:X}"
|
offset_str = f"+0x{offset:X}"
|
||||||
|
|
||||||
|
|
||||||
if self.parent:
|
if self.parent:
|
||||||
self.parent.check_rodata_sym(func_addr, sym)
|
self.parent.check_rodata_sym(func_addr, sym)
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ class N64SegCodeSubsegment(Segment):
|
|||||||
ret[func_addr] = func
|
ret[func_addr] = func
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def add_labels(self, funcs, addsuffix):
|
def add_labels(self, funcs):
|
||||||
ret = {}
|
ret = {}
|
||||||
|
|
||||||
for func in funcs:
|
for func in funcs:
|
||||||
@ -311,9 +312,6 @@ class N64SegCodeSubsegment(Segment):
|
|||||||
if insn[0].mnemonic != "branch" and insn[0].mnemonic.startswith("b") or insn[0].mnemonic.startswith("j"):
|
if insn[0].mnemonic != "branch" and insn[0].mnemonic.startswith("b") or insn[0].mnemonic.startswith("j"):
|
||||||
indent_next = True
|
indent_next = True
|
||||||
|
|
||||||
if addsuffix:
|
|
||||||
func_text.append(f"endlabel {sym.name}")
|
|
||||||
|
|
||||||
ret[func] = (func_text, rom_addr)
|
ret[func] = (func_text, rom_addr)
|
||||||
|
|
||||||
if options.get("find_file_boundaries"):
|
if options.get("find_file_boundaries"):
|
||||||
@ -360,7 +358,7 @@ class N64SegCodeSubsegment(Segment):
|
|||||||
rom_offset += 4
|
rom_offset += 4
|
||||||
|
|
||||||
def should_scan(self) -> bool:
|
def should_scan(self) -> bool:
|
||||||
return options.mode_active("code")
|
return self.should_split()
|
||||||
|
|
||||||
def should_split(self) -> bool:
|
def should_split(self) -> bool:
|
||||||
return self.extract and options.mode_active("code")
|
return self.extract and options.mode_active("code")
|
||||||
|
@ -33,6 +33,13 @@ class N64SegData(N64SegCodeSubsegment):
|
|||||||
def get_linker_section(self) -> str:
|
def get_linker_section(self) -> str:
|
||||||
return ".data"
|
return ".data"
|
||||||
|
|
||||||
|
def get_linker_entries(self):
|
||||||
|
from segtypes.linker_entry import LinkerEntry
|
||||||
|
|
||||||
|
path = self.out_path()
|
||||||
|
|
||||||
|
return [LinkerEntry(self, [path], path, self.get_linker_section())]
|
||||||
|
|
||||||
def get_symbols(self):
|
def get_symbols(self):
|
||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
@ -141,7 +148,7 @@ class N64SegData(N64SegCodeSubsegment):
|
|||||||
return sym_str
|
return sym_str
|
||||||
|
|
||||||
def disassemble_data(self, rom_bytes):
|
def disassemble_data(self, rom_bytes):
|
||||||
rodata_encountered = "rodata" in self.type
|
rodata_encountered = self.type == "rodata"
|
||||||
ret = ".include \"macro.inc\"\n\n"
|
ret = ".include \"macro.inc\"\n\n"
|
||||||
ret += f'.section {self.get_linker_section()}'
|
ret += f'.section {self.get_linker_section()}'
|
||||||
|
|
||||||
@ -154,6 +161,9 @@ class N64SegData(N64SegCodeSubsegment):
|
|||||||
mnemonic = syms[i].access_mnemonic
|
mnemonic = syms[i].access_mnemonic
|
||||||
sym = self.parent.get_symbol(syms[i].vram_start, create=True, define=True, local_only=True)
|
sym = self.parent.get_symbol(syms[i].vram_start, create=True, define=True, local_only=True)
|
||||||
|
|
||||||
|
if sym.vram_start == 0x80097D90:
|
||||||
|
dog = 5
|
||||||
|
|
||||||
sym_str = f"\n\nglabel {sym.name}\n"
|
sym_str = f"\n\nglabel {sym.name}\n"
|
||||||
dis_start = self.parent.ram_to_rom(syms[i].vram_start)
|
dis_start = self.parent.ram_to_rom(syms[i].vram_start)
|
||||||
dis_end = self.parent.ram_to_rom(syms[i + 1].vram_start)
|
dis_end = self.parent.ram_to_rom(syms[i + 1].vram_start)
|
||||||
|
@ -57,6 +57,7 @@ class N64SegGroup(N64Segment):
|
|||||||
segment.parent = self
|
segment.parent = self
|
||||||
|
|
||||||
if segment.rom_start != "auto":
|
if segment.rom_start != "auto":
|
||||||
|
assert isinstance(segment.rom_start, int)
|
||||||
segment.vram_start = self.rom_to_ram(segment.rom_start)
|
segment.vram_start = self.rom_to_ram(segment.rom_start)
|
||||||
|
|
||||||
# TODO: assumes section order - generalize and stuff
|
# TODO: assumes section order - generalize and stuff
|
||||||
|
@ -2,10 +2,47 @@ from pathlib import Path
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
from segtypes.n64.segment import N64Segment
|
from segtypes.n64.segment import N64Segment
|
||||||
from util import options
|
from util import options
|
||||||
|
from util import log
|
||||||
|
|
||||||
class N64SegImg(N64Segment):
|
class N64SegImg(N64Segment):
|
||||||
|
def __init__(self, segment, rom_start, rom_end):
|
||||||
|
super().__init__(segment, rom_start, rom_end)
|
||||||
|
|
||||||
|
if type(segment) is dict:
|
||||||
|
if self.extract:
|
||||||
|
self.width = segment["width"]
|
||||||
|
self.height = segment["height"]
|
||||||
|
|
||||||
|
self.flip_horizontal = bool(segment.get("flip_x", False))
|
||||||
|
self.flip_vertical = bool(segment.get("flip_y", False))
|
||||||
|
|
||||||
|
if segment.get("flip"):
|
||||||
|
self.warn(f"'flip' parameter for img segments is deprecated; use flip_x and flip_y instead")
|
||||||
|
flip = segment.get("flip")
|
||||||
|
|
||||||
|
self.flip_vertical = flip == "both" or flip.startswith("v") or flip == "y"
|
||||||
|
self.flip_horizontal = flip == "both" or flip.startswith("h") or flip == "x"
|
||||||
|
else:
|
||||||
|
if self.extract:
|
||||||
|
if len(segment) < 5:
|
||||||
|
log.error(f"Error: {self.name} is missing width and height parameters")
|
||||||
|
self.width = segment[3]
|
||||||
|
self.height = segment[4]
|
||||||
|
|
||||||
|
self.flip_horizontal = False
|
||||||
|
self.flip_vertical = False
|
||||||
|
|
||||||
|
if self.extract and self.max_length() is not None:
|
||||||
|
expected_len = int(self.max_length())
|
||||||
|
actual_len = self.rom_end - self.rom_start
|
||||||
|
if actual_len > expected_len and actual_len - expected_len > self.subalign:
|
||||||
|
log.error(f"Error: {self.name} should end at 0x{self.rom_start + expected_len:X}, but it ends at 0x{self.rom_end:X}\n(hint: add a 'bin' segment after it)")
|
||||||
|
|
||||||
def out_path(self) -> Optional[Path]:
|
def out_path(self) -> Optional[Path]:
|
||||||
return options.get_asset_path() / self.dir / f"{self.name}.png"
|
return options.get_asset_path() / self.dir / f"{self.name}.png"
|
||||||
|
|
||||||
def should_split(self) -> bool:
|
def should_split(self) -> bool:
|
||||||
return self.extract and options.mode_active("img")
|
return self.extract and options.mode_active("img")
|
||||||
|
|
||||||
|
def max_length(self) -> Optional[int]:
|
||||||
|
return None
|
||||||
|
@ -27,17 +27,18 @@ class N64SegPalette(N64Segment):
|
|||||||
self.name.split(".")[0]
|
self.name.split(".")[0]
|
||||||
) if type(segment) is dict else self.name.split(".")[0]
|
) if type(segment) is dict else self.name.split(".")[0]
|
||||||
|
|
||||||
if self.rom_end == "auto":
|
if self.extract:
|
||||||
log.error(f"segment {self.name} needs to know where it ends; add a position marker [0xDEADBEEF] after it")
|
if self.rom_end == "auto":
|
||||||
|
log.error(f"segment {self.name} needs to know where it ends; add a position marker [0xDEADBEEF] after it")
|
||||||
|
|
||||||
if self.max_length() and isinstance(self.rom_end, int):
|
if self.max_length() and isinstance(self.rom_end, int):
|
||||||
expected_len = int(self.max_length())
|
expected_len = int(self.max_length())
|
||||||
actual_len = self.rom_end - self.rom_start
|
actual_len = self.rom_end - self.rom_start
|
||||||
if actual_len > expected_len and actual_len - expected_len > self.subalign:
|
if actual_len > expected_len and actual_len - expected_len > self.subalign:
|
||||||
log.error(f"Error: {self.name} should end at 0x{self.rom_start + expected_len:X}, but it ends at 0x{self.rom_end:X}\n(hint: add a 'bin' segment after it)")
|
log.error(f"Error: {self.name} should end at 0x{self.rom_start + expected_len:X}, but it ends at 0x{self.rom_end:X}\n(hint: add a 'bin' segment after it)")
|
||||||
|
|
||||||
def should_split(self):
|
def should_split(self):
|
||||||
return super().should_split() or options.mode_active("img")
|
return self.extract and (super().should_split() or options.mode_active("img"))
|
||||||
|
|
||||||
def out_path(self) -> Optional[Path]:
|
def out_path(self) -> Optional[Path]:
|
||||||
return options.get_asset_path() / self.dir / f"{self.name}.png"
|
return options.get_asset_path() / self.dir / f"{self.name}.png"
|
||||||
|
@ -7,37 +7,6 @@ from util.color import unpack_color
|
|||||||
|
|
||||||
# TODO: move common behaviour to N64ImgSegment and have all image segments extend that instead
|
# TODO: move common behaviour to N64ImgSegment and have all image segments extend that instead
|
||||||
class N64SegRgba16(N64SegImg):
|
class N64SegRgba16(N64SegImg):
|
||||||
def __init__(self, segment, rom_start, rom_end):
|
|
||||||
super().__init__(segment, rom_start, rom_end)
|
|
||||||
|
|
||||||
if type(segment) is dict:
|
|
||||||
self.width = segment["width"]
|
|
||||||
self.height = segment["height"]
|
|
||||||
self.flip = segment.get("flip", "noflip")
|
|
||||||
elif len(segment) < 5:
|
|
||||||
log.error("missing parameters")
|
|
||||||
else:
|
|
||||||
self.width = segment[3]
|
|
||||||
self.height = segment[4]
|
|
||||||
self.flip = "noflip"
|
|
||||||
|
|
||||||
if self.max_length():
|
|
||||||
expected_len = int(self.max_length())
|
|
||||||
actual_len = self.rom_end - self.rom_start
|
|
||||||
if actual_len > expected_len and actual_len - expected_len > self.subalign:
|
|
||||||
log.error(f"Error: {self.name} should end at 0x{self.rom_start + expected_len:X}, but it ends at 0x{self.rom_end:X}\n(hint: add a 'bin' segment after it)")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def flip_vertical(self):
|
|
||||||
return self.flip == "both" or self.flip.startswith("v") or self.flip == "y"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def flip_horizontal(self):
|
|
||||||
return self.flip == "both" or self.flip.startswith("h") or self.flip == "x"
|
|
||||||
|
|
||||||
def should_split(self):
|
|
||||||
return super().should_split() or options.mode_active("img")
|
|
||||||
|
|
||||||
def split(self, rom_bytes):
|
def split(self, rom_bytes):
|
||||||
path = self.out_path()
|
path = self.out_path()
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
@ -6,12 +6,12 @@ def iter_in_groups(iterable, n, fillvalue=None):
|
|||||||
return zip_longest(*args, fillvalue=fillvalue)
|
return zip_longest(*args, fillvalue=fillvalue)
|
||||||
|
|
||||||
def iter_image_indexes(width, height, bytes_per_x=1, bytes_per_y=1, flip_h=False, flip_v=False):
|
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)
|
w = int(width * bytes_per_x)
|
||||||
h = int(height * bytes_per_y)
|
h = int(height * bytes_per_y)
|
||||||
|
|
||||||
xrange = range(w - ceil(bytes_per_x), -1, -ceil(bytes_per_x)) if flip_h else range(0, w, ceil(bytes_per_x))
|
xrange = range(w - ceil(bytes_per_x), -1, -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 flip_v else range(0, h, ceil(bytes_per_y))
|
yrange = range(h - ceil(bytes_per_y), -1, -ceil(bytes_per_y)) if flip_v else range(0, h, ceil(bytes_per_y))
|
||||||
|
|
||||||
for y in yrange:
|
for y in yrange:
|
||||||
for x in xrange:
|
for x in xrange:
|
||||||
yield x, y, (y * w) + x
|
yield x, y, (y * w) + x
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import sys
|
import sys
|
||||||
from colorama import init, Fore, Style
|
from colorama import init, Fore, Style
|
||||||
from typing import Union
|
from typing import Optional
|
||||||
|
|
||||||
init(autoreset=True)
|
init(autoreset=True)
|
||||||
|
|
||||||
newline = True
|
newline = True
|
||||||
|
|
||||||
Status = Union[None, str]
|
Status = Optional[str]
|
||||||
|
|
||||||
def write(*args, status=None, **kwargs):
|
def write(*args, status=None, **kwargs):
|
||||||
global newline
|
global newline
|
||||||
|
@ -27,7 +27,7 @@ def get(opt, default=None):
|
|||||||
return opts.get(opt, default)
|
return opts.get(opt, default)
|
||||||
|
|
||||||
def get_platform() -> str:
|
def get_platform() -> str:
|
||||||
return opts.get("platform", "n64")
|
return opts.get("platform", "N64")
|
||||||
|
|
||||||
def get_compiler() -> str:
|
def get_compiler() -> str:
|
||||||
return opts.get("compiler", "IDO")
|
return opts.get("compiler", "IDO")
|
||||||
|
@ -2172,14 +2172,12 @@ segments:
|
|||||||
subsegments:
|
subsegments:
|
||||||
- [0x38F900, c]
|
- [0x38F900, c]
|
||||||
- [0x390340, bin]
|
- [0x390340, bin]
|
||||||
- [0x3903D0, bin]
|
- [0x3903D0, ia4, battle/lucky, 64, 32]
|
||||||
- start: 0x390810
|
- [0x3907D0, ia4, battle/miss, 64, 32]
|
||||||
type: ia4
|
- [0x390BD0, ia4, battle/good, 64, 32]
|
||||||
name: battle/text_action_command_ratings
|
- [0x390FD0, ia4, battle/nice, 64, 32]
|
||||||
width: 64
|
- [0x3913D0, ia4, battle/super, 64, 32]
|
||||||
height: 125
|
- [0x3917D0, bin]
|
||||||
flip: vertical
|
|
||||||
- [0x3917B0, bin]
|
|
||||||
- type: code
|
- type: code
|
||||||
start: 0x391D30
|
start: 0x391D30
|
||||||
vram: 0xE0092000
|
vram: 0xE0092000
|
||||||
@ -2471,20 +2469,114 @@ segments:
|
|||||||
subsegments:
|
subsegments:
|
||||||
- [0x3EB4E0, c]
|
- [0x3EB4E0, c]
|
||||||
- [0x3EBC30, bin]
|
- [0x3EBC30, bin]
|
||||||
- [0x3ED4E0, ia8, world/text_chapter, 128, 38]
|
- [0x3EBE60, ia8, world/ch0, 144, 40]
|
||||||
- [0x3EE7E0, bin]
|
- [0x3ED4E0, ia8, world/text_chapter, 128, 40]
|
||||||
|
- [0x3EE8E0, ia8, world/text_end_of, 104, 40]
|
||||||
|
- [0x3EF920, ia8, world/exclamation_point, 16, 40]
|
||||||
|
- [0x3EFBA0, ia8, world/ch1, 64, 64]
|
||||||
|
- [0x3F0BA0, ia8, world/ch2, 64, 64]
|
||||||
|
- [0x3F1BA0, ia8, world/ch3, 64, 64]
|
||||||
|
- [0x3F2BA0, ia8, world/ch4, 64, 64]
|
||||||
|
- [0x3F3BA0, ia8, world/ch5, 64, 64]
|
||||||
|
- [0x3F4BA0, ia8, world/ch6, 64, 64]
|
||||||
|
- [0x3F5BA0, ia8, world/ch7, 64, 64]
|
||||||
|
- [0x3F6BA0, ia8, world/ch8, 64, 64]
|
||||||
|
- [0x3F7BA0, rgba16, world/chapter_rainbow, 8, 16]
|
||||||
|
- [0x3F7CA0, bin]
|
||||||
- type: code
|
- type: code
|
||||||
start: 0x3F83F0
|
start: 0x3F83F0
|
||||||
vram: 0xE0110000
|
vram: 0xE0110000
|
||||||
subsegments:
|
subsegments:
|
||||||
- [0x3F83F0, c]
|
- [0x3F83F0, c]
|
||||||
- [0x3F8CA0, bin]
|
- [0x3F8CA0, bin]
|
||||||
|
- [0x3F8CC0, i4, ice_smash, 64, 128]
|
||||||
|
- [0x3F9CC0, bin]
|
||||||
- type: code
|
- type: code
|
||||||
start: 0x3F9E50
|
start: 0x3F9E50
|
||||||
vram: 0xE0112000
|
vram: 0xE0112000
|
||||||
subsegments:
|
subsegments:
|
||||||
- [0x3F9E50, c]
|
- [0x3F9E50, c]
|
||||||
- [0x3FA480, bin]
|
- [0x3FA480, bin]
|
||||||
|
- start: 0x3FA4B0
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/card_front
|
||||||
|
flip_y: true
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
- [0x3FA6B0, palette, star_cards/card_front]
|
||||||
|
- [0x3FA6D0, bin] # PAD
|
||||||
|
- start: 0x3FA8B0
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/card_back
|
||||||
|
flip_y: true
|
||||||
|
width: 32
|
||||||
|
height: 64
|
||||||
|
- [0x3FACB0, palette, star_cards/card_back]
|
||||||
|
- [0x3FACD0, bin] # PAD
|
||||||
|
- start: 0x3FAEB0
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/wave
|
||||||
|
flip_y: true
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
- [0x3FB0B0, palette, star_cards/wave]
|
||||||
|
- [0x3FB0D0, bin] # PAD
|
||||||
|
- start: 0x3FB2B0
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/squares
|
||||||
|
flip_y: true
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
- [0x3FB330, palette, star_cards/squares]
|
||||||
|
- [0x3FB350, bin] # PAD
|
||||||
|
- start: 0x3FB530
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/eldstar
|
||||||
|
flip_y: true
|
||||||
|
width: 48
|
||||||
|
height: 48
|
||||||
|
- [0x3FB9B0, palette, star_cards/eldstar]
|
||||||
|
- [0x3FB9D0, bin] # PAD
|
||||||
|
- start: 0x3FBBB0
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/mamar
|
||||||
|
flip_y: true
|
||||||
|
width: 48
|
||||||
|
height: 48
|
||||||
|
- [0x3FC030, palette, star_cards/mamar]
|
||||||
|
- [0x3FC050, bin] # PAD
|
||||||
|
- start: 0x3FC230
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/skolar
|
||||||
|
flip_y: true
|
||||||
|
width: 48
|
||||||
|
height: 48
|
||||||
|
- [0x3FC6B0, palette, star_cards/skolar]
|
||||||
|
- [0x3FC6D0, bin] # PAD
|
||||||
|
- start: 0x3FC8B0
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/muskular
|
||||||
|
flip_y: true
|
||||||
|
width: 48
|
||||||
|
height: 48
|
||||||
|
- [0x3FCD30, palette, star_cards/muskular]
|
||||||
|
- [0x3FCD50, bin] # PAD
|
||||||
|
- start: 0x3FCF30
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/misstar
|
||||||
|
flip_y: true
|
||||||
|
width: 48
|
||||||
|
height: 48
|
||||||
|
- [0x3FD3B0, palette, star_cards/misstar]
|
||||||
|
- [0x3FD3D0, bin] # PAD
|
||||||
|
- start: 0x3FDC30
|
||||||
|
type: ci4
|
||||||
|
name: star_cards/klevar
|
||||||
|
flip_y: true
|
||||||
|
width: 48
|
||||||
|
height: 48
|
||||||
|
- [0x3FE0B0, palette, star_cards/klevar]
|
||||||
|
- [0x3FE0D0, bin]
|
||||||
- type: code
|
- type: code
|
||||||
start: 0x3FEAE0
|
start: 0x3FEAE0
|
||||||
vram: 0xE0114000
|
vram: 0xE0114000
|
||||||
@ -2509,6 +2601,35 @@ segments:
|
|||||||
subsegments:
|
subsegments:
|
||||||
- [0x404220, c]
|
- [0x404220, c]
|
||||||
- [0x404E40, bin]
|
- [0x404E40, bin]
|
||||||
|
- start: 0x404F40
|
||||||
|
type: ci4
|
||||||
|
name: world/cloud
|
||||||
|
flip_y: true
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
- [0x405140, palette, world/cloud]
|
||||||
|
- start: 0x405340
|
||||||
|
type: ci4
|
||||||
|
name: world/waterblock
|
||||||
|
flip_y: true
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
- [0x405540, palette, world/waterblock]
|
||||||
|
- start: 0x405740
|
||||||
|
type: ci4
|
||||||
|
name: world/yellow_carpet
|
||||||
|
flip_y: true
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
- [0x405940, palette, world/yellow_carpet]
|
||||||
|
- start: 0x405B40
|
||||||
|
type: ci4
|
||||||
|
name: world/numbers
|
||||||
|
flip_y: true
|
||||||
|
width: 32
|
||||||
|
height: 160
|
||||||
|
- [0x406540, palette, world/numbers]
|
||||||
|
- [0x406740, bin]
|
||||||
- type: code
|
- type: code
|
||||||
start: 0x406B40
|
start: 0x406B40
|
||||||
vram: 0xE011C000
|
vram: 0xE011C000
|
||||||
|
Loading…
Reference in New Issue
Block a user