dmgtris/build.py

163 lines
4.6 KiB
Python
Executable File

#!/usr/bin/env python
# Game ID and title of the game. ID has to be four characters, title can be up to 11
GAME_ID = "DTGM"
GAME_TITLE = "DMGTRIS"
# Version of the game as embedded in the rom
GAME_VERSION = "0x01"
# Mapper type and sram size
MAPPER_TYPE = "MBC5+RAM+BATTERY"
SRAM_AMOUNT = "0x04"
# Rom filename, without extension
ROM_NAME = "PandorasBlocks"
# Extra flags
RGBASM_FLAGS = ["-Q", "25"]
RGBLINK_FLAGS = []
RGBFIX_FLAGS = ["-c"]
# You will not be likely to need to change these options.
OLD_LICENSEE = "0x33"
PAD_VALUE = "0xFF"
LICENSEE = "HB"
# Do not edit below this line.
import sys, shutil, hashlib, subprocess
from pathlib import Path
def clean():
shutil.rmtree("./bin", ignore_errors=True)
shutil.rmtree("./obj", ignore_errors=True)
def assemble(file, out, extra = []):
cmd = [
"rgbasm",
"-p", PAD_VALUE,
"-Isrc/",
"-Isrc/include",
"-Wall",
"-Wextra"
]
cmd += RGBASM_FLAGS
cmd += extra
cmd += [
"-o", out, file
]
result = subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, text=True)
if result.returncode == 0:
return True
else:
print(result.stdout)
return False
def link(files, out, extra = []):
cmd = [
"rgblink",
"-p", PAD_VALUE
]
cmd += RGBLINK_FLAGS
cmd += extra
cmd += [
"-o", out
]
cmd += files
result = subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, text=True)
if result.returncode == 0:
return True
else:
print(result.stdout)
return False
def fix(file, extra = []):
cmd = [
"rgbfix",
"-v",
"-p", PAD_VALUE,
"-i", GAME_ID,
"-k", LICENSEE,
"-l", OLD_LICENSEE,
"-m", MAPPER_TYPE,
"-n", GAME_VERSION,
"-r", SRAM_AMOUNT,
"-t", GAME_TITLE
]
cmd += RGBFIX_FLAGS
cmd += extra
cmd += [file]
result = subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, text=True)
if result.returncode == 0:
return True
else:
print(result.stdout)
return False
def build():
# Make sure the output directories exist.
Path("./bin").mkdir(exist_ok=True)
Path("./obj").mkdir(exist_ok=True)
Path("./obj/a").mkdir(exist_ok=True)
Path("./obj/n").mkdir(exist_ok=True)
# RGBASM pass
files = [f for f in Path("./src").glob("*.asm") if f.is_file()]
for file in files:
# Check if the file needs reassembly
digest_file = Path(f"./obj/{file.stem}.sha256")
n_file = Path(f"./obj/n/{file.stem}.o")
a_file = Path(f"./obj/a/{file.stem}.o")
old_digest = ""
new_digest = ""
if digest_file.exists(): old_digest = digest_file.read_text()
with file.open("rb") as f: new_digest = hashlib.file_digest(f, "sha256").hexdigest()
if old_digest != new_digest:
print(f"Assembling {file.name}...")
n_file.unlink(missing_ok=True)
n_result = assemble(str(file), str(n_file), [])
if not n_result:
print("Aborting.")
return
a_file.unlink(missing_ok=True)
a_result = assemble(str(file), str(a_file), ["-D" "BUILD_POCKET"])
if not a_result:
print("Aborting.")
return
digest_file.write_text(new_digest)
# RGBLINK + RGBFIX pass
print(f"Linking bin/{ROM_NAME}.gbc...")
n_files = [str(f) for f in Path("./obj/n").glob("*.o") if f.is_file()]
Path(f"./bin/{ROM_NAME}.gbc").unlink(missing_ok=True)
Path(f"./bin/{ROM_NAME}.map").unlink(missing_ok=True)
Path(f"./bin/{ROM_NAME}.sym").unlink(missing_ok=True)
n_result = link(n_files, f"bin/{ROM_NAME}.gbc", ["-m", f"bin/{ROM_NAME}.map", "-n", f"bin/{ROM_NAME}.sym"])
if not n_result:
print("Aborting.")
return
print(f"Fixing bin/{ROM_NAME}.gbc...")
n_result = fix(f"bin/{ROM_NAME}.gbc")
if not n_result:
print("Aborting.")
return
print(f"Linking bin/{ROM_NAME}.pocket...")
Path(f"./bin/{ROM_NAME}.pocket").unlink(missing_ok=True)
a_files = [str(f) for f in Path("./obj/a").glob("*.o") if f.is_file()]
a_result = link(a_files, f"bin/{ROM_NAME}.pocket")
if not a_result:
print("Aborting.")
return
print(f"Fixing bin/{ROM_NAME}.pocket...")
a_result = fix(f"bin/{ROM_NAME}.pocket", ["-L", "src/include/pocket-logo.1bpp"])
if not a_result:
print("Aborting.")
return
if __name__ == "__main__":
if sys.argv[-1] == "clean": clean()
if sys.argv[-1] == "rebuild": clean(); build()
else: build()