mirror of
https://github.com/pmret/papermario.git
synced 2024-11-08 12:02:30 +01:00
commit
36773e4007
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,6 +17,7 @@ settings.mk
|
||||
*.i
|
||||
*.Yay0
|
||||
bin/
|
||||
img/
|
||||
build/
|
||||
docs/doxygen/
|
||||
include/ld_addrs.h
|
||||
|
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -10,7 +10,6 @@
|
||||
"-D_LANGUAGE_C",
|
||||
"-DSCRIPT(...)={}",
|
||||
],
|
||||
"python.pythonPath": "/usr/bin/python3",
|
||||
"git.ignoreLimitWarning": true,
|
||||
"search.exclude": {
|
||||
"build": true,
|
||||
|
50
Makefile
50
Makefile
@ -98,14 +98,14 @@ submodules:
|
||||
git submodule update --init --recursive
|
||||
|
||||
split:
|
||||
rm -rf bin
|
||||
$(SPLAT) --modes ld bin Yay0 PaperMarioMapFS
|
||||
rm -rf bin img
|
||||
$(SPLAT) --modes ld bin Yay0 PaperMarioMapFS rgba16 rgba32 ia4 ia8 ia16 i4 i8 ci4 ci8
|
||||
|
||||
split-bin:
|
||||
$(SPLAT) --modes ld bin
|
||||
split-%:
|
||||
$(SPLAT) --modes ld $*
|
||||
|
||||
split-all:
|
||||
rm -rf bin
|
||||
rm -rf bin img
|
||||
$(SPLAT) --modes all
|
||||
|
||||
test: $(ROM)
|
||||
@ -137,13 +137,51 @@ $(BUILD_DIR)/%.c.o: %.c $(MDEPS)
|
||||
# Compile C files (with DSL macros)
|
||||
$(foreach cfile, $(DSL_C_FILES), $(BUILD_DIR)/$(cfile).o): $(BUILD_DIR)/%.c.o: %.c $(MDEPS) tools/compile_dsl_macros.py
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(CPP) $(CPPFLAGS) -o - $< $(CPPMFLAGS) | tools/compile_dsl_macros.py | $(CC) $(CFLAGS) -o - | $(OLD_AS) $(OLDASFLAGS) -o $@ -
|
||||
$(CPP) $(CPPFLAGS) -o - $< $(CPPMFLAGS) | $(PYTHON) tools/compile_dsl_macros.py | $(CC) $(CFLAGS) -o - | $(OLD_AS) $(OLDASFLAGS) -o $@ -
|
||||
|
||||
# Assemble handwritten ASM
|
||||
$(BUILD_DIR)/%.s.o: %.s
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(AS) $(ASFLAGS) -o $@ $<
|
||||
|
||||
# Images
|
||||
$(BUILD_DIR)/%.png.o: $(BUILD_DIR)/%.png
|
||||
$(LD) -r -b binary -o $@ $<
|
||||
$(BUILD_DIR)/%.rgba16.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py rgba16 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.rgba32.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py rgba32 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.ci8.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py ci8 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.ci8palette.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py ci8palette $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.ci4.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py ci4 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.ci4palette.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py ci4palette $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.ia4.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py ia4 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.ia8.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py ia8 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.ia16.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py ia16 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.i4.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py i4 $< $@ $(IMG_FLAGS)
|
||||
$(BUILD_DIR)/%.i8.png: %.png
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(PYTHON) tools/convert_image.py i8 $< $@ $(IMG_FLAGS)
|
||||
|
||||
|
||||
ASSET_FILES := $(foreach asset, $(ASSETS), $(BUILD_DIR)/bin/assets/$(asset))
|
||||
YAY0_ASSET_FILES := $(foreach asset, $(filter-out %_tex, $(ASSET_FILES)), $(asset).Yay0)
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
capstone
|
||||
PyYAML
|
||||
lark-parser
|
||||
pypng
|
||||
|
@ -55,3 +55,6 @@ ASSETS := \
|
||||
kmr_bg nok_bg sbk_bg sbk3_bg iwa_bg hos_bg arn_bg obk_bg omo_bg yos_bg jan_bg fla_bg flb_bg sra_bg yki_bg sam_bg kpa_bg title_bg \
|
||||
title_data \
|
||||
party_kurio party_kameki party_pinki party_pareta party_resa party_akari party_opuku party_pokopi
|
||||
|
||||
# Image settings
|
||||
$(BUILD_DIR)/img/battle/text_action_command_ratings.ia4.png: IMG_FLAGS = --flip-y
|
||||
|
193
tools/convert_image.py
Executable file
193
tools/convert_image.py
Executable file
@ -0,0 +1,193 @@
|
||||
#! /usr/bin/python3
|
||||
|
||||
from sys import argv, stderr
|
||||
from math import floor, ceil
|
||||
from itertools import zip_longest
|
||||
import png
|
||||
|
||||
def unpack_color(s):
|
||||
r = (s >> 11) & 0x1F
|
||||
g = (s >> 6) & 0x1F
|
||||
b = (s >> 1) & 0x1F
|
||||
a = (s & 1) * 0xFF
|
||||
|
||||
r = ceil(0xFF * (r / 31))
|
||||
g = ceil(0xFF * (g / 31))
|
||||
b = ceil(0xFF * (b / 31))
|
||||
|
||||
return r, g, b, a
|
||||
|
||||
def pack_color(r, g, b, a):
|
||||
r = floor(31 * (r / 255))
|
||||
g = floor(31 * (g / 255))
|
||||
b = floor(31 * (b / 255))
|
||||
|
||||
s = round(a / 0xFF)
|
||||
s |= (r & 0x1F) << 11
|
||||
s |= (g & 0x1F) << 6
|
||||
s |= (b & 0x1F) << 1
|
||||
|
||||
return s
|
||||
|
||||
def rgb_to_intensity(r, g, b):
|
||||
return round(r * 0.2126 + g * 0.7152 + 0.0722 * b)
|
||||
|
||||
def iter_in_groups(iterable, n, fillvalue=None):
|
||||
args = [iter(iterable)] * n
|
||||
return zip_longest(*args, fillvalue=fillvalue)
|
||||
|
||||
|
||||
|
||||
def reversed_if(iterator, cond):
|
||||
if cond:
|
||||
return reversed(list(iterator))
|
||||
else:
|
||||
return iterator
|
||||
|
||||
class Converter():
|
||||
def __init__(self, mode, infile, outfile, *argv):
|
||||
self.mode = mode
|
||||
self.infile = infile
|
||||
self.outfile = outfile
|
||||
self.flip_y = "--flip-y" in argv
|
||||
|
||||
self.warned = False
|
||||
|
||||
def warn(self, msg):
|
||||
if not self.warned:
|
||||
self.warned = True
|
||||
print(self.infile + ": warning: " + msg, file=stderr)
|
||||
|
||||
def convert(self):
|
||||
img = png.Reader(self.infile)
|
||||
|
||||
if self.mode == "rgba32":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.asRGBA()[2], self.flip_y):
|
||||
f.write(row)
|
||||
elif self.mode == "rgba16":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.asRGBA()[2], self.flip_y):
|
||||
for rgba in iter_in_groups(row, 4):
|
||||
if rgba[3] not in (0, 0xFF):
|
||||
self.warn("alpha mask mode but translucent pixels used")
|
||||
|
||||
color = pack_color(*rgba)
|
||||
f.write(color.to_bytes(2, byteorder="big"))
|
||||
elif self.mode == "ci8":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.read()[2], self.flip_y):
|
||||
f.write(row)
|
||||
elif self.mode == "ci4":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.read()[2], self.flip_y):
|
||||
for a, b in iter_in_groups(row, 2):
|
||||
byte = (a << 4) | b
|
||||
f.write(byte.to_bytes(1, byteorder="big"))
|
||||
elif self.mode == "ci8palette" or self.mode == "ci4palette":
|
||||
img.preamble(True)
|
||||
palette = img.palette(alpha="force")
|
||||
|
||||
with open(self.outfile, "wb") as f:
|
||||
for rgba in palette:
|
||||
if rgba[3] not in (0, 0xFF):
|
||||
self.warn("alpha mask mode but translucent pixels used")
|
||||
|
||||
color = pack_color(*rgba)
|
||||
f.write(color.to_bytes(2, byteorder="big"))
|
||||
elif self.mode == "ia4":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.asRGBA()[2], self.flip_y):
|
||||
for c1, c2 in iter_in_groups(iter_in_groups(row, 4), 2):
|
||||
i1 = rgb_to_intensity(*c1[:3])
|
||||
a1 = c1[3]
|
||||
|
||||
i2 = rgb_to_intensity(*c2[:3])
|
||||
a2 = c2[3]
|
||||
|
||||
i1 = floor(7 * (i1 / 0xFF))
|
||||
i2 = floor(7 * (i2 / 0xFF))
|
||||
|
||||
if a1 not in (0, 0xFF) or a2 not in (0, 0xFF):
|
||||
self.warn("alpha mask mode but translucent pixels used")
|
||||
if c1[0] != c1[1] != c1[2]:
|
||||
self.warn("grayscale mode but image is not")
|
||||
if c2[0] != c2[1] != c2[2]:
|
||||
self.warn("grayscale mode but image is not")
|
||||
|
||||
a1 = 1 if a1 > 128 else 0
|
||||
a2 = 1 if a2 > 128 else 0
|
||||
|
||||
h = (i1 << 1) | a1
|
||||
l = (i2 << 1) | a2
|
||||
|
||||
byte = (h << 4) | l
|
||||
f.write(byte.to_bytes(1, byteorder="big"))
|
||||
elif self.mode == "ia8":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.asRGBA()[2], self.flip_y):
|
||||
for rgba in iter_in_groups(row, 4):
|
||||
i = rgb_to_intensity(*rgba[:3])
|
||||
a = rgba[3]
|
||||
|
||||
i = floor(15 * (i / 0xFF))
|
||||
a = floor(15 * (a / 0xFF))
|
||||
|
||||
if rgba[0] != rgba[1] != rgba[2]:
|
||||
self.warn("grayscale mode but image is not")
|
||||
|
||||
byte = (i << 4) | a
|
||||
f.write(byte.to_bytes(1, byteorder="big"))
|
||||
elif self.mode == "ia16":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.asRGBA()[2], self.flip_y):
|
||||
for rgba in iter_in_groups(row, 4):
|
||||
i = rgb_to_intensity(*rgba[:3])
|
||||
a = rgba[3]
|
||||
|
||||
if rgba[0] != rgba[1] != rgba[2]:
|
||||
self.warn("grayscale mode but image is not")
|
||||
|
||||
f.write(bytes((i, a)))
|
||||
elif self.mode == "i4":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.asRGBA()[2], self.flip_y):
|
||||
for c1, c2 in iter_in_groups(iter_in_groups(row, 4), 2):
|
||||
if c1[3] != 0xFF or c2[3] != 0xFF:
|
||||
self.warn("discarding alpha channel")
|
||||
|
||||
i1 = rgb_to_intensity(*c1[:3])
|
||||
i2 = rgb_to_intensity(*c2[:3])
|
||||
|
||||
i1 = floor(15 * (i1 / 0xFF))
|
||||
i2 = floor(15 * (i2 / 0xFF))
|
||||
|
||||
if c1[0] != c1[1] != c1[2]:
|
||||
self.warn("grayscale mode but image is not")
|
||||
if c2[0] != c2[1] != c2[2]:
|
||||
self.warn("grayscale mode but image is not")
|
||||
|
||||
byte = (i1 << 4) | i2
|
||||
f.write(byte.to_bytes(1, byteorder="big"))
|
||||
elif self.mode == "i8":
|
||||
with open(self.outfile, "wb") as f:
|
||||
for row in reversed_if(img.asRGBA()[2], self.flip_y):
|
||||
for rgba in iter_in_groups(row, 4):
|
||||
if rgba[3] != 0xFF or rgba[3] != 0xFF:
|
||||
self.warn("discarding alpha channel")
|
||||
if rgba[0] != rgba[1] != rgba[2]:
|
||||
self.warn("grayscale mode but image is not")
|
||||
|
||||
i = rgb_to_intensity(*rgba[:3])
|
||||
f.write(i.to_bytes(1, byteorder="big"))
|
||||
else:
|
||||
print("unsupported mode", file=stderr)
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(argv) < 4:
|
||||
print("usage: convert_image.py MODE INFILE OUTFILE [--flip-y]")
|
||||
exit(1)
|
||||
|
||||
Converter(*argv[1:]).convert()
|
@ -1 +1 @@
|
||||
Subproject commit 037d80e00cb3aeae37bdad77bfac871036982456
|
||||
Subproject commit e7a811adf8e9cc5505c0992d0e73e9589c6ccd2e
|
@ -212,6 +212,14 @@ segments:
|
||||
- [0x8a860, "c", "code_8a860_len_3f30"]
|
||||
- [0x8e790, "c", "code_8e790_len_2850"]
|
||||
- [0x90fe0, "bin"]
|
||||
- [0x93CD0, ci4, ui/hammer, 32, 32]
|
||||
- [0x93ED0, ci4palette, ui/hammer]
|
||||
- [0x93EF0, ci4palette, ui/hammer.disabled]
|
||||
- [0x93FF0, bin]
|
||||
- [0x9D658, rgba32, ui/stat_heart, 16, 16]
|
||||
- [0x9DA58, bin]
|
||||
- [0x9DA60, rgba32, ui/stat_flower, 16, 16]
|
||||
- [0x9DE60, bin]
|
||||
- type: code
|
||||
start: 0xA5DD0
|
||||
vram: 0x8010F6D0
|
||||
@ -268,8 +276,17 @@ segments:
|
||||
- [0x1086a0, "c", "code_1086a0_len_fc0"]
|
||||
- [0x109660, "c", "code_109660_len_1270"]
|
||||
- [0x10A8D0, "c", "code_10A8D0"]
|
||||
- [0x10A9F0, "bin"] # todo split this further
|
||||
- [0x131340, "bin"] # 0x8023E000
|
||||
- [0x10A9F0, i4, shadow/square, 16, 16]
|
||||
- [0x10AA70, i4, shadow/circle, 16, 16]
|
||||
- [0x10AAF0, bin]
|
||||
- [0x10AB70, i4, shadow/10AB70, 32, 32]
|
||||
- [0x10AD70, i4, shadow/10AD70, 32, 32]
|
||||
- [0x10AF70, bin] # TODO
|
||||
- [0x1164B8, ci8, peach_letter, 150, 105]
|
||||
- [0x11A23E, bin]
|
||||
- [0x11A240, ci8palette, peach_letter]
|
||||
- [0x11A440, bin]
|
||||
- [0x131340, bin]
|
||||
- type: code
|
||||
start: 0x135EE0
|
||||
vram: 0x80242BA0
|
||||
@ -280,6 +297,28 @@ segments:
|
||||
- [0x140C70, "c"]
|
||||
- [0x1421C0, "c"]
|
||||
- [0x1422A0, "bin"]
|
||||
- [0x1443F0, ci8, pause/world_map, 320, 320]
|
||||
- [0x15D3F0, ci8palette, pause/world_map]
|
||||
- [0x15D5F0, ci4, pause/spirits_bg, 128, 110]
|
||||
- [0x15F170, ci4palette, pause/spirits_bg]
|
||||
- [0x15F270, bin]
|
||||
- [0x15F970, ci4, pause/banner_hp, 64, 16]
|
||||
- [0x15FB70, ci4palette, pause/banner_hp]
|
||||
- [0x15FD70, ci4, pause/banner_fp, 64, 16]
|
||||
- [0x15FF70, ci4palette, pause/banner_fp]
|
||||
- [0x160170, ci4, pause/banner_bp, 64, 16]
|
||||
- [0x160370, ci4palette, pause/banner_bp]
|
||||
- [0x160570, ci4, pause/banner_boots, 48, 16]
|
||||
- [0x1606F0, ci4palette, pause/banner_boots]
|
||||
- [0x1608F0, ci4, pause/banner_hammer, 48, 16]
|
||||
- [0x160A70, ci4palette, pause/banner_hammer]
|
||||
- [0x160C70, ci4, pause/banner_star_energy, 48, 16]
|
||||
- [0x160DF0, ci4palette, pause/banner_star_energy]
|
||||
- [0x160FF0, ci4, pause/available, 64, 16]
|
||||
- [0x1611F0, ci4palette, pause/available]
|
||||
- [0x1613F0, ci4, pause/prompt_check_abilities, 128, 16]
|
||||
- [0x1617F0, ci4palette, pause/prompt_check_abilities]
|
||||
- [0x1619F0, bin]
|
||||
- type: code
|
||||
start: 0x163400
|
||||
vram: 0x80242BA0
|
||||
@ -313,6 +352,21 @@ segments:
|
||||
- [0x1AF230, "c"]
|
||||
- [0x1AF2D0, "bin"]
|
||||
- [0x1CC310, "bin"] # icon images and palettes, vram unknown
|
||||
- [0x1FE1B0, rgba16, title/logo_n64, 128, 112]
|
||||
- [0x2051B0, rgba16, title/logo_is, 256, 122]
|
||||
- [0x2131B0, rgba16, title/logo_nintendo, 256, 48]
|
||||
- [0x2191B0, ci8, title/bg_1, 264, 162]
|
||||
- [0x2238C0, ci8palette, title/bg_1]
|
||||
- [0x223AC0, ci8, title/bg_2, 264, 162]
|
||||
- [0x22E1D0, ci8palette, title/bg_2]
|
||||
- [0x22E3D0, ci8, title/bg_3, 264, 162]
|
||||
- [0x238AE0, ci8palette, title/bg_3]
|
||||
- [0x238CE0, ci8, title/bg_4, 264, 162]
|
||||
- [0x2433F0, ci8palette, title/bg_4]
|
||||
- [0x2435F0, ia8, title/tape, 128, 128]
|
||||
- [0x2475F0, ci8, title/bowser_silhouette, 128, 128]
|
||||
- [0x24B5F0, ci8palette, title/bowser_silhouette]
|
||||
- [0x24B7F0, bin]
|
||||
- type: code
|
||||
start: 0x3169F0
|
||||
vram: 0x80200000
|
||||
@ -482,13 +536,13 @@ segments:
|
||||
files:
|
||||
- [0x33CDF0, "c"]
|
||||
- [0x33d5d0, "bin"]
|
||||
- [0x33D610, "bin"]
|
||||
- type: code
|
||||
start: 0x33E8C0
|
||||
vram: 0xE002A000
|
||||
files:
|
||||
- [0x33E8C0, "c"]
|
||||
- [0x33efe0, "bin"]
|
||||
- [0x33D610, "bin"]
|
||||
- type: code
|
||||
start: 0x33FE80
|
||||
vram: 0xE002C000
|
||||
@ -731,6 +785,13 @@ segments:
|
||||
- [0x38F900, "c"]
|
||||
- [0x390340, "bin"]
|
||||
- [0x3903D0, "bin"]
|
||||
- start: 0x390810
|
||||
type: ia4
|
||||
name: battle/text_action_command_ratings
|
||||
width: 64
|
||||
height: 125
|
||||
flip: vertical
|
||||
- [0x3917B0, bin]
|
||||
- type: code
|
||||
start: 0x391D30
|
||||
vram: 0xE0092000
|
||||
@ -814,6 +875,8 @@ segments:
|
||||
- [0x3BA030, "c"]
|
||||
- [0x3BAC60, "bin"]
|
||||
- [0x3BAEA0, "bin"] # todo split this further ADD STUFF AFTER HERE
|
||||
- [0x3ED4E0, "ia8", "world/text_chapter", 128, 38]
|
||||
- [0x3EE7E0, "bin"]
|
||||
- type: code
|
||||
start: 0x415D90
|
||||
vram: 0x802A1000
|
||||
|
Loading…
Reference in New Issue
Block a user