Initial commit

This commit is contained in:
Luke Street 2023-08-05 18:29:21 -04:00
commit 479692652a
48 changed files with 79125 additions and 0 deletions

13
.clang-format Normal file
View File

@ -0,0 +1,13 @@
---
BasedOnStyle: LLVM
IndentWidth: 2
ColumnLimit: 100
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
AlwaysBreakTemplateDeclarations: Yes
SpacesInAngles: Always # for C++98-compatible nested template arguments
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 0
BreakConstructorInitializers: BeforeComma

10
.gitattributes vendored Normal file
View File

@ -0,0 +1,10 @@
# Auto detect text files and perform LF normalization
* text=auto
# Explicitly declare text files
*.py text
# Enforce platform-specific encodings
*.bat text eol=crlf
*.sh text eol=lf
*.sha1 text eol=lf

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
__pycache__
build
build.ninja
orig/*
!orig/*.sha1
tools/mwcc_compiler/*
!tools/mwcc_compiler/.gitkeep
.ninja_deps
.ninja_log

24
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,24 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/include/**",
"${workspaceFolder}/libc/**"
],
"cStandard": "c99",
"cppStandard": "c++98",
"intelliSenseMode": "linux-clang-x86",
"compilerPath": "",
"configurationProvider": "ms-vscode.makefile-tools",
"browse": {
"path": [
"${workspaceFolder}/include",
"${workspaceFolder}/libc"
],
"limitSymbolsToIncludedHeaders": true
}
}
],
"version": 4
}

8
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"recommendations": [
"ms-vscode.cpptools",
"xaver.clang-format",
"akiramiyakoda.cppincludeguard",
"ms-python.black-formatter"
]
}

41
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,41 @@
{
"[c]": {
"files.encoding": "shiftjis",
"editor.defaultFormatter": "xaver.clang-format"
},
"[cpp]": {
"files.encoding": "shiftjis",
"editor.defaultFormatter": "xaver.clang-format"
},
"[python]":{
"editor.defaultFormatter": "ms-python.black-formatter"
},
"editor.tabSize": 2,
"files.autoSave": "onFocusChange",
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"C/C++ Include Guard.Macro Type": "Filename",
"C/C++ Include Guard.Prefix": "_",
"C/C++ Include Guard.Suffix": "",
"C/C++ Include Guard.Comment Style": "Line",
"C/C++ Include Guard.Subfolder Prefixes": [
{
"folderPath": "include/dolphin",
"prefix": "DOLPHIN_"
},
{
"folderPath": "include/musyx",
"prefix": "MUSYX_"
},
{
"folderPath": "include/rstl",
"prefix": "RSTL_"
},
],
"C/C++ Include Guard.Auto Update Path Allowlist": [
"include"
],
"C/C++ Include Guard.Auto Update Path Blocklist": [
"include/zlib"
]
}

44
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,44 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "ninja",
"type": "shell",
"command": "ninja",
"group": {
"kind": "build",
"isDefault": false
}
},
{
"label": "all_source",
"type": "shell",
"command": "ninja all_source",
"group": "build",
"problemMatcher": []
},
{
"label": "all_source_host",
"type": "shell",
"command": "ninja all_source_host",
"problemMatcher": {
"base": "$gcc"
},
"group": "build"
},
{
"label": "current file (host)",
"type": "shell",
"command": "ninja host/${relativeFile}",
"problemMatcher": {
"base": "$gcc"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

12
config/G2ME01/splits.txt Normal file
View File

@ -0,0 +1,12 @@
Runtime/__init_cpp_exceptions.cpp:
.text start:0x80345C34 end:0x80345CA4
.ctors start:0x803A54A0 end:0x803A54A4
.dtors start:0x803A56A0 end:0x803A56A8
.sdata start:0x80418CA8 end:0x80418CB0
Runtime/Gecko_ExceptionPPC.cp:
.text start:0x80345CA4 end:0x803470DC
.rodata start:0x803B03B0 end:0x803B0448
.data start:0x803BBFD8 end:0x803BC0C0
.bss start:0x803E0640 end:0x803E0650

25648
config/G2ME01/symbols.txt Normal file

File diff suppressed because it is too large Load Diff

0
config/G2MJ01/splits.txt Normal file
View File

25688
config/G2MJ01/symbols.txt Normal file

File diff suppressed because it is too large Load Diff

0
config/G2MP01/splits.txt Normal file
View File

25687
config/G2MP01/symbols.txt Normal file

File diff suppressed because it is too large Load Diff

430
configure.py Normal file
View File

@ -0,0 +1,430 @@
#!/usr/bin/env python3
LIBS = [
{
"lib": "MSL_C.PPCEABI.bare.H",
"mw_version": "1.3.2",
"cflags": "$cflags_runtime",
"host": False,
"objects": [
# TODO: need to remove from FORCEFILES
["Runtime/__init_cpp_exceptions.cpp", False],
# TODO: need to implement all
["Runtime/Gecko_ExceptionPPC.cp", False],
],
},
]
VERSIONS = [
"G2ME01", # 0
"G2MJ01", # 1
"G2MP01", # 2
]
import os
import io
import sys
import argparse
from pathlib import Path
from shutil import which
from tools import ninja_syntax
def path(input: list[Path] | Path | None) -> list[str] | None:
if input is None:
return None
elif isinstance(input, list):
return list(map(str, input))
else:
return [str(input)]
parser = argparse.ArgumentParser()
versions_str = ", ".join(VERSIONS)
parser.add_argument(
"--version",
dest="version",
default="G2ME01",
help=f"version to build ({versions_str})",
)
parser.add_argument(
"--build-dir",
dest="build_dir",
type=Path,
default=Path("build"),
help="base build directory",
)
parser.add_argument(
"--build-dtk",
dest="build_dtk",
type=Path,
help="path to decomp-toolkit source",
)
parser.add_argument(
"--compilers",
dest="compilers",
type=Path,
default=Path("tools/mwcc_compiler"),
help="path to compilers",
)
parser.add_argument(
"--map",
dest="map",
action="store_true",
help="generate map file",
)
parser.add_argument(
"--debug",
dest="debug",
action="store_true",
help="build with debug info (non-matching)",
)
args = parser.parse_args()
# On Windows, we need this to use && in commands
chain = "cmd /c " if os.name == "nt" else ""
out = io.StringIO()
n = ninja_syntax.Writer(out)
n.variable("ninja_required_version", "1.3")
n.newline()
n.comment("The arguments passed to configure.py, for rerunning it.")
configure_args = sys.argv[1:]
# Ignore DEVKITPPC env var on Windows
if os.name != "nt" and "DEVKITPPC" in os.environ and not args.devkitppc:
configure_args.extend(["--devkitppc", os.environ["DEVKITPPC"]])
n.variable("configure_args", configure_args)
n.variable("python", f'"{sys.executable}"')
n.newline()
###
# Variables
###
n.comment("Variables")
version = args.version
version_num = VERSIONS.index(args.version)
build_path = args.build_dir / version
cflags_base = f"-proc gekko -nodefaults -Cpp_exceptions off -RTTI off -fp hard -fp_contract on -O4,p -maxerrors 1 -enum int -inline auto -str reuse -nosyspath -DVERSION={version_num} -i include -i libc"
if args.debug:
cflags_base += " -sym on -D_DEBUG"
else:
cflags_base += " -DNDEBUG"
n.variable("cflags_base", cflags_base)
n.variable(
"cflags_retro",
"$cflags_base -use_lmw_stmw on -str reuse,pool,readonly -gccinc -inline deferred,noauto -common on",
)
n.variable(
"cflags_runtime",
"$cflags_base -use_lmw_stmw on -str reuse,pool,readonly -gccinc -inline deferred,auto",
)
n.variable("cflags_musyx", "$cflags_base -str reuse,pool,readonly -fp_contract off")
asflags = f"-mgekko -I include --defsym version={version_num} -W --strip-local-absolute -gdwarf-2"
n.variable("asflags", asflags)
ldscript_path = build_path / "ldscript.lcf"
ldflags = f"-fp fmadd -nodefaults -lcf {ldscript_path}"
if args.map:
map_path = args.build_dir / f"{version}.MAP"
ldflags += f" -map {map_path}"
if args.debug:
ldflags += " -g"
n.variable("ldflags", ldflags)
mw_link_version = "1.3.2"
n.variable("mw_version", mw_link_version)
if os.name == "nt":
exe = ".exe"
wine = ""
else:
if "_NT-" in os.uname().sysname:
# MSYS2
wine = ""
elif args.wine:
wine = f"{args.wine} "
elif which("wibo") is not None:
wine = "wibo "
else:
wine = "wine "
exe = ""
n.newline()
###
# Tooling
###
n.comment("decomp-toolkit")
tools_path = Path("tools")
build_tools_path = args.build_dir / "tools"
if args.build_dtk:
dtk = build_tools_path / "release" / f"dtk{exe}"
n.rule(
name="cargo",
command="cargo build --release --manifest-path $in --bin $bin --target-dir $target",
description="CARGO $bin",
depfile=path(Path("$target") / "release" / "$bin.d"),
deps="gcc",
)
n.build(
outputs=path(dtk),
rule="cargo",
inputs=path(args.build_dtk / "Cargo.toml"),
variables={
"bin": "dtk",
"target": build_tools_path,
},
)
else:
dtk = build_tools_path / f"dtk{exe}"
download_dtk = tools_path / "download_dtk.py"
n.rule(
name="download_dtk",
command=f"$python {download_dtk} $in $out",
description="DOWNLOAD $out",
)
n.build(
outputs=path(dtk),
rule="download_dtk",
inputs="dtk_version",
implicit=path([download_dtk]),
)
n.newline()
###
# Rules
###
compiler_path = args.compilers / "$mw_version"
mwcc = compiler_path / "mwcceppc.exe"
mwld = compiler_path / "mwldeppc.exe"
mwcc_cmd = f"{chain}{wine}{mwcc} $cflags -MMD -c $in -o $basedir"
mwld_cmd = f"{wine}{mwld} $ldflags -o $out @$out.rsp"
ar_cmd = f"{dtk} ar create $out @$out.rsp"
if os.name != "nt":
transform_dep = tools_path / "transform-dep.py"
transform_dep_cmd = f" && $python {transform_dep} $basefile.d $basefile.d"
mwcc_cmd += transform_dep_cmd
n.comment("Link ELF file")
n.rule(
name="link",
command=mwld_cmd,
description="LINK $out",
rspfile="$out.rsp",
rspfile_content="$in_newline",
)
n.newline()
n.comment("MWCC build")
n.rule(
name="mwcc",
command=mwcc_cmd,
description="MWCC $out",
depfile="$basefile.d",
deps="gcc",
)
n.newline()
###
# Rules for source files
###
n.comment("Source files")
src_path = Path("src")
asm_path = Path("asm")
build_src_path = build_path / "src"
units_path = build_path / "units.txt"
def locate_unit(unit):
for lib in LIBS:
for obj in lib["objects"]:
if obj[0] == unit:
return [lib, obj]
return None
has_units = False
if units_path.is_file():
has_units = True
src_path = Path("src")
link_inputs = []
used_compiler_versions = set()
with open(units_path) as r:
for line in r:
obj_path, unit = line.rstrip().split(":", 2)
unit_path = src_path / unit
if unit_path.exists():
result = locate_unit(unit)
if result:
lib, object = result
lib_name = lib["lib"]
completed = None
options = {
"add_to_all": True,
"mw_version": None,
"cflags": None,
}
if type(object) is list:
if len(object) > 1:
completed = object[1]
if len(object) > 2:
options.update(object[2])
object = object[0]
mw_version = options["mw_version"] or lib["mw_version"]
used_compiler_versions.add(mw_version)
n.comment(f"{unit}: {lib_name} (linked {completed})")
base_object = Path(object).with_suffix('')
src_obj_path = build_src_path / f"{base_object}.o"
n.build(
outputs=path(src_obj_path),
rule="mwcc",
inputs=path(unit_path),
variables={
"mw_version": mw_version,
"cflags": options["cflags"] or lib["cflags"],
"basedir": os.path.dirname(build_src_path / f"{base_object}"),
"basefile": path(build_src_path / f"{base_object}"),
},
)
if completed:
obj_path = src_obj_path
else:
print(f"No configuration entry found for {unit}")
exit(1)
link_inputs.append(obj_path)
n.newline()
# Check if all compiler versions exist
for mw_version in used_compiler_versions:
mw_path = args.compilers / mw_version / "mwcceppc.exe"
if not os.path.exists(mw_path):
print(f"Compiler {mw_path} does not exist")
exit(1)
# Check if linker exists
mw_path = args.compilers / mw_link_version / "mwldeppc.exe"
if not os.path.exists(mw_path):
print(f"Linker {mw_path} does not exist")
exit(1)
###
# Link
###
n.comment("Link")
if args.map:
n.build(
outputs=path(build_path / "main.elf"),
rule="link",
inputs=path(link_inputs),
implicit=path(ldscript_path),
implicit_outputs=path(map_path),
)
else:
n.build(
outputs=path(build_path / "main.elf"),
rule="link",
inputs=path(link_inputs),
implicit=path(ldscript_path),
)
n.newline()
###
# Generate DOL
###
n.comment("Generate DOL")
n.rule(
name="elf2dol",
command=f"{dtk} elf2dol $in $out",
description="DOL $out",
)
n.build(
outputs=path(build_path / "main.dol"),
rule="elf2dol",
inputs=path(build_path / "main.elf"),
implicit=path(dtk),
)
n.newline()
###
# Check DOL hash
###
n.comment("Check DOL hash")
n.rule(
name="check",
command=f"{dtk} shasum -c $in -o $out",
description="CHECK $in",
)
n.build(
outputs=path(build_path / "main.dol.ok"),
rule="check",
inputs=path(Path("orig") / f"{version}.sha1"),
implicit=path([build_path / "main.dol", dtk]),
)
n.newline()
###
# DOL split
###
n.comment("Generate objects from original DOL")
dol_path = Path("orig") / version / "sys" / "main.dol"
config_path = Path("config") / version
splits_path = config_path / "splits.txt"
symbols_path = config_path / "symbols.txt"
n.rule(
name="split",
command=f"{dtk} dol split $in $out -p $splits -s $symbols",
description="SPLIT $in",
)
n.build(
inputs=path(dol_path),
outputs=path(build_path),
rule="split",
implicit=path([dtk, "$splits", "$symbols"]),
implicit_outputs=path(units_path),
variables={
"splits": splits_path,
"symbols": symbols_path,
},
)
n.newline()
###
# Regenerate on change
###
n.comment("Reconfigure on change")
script = os.path.relpath(__file__)
n.rule(
name="configure",
command=f"$python {script} $configure_args",
generator=True,
description=f"RUN {script}",
)
n.build(
outputs="build.ninja",
rule="configure",
implicit=path([script, tools_path / "ninja_syntax.py"]),
)
n.newline()
###
# Default rule
###
n.comment("Default rule")
if has_units:
n.default(path(build_path / "main.dol.ok"))
else:
n.default(path(build_path))
###
# Write build.ninja
###
with open("build.ninja", "w") as f:
f.write(out.getvalue())
n.close()

View File

@ -0,0 +1,71 @@
#ifndef __PPC_EABI_LINKER
#define __PPC_EABI_LINKER
__declspec(section ".init") extern char _stack_addr[];
__declspec(section ".init") extern char _stack_end[];
__declspec(section ".init") extern char _heap_addr[];
__declspec(section ".init") extern char _heap_end[];
__declspec(section ".init") extern const char _fextabindex_rom[];
__declspec(section ".init") extern char _fextabindex[];
__declspec(section ".init") extern char _eextabindex[];
__declspec(section ".init") extern char _SDA_BASE_[];
__declspec(section ".init") extern char _SDA2_BASE_[];
typedef struct __rom_copy_info {
char* rom;
char* addr;
unsigned int size;
} __rom_copy_info;
__declspec(section ".init") extern __rom_copy_info _rom_copy_info[];
typedef struct __bss_init_info {
char* addr;
unsigned int size;
} __bss_init_info;
__declspec(section ".init") extern __bss_init_info _bss_init_info[];
typedef struct __eti_init_info {
void* eti_start;
void* eti_end;
void* code_start;
unsigned long code_size;
} __eti_init_info;
__declspec(section ".init") extern __eti_init_info _eti_init_info[];
__declspec(section ".init") extern const char _f_init_rom[];
__declspec(section ".init") extern char _f_init[];
__declspec(section ".init") extern char _e_init[];
__declspec(section ".init") extern const char _f_text_rom[];
__declspec(section ".init") extern char _f_text[];
__declspec(section ".init") extern char _e_text[];
__declspec(section ".init") extern const char _f_rodata_rom[];
__declspec(section ".init") extern char _f_rodata[];
__declspec(section ".init") extern char _e_rodata[];
__declspec(section ".init") extern const char _fextab_rom[];
__declspec(section ".init") extern char _fextab[];
__declspec(section ".init") extern char _eextab[];
__declspec(section ".init") extern const char _f_data_rom[];
__declspec(section ".init") extern char _f_data[];
__declspec(section ".init") extern char _e_data[];
__declspec(section ".init") extern char _f_bss[];
__declspec(section ".init") extern char _e_bss[];
__declspec(section ".init") extern const char _f_sdata_rom[];
__declspec(section ".init") extern char _f_sdata[];
__declspec(section ".init") extern char _e_sdata[];
__declspec(section ".init") extern char _f_sbss[];
__declspec(section ".init") extern char _e_sbss[];
__declspec(section ".init") extern const char _f_sdata2_rom[];
__declspec(section ".init") extern char _f_sdata2[];
__declspec(section ".init") extern char _e_sdata2[];
__declspec(section ".init") extern char _f_sbss2[];
__declspec(section ".init") extern char _e_sbss2[];
__declspec(section ".init") extern const char _f_PPC_EMB_sdata0_rom[];
__declspec(section ".init") extern char _f_PPC_EMB_sdata0[];
__declspec(section ".init") extern char _e_PPC_EMB_sdata0[];
__declspec(section ".init") extern char _f_PPC_EMB_sbss0[];
__declspec(section ".init") extern char _e_PPC_EMB_sbss0[];
#endif // __PPC_EABI_LINKER

198
include/macros.inc Normal file
View File

@ -0,0 +1,198 @@
# General Purpose Registers (GPRs)
.set r0, 0
.set r1, 1
.set r2, 2
.set r3, 3
.set r4, 4
.set r5, 5
.set r6, 6
.set r7, 7
.set r8, 8
.set r9, 9
.set r10, 10
.set r11, 11
.set r12, 12
.set r13, 13
.set r14, 14
.set r15, 15
.set r16, 16
.set r17, 17
.set r18, 18
.set r19, 19
.set r20, 20
.set r21, 21
.set r22, 22
.set r23, 23
.set r24, 24
.set r25, 25
.set r26, 26
.set r27, 27
.set r28, 28
.set r29, 29
.set r30, 30
.set r31, 31
# Floating Point Registers (FPRs)
.set f0, 0
.set f1, 1
.set f2, 2
.set f3, 3
.set f4, 4
.set f5, 5
.set f6, 6
.set f7, 7
.set f8, 8
.set f9, 9
.set f10, 10
.set f11, 11
.set f12, 12
.set f13, 13
.set f14, 14
.set f15, 15
.set f16, 16
.set f17, 17
.set f18, 18
.set f19, 19
.set f20, 20
.set f21, 21
.set f22, 22
.set f23, 23
.set f24, 24
.set f25, 25
.set f26, 26
.set f27, 27
.set f28, 28
.set f29, 29
.set f30, 30
.set f31, 31
# Graphics Quantization Registers (GQRs)
.set qr0, 0
.set qr1, 1
.set qr2, 2
.set qr3, 3
.set qr4, 4
.set qr5, 5
.set qr6, 6
.set qr7, 7
# Special Purpose Registers (SPRs)
.set XER, 1
.set LR, 8
.set CTR, 9
.set DSISR, 18
.set DAR, 19
.set DEC, 22
.set SDR1, 25
.set SRR0, 26
.set SRR1, 27
.set SPRG0, 272
.set SPRG1, 273
.set SPRG2, 274
.set SPRG3, 275
.set EAR, 282
.set PVR, 287
.set IBAT0U, 528
.set IBAT0L, 529
.set IBAT1U, 530
.set IBAT1L, 531
.set IBAT2U, 532
.set IBAT2L, 533
.set IBAT3U, 534
.set IBAT3L, 535
.set DBAT0U, 536
.set DBAT0L, 537
.set DBAT1U, 538
.set DBAT1L, 539
.set DBAT2U, 540
.set DBAT2L, 541
.set DBAT3U, 542
.set DBAT3L, 543
.set GQR0, 912
.set GQR1, 913
.set GQR2, 914
.set GQR3, 915
.set GQR4, 916
.set GQR5, 917
.set GQR6, 918
.set GQR7, 919
.set HID2, 920
.set WPAR, 921
.set DMA_U, 922
.set DMA_L, 923
.set UMMCR0, 936
.set UPMC1, 937
.set UPMC2, 938
.set USIA, 939
.set UMMCR1, 940
.set UPMC3, 941
.set UPMC4, 942
.set USDA, 943
.set MMCR0, 952
.set PMC1, 953
.set PMC2, 954
.set SIA, 955
.set MMCR1, 956
.set PMC3, 957
.set PMC4, 958
.set SDA, 959
.set HID0, 1008
.set HID1, 1009
.set IABR, 1010
.set DABR, 1013
.set L2CR, 1017
.set ICTC, 1019
.set THRM1, 1020
.set THRM2, 1021
.set THRM3, 1022
# Defines a sized symbol with function type.
# Usage:
# .fn my_function, local
# /* asm here */
# .endfn my_function
.macro .fn name, visibility=global
.\visibility "\name"
.type "\name", @function
"\name":
.endm
.macro .endfn name
.size "\name", . - "\name"
.endm
# Defines a sized symbol with object type.
# Usage:
# .obj my_object, local
# /* data here */
# .endobj my_object
.macro .obj name, visibility=global
.\visibility "\name"
.type "\name", @object
"\name":
.endm
.macro .endobj name
.size "\name", . - "\name"
.endm
# Defines a sized symbol without a type.
# Usage:
# .sym my_sym, local
# /* anything here */
# .endsym my_sym
.macro .sym name, visibility=global
.\visibility "\name"
"\name":
.endm
.macro .endsym name
.size "\name", . - "\name"
.endm
# Generates a relative relocation against a symbol.
# Usage:
# .rel my_function, .L_label
.macro .rel name, label
.4byte "\name" + ("\label" - "\name")
.endm

