papermario/tools/splat_ext/pm_sprite_shading_profiles.py
Ethan Roseman 8837fbdf65
Player sprites & more (#1055)
* WIP work on sprites (sprite_stuff.py)

* cleanup of various stuff

* separate compiler installation into separate script

* wipz

* more

* renames, bugfixes

* more

* very grood

* cleanin

* goods and services

* oopth

* oopth2

* Parse palette data from xml

* more work

* more wipperz

* more

* it working

* git subrepo pull --force tools/splat

subrepo:
  subdir:   "tools/splat"
  merged:   "e72a868f9f"
upstream:
  origin:   "https://github.com/ethteck/splat.git"
  branch:   "master"
  commit:   "e72a868f9f"
git-subrepo:
  version:  "0.4.5"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "aa416e4"

* fix symbol_addrs for new splat

* upd8s

* Use generated header, other versions, fixes

* fixes & formatting

* wip fusing npc + player extraction & cleanup

* remove npc_files

* buildin

* fix some bugs

* Cleanup, yay0s separately

* cleen

* cleanup

* Respect stack during build

* jp spritz

* dun

* fix c files

---------

Co-authored-by: pixel-stuck <mathmcclintic@gmail.com>
2023-06-26 19:27:37 +09:00

226 lines
6.3 KiB
Python

import os
import sys
from pathlib import Path
TOOLS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(str(Path(TOOLS_DIR) / "build/sprite"))
from sprite_shading_profiles import SpriteShadingGroup, SpriteShadingProfile, Light
import json
import struct
from typing import Literal
from segtypes.n64.segment import N64Segment
from util import options
GROUPS = [
SpriteShadingGroup("TIK"),
SpriteShadingGroup("KMR"),
SpriteShadingGroup("ISK"),
SpriteShadingGroup("HOS"),
SpriteShadingGroup("OSR"),
SpriteShadingGroup("KKJ"),
SpriteShadingGroup("JSN"),
SpriteShadingGroup("MIM"),
SpriteShadingGroup("ARN"),
SpriteShadingGroup("DGB"),
SpriteShadingGroup("KZN"),
SpriteShadingGroup("unused"),
SpriteShadingGroup("ISK_BTL"),
]
def extract(input_data: bytes, endian: Literal["big", "little"] = "big") -> str:
PROFILE_NAMES = [
[
"TIK_01",
"TIK_02",
"TIK_03",
"TIK_04",
"TIK_05",
"TIK_06",
"TIK_07",
"TIK_08",
"TIK_09",
"TIK_10",
"TIK_12",
"TIK_14",
"TIK_15",
"TIK_18",
"TIK_20",
"TIK_21",
"TIK_22",
"TIK_23",
"TIK_24",
"TIK_25",
],
["KMR_30"],
[
"ISK_03",
"ISK_04",
"ISK_05",
"ISK_06",
"ISK_07",
"ISK_08",
"ISK_09",
"ISK_10",
"ISK_11",
"ISK_12",
"ISK_13",
"ISK_14",
"ISK_16",
"ISK_UNUSED",
"ISK_18",
"ISK_19",
],
["HOS_01"],
["OSR_02"],
[
"KKJ_10",
"KKJ_11",
"KKJ_12",
"KKJ_13",
"KKJ_17",
"KKJ_20",
"KKJ_22",
"KKJ_23",
"KKJ_24",
"KKJ_25",
"KKJ_26",
"KKJ_27",
],
["JAN_17", "JAN_19"],
[
"MIM_01",
"MIM_02",
"MIM_03",
"MIM_04",
"MIM_05",
"MIM_06",
"MIM_07",
"MIM_08",
"MIM_09",
"MIM_11",
"MIM_12",
],
["ARN_09", "ARN_10", "ARN_11", "ARN_12", "ARN_13"],
["DGB_06"],
[
"KZN_01",
"KZN_02",
"KZN_03",
"KZN_04",
"KZN_05",
"KZN_06",
"KZN_07",
"KZN_08",
"KZN_09",
"KZN_10",
"KZN_11",
"KZN_17",
"KZN_18",
"KZN_19",
"KZN_20",
"KZN_22",
"KZN_23",
],
["UNUSED"],
["BTL_ISK"],
]
END = ">" if endian == "big" else "<"
offsets_table = input_data[:0x1D0]
lighting_data = input_data[0x1D0:]
for g, group in enumerate(GROUPS):
b = g * 8
data_offset = struct.unpack(END + "i", offsets_table[b : b + 4])[0]
pl_it = struct.unpack(END + "i", offsets_table[b + 4 : b + 8])[0]
profile_list = []
for _ in range(len(PROFILE_NAMES[g])):
profile_list.append(
struct.unpack(END + "i", offsets_table[pl_it : pl_it + 4])[0]
)
pl_it += 4
for j, pl_offset in enumerate(profile_list):
profile_offset = data_offset + pl_offset
num_lights = lighting_data[profile_offset]
profile = SpriteShadingProfile(
name=PROFILE_NAMES[g][j].lower(),
ambient=[
lighting_data[profile_offset + 2],
lighting_data[profile_offset + 3],
lighting_data[profile_offset + 4],
],
power=lighting_data[profile_offset + 5],
)
profile_offset += 6
for _ in range(num_lights):
profile.lights.append(
Light(
flags=lighting_data[profile_offset],
rgb=[
lighting_data[profile_offset + 1],
lighting_data[profile_offset + 2],
lighting_data[profile_offset + 3],
],
pos=[
struct.unpack(
END + "h",
lighting_data[profile_offset + 4 : profile_offset + 6],
)[0],
struct.unpack(
END + "h",
lighting_data[profile_offset + 6 : profile_offset + 8],
)[0],
struct.unpack(
END + "h",
lighting_data[profile_offset + 8 : profile_offset + 10],
)[0],
],
falloff=struct.unpack(
END + "f",
lighting_data[profile_offset + 10 : profile_offset + 14],
)[0],
)
)
profile_offset += 0x10
group.profiles.append(profile)
return json.dumps(
[g.to_json() for g in GROUPS],
sort_keys=False,
indent=2,
)
class N64SegPm_sprite_shading_profiles(N64Segment):
OUT_DIR: Path = options.opts.asset_path / "sprite"
def scan(self, rom_bytes):
data = rom_bytes[self.rom_start : self.rom_end]
self.json_out = extract(data)
def split(self, rom_bytes):
self.out_path().parent.mkdir(parents=True, exist_ok=True)
with open(self.out_path(), "w") as f:
f.write(self.json_out)
def out_path(self) -> Path:
return self.OUT_DIR / f"{self.name}.json"
def get_linker_entries(self):
from segtypes.linker_entry import LinkerEntry
return [
LinkerEntry(
self,
[self.OUT_DIR / f"{self.name}.json"],
options.opts.asset_path / self.dir / f"{self.name}.bin",
self.get_linker_section(),
)
]