Skip to content

Commit

Permalink
Update to latest dtk-template
Browse files Browse the repository at this point in the history
  • Loading branch information
henriquegemignani committed Jan 12, 2025
1 parent 289df2c commit 0eaa595
Show file tree
Hide file tree
Showing 5 changed files with 739 additions and 285 deletions.
81 changes: 70 additions & 11 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@
import sys
from pathlib import Path
from typing import Any, Dict, List
from tools.project import *

from tools.project import (
Object,
ProgressCategory,
ProjectConfig,
calculate_progress,
generate_build,
is_windows,
)

# Game versions
DEFAULT_VERSION = 0
Expand Down Expand Up @@ -110,6 +118,12 @@
action="store_true",
help="builds equivalent (but non-matching) or modded objects",
)
parser.add_argument(
"--no-progress",
dest="progress",
action="store_false",
help="disable progress calculation",
)
args = parser.parse_args()

config = ProjectConfig()
Expand All @@ -122,10 +136,10 @@
config.objdiff_path = args.objdiff
config.binutils_path = args.binutils
config.compilers_path = args.compilers
config.debug = args.debug
config.generate_map = args.map
config.non_matching = args.non_matching
config.sjiswrap_path = args.sjiswrap
config.progress = args.progress
if not is_windows():
config.wrapper = args.wrapper
# Don't build asm unless we're --non-matching
Expand All @@ -135,9 +149,9 @@
# Tool versions
config.binutils_tag = "2.42-1"
config.compilers_tag = "20240706"
config.dtk_tag = "v0.9.5"
config.objdiff_tag = "v2.0.0-beta.5"
config.sjiswrap_tag = "v1.1.1"
config.dtk_tag = "v1.3.0"
config.objdiff_tag = "v2.4.0"
config.sjiswrap_tag = "v1.2.0"
config.wibo_tag = "0.6.11"

# Project
Expand All @@ -148,16 +162,26 @@
"--strip-local-absolute",
"-I include",
f"-I build/{config.version}/include",
f"--defsym version={version_num}",
f"--defsym BUILD_VERSION={version_num}",
f"--defsym VERSION_{config.version}",
]
config.ldflags = [
"-fp hardware",
"-nodefaults",
"-listclosure",
]
if args.debug:
config.ldflags.append("-g") # Or -gdwarf-2 for Wii linkers
if args.map:
config.ldflags.append("-mapunused")
# config.ldflags.append("-listclosure") # For Wii linkers

# Use for any additional files that should cause a re-configure when modified
config.reconfig_deps = []

# Optional numeric ID for decomp.me preset
# Can be overridden in libraries or objects
config.scratch_preset_id = None

# Base flags, common to most GC/Wii games.
# Generally leave untouched, with overrides added below.
cflags_base = [
Expand All @@ -180,7 +204,8 @@
"-i include",
"-i libc",
f"-i build/{config.version}/include",
f"-DVERSION={version_num}",
f"-DBUILD_VERSION={version_num}",
f"-DVERSION_{config.version}",
]

# GC 3.0 and above require -enc SJIS instead of -multibyte
Expand All @@ -190,7 +215,8 @@
cflags_base.append("-multibyte")

# Debug flags
if config.debug:
if args.debug:
# Or -sym dwarf-2 for Wii compilers
cflags_base.extend(["-sym on", "-DDEBUG=1"])
else:
cflags_base.append("-DNDEBUG=1")
Expand Down Expand Up @@ -233,13 +259,13 @@
# RELs not yet set up for non-USA versions
config.build_rels = False


# Helper function for Dolphin libraries
def DolphinLib(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
return {
"lib": lib_name,
"mw_version": "GC/1.2.5n",
"cflags": cflags_base,
"progress_category": "sdk",
"host": False,
"objects": objects,
}
Expand All @@ -251,6 +277,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
"lib": lib_name,
"mw_version": "GC/1.3.2",
"cflags": cflags_rel,
"progress_category": "game",
"host": True,
"objects": objects,
}
Expand All @@ -260,13 +287,20 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
NonMatching = False # Object does not match and should not be linked
Equivalent = config.non_matching # Object should be linked when configured with --non-matching