30
libc/ansi_files.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef _DOLPHIN_ANSI_FILES_H
#define _DOLPHIN_ANSI_FILES_H
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus
#define set_eof(file) \
do { \
(file)->state.io_state = __neutral; \
(file)->state.eof = 1; \
(file)->buffer_len = 0; \
} while (0)
#define set_error(file) \
do { \
(file)->state.error = 1; \
(file)->buffer_len = 0; \
} while (0)
int __flush_buffer(FILE* file, size_t* length);
void __prep_buffer(FILE* file);
int __flush_all();
#ifdef __cplusplus
};
#endif // ifdef __cplusplus
#endif

20
libc/assert.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef _ASSERT_H_
#define _ASSERT_H_
#ifdef __cplusplus
extern "C" {
#endif
#if __STDC_VERSION__ >= 201112L
// The C11 way
#define static_assert(cond, msg) _Static_assert(cond, #msg)
#else
// The old, hacky way
#define static_assert(cond, msg) typedef char static_assertion_##msg[(cond) ? 1 : -1]
#endif
#ifdef __cplusplus
}
#endif
#endif

14
libc/buffer_io.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef _BUFFER_IO
#define _BUFFER_IO
#include <stdio.h>
enum { __align_buffer, __dont_align_buffer };
void __convert_from_newlines(unsigned char* p, size_t* n);
void __convert_to_newlines(unsigned char* p, size_t* n);
void __prep_buffer(FILE*);
int __load_buffer(FILE*, size_t* bytes_loaded, int alignment);
int __flush_buffer(FILE*, size_t* bytes_flushed);
#endif // _BUFFER_IO

