diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..e677285 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,36 @@ +name: Build + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + container: ghcr.io/primedecomp/build:main + strategy: + fail-fast: false + matrix: + version: [G2ME01, G2MJ01, G2MP01] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Git config + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Build + run: | + python configure.py --map --version ${{matrix.version}} --compilers /compilers/GC --orig /orig + ninja + # - name: Upload progress + # if: github.ref == 'refs/heads/main' + # continue-on-error: true + # env: + # PROGRESS_API_KEY: ${{secrets.PROGRESS_API_KEY}} + # run: | + # python tools/upload-progress.py -b https://progress.deco.mp/ -p prime -v ${{matrix.version}} \ + # build/mp1.${{matrix.version}}/main.dol.progress + - name: Upload map + uses: actions/upload-artifact@v3 + with: + name: ${{matrix.version}}.MAP + path: build/${{matrix.version}}.MAP diff --git a/README.md b/README.md new file mode 100644 index 0000000..b9dfe51 --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +Metroid Prime 2: Echoes [![Build Status]][actions] +============= + +[Build Status]: https://github.com/PrimeDecomp/echoes/actions/workflows/build.yml/badge.svg +[actions]: https://github.com/PrimeDecomp/echoes/actions/workflows/build.yml + + + +A decompilation of Metroid Prime 2: Echoes. + +This repository builds the following DOLs: + +``` +6ef9b491d0cc08bc81a124fdedb8bfaec34d0010 build/G2ME01/main.dol +7f24a768f7b1a687adb88e56559ad8637ed80589 build/G2MJ01/main.dol +5a670d5da3d181e86a0df7cf7751c7055eee35fb build/G2MP01/main.dol +``` + + + +Dependencies +============ + +Windows: +-------- +- Install [ninja](https://github.com/ninja-build/ninja/releases) and add it to `%PATH%`. +- Install [Python](https://www.python.org/downloads/) and add it to `%PATH%`. + - Also available from the [Windows Store](https://apps.microsoft.com/store/detail/python-311/9NRWMJP3717K). + +macOS: +------ +- Install [ninja](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages): + ``` + brew install ninja + ``` +- Install [wine-crossover](https://github.com/Gcenx/homebrew-wine): + ``` + brew install --cask --no-quarantine gcenx/wine/wine-crossover + ``` + +Linux: +------ +- Install [ninja](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages). +- Install wine from your package manager. + - Faster alternative: [WiBo](https://github.com/decompals/WiBo), a minimal 32-bit Windows binary wrapper. + Ensure the binary is in `PATH`. + +Building +======== + +- Checkout the repository: + ``` + git clone https://github.com/PrimeDecomp/echoes.git + ``` +- Download [GC_WII_COMPILERS.zip](https://cdn.discordapp.com/attachments/727918646525165659/1129759991696457728/GC_WII_COMPILERS.zip) +- Extract the _contents_ of the `GC` directory to `tools/mwcc_compiler`. + - Resulting structure should be (for example) `tools/mwcc_compiler/1.3.2/mwcceppc.exe` +- Using [Dolphin Emulator](https://dolphin-emu.org/), extract your game to `orig/G2ME01`. +![](assets/dolphin-extract.png) + - To save space, the only necessary files are the following. Any others can be deleted. + - `sys/main.dol` + - `files/RelProd/*.rel` +- Configure: + ``` + python configure.py + ``` +- Build: + ``` + ninja + ``` diff --git a/assets/dolphin-extract.png b/assets/dolphin-extract.png new file mode 100644 index 0000000..43d83ba Binary files /dev/null and b/assets/dolphin-extract.png differ diff --git a/configure.py b/configure.py index b8550cf..f96e8aa 100644 --- a/configure.py +++ b/configure.py @@ -8,7 +8,7 @@ LIBS = [ "objects": [ # TODO: need to remove from FORCEFILES ["Runtime/__init_cpp_exceptions.cpp", False], - # TODO: need to implement all + # TODO: need to implement all ["Runtime/Gecko_ExceptionPPC.cp", False], ], }, @@ -51,7 +51,7 @@ parser.add_argument( dest="build_dir", type=Path, default=Path("build"), - help="base build directory", + help="base build directory (default: build)", ) parser.add_argument( "--build-dtk", @@ -64,7 +64,14 @@ parser.add_argument( dest="compilers", type=Path, default=Path("tools/mwcc_compiler"), - help="path to compilers", + help="path to compilers (default: tools/mwcc_compiler)", +) +parser.add_argument( + "--orig", + dest="orig", + type=Path, + default=Path("orig"), + help="path to retail files (default: orig)", ) parser.add_argument( "--map", @@ -186,8 +193,8 @@ else: n.build( outputs=path(dtk), rule="download_dtk", - inputs="dtk_version", - implicit=path([download_dtk]), + inputs=path(tools_path / "dtk_version"), + implicit=path(download_dtk), ) n.newline() @@ -236,6 +243,7 @@ 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"]: @@ -279,7 +287,7 @@ if units_path.is_file(): n.comment(f"{unit}: {lib_name} (linked {completed})") - base_object = Path(object).with_suffix('') + base_object = Path(object).with_suffix("") src_obj_path = build_src_path / f"{base_object}.o" n.build( outputs=path(src_obj_path), @@ -288,7 +296,9 @@ if units_path.is_file(): variables={ "mw_version": mw_version, "cflags": options["cflags"] or lib["cflags"], - "basedir": os.path.dirname(build_src_path / f"{base_object}"), + "basedir": os.path.dirname( + build_src_path / f"{base_object}" + ), "basefile": path(build_src_path / f"{base_object}"), }, ) @@ -373,20 +383,20 @@ if units_path.is_file(): # DOL split ### n.comment("Generate objects from original DOL") -dol_path = Path("orig") / version / "sys" / "main.dol" +dol_path = args.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", + command=f"{dtk} dol split $in $out -p $splits -s $symbols --no-update", description="SPLIT $in", ) n.build( inputs=path(dol_path), outputs=path(build_path), rule="split", - implicit=path([dtk, "$splits", "$symbols"]), + implicit=path([dtk, splits_path, symbols_path]), implicit_outputs=path(units_path), variables={ "splits": splits_path, @@ -409,7 +419,7 @@ n.rule( n.build( outputs="build.ninja", rule="configure", - implicit=path([script, tools_path / "ninja_syntax.py"]), + implicit=path([script, tools_path / "ninja_syntax.py", build_path]), ) n.newline() diff --git a/tools/dtk_version b/tools/dtk_version index 268b033..937cd78 100644 --- a/tools/dtk_version +++ b/tools/dtk_version @@ -1 +1 @@ -v0.3.0 +v0.3.1