# Object is only matching for specific versions
def MatchingFor(*versions):
return config.version in versions


config.warn_missing_config = True
config.warn_missing_source = False
config.libs = [
{
"lib": "MetroidPrime",
"cflags": cflags_retro,
"mw_version": "GC/2.7",
"progress_category": "game", # str | List[str]
"host": True,
"objects": [
Object(NonMatching, "MetroidPrime/main.cpp"),
Expand All @@ -290,6 +324,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
"lib": "Kyoto_CW",
"mw_version": "GC/2.7",
"cflags": cflags_retro,
"progress_category": "game", # str | List[str]
"host": True,
"objects": [
Object(Matching, "Kyoto/Basics/CStopwatch.cpp"),
Expand All @@ -310,6 +345,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
"lib": "Runtime.PPCEABI.H",
"mw_version": config.linker_version,
"cflags": cflags_runtime,
"progress_category": "sdk", # str | List[str]
"host": False,
"objects": [
Object(Matching, "Runtime/global_destructor_chain.c"),
Expand Down Expand Up @@ -370,6 +406,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
"lib": "REL",
"mw_version": "GC/2.7",
"cflags": cflags_rel,
"progress_category": "game", # str | List[str]
"host": False,
"objects": [
Object(Matching, "REL/REL_Setup.cpp"),
Expand All @@ -394,8 +431,30 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
),
]


# Optional callback to adjust link order. This can be used to add, remove, or reorder objects.
# This is called once per module, with the module ID and the current link order.
#
# For example, this adds "dummy.c" to the end of the DOL link order if configured with --non-matching.
# "dummy.c" *must* be configured as a Matching (or Equivalent) object in order to be linked.
def link_order_callback(module_id: int, objects: List[str]) -> List[str]:
# Don't modify the link order for matching builds
if not config.non_matching:
return objects
if module_id == 0: # DOL
return objects + ["dummy.c"]
return objects

# Uncomment to enable the link order callback.
# config.link_order_callback = link_order_callback


# Optional extra categories for progress tracking
config.progress_categories = []
# Adjust as desired for your project
config.progress_categories = [
ProgressCategory("game", "Game Code"),
ProgressCategory("sdk", "SDK Code"),
]
config.progress_each_module = args.verbose

if args.mode == "configure":
Expand Down
46 changes: 30 additions & 16 deletions tools/decompctx.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,63 @@
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = os.path.abspath(os.path.join(script_dir, ".."))
src_dir = os.path.join(root_dir, "src")
include_dirs = [
os.path.join(root_dir, "include"),
os.path.join(root_dir, "libc"),
]
include_dirs: List[str] = [] # Set with -I flag

include_pattern = re.compile(r'^#\s*include\s*[<"](.+?)[>"]$')
include_pattern = re.compile(r'^#\s*include\s*[<"](.+?)[>"]')
guard_pattern = re.compile(r"^#\s*ifndef\s+(.*)$")
once_pattern = re.compile(r"^#\s*pragma\s+once$")

defines = set()
deps = []


def import_h_file(in_file: str, r_path: str, deps: List[str]) -> str:
def import_h_file(in_file: str, r_path: str) -> str:
rel_path = os.path.join(root_dir, r_path, in_file)
if os.path.exists(rel_path):
return import_c_file(rel_path, deps)
return import_c_file(rel_path)
for include_dir in include_dirs:
inc_path = os.path.join(include_dir, in_file)
if os.path.exists(inc_path):
return import_c_file(inc_path, deps)
return import_c_file(inc_path)
else:
print("Failed to locate", in_file)
return ""


def import_c_file(in_file: str, deps: List[str]) -> str:
def import_c_file(in_file: str) -> str:
in_file = os.path.relpath(in_file, root_dir)
deps.append(in_file)
out_text = ""

try:
with open(in_file, encoding="utf-8") as file:
out_text += process_file(in_file, list(file), deps)
out_text += process_file(in_file, list(file))
except Exception:
with open(in_file) as file:
out_text += process_file(in_file, list(file), deps)
out_text += process_file(in_file, list(file))
return out_text


def process_file(in_file: str, lines: List[str], deps: List[str]) -> str:
def process_file(in_file: str, lines: List[str]) -> str:
out_text = ""
for idx, line in enumerate(lines):
guard_match = guard_pattern.match(line.strip())
if idx == 0:
guard_match = guard_pattern.match(line.strip())
if guard_match:
if guard_match[1] in defines:
break
defines.add(guard_match[1])
else:
once_match = once_pattern.match(line.strip())
if once_match:
if in_file in defines:
break
defines.add(in_file)
print("Processing file", in_file)
include_match = include_pattern.match(line.strip())
if include_match and not include_match[1].endswith(".s"):
out_text += f'/* "{in_file}" line {idx} "{include_match[1]}" */\n'
out_text += import_h_file(include_match[1], os.path.dirname(in_file), deps)
out_text += import_h_file(include_match[1], os.path.dirname(in_file))
out_text += f'/* end "{include_match[1]}" */\n'
else:
out_text += line
Expand Down Expand Up @@ -100,10 +105,19 @@ def main():
"--depfile",
help="""Dependency file""",
)
parser.add_argument(
"-I",
"--include",
help="""Include directory""",
action="append",
)
args = parser.parse_args()

deps = []
output = import_c_file(args.c_file, deps)
if args.include is None:
exit("No include directories specified")
global include_dirs
include_dirs = args.include
output = import_c_file(args.c_file)

with open(os.path.join(root_dir, args.output), "w", encoding="utf-8") as f:
f.write(output)
Expand Down
47 changes: 31 additions & 16 deletions tools/download_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def dtk_url(tag: str) -> str:
repo = "https://github.com/encounter/decomp-toolkit"
return f"{repo}/releases/download/{tag}/dtk-{system}-{arch}{suffix}"


def objdiff_cli_url(tag: str) -> str:
uname = platform.uname()
suffix = ""
Expand Down Expand Up @@ -90,6 +91,21 @@ def wibo_url(tag: str) -> str:
"wibo": wibo_url,
}

def download(url, response, output) -> None:
if url.endswith(".zip"):
data = io.BytesIO(response.read())
with zipfile.ZipFile(data) as f:
f.extractall(output)
# Make all files executable
for root, _, files in os.walk(output):
for name in files:
os.chmod(os.path.join(root, name), 0o755)
output.touch(mode=0o755) # Update dir modtime
else:
with open(output, "wb") as f:
shutil.copyfileobj(response, f)
st = os.stat(output)
os.chmod(output, st.st_mode | stat.S_IEXEC)

def main() -> None:
parser = argparse.ArgumentParser()
Expand All @@ -103,22 +119,21 @@ def main() -> None:

print(f"Downloading {url} to {output}")
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
with urllib.request.urlopen(req) as response:
if url.endswith(".zip"):
data = io.BytesIO(response.read())
with zipfile.ZipFile(data) as f:
f.extractall(output)
# Make all files executable
for root, _, files in os.walk(output):
for name in files:
os.chmod(os.path.join(root, name), 0o755)
output.touch(mode=0o755) # Update dir modtime
else:
with open(output, "wb") as f:
shutil.copyfileobj(response, f)
st = os.stat(output)
os.chmod(output, st.st_mode | stat.S_IEXEC)

try:
with urllib.request.urlopen(req) as response:
download(url, response, output)
except urllib.error.URLError as e:
if str(e).find("CERTIFICATE_VERIFY_FAILED") == -1:
raise e
try:
import certifi
import ssl
except:
print("\"certifi\" module not found. Please install it using \"python -m pip install certifi\".")
return

with urllib.request.urlopen(req, context=ssl.create_default_context(cafile=certifi.where())) as response:
download(url, response, output)

if __name__ == "__main__":
main()
Loading

0 comments on commit 0eaa595

Please sign in to comment.