17
libc/console_io.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef _CONSOLE_IO
#define _CONSOLE_IO
#include "stddef.h"
#include "file_struc.h"
#ifdef __cplusplus
extern "C" {
#endif
int __write_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc);
#ifdef __cplusplus
}
#endif
#endif // _CONSOLE_IO

69
libc/ctype.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef _CTYPE_H_
#define _CTYPE_H_
#ifdef __cplusplus
extern "C" {
#endif
// eof.h
#define EOF -1L
extern unsigned char __ctype_map[];
extern unsigned char __lower_map[];
extern unsigned char __upper_map[];
#define __control_char 0x01
#define __motion_char 0x02
#define __space_char 0x04
#define __punctuation 0x08
#define __digit 0x10
#define __hex_digit 0x20
#define __lower_case 0x40
#define __upper_case 0x80
#define __letter (__lower_case | __upper_case)
#define __alphanumeric (__letter | __digit)
#define __graphic (__alphanumeric | __punctuation)
#define __printable (__graphic | __space_char)
#define __whitespace (__motion_char | __space_char)
#define __control (__motion_char | __control_char)
#define __zero_fill(c) ((int)(unsigned char)(c))
#ifndef _CTYPE_INLINE
#define _CTYPE_INLINE static inline
#endif
_CTYPE_INLINE
int isalnum(int c) { return __ctype_map[__zero_fill(c)] & __alphanumeric; }
_CTYPE_INLINE
int isalpha(int c) { return __ctype_map[__zero_fill(c)] & __letter; }
_CTYPE_INLINE
int iscntrl(int c) { return __ctype_map[__zero_fill(c)] & __control; }
_CTYPE_INLINE
int isdigit(int c) { return __ctype_map[__zero_fill(c)] & __digit; }
_CTYPE_INLINE
int isgraph(int c) { return __ctype_map[__zero_fill(c)] & __graphic; }
_CTYPE_INLINE
int islower(int c) { return __ctype_map[__zero_fill(c)] & __lower_case; }
_CTYPE_INLINE
int isprint(int c) { return __ctype_map[__zero_fill(c)] & __printable; }
_CTYPE_INLINE
int ispunct(int c) { return __ctype_map[__zero_fill(c)] & __punctuation; }
_CTYPE_INLINE
int isspace(int c) { return __ctype_map[__zero_fill(c)] & __whitespace; }
_CTYPE_INLINE
int isupper(int c) { return __ctype_map[__zero_fill(c)] & __upper_case; }
_CTYPE_INLINE
int isxdigit(int c) { return __ctype_map[__zero_fill(c)] & __hex_digit; }
_CTYPE_INLINE
int tolower(int c) { return ((c == EOF) ? EOF : ((int)__lower_map[__zero_fill(c)])); }
_CTYPE_INLINE
int toupper(int c) { return ((c == EOF) ? EOF : ((int)__upper_map[__zero_fill(c)])); }
_CTYPE_INLINE
int iswblank(int c) { return ((c == (int)L' ') || (c == (int)L'\t')); }
#ifdef __cplusplus
}
#endif
#endif

