ci8 in code segments

This commit is contained in:
Alex Bates 2021-02-05 09:07:38 +00:00
parent d72e0079e8
commit c46c637c31
10 changed files with 158 additions and 109 deletions

1
.gitignore vendored
View File

@ -30,6 +30,7 @@ build.ninja
/img /img
/msg /msg
/sprite /sprite
/src/**/*.png
# Star Rod # Star Rod
/sprite/SpriteTable.xml /sprite/SpriteTable.xml

View File

@ -102,11 +102,13 @@ def build_image(f: str, segment):
out = "$builddir/" + path + "." + img_type + ".png" out = "$builddir/" + path + "." + img_type + ".png"
flags = "" flags = ""
"""
if img_type != "palette": if img_type != "palette":
if segment.flip_horizontal: if segment.flip_horizontal:
flags += "--flip-x" flags += "--flip-x"
if segment.flip_vertical: if segment.flip_vertical:
flags += "--flip-y" flags += "--flip-y"
"""
n.build(out, "img", path + ".png", implicit="tools/convert_image.py", variables={ n.build(out, "img", path + ".png", implicit="tools/convert_image.py", variables={
"img_type": img_type, "img_type": img_type,

View File

@ -1,8 +1,4 @@
#include "common.h" #include "coconut.h"
#include "script_api/battle.h"
ApiStatus func_802A1000_72F720(ScriptInstance* script, s32 isInitialCall);
ApiStatus func_802A11D4_72F8F4(ScriptInstance* script, s32 isInitialCall);
MenuIcon* D_802A1E80; MenuIcon* D_802A1E80;
void* D_80108A64; // an image void* D_80108A64; // an image
@ -180,90 +176,3 @@ Script D_802A1784_7300E4 = SCRIPT({
SetAnimation(0, 0, 0x10025); SetAnimation(0, 0, 0x10025);
sleep 45; sleep 45;
}); });
static s32 pad = 0;
// TODO: coconut.png
s32 D_802A1800_730160[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000088, 0x88000000, 0x00000000, 0x00000000, 0x00008888, 0x88880000, 0x00000000, 0x00000000, 0x00088745, 0x25788000, 0x00000000, 0x00000000, 0x00887252, 0x22378800, 0x00000000, 0x00000000, 0x08872521, 0x25237880, 0x00000000, 0x00000000, 0x08823512, 0x12523880, 0x00000000, 0x00000000, 0x88725225, 0x22523788, 0x00000000, 0x00000000, 0x88325235, 0x22532388, 0x00000000, 0x00000008, 0x87322252, 0x22323378, 0x80000000, 0x00000008, 0x85352252, 0x23237358, 0x80000000, 0x00000008, 0x83522252, 0x22323738, 0x80000000, 0x00000008, 0x82722255, 0x22523738, 0x80000000, 0x00000008, 0x84732233, 0x32733738, 0x80000000, 0x00000008, 0x85472733, 0x33734558, 0x80000000, 0x00000008, 0x87433743, 0x43734478, 0x80000000, 0x00000000, 0x88543744, 0x37444588, 0x00000000, 0x00000000, 0x88854474, 0x47445888, 0x00000000, 0x00000000, 0x08888757, 0x55788880, 0x00000000, 0x00000000, 0x00888888, 0x88888800, 0x00000000, 0x00000000, 0x00008888, 0x88880000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
s32 D_802A1A00_730360[] = {
0x294AED8F, 0xD48BC409, 0xABC78B49, 0x83077A85, 0x39010001, 0x00010001, 0x00010001, 0x00010001,
};
s32 D_802A1A20_730380[] = {
0xFFF0FFF0, 0x00000000, 0x00000000, 0x000000FF, 0x000FFFF0, 0x00000000, 0x04000000, 0x000000FF, 0x000F000F, 0x00000000, 0x04000400, 0x000000FF, 0xFFF0000F, 0x00000000, 0x00000400, 0x000000FF,
};
Gfx D_802A1A60_7303C0[] = {
gsDPPipeSync(),
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
gsDPSetCombineMode(G_CC_DECALRGBA, G_CC_DECALRGBA),
gsDPSetTexturePersp(G_TP_PERSP),
gsDPSetTextureDetail(G_TD_CLAMP),
gsDPSetTextureLOD(G_TL_TILE),
gsDPSetTextureLUT(G_TT_NONE),
gsDPSetTextureFilter(G_TF_AVERAGE),
gsDPSetTextureConvert(G_TC_FILT),
gsDPSetTextureLUT(G_TT_RGBA16),
gsDPLoadTLUT_pal16(0, &D_802A1A00_730360),
gsDPLoadTextureTile_4b(&D_802A1800_730160, G_IM_FMT_CI, 32, 0, 0, 0, 31, 31, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD),
gsSPClearGeometryMode(G_LIGHTING),
gsSPClearGeometryMode(G_SHADING_SMOOTH),
gsSPVertex(&D_802A1A20_730380, 4, 0),
gsSP1Triangle(0, 1, 2, 0),
gsSP1Triangle(0, 2, 3, 0),
gsDPPipeSync(),
gsSPEndDisplayList(),
};
s32 D_802A1B50_7304B0[] = {
0x00000004, 0x0000000D, 0x00000001, 0x0000003C, &D_802A1A60_7303C0, 0x00000002, 0x00000000,
};
Script D_802A1B6C_7304B0 = SCRIPT({
SI_VAR(10) =c ItemId_COCONUT;
await D_802A1240_72F960;
UseCamPreset(3);
MoveBattleCamOver(15);
SetAnimation(0, 0, 0x10016);
PlaySound(1018);
sleep 3;
func_802D3474(SI_VAR(10), D_802A1B50_7304B0);
SI_VAR(0) = 1.0;
MultiplyByActorScale(SI_VAR(0));
func_802D38EC(SI_VAR(10), SI_VAR(0), SI_VAR(0), SI_VAR(0));
GetActorPos(0, SI_VAR(0), SI_VAR(1), SI_VAR(2));
SI_VAR(3) = 20;
SI_VAR(4) = 42;
SI_VAR(5) = 5;
MultiplyVec3ByActorScale(SI_VAR(3), SI_VAR(4), SI_VAR(5));
SI_VAR(0) += SI_VAR(3);
SI_VAR(1) += SI_VAR(4);
SI_VAR(2) += SI_VAR(5);
func_802D36E0(SI_VAR(10), SI_VAR(0), SI_VAR(1), SI_VAR(2));
InitTargetIterator();
SetGoalToTarget(ActorID_SELF);
GetGoalPos(ActorID_SELF, SI_VAR(0), SI_VAR(1), SI_VAR(2));
spawn {
SI_VAR(0) = 0;
loop 18 {
SI_VAR(0) += -60;
func_802D3840(SI_VAR(10), 0, 0, SI_VAR(0));
sleep 1;
}
}
func_802D39FC(SI_VAR(10), 0.8);
SI_VAR(2) += 5;
func_802D3C58(SI_VAR(10), SI_VAR(0), SI_VAR(1), SI_VAR(2), 18);
GetItemPower(ItemId_COCONUT, SI_VAR(3), SI_VAR(4));
ApplyShrinkFromOwner(SI_VAR(3));
ItemDamageEnemy(SI_VAR(9), 0x18000000, 0, SI_VAR(3), 32);
SI_VAR(0) += 60;
SI_VAR(1) += 0;
func_802D3C58(SI_VAR(10), SI_VAR(0), SI_VAR(1), SI_VAR(2), 16);
func_802D3624(SI_VAR(10));
await D_802A1670_72FFD0;
});

View File

@ -0,0 +1,77 @@
#include "coconut.h"
s32 D_802A1A20_730380[] = {
0xFFF0FFF0, 0x00000000, 0x00000000, 0x000000FF, 0x000FFFF0, 0x00000000, 0x04000000, 0x000000FF, 0x000F000F, 0x00000000, 0x04000400, 0x000000FF, 0xFFF0000F, 0x00000000, 0x00000400, 0x000000FF,
};
Gfx D_802A1A60_7303C0[] = {
gsDPPipeSync(),
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
gsDPSetCombineMode(G_CC_DECALRGBA, G_CC_DECALRGBA),
gsDPSetTexturePersp(G_TP_PERSP),
gsDPSetTextureDetail(G_TD_CLAMP),
gsDPSetTextureLOD(G_TL_TILE),
gsDPSetTextureLUT(G_TT_NONE),
gsDPSetTextureFilter(G_TF_AVERAGE),
gsDPSetTextureConvert(G_TC_FILT),
gsDPSetTextureLUT(G_TT_RGBA16),
gsDPLoadTLUT_pal16(0, &D_802A1A00_730360),
gsDPLoadTextureTile_4b(&D_802A1800_730160, G_IM_FMT_CI, 32, 0, 0, 0, 31, 31, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD),
gsSPClearGeometryMode(G_LIGHTING),
gsSPClearGeometryMode(G_SHADING_SMOOTH),
gsSPVertex(&D_802A1A20_730380, 4, 0),
gsSP1Triangle(0, 1, 2, 0),
gsSP1Triangle(0, 2, 3, 0),
gsDPPipeSync(),
gsSPEndDisplayList(),
};
s32 D_802A1B50_7304B0[] = {
0x00000004, 0x0000000D, 0x00000001, 0x0000003C, &D_802A1A60_7303C0, 0x00000002, 0x00000000,
};
Script D_802A1B6C_7304B0 = SCRIPT({
SI_VAR(10) =c ItemId_COCONUT;
await D_802A1240_72F960;
UseCamPreset(3);
MoveBattleCamOver(15);
SetAnimation(0, 0, 0x10016);
PlaySound(1018);
sleep 3;
func_802D3474(SI_VAR(10), D_802A1B50_7304B0);
SI_VAR(0) = 1.0;
MultiplyByActorScale(SI_VAR(0));
func_802D38EC(SI_VAR(10), SI_VAR(0), SI_VAR(0), SI_VAR(0));
GetActorPos(0, SI_VAR(0), SI_VAR(1), SI_VAR(2));
SI_VAR(3) = 20;
SI_VAR(4) = 42;
SI_VAR(5) = 5;
MultiplyVec3ByActorScale(SI_VAR(3), SI_VAR(4), SI_VAR(5));
SI_VAR(0) += SI_VAR(3);
SI_VAR(1) += SI_VAR(4);
SI_VAR(2) += SI_VAR(5);
func_802D36E0(SI_VAR(10), SI_VAR(0), SI_VAR(1), SI_VAR(2));
InitTargetIterator();
SetGoalToTarget(ActorID_SELF);
GetGoalPos(ActorID_SELF, SI_VAR(0), SI_VAR(1), SI_VAR(2));
spawn {
SI_VAR(0) = 0;
loop 18 {
SI_VAR(0) += -60;
func_802D3840(SI_VAR(10), 0, 0, SI_VAR(0));
sleep 1;
}
}
func_802D39FC(SI_VAR(10), 0.8);
SI_VAR(2) += 5;
func_802D3C58(SI_VAR(10), SI_VAR(0), SI_VAR(1), SI_VAR(2), 18);
GetItemPower(ItemId_COCONUT, SI_VAR(3), SI_VAR(4));
ApplyShrinkFromOwner(SI_VAR(3));
ItemDamageEnemy(SI_VAR(9), 0x18000000, 0, SI_VAR(3), 32);
SI_VAR(0) += 60;
SI_VAR(1) += 0;
func_802D3C58(SI_VAR(10), SI_VAR(0), SI_VAR(1), SI_VAR(2), 16);
func_802D3624(SI_VAR(10));
await D_802A1670_72FFD0;
});

View File

@ -0,0 +1,13 @@
#ifndef BATTLE_ITEM_COCONUT
#define BATTLE_ITEM_COCONUT
#include "common.h"
#include "script_api/battle.h"
#undef NAMESPACE
#define NAMESPACE battle_item_coconut
ApiStatus func_802A1000_72F720(ScriptInstance* script, s32 isInitialCall);
ApiStatus func_802A11D4_72F8F4(ScriptInstance* script, s32 isInitialCall);
#endif

View File

@ -2346,10 +2346,9 @@ segments:
files: files:
- [0x72F720, c, aux] - [0x72F720, c, aux]
- [0x72F960, .data, aux] - [0x72F960, .data, aux]
# - [0x72F960, .data, aux] - [0x72FF20, ci4, coconut, 32, 32]
# - [0x72F960, ci8, coconut, w, h] - [0x730120, palette, coconut]
# - [0x72F960, palette, coconut] - [0x730140, .data, coconut]
# - [0x72F960, .data, coconut]
- name: battle/item/electro_pop - name: battle/item/electro_pop
type: code type: code
start: 0x7305A0 start: 0x7305A0

View File

@ -1,10 +1,11 @@
from segtypes.n64.ci8 import N64SegCi8 from segtypes.n64.ci8 import N64SegCi8
class N64SegCi4(N64SegCi8): class N64SegCi4(N64SegCi8):
def parse_image(self, data): @staticmethod
def parse_image(data, width, height):
img_data = bytearray() img_data = bytearray()
for i in range(self.width * self.height // 2): for i in range(width * height // 2):
img_data.append(data[i] >> 4) img_data.append(data[i] >> 4)
img_data.append(data[i] & 0xF) img_data.append(data[i] & 0xF)

View File

@ -18,7 +18,7 @@ class N64SegCi8(N64SegRgba16):
if self.compressed: if self.compressed:
data = Yay0decompress.decompress_yay0(data) data = Yay0decompress.decompress_yay0(data)
self.image = self.parse_image(data) self.image = N64SegCi8.parse_image(data)
def postsplit(self, segments): def postsplit(self, segments):
palettes = [seg for seg in segments if seg.type == palettes = [seg for seg in segments if seg.type ==
@ -52,7 +52,8 @@ class N64SegCi8(N64SegRgba16):
self.log( self.log(
f"No unnamed palette for {self.name}; wrote image data to {self.path}") f"No unnamed palette for {self.name}; wrote image data to {self.path}")
def parse_image(self, data): @staticmethod
def parse_image(data):
return data return data
def max_length(self): def max_length(self):

View File

@ -58,11 +58,13 @@ class N64SegCode(N64Segment):
end = split_file["end"] end = split_file["end"]
name = None if "name" not in split_file else split_file["name"] name = None if "name" not in split_file else split_file["name"]
subtype = split_file["type"] subtype = split_file["type"]
args = []
else: else:
start = split_file[0] start = split_file[0]
end = seg_end if i == len(segment["files"]) - 1 else segment["files"][i + 1][0] end = seg_end if i == len(segment["files"]) - 1 else segment["files"][i + 1][0]
name = None if len(split_file) < 3 else split_file[2] name = None if len(split_file) < 3 else split_file[2]
subtype = split_file[1] subtype = split_file[1]
args = split_file[3:]
if start < prev_start: if start < prev_start:
print(f"Error: Code segment {seg_name} has files out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})") print(f"Error: Code segment {seg_name} has files out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})")
@ -75,7 +77,7 @@ class N64SegCode(N64Segment):
vram = seg_vram + (start - seg_start) vram = seg_vram + (start - seg_start)
fl = {"start": start, "end": end, "name": name, "vram": vram, "subtype": subtype} fl = {"start": start, "end": end, "name": name, "vram": vram, "subtype": subtype, "args": args}
ret.append(fl) ret.append(fl)
prev_start = start prev_start = start
@ -488,10 +490,8 @@ class N64SegCode(N64Segment):
return ret return ret
def should_run(self): def should_run(self):
possible_subtypes = ["c", "asm", "hasm", "bin", "data", "rodata"] # we have lots of subtypes
subtypes = set(f["subtype"] for f in self.files) return True
return super().should_run() or (st in self.options["modes"] and st in subtypes for st in possible_subtypes)
@staticmethod @staticmethod
def is_valid_ascii(bytes): def is_valid_ascii(bytes):
@ -707,6 +707,8 @@ class N64SegCode(N64Segment):
md.detail = True md.detail = True
md.skipdata = True md.skipdata = True
palettes = {}
for split_file in self.files: for split_file in self.files:
file_type = split_file["subtype"] file_type = split_file["subtype"]
@ -819,9 +821,50 @@ class N64SegCode(N64Segment):
with open(bin_path, "wb") as f: with open(bin_path, "wb") as f:
f.write(rom_bytes[split_file["start"]: split_file["end"]]) f.write(rom_bytes[split_file["start"]: split_file["end"]])
elif file_type in ["i4", "i8", "ia4", "ia8", "ia16", "rgba16", "rgba32", "ci4", "ci8"]:
pass
elif file_type == "palette":
from segtypes.n64.palette import N64SegPalette
out_path = os.path.join(
base_path,
"src",
split_file["name"] + "." + self.get_ext(split_file["subtype"])
)
img_bytes = rom_bytes[split_file["start"]:split_file["end"]]
palette = N64SegPalette.parse_palette(img_bytes)
palettes[split_file["name"]] = palette
import png
for split_file in self.files:
file_type = split_file["subtype"]
img_bytes = rom_bytes[split_file["start"]:split_file["end"]]
out_path = os.path.join(
base_path,
"src",
split_file["name"] + "." + self.get_ext(split_file["subtype"])
)
if file_type == "ci4":
from segtypes.n64.ci4 import N64SegCi4
width, height = split_file["args"]
palette = palettes[split_file["name"]]
image = N64SegCi4.parse_image(img_bytes, width, height)
w = png.Writer(width, height, palette=palette)
with open(out_path, "wb") as f:
w.write_array(f, image)
# TODO other image types
@staticmethod @staticmethod
def get_subdir(subtype): def get_subdir(subtype):
if subtype in ["c", ".data", ".rodata", ".bss"]: if subtype in ["c", ".data", ".rodata", ".bss", "i4", "i8", "ia4", "ia8", "ia16", "rgba16", "rgba32", "ci4", "ci8", "palette"]:
return "src" return "src"
elif subtype in ["asm", "hasm", "header"]: elif subtype in ["asm", "hasm", "header"]:
return "asm" return "asm"
@ -835,13 +878,15 @@ class N64SegCode(N64Segment):
return "s" return "s"
elif subtype == "bin": elif subtype == "bin":
return "bin" return "bin"
elif subtype in ["i4", "i8", "ia4", "ia8", "ia16", "rgba16", "rgba32", "ci4", "ci8", "palette"]:
return subtype + ".png"
return subtype return subtype
@staticmethod @staticmethod
def get_ld_obj_type(subtype, section_name): def get_ld_obj_type(subtype, section_name):
if subtype in "c": if subtype in "c":
return ".text" return ".text"
elif subtype in ["bin", ".data", "data"]: elif subtype in ["bin", ".data", "data", "i4", "i8", "ia4", "ia8", "ia16", "rgba16", "rgba32", "ci4", "ci8", "palette"]:
return ".data" return ".data"
elif subtype in [".rodata", "rodata"]: elif subtype in [".rodata", "rodata"]:
return ".rodata" return ".rodata"

View File

@ -41,9 +41,10 @@ class N64SegPalette(N64Segment):
if self.compressed: if self.compressed:
data = Yay0decompress.decompress_yay0(data) data = Yay0decompress.decompress_yay0(data)
self.palette = self.parse_palette(data) self.palette = N64SegPalette.parse_palette(data)
def parse_palette(self, data): @staticmethod
def parse_palette(data):
palette = [] palette = []
for a, b in iter_in_groups(data, 2): for a, b in iter_in_groups(data, 2):