Skip to content

Commit

Permalink
Merge branch 'master' into asm-update
Browse files Browse the repository at this point in the history
  • Loading branch information
ethteck committed Nov 2, 2020
2 parents d6fbf1d + 36773e4 commit a102b75
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ settings.mk
*.i
*.Yay0
bin/
img/
build/
docs/doxygen/
include/ld_addrs.h
Expand Down
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"-D_LANGUAGE_C",
"-DSCRIPT(...)={}",
],
"python.pythonPath": "/usr/bin/python3",
"git.ignoreLimitWarning": true,
"search.exclude": {
"build": true,
Expand Down
50 changes: 44 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ capstone
PyYAML
lark-parser
python-ranges
pypng
3 changes: 3 additions & 0 deletions sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 193 additions & 0 deletions tools/convert_image.py
Original file line number Diff line number Diff line change
@@ -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()
Loading

0 comments on commit a102b75

Please sign in to comment.