21
libc/errno.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _ERRNO_H_
#define _ERRNO_H_
#ifdef __cplusplus
extern "C" {
#endif
extern int errno;
#define ENOERR 0
#define EDOM 33
#define ERANGE 34
#define ESIGPARM 36
#define EFPOS 40
#define EILSEQ 84
#ifdef __cplusplus
}
#endif
#endif

22
libc/file_struc.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef _FILE_STRUC
#define _FILE_STRUC
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned long __file_handle;
typedef unsigned long fpos_t;
typedef void (*__idle_proc)(void);
typedef int (*__pos_proc)(__file_handle file, fpos_t* position, int mode, __idle_proc idle_proc);
typedef int (*__io_proc)(__file_handle file, unsigned char* buff, size_t* count,
__idle_proc idle_proc);
typedef int (*__close_proc)(__file_handle file);
#ifdef __cplusplus
}
#endif
#endif // _FILE_STRUC

18
libc/float.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _FLOAT_H_
#define _FLOAT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define FLT_MAX 3.402823466e+38f
#define FLT_EPSILON 1.192092896e-07f
#define FLT_MIN 1.175494351e-38f
#define DBL_EPSILON 1.1920929e-07
#ifdef __cplusplus
}
#endif
#endif

24
libc/limits.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _LIMITS_H_
#define _LIMITS_H_
#define SCHAR_MAX 0x7f
#define UCHAR_MAX 0xffU
#if defined(__MWERKS__) && __option(unsigned_char)
#define CHAR_MIN 0U
#define CHAR_MAX UCHAR_MAX
#else
#define CHAR_MIN SCHAR_MIN
#define CHAR_MAX SCHAR_MAX
#endif
#define SHRT_MAX 0x7fff
#define USHRT_MAX 0xffffU
#define INT_MAX 0x7fffffff
#define UINT_MAX 0xffffffffU
#define LONG_MAX 0x7fffffffL
#define ULONG_MAX 0xffffffffUL
#endif

