mirror of
https://github.com/PrimeDecomp/echoes.git
synced 2024-11-26 23:00:24 +00:00
Initial commit
This commit is contained in:
commit
479692652a
13
.clang-format
Normal file
13
.clang-format
Normal 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
10
.gitattributes
vendored
Normal 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
9
.gitignore
vendored
Normal 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
24
.vscode/c_cpp_properties.json
vendored
Normal 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
8
.vscode/extensions.json
vendored
Normal 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
41
.vscode/settings.json
vendored
Normal 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
44
.vscode/tasks.json
vendored
Normal 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
12
config/G2ME01/splits.txt
Normal 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
25648
config/G2ME01/symbols.txt
Normal file
File diff suppressed because it is too large
Load Diff
0
config/G2MJ01/splits.txt
Normal file
0
config/G2MJ01/splits.txt
Normal file
25688
config/G2MJ01/symbols.txt
Normal 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
0
config/G2MP01/splits.txt
Normal file
25687
config/G2MP01/symbols.txt
Normal file
25687
config/G2MP01/symbols.txt
Normal file
File diff suppressed because it is too large
Load Diff
430
configure.py
Normal file
430
configure.py
Normal 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()
|
71
include/__ppc_eabi_linker.h
Normal file
71
include/__ppc_eabi_linker.h
Normal 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
198
include/macros.inc
Normal 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
30
libc/ansi_files.h
Normal 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
20
libc/assert.h
Normal 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
14
libc/buffer_io.h
Normal 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
17
libc/console_io.h
Normal 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
69
libc/ctype.h
Normal 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
21
libc/errno.h
Normal 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
22
libc/file_struc.h
Normal 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
18
libc/float.h
Normal 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
24
libc/limits.h
Normal 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
39
libc/locale.h
Normal 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
213
libc/math.h
Normal 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
22
libc/mem_funcs.h
Normal 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
39
libc/stdarg.h
Normal 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
23
libc/stddef.h
Normal 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
14
libc/stdint.h
Normal 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
135
libc/stdio.h
Normal 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
25
libc/stdlib.h
Normal 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
27
libc/string.h
Normal 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
16
libc/wchar.h
Normal 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
1
orig/G2ME01.sha1
Normal file
@ -0,0 +1 @@
|
||||
6ef9b491d0cc08bc81a124fdedb8bfaec34d0010 build/G2ME01/main.dol
|
1
orig/G2MJ01.sha1
Normal file
1
orig/G2MJ01.sha1
Normal file
@ -0,0 +1 @@
|
||||
7f24a768f7b1a687adb88e56559ad8637ed80589 build/G2MJ01/main.dol
|
1
orig/G2MP01.sha1
Normal file
1
orig/G2MP01.sha1
Normal file
@ -0,0 +1 @@
|
||||
5a670d5da3d181e86a0df7cf7751c7055eee35fb build/G2MP01/main.dol
|
40
src/Runtime/Gecko_ExceptionPPC.cp
Normal file
40
src/Runtime/Gecko_ExceptionPPC.cp
Normal 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;
|
||||
}
|
||||
}
|
36
src/Runtime/NMWException.h
Normal file
36
src/Runtime/NMWException.h
Normal 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
|
58
src/Runtime/__init_cpp_exceptions.cpp
Normal file
58
src/Runtime/__init_cpp_exceptions.cpp
Normal 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
0
tools/__init__.py
Normal file
9
tools/asmdiff.sh
Normal file
9
tools/asmdiff.sh
Normal 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
41
tools/download_dtk.py
Normal 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
1
tools/dtk_version
Normal file
@ -0,0 +1 @@
|
||||
v0.3.0
|
0
tools/mwcc_compiler/.gitkeep
Normal file
0
tools/mwcc_compiler/.gitkeep
Normal file
199
tools/ninja_syntax.py
Normal file
199
tools/ninja_syntax.py
Normal 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
67
tools/transform-dep.py
Normal 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()
|
Loading…
Reference in New Issue
Block a user