39
libc/locale.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef _LOCALE_H_
#define _LOCALE_H_
#ifdef __cplusplus
extern "C" {
#endif
struct lconv {
char* decimal_point;
char* thousands_sep;
char* grouping;
char* mon_decimal_point;
char* mon_thousands_sep;
char* mon_grouping;
char* positive_sign;
char* negative_sign;
char* currency_symbol;
char frac_digits;
char p_cs_precedes;
char n_cs_precedes;
char p_sep_by_space;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
char* int_curr_symbol;
char int_frac_digits;
char int_p_cs_precedes;
char int_n_cs_precedes;
char int_p_sep_by_space;
char int_n_sep_by_space;
char int_p_sign_posn;
char int_n_sign_posn;
};
#ifdef __cplusplus
}
#endif
#endif

213
libc/math.h Normal file
View File

@ -0,0 +1,213 @@
#ifndef _MATH_H_
#define _MATH_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _MATH_INLINE
#define _MATH_INLINE static inline
#endif
#ifdef __MWERKS__
/* Metrowerks */
#if __option(little_endian)
#define __IEEE_LITTLE_ENDIAN
#else
#define __IEEE_BIG_ENDIAN
#endif
#else
/* GCC */
#ifdef __BIG_ENDIAN__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __LITTLE_ENDIAN__
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#ifndef __IEEE_BIG_ENDIAN
#ifndef __IEEE_LITTLE_ENDIAN
#error Must define endianness
#endif
#endif
#ifndef _INT32
typedef int _INT32;
typedef unsigned int _UINT32;
#endif
int abs(int n);
#ifdef __MWERKS__
#define abs(n) __abs(n)
#define labs(n) __labs(n)
static inline double fabs(double x) { return __fabs(x); }
#else
// static inline int abs(int n) {
// int mask = n >> 31;
// return (n + mask) ^ mask;
// }
#endif
extern _INT32 __float_huge[];
extern _INT32 __float_nan[];
extern _INT32 __double_huge[];
extern _INT32 __extended_huge[];
#define HUGE_VAL (*(double*)__double_huge)
#define INFINITY (*(float*)__float_huge)
#define NAN (*(float*)__float_nan)
#define HUGE_VALF (*(float*)__float_huge)
#define HUGE_VALL (*(long double*)__extended_huge)
double fabs(double x);
double fmod(double x, double m);
double sin(double x);
double cos(double x);
double atan(double x);
double atan2(double y, double x);
double tan(double x);
_MATH_INLINE float fabsf(float x) { return (float)fabs((double)x); }
_MATH_INLINE float sinf(float x) { return (float)sin((double)x); }
_MATH_INLINE float cosf(float x) { return (float)cos((double)x); }
_MATH_INLINE float atan2f(float y, float x) { return (float)atan2((double)y, (double)x); }
float fmodf(float x, float m) { return (float)fmod((double)x, (double)m); }
float tanf(float x);
double acos(double x);
float acosf(float x);
double ldexp(double x, int exp);
double copysign(double x, double y);
double floor(double x);
float floorf(float x) { return floor(x); }
double fabs(double x);
double pow(double x, double y);
float powf(float __x, float __y) { return pow(__x, __y); }
#ifdef __MWERKS__
#pragma cplusplus on
#endif
#ifdef __IEEE_LITTLE_ENDIAN
#define __HI(x) (sizeof(x) == 8 ? *(1 + (_INT32*)&x) : (*(_INT32*)&x))
#define __LO(x) (*(_INT32*)&x)
#define __UHI(x) (sizeof(x) == 8 ? *(1 + (_UINT32*)&x) : (*(_UINT32*)&x))
#define __ULO(x) (*(_UINT32*)&x)
#else
#define __LO(x) (sizeof(x) == 8 ? *(1 + (_INT32*)&x) : (*(_INT32*)&x))
#define __HI(x) (*(_INT32*)&x)
#define __ULO(x) (sizeof(x) == 8 ? *(1 + (_UINT32*)&x) : (*(_UINT32*)&x))
#define __UHI(x) (*(_UINT32*)&x)
#endif
#define FP_NAN 1
#define FP_INFINITE 2
#define FP_ZERO 3
#define FP_NORMAL 4
#define FP_SUBNORMAL 5
static inline int __fpclassifyf(float x) {
switch ((*(_INT32*)&x) & 0x7f800000) {
case 0x7f800000: {
if ((*(_INT32*)&x) & 0x007fffff)
return FP_NAN;
else
return FP_INFINITE;
break;
}
case 0: {
if ((*(_INT32*)&x) & 0x007fffff)
return FP_SUBNORMAL;
else
return FP_ZERO;
break;
}
}
return FP_NORMAL;
}
static inline int __fpclassifyd(double x) {
switch (__HI(x) & 0x7ff00000) {
case 0x7ff00000: {
if ((__HI(x) & 0x000fffff) || (__LO(x) & 0xffffffff))
return FP_NAN;
else
return FP_INFINITE;
break;
}
case 0: {
if ((__HI(x) & 0x000fffff) || (__LO(x) & 0xffffffff))
return FP_SUBNORMAL;
else
return FP_ZERO;
break;
}
}
return FP_NORMAL;
}
#define fpclassify(x) \
(sizeof(x) == sizeof(float) ? __fpclassifyf((float)(x)) : __fpclassifyd((double)(x)))
#define isnormal(x) (fpclassify(x) == FP_NORMAL)
#define isnan(x) (fpclassify(x) == FP_NAN)
#define isinf(x) (fpclassify(x) == FP_INFINITE)
#define isfinite(x) ((fpclassify(x) > FP_INFINITE))
static inline float sqrtf(float x) {
const double _half = .5;
const double _three = 3.0;
volatile float y;
if (x > 0.0f) {
double guess = __frsqrte((double)x); /* returns an approximation to */
guess = _half * guess * (_three - guess * guess * x); /* now have 12 sig bits
*/
guess = _half * guess * (_three - guess * guess * x); /* now have 24 sig bits
*/
guess = _half * guess * (_three - guess * guess * x); /* now have 32 sig bits
*/
y = (float)(x * guess);
return y;
}
return x;
}
static inline double sqrt(double x) {
if (x > 0.0) {
double guess = __frsqrte(x); /* returns an approximation to */
guess = .5 * guess * (3.0 - guess * guess * x); /* now have 8 sig bits */
guess = .5 * guess * (3.0 - guess * guess * x); /* now have 16 sig bits */
guess = .5 * guess * (3.0 - guess * guess * x); /* now have 32 sig bits */
guess = .5 * guess * (3.0 - guess * guess * x); /* now have > 53 sig bits */
return x * guess;
} else if (x == 0.0) {
return 0;
} else if (x) {
return NAN;
}
return INFINITY;
}
static inline float ldexpf(float x, int exp) { return (float)ldexp((double)x, exp); }
static inline double scalbn(double x, int n) { return ldexp(x, n); }
static inline float scalbnf(float x, int n) { return (float)ldexpf(x, n); }
#ifdef __MWERKS__
#pragma cplusplus reset
#endif
#ifdef __cplusplus
}
#endif
#endif

22
libc/mem_funcs.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef _MEM_FUNCS_H_
#define _MEM_FUNCS_H_
#ifdef __cplusplus
extern "C" {
#endif
#define __min_bytes_for_long_copy 32
void __copy_mem(void* dst, const void* src, unsigned long n);
void __move_mem(void* dst, const void* src, unsigned long n);
void __copy_longs_aligned(void* dst, const void* src, unsigned long n);
void __copy_longs_rev_aligned(void* dst, const void* src, unsigned long n);
void __copy_longs_unaligned(void* dst, const void* src, unsigned long n);
void __copy_longs_rev_unaligned(void* dst, const void* src, unsigned long n);
void __fill_mem(void* dst, int val, unsigned long n);
#ifdef __cplusplus
}
#endif
#endif

39
libc/stdarg.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef _STDARG_H_
#define _STDARG_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __MWERKS__
typedef struct {
char gpr;
char fpr;
char reserved[2];
char* input_arg_area;
char* reg_save_area;
} __va_list[1];
typedef __va_list va_list;
#ifndef __MWERKS__
extern void __builtin_va_info(va_list*);
#endif
void* __va_arg(va_list v_list, unsigned char type);
#define va_start(ap, fmt) ((void)fmt, __builtin_va_info(&ap))
#define va_arg(ap, t) (*((t*)__va_arg(ap, _var_arg_typeof(t))))
#define va_end(ap) (void)0
#else
typedef __builtin_va_list va_list;
#define va_start(v, l) __builtin_va_start(v, l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v, l) __builtin_va_arg(v, l)
#endif
#ifdef __cplusplus
}
#endif
#endif

23
libc/stddef.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _STDDEF_H_
#define _STDDEF_H_
#ifdef __cplusplus
extern "C" {
#endif
#define offsetof(type, member) ((size_t) & (((type*)0)->member))
/* These break 1.2.5 */
//typedef __typeof__(sizeof(0)) size_t;
//typedef __typeof__((char*)0 - (char*)0) ptrdiff_t;
typedef unsigned long size_t;
typedef long ptrdiff_t;
#ifndef NULL
#define NULL 0L
#endif
#ifdef __cplusplus
}
#endif
#endif

14
libc/stdint.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef _STDINT_H_
#define _STDINT_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned long int uintptr_t;
#ifdef __cplusplus
}
#endif
#endif

135
libc/stdio.h Normal file
View File

@ -0,0 +1,135 @@
#ifndef _STDIO
#define _STDIO
#include "types.h"
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define __ungetc_buffer_size 2
typedef unsigned long __file_handle;
typedef unsigned long fpos_t;
#ifndef __cplusplus
typedef unsigned short wchar_t;
#endif
enum __io_modes {
__read = 1,
__write = 2,
__read_write = 3,
__append = 4,
};
enum __file_kinds {
__closed_file,
__disk_file,
__console_file,
__unavailable_file,
};
enum __file_orientation {
__unoriented,
__char_oriented,
__wide_oriented,
};
enum __io_results {
__no_io_error,
__io_error,
__io_EOF,
};
typedef struct {
unsigned int open_mode : 2;
unsigned int io_mode : 3;
unsigned int buffer_mode : 2;
unsigned int file_kind : 3;
unsigned int file_orientation : 2;
unsigned int binary_io : 1;
} __file_modes;
enum __io_states {
__neutral,
__writing,
__reading,
__rereading,
};
typedef struct {
unsigned int io_state : 3;
unsigned int free_buffer : 1;
unsigned char eof;
unsigned char error;
} __file_state;
typedef void (*__idle_proc)(void);
typedef int (*__pos_proc)(__file_handle file, fpos_t* position, int mode, __idle_proc idle_proc);
typedef int (*__io_proc)(__file_handle file, unsigned char* buff, size_t* count,
__idle_proc idle_proc);
typedef int (*__close_proc)(__file_handle file);
typedef struct _IO_FILE {
__file_handle handle;
__file_modes mode;
__file_state state;
unsigned char is_dynamically_allocated;
unsigned char char_buffer;
unsigned char char_buffer_overflow;
unsigned char ungetc_buffer[__ungetc_buffer_size];
wchar_t ungetwc_buffer[__ungetc_buffer_size];
unsigned long position;
unsigned char* buffer;
unsigned long buffer_size;
unsigned char* buffer_ptr;
unsigned long buffer_len;
unsigned long buffer_alignment;
unsigned long saved_buffer_len;
unsigned long buffer_pos;
__pos_proc position_proc;
__io_proc read_proc;
__io_proc write_proc;
__close_proc close_proc;
__idle_proc idle_proc;
struct _IO_FILE* next_file_struct;
} FILE;
typedef struct {
char* CharStr;
size_t MaxCharCount;
size_t CharsWritten;
} __OutStrCtrl;
typedef struct {
char* NextChar;
int NullCharDetected;
} __InStrCtrl;
#define EOF -1L
enum __ReadProcActions { __GetChar, __UngetChar, __CheckForError };
#define _IONBF 0
#define _IOLBF 1
#define _IOFBF 2
int puts(const char* s);
int printf(const char*, ...);
int sprintf(char* s, const char* format, ...);
int vprintf(const char* format, va_list arg);
int vsprintf(char* s, const char* format, va_list arg);
size_t fread(const void*, size_t memb_size, size_t num_memb, FILE*);
size_t fwrite(const void*, size_t memb_size, size_t num_memb, FILE*);
int fseek(FILE* file, long offset, int mode);
size_t __fwrite(const void*, size_t, size_t, FILE*);
#ifdef __cplusplus
}
#endif
#endif // _STDIO

25
libc/stdlib.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef _STDLIB_H_
#define _STDLIB_H_
#include <stddef.h>
#include <wchar.h>
#define RAND_MAX 32767
#ifdef __cplusplus
extern "C" {
#endif
void srand(unsigned int seed);
int rand(void);
void exit(int status);
size_t wcstombs(char* dest, const wchar_t* src, size_t max);
typedef int (*_compare_function)(const void*, const void*);
void qsort(void*, size_t, size_t, _compare_function);
#ifdef __cplusplus
}
#endif
#endif

27
libc/string.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _STRING_H_
#define _STRING_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#pragma section code_type ".init"
void* memcpy(void* dst, const void* src, size_t n);
void* memset(void* dst, int val, size_t n);
void __fill_mem(void* dst, int val, size_t n);
#pragma section code_type
size_t strlen(const char* s);
char* strcpy(char* dest, const char* src);
char* strncpy(char* dest, const char* src, size_t num);
int strcmp(const char* s1, const char* s2);
int strncmp(const char* s1, const char* s2, size_t n);
char* strncat(char* dest, const char* src, size_t n);
#ifdef __cplusplus
}
#endif
#endif

16
libc/wchar.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _WCHAR_H_
#define _WCHAR_H_
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
int fwide(FILE* stream, int mode);
#ifdef __cplusplus
}
#endif
#endif

1
orig/G2ME01.sha1 Normal file
View File

@ -0,0 +1 @@
6ef9b491d0cc08bc81a124fdedb8bfaec34d0010 build/G2ME01/main.dol

1
orig/G2MJ01.sha1 Normal file
View File

@ -0,0 +1 @@
7f24a768f7b1a687adb88e56559ad8637ed80589 build/G2MJ01/main.dol

1
orig/G2MP01.sha1 Normal file
View File

@ -0,0 +1 @@
5a670d5da3d181e86a0df7cf7751c7055eee35fb build/G2MP01/main.dol

View File

@ -0,0 +1,40 @@
#include "__ppc_eabi_linker.h"
#include "NMWException.h"
#if __MWERKS__
#pragma exceptions on
#endif
typedef struct ProcessInfo {
__eti_init_info* exception_info;
char* TOC;
int active;
} ProcessInfo;
static ProcessInfo fragmentinfo[1];
int __register_fragment(struct __eti_init_info* info, char* TOC) {
ProcessInfo* f;
int i;
for (i = 0, f = fragmentinfo; i < 1; ++i, ++f) {
if (f->active == 0) {
f->exception_info = info;
f->TOC = TOC;
f->active = 1;
return i;
}
}
return -1;
}
void __unregister_fragment(int fragmentId) {
ProcessInfo* f;
if (fragmentId >= 0 && fragmentId < 1) {
f = &fragmentinfo[fragmentId];
f->exception_info = 0;
f->TOC = 0;
f->active = 0;
}
}

View File

@ -0,0 +1,36 @@
#ifndef _NMWEXCEPTION
#define _NMWEXCEPTION
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define CTORARG_TYPE int
#define CTORARG_PARTIAL (0)
#define CTORARG_COMPLETE (1)
#define CTORCALL_COMPLETE(ctor, objptr) \
(((void (*)(void*, CTORARG_TYPE))ctor)(objptr, CTORARG_COMPLETE))
#define DTORARG_TYPE int
#define DTORCALL_COMPLETE(dtor, objptr) (((void (*)(void*, DTORARG_TYPE))dtor)(objptr, -1))
typedef struct DestructorChain {
struct DestructorChain* next;
void* destructor;
void* object;
} DestructorChain;
void __unregister_fragment(int fragmentID);
int __register_fragment(struct __eti_init_info* info, char* TOC);
void* __register_global_object(void* object, void* destructor, void* regmem);
void __destroy_global_chain(void);
#ifdef __cplusplus
}
#endif
#endif // _NMWEXCEPTION

View File

@ -0,0 +1,58 @@
#include "NMWException.h"
#include "__ppc_eabi_linker.h"
// #if __MWERKS__
// #pragma exceptions off
// #pragma internal on
// #endif
#ifdef __cplusplus
extern "C" {
#endif
extern void __init_cpp_exceptions(void);
extern void __fini_cpp_exceptions(void);
#ifdef __cplusplus
}
#endif
static int fragmentID = -2;
void __exception_info_constants(void** info, char** R2) {
register char* temp;
/* clang-format off */
asm {
mr temp,r2
}
/* clang-format on */
*R2 = temp;
*info = _eti_init_info;
}
// UNUSED: __find_exception_addresses__FPvPcPPvPPv
void __init_cpp_exceptions(void) {
char* R2;
void* info;
if (fragmentID == -2) {
__exception_info_constants(&info, &R2);
fragmentID = __register_fragment((struct __eti_init_info*)info, R2);
}
}
void __fini_cpp_exceptions(void) {
if (fragmentID != -2) {
__unregister_fragment(fragmentID);
fragmentID = -2;
}
}
/* clang-format off */
__declspec(section ".ctors") static void *const
__init_cpp_exceptions_reference = __init_cpp_exceptions;
__declspec(section ".dtors") static void *const
__destroy_global_chain_reference = __destroy_global_chain;
__declspec(section ".dtors") static void *const
__fini_cpp_exceptions_reference = __fini_cpp_exceptions;
/* clang-format on */

0
tools/__init__.py Normal file
View File

9
tools/asmdiff.sh Normal file
View File

@ -0,0 +1,9 @@
#!/bin/bash -e
VERSION="${VERSION:=0}"
OBJDUMP="$DEVKITPPC/bin/powerpc-eabi-objdump -Dz -bbinary -EB -mpowerpc -M gekko"
if [ ! -z "$1" ]; then
OPTIONS="--start-address=$(($1)) --stop-address=$(($2))"
fi
$OBJDUMP $OPTIONS main.dol > main.dump
$OBJDUMP $OPTIONS new.dol > new.dump
diff -u --color=always main.dump new.dump

41
tools/download_dtk.py Normal file
View File

@ -0,0 +1,41 @@
import argparse
import urllib.request
import os
import stat
import platform
from pathlib import Path
REPO = "https://github.com/encounter/decomp-toolkit"
def main():
parser = argparse.ArgumentParser()
parser.add_argument("tag_file", help="file containing GitHub tag")
parser.add_argument("output", type=Path, help="output file path")
args = parser.parse_args()
with open(args.tag_file, "r") as f:
tag = f.readline().rstrip()
uname = platform.uname()
suffix = ""
system = uname.system.lower()
if system == "darwin":
system = "macos"
elif system == "windows":
suffix = ".exe"
arch = uname.machine.lower()
if arch == "amd64":
arch = "x86_64"
url = f"{REPO}/releases/download/{tag}/dtk-{system}-{arch}{suffix}"
output = args.output
# print(f"Downloading {url} to {output}")
urllib.request.urlretrieve(url, output)
st = os.stat(output)
os.chmod(output, st.st_mode | stat.S_IEXEC)
if __name__ == "__main__":
main()

1
tools/dtk_version Normal file
View File

@ -0,0 +1 @@
v0.3.0

View File

199
tools/ninja_syntax.py Normal file
View File

@ -0,0 +1,199 @@
#!/usr/bin/python
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Python module for generating .ninja files.
Note that this is emphatically not a required piece of Ninja; it's
just a helpful utility for build-file-generation systems that already
use Python.
"""
import re
import textwrap
def escape_path(word):
return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:')
class Writer(object):
def __init__(self, output, width=78):
self.output = output
self.width = width
def newline(self):
self.output.write('\n')
def comment(self, text):
for line in textwrap.wrap(text, self.width - 2, break_long_words=False,
break_on_hyphens=False):
self.output.write('# ' + line + '\n')
def variable(self, key, value, indent=0):
if value is None:
return
if isinstance(value, list):
value = ' '.join(filter(None, value)) # Filter out empty strings.
self._line('%s = %s' % (key, value), indent)
def pool(self, name, depth):
self._line('pool %s' % name)
self.variable('depth', depth, indent=1)
def rule(self, name, command, description=None, depfile=None,
generator=False, pool=None, restat=False, rspfile=None,
rspfile_content=None, deps=None):
self._line('rule %s' % name)
self.variable('command', command, indent=1)
if description:
self.variable('description', description, indent=1)
if depfile:
self.variable('depfile', depfile, indent=1)
if generator:
self.variable('generator', '1', indent=1)
if pool:
self.variable('pool', pool, indent=1)
if restat:
self.variable('restat', '1', indent=1)
if rspfile:
self.variable('rspfile', rspfile, indent=1)
if rspfile_content:
self.variable('rspfile_content', rspfile_content, indent=1)
if deps:
self.variable('deps', deps, indent=1)
def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
variables=None, implicit_outputs=None, pool=None, dyndep=None):
outputs = as_list(outputs)
out_outputs = [escape_path(x) for x in outputs]
all_inputs = [escape_path(x) for x in as_list(inputs)]
if implicit:
implicit = [escape_path(x) for x in as_list(implicit)]
all_inputs.append('|')
all_inputs.extend(implicit)
if order_only:
order_only = [escape_path(x) for x in as_list(order_only)]
all_inputs.append('||')
all_inputs.extend(order_only)
if implicit_outputs:
implicit_outputs = [escape_path(x)
for x in as_list(implicit_outputs)]
out_outputs.append('|')
out_outputs.extend(implicit_outputs)
self._line('build %s: %s' % (' '.join(out_outputs),
' '.join([rule] + all_inputs)))
if pool is not None:
self._line(' pool = %s' % pool)
if dyndep is not None:
self._line(' dyndep = %s' % dyndep)
if variables:
if isinstance(variables, dict):
iterator = iter(variables.items())
else:
iterator = iter(variables)
for key, val in iterator:
self.variable(key, val, indent=1)
return outputs
def include(self, path):
self._line('include %s' % path)
def subninja(self, path):
self._line('subninja %s' % path)
def default(self, paths):
self._line('default %s' % ' '.join(as_list(paths)))
def _count_dollars_before_index(self, s, i):
"""Returns the number of '$' characters right in front of s[i]."""
dollar_count = 0
dollar_index = i - 1
while dollar_index > 0 and s[dollar_index] == '$':
dollar_count += 1
dollar_index -= 1
return dollar_count
def _line(self, text, indent=0):
"""Write 'text' word-wrapped at self.width characters."""
leading_space = ' ' * indent
while len(leading_space) + len(text) > self.width:
# The text is too wide; wrap if possible.
# Find the rightmost space that would obey our width constraint and
# that's not an escaped space.
available_space = self.width - len(leading_space) - len(' $')
space = available_space
while True:
space = text.rfind(' ', 0, space)
if (space < 0 or
self._count_dollars_before_index(text, space) % 2 == 0):
break
if space < 0:
# No such space; just use the first unescaped space we can find.
space = available_space - 1
while True:
space = text.find(' ', space + 1)
if (space < 0 or
self._count_dollars_before_index(text, space) % 2 == 0):
break
if space < 0:
# Give up on breaking.
break
self.output.write(leading_space + text[0:space] + ' $\n')
text = text[space+1:]
# Subsequent lines are continuations, so indent them.
leading_space = ' ' * (indent+2)
self.output.write(leading_space + text + '\n')
def close(self):
self.output.close()
def as_list(input):
if input is None:
return []
if isinstance(input, list):
return input
return [input]
def escape(string):
"""Escape a string such that it can be embedded into a Ninja file without
further interpretation."""
assert '\n' not in string, 'Ninja syntax does not allow newlines'
# We only have one special metacharacter: '$'.
return string.replace('$', '$$')
def expand(string, vars, local_vars={}):
"""Expand a string containing $vars as Ninja would.
Note: doesn't handle the full Ninja variable syntax, but it's enough
to make configure.py's use of it work.
"""
def exp(m):
var = m.group(1)
if var == '$':
return '$'
return local_vars.get(var, vars.get(var, ''))
return re.sub(r'\$(\$|\w*)', exp, string)

67
tools/transform-dep.py Normal file
View File

@ -0,0 +1,67 @@
#!/usr/bin/env python3
import argparse
import os
from platform import uname
wineprefix = os.path.join(os.environ['HOME'], '.wine')
if 'WINEPREFIX' in os.environ:
wineprefix = os.environ['WINEPREFIX']
winedevices = os.path.join(wineprefix, 'dosdevices')
def in_wsl() -> bool:
return 'microsoft-standard' in uname().release
def import_d_file(in_file) -> str:
out_text = ''
with open(in_file) as file:
for idx, line in enumerate(file):
if idx == 0:
if line.endswith(' \\\n'):
out_text += line[:-3].replace('\\', '/') + " \\\n"
else:
out_text += line.replace('\\', '/')
else:
suffix = ''
if line.endswith(' \\\n'):
suffix = ' \\'
path = line.lstrip()[:-3]
else:
path = line.strip()
# lowercase drive letter
path = path[0].lower() + path[1:]
if path[0] == 'z':
# shortcut for z:
path = path[2:].replace('\\', '/')
elif in_wsl():
path = path[0:1] + path[2:]
path = os.path.join('/mnt', path.replace('\\', '/'))
else:
# use $WINEPREFIX/dosdevices to resolve path
path = os.path.realpath(os.path.join(winedevices, path.replace('\\', '/')))
out_text += "\t" + path + suffix + "\n"
return out_text
def main():
parser = argparse.ArgumentParser(
description="""Transform a .d file from Wine paths to normal paths"""
)
parser.add_argument(
"d_file",
help="""Dependency file in""",
)
parser.add_argument(
"d_file_out",
help="""Dependency file out""",
)
args = parser.parse_args()
output = import_d_file(args.d_file)
with open(args.d_file_out, "w", encoding="UTF-8") as f:
f.write(output)
if __name__ == "__main__":
main()