# Copyright 2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 PYTHON_COMPAT=( python3_{10..15} ) inherit cmake edo flag-o-matic python-any-r1 xdg MY_PN="Goemon64Recomp" # Upstream tags this v0.2.0-dev, which is not a valid version suffix here. MY_PV="0.2.0-dev" # The original NTSC-U ROM. MY_ROM="mnsg.us.z64" MY_ROM_SHA1="df8083a54296b8c151917c5333e1c85f014a2a66" MY_ROM_DECOMPRESSED="mnsg.us.decompressed.z64" # Every git submodule, recursively, as "path|owner/repo|commit". Upstream pins # each of these to an exact commit and builds them in tree; # lib/freetype-windows-binaries is left out because it is Windows only. G64_SUBMODULES=( "Goemon64RecompSyms|klorfmorf/Goemon64RecompSyms|49f4e3269f05c737cb4bf698b9ef7142c92f1ac7" "lib/N64ModernRuntime|klorfmorf/N64ModernRuntime|fc4592a31414daf0040c19907e0b1976b2e48a67" "lib/RmlUi|mikke89/RmlUi|7a06f27db04fe5d13a5dacc19b2b4544673a4eca" "lib/lunasvg|sammycage/lunasvg|4166d0cccfc059b39d5ecfc372524375e59448f9" "lib/mnsg|klorfmorf/mnsg|be85f9018b1fb2ffa332270d6abfb9f8c3cae323" "lib/rt64|klorfmorf/rt64|abb3d7ad0ed60a8a74aa839222d4c107e828b7f5" "lib/N64ModernRuntime/N64Recomp|N64Recomp/N64Recomp|07fcdac76da3e47105238d45defe83d56c2821f5" "lib/N64ModernRuntime/thirdparty/miniz|richgel999/miniz|8573fd7cd6f49b262a0ccc447f3c6acfc415e556" "lib/N64ModernRuntime/thirdparty/o1heap|N64Recomp/o1heap|a124b850791db2a33f7354d2b0aa7da821cef6f5" "lib/N64ModernRuntime/thirdparty/xxHash|Cyan4973/xxHash|ac3a25da3d957d9ef3e4114d9f8332d34ce83a46" "lib/mnsg/tools/asm-differ|simonlindholm/asm-differ|4eb23bcd4bbeab81c16535c6318389e0c55584f7" "lib/mnsg/tools/decomp-permuter|simonlindholm/decomp-permuter|ec2efeebb33e2b1de81e39fbf7cbe3cd97350472" "lib/mnsg/tools/m2c|matt-kempster/m2c|a21c1dcd7255b176c032bb932f521846e98d4372" "lib/N64ModernRuntime/N64Recomp/lib/ELFIO|serge1/ELFIO|ad8b641f9682b6091ba8b9f7c8152255c1a2c803" "lib/N64ModernRuntime/N64Recomp/lib/fmt|fmtlib/fmt|0e8aad961d66904cfda8d7cc894f6f6eee2d9f30" "lib/N64ModernRuntime/N64Recomp/lib/rabbitizer|Decompollaborate/rabbitizer|e0d8003047938e2ec3697eaf8d61a84d11d17b43" "lib/N64ModernRuntime/N64Recomp/lib/sljit|zherczeg/sljit|f6326087b3404efb07c6d3deed97b3c3b8098c0c" "lib/N64ModernRuntime/N64Recomp/lib/tomlplusplus|marzer/tomlplusplus|1f7884e59165e517462f922e7b6de131bd9844f3" "lib/rt64/src/contrib/ddspp|redorav/ddspp|2bdf73882b9169ca9d7a307b24d65d6c4e196084" "lib/rt64/src/contrib/dxc|rt64/dxc-bin|cc15e715ee378a4f675b335bd1071ff105873fc8" "lib/rt64/src/contrib/hlslpp|redorav/hlslpp|6f5274c66132e8f951c400103d897582b8f21491" "lib/rt64/src/contrib/im3d|john-chapman/im3d|d03941725fd0bd08c78c46e3e5b0265526e9d060" "lib/rt64/src/contrib/imgui|ocornut/imgui|277ae93c41314ba5f4c7444f37c4319cdf07e8cf" "lib/rt64/src/contrib/implot|epezent/implot|f156599faefe316f7dd20fe6c783bf87c8bb6fd9" "lib/rt64/src/contrib/mupen64plus-core|mupen64plus/mupen64plus-core|860fac3fbae94194a392c1d9857e185eda6d083e" "lib/rt64/src/contrib/mupen64plus-win32-deps|mupen64plus/mupen64plus-win32-deps|de8111fdcb89144abc16c85650ce4e21e028bfb5" "lib/rt64/src/contrib/nativefiledialog-extended|btzy/nativefiledialog-extended|17b6e8ce219c0677f94b63636abb9296b28841ca" "lib/rt64/src/contrib/plume|renderbag/plume|51b1ad443b9f202c5cfc930ae25345d3f2ba7716" "lib/rt64/src/contrib/re-spirv|rt64/re-spirv|5d6b756ee62760f71b65d37e41a0b5a3dab90507" "lib/rt64/src/contrib/spirv-cross|KhronosGroup/SPIRV-Cross|6173e24b31f09a0c3217103a130e74c4ddec14a6" "lib/rt64/src/contrib/stb|nothings/stb|ae721c50eaf761660b4f90cc590453cdb0c2acd0" "lib/rt64/src/contrib/xxHash|Cyan4973/xxHash|1864a50c9b5cf8500d8e9e61ed92aa0dd3772750" "lib/rt64/src/contrib/zstd|facebook/zstd|0ff651dd876823b99fa5c5f53292be28381aee9b" "lib/rt64/src/contrib/plume/contrib/D3D12MemoryAllocator|GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator|9ef66bc14edd10dee0de3a545b98578363552f66" "lib/rt64/src/contrib/plume/contrib/Vulkan-Headers|KhronosGroup/Vulkan-Headers|2fa203425eb4af9dfc6b03f97ef72b0b5bcb8350" "lib/rt64/src/contrib/plume/contrib/VulkanMemoryAllocator|GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator|29b35ea4232688c0f42cdff0c10848290760a417" "lib/rt64/src/contrib/plume/contrib/volk|zeux/volk|be3dbd49bf77052665e96b6c7484af855e7e5f67" "lib/rt64/src/contrib/re-spirv/external/SPIRV-Headers|KhronosGroup/SPIRV-Headers|f013f08e4455bcc1f0eed8e3dd5e2009682656d9" ) DESCRIPTION="Static recompilation of Mystical Ninja Starring Goemon." HOMEPAGE="https://github.com/klorfmorf/Goemon64Recomp" SRC_URI="https://github.com/klorfmorf/${MY_PN}/archive/refs/tags/v${MY_PV}.tar.gz -> ${P}.tar.gz" _g64_mod= for _g64_mod in "${G64_SUBMODULES[@]}"; do _g64_repo="${_g64_mod#*|}" _g64_repo="${_g64_repo%%|*}" _g64_sha="${_g64_mod##*|}" SRC_URI+=" https://github.com/${_g64_repo}/archive/${_g64_sha}.tar.gz -> ${_g64_repo##*/}-${_g64_sha}.tar.gz" done unset _g64_mod _g64_repo _g64_sha S="${WORKDIR}/${MY_PN}-${MY_PV}" LICENSE="GPL-3" SLOT="0" # Not installable yet: the ROM cannot be decompressed here, and the recompiler # has the same problem as games-action/zelda64recomp. See src_prepare and # src_configure. Keyword this once both are resolved. #KEYWORDS="~amd64" # The ROM cannot be distributed and has to be supplied by the user. RESTRICT="bindist mirror" RDEPEND=" media-libs/freetype:2 media-libs/libglvnd media-libs/libsdl2 x11-libs/libX11 " DEPEND="${RDEPEND}" # shellcheck disable=SC2016 BDEPEND=" ${PYTHON_DEPS} $(python_gen_any_dep 'dev-python/pyyaml[${PYTHON_USEDEP}]') dev-util/vulkan-headers " python_check_deps() { python_has_version "dev-python/pyyaml[${PYTHON_USEDEP}]" } pkg_setup() { python-any-r1_pkg_setup } src_prepare() { # The ROM is not a distfile: it cannot be distributed, and a package wide # RESTRICT="fetch" would stop Portage fetching the submodule archives too. # Check it by hand instead. if [[ ! -f ${DISTDIR}/${MY_ROM} ]]; then eerror "Place your unmodified NTSC-U ROM in ${DISTDIR} as ${MY_ROM}." die "${MY_ROM} not found" fi local got got=$(sha1sum "${DISTDIR}/${MY_ROM}") || die if [[ ${got%% *} != "${MY_ROM_SHA1}" ]]; then eerror "${MY_ROM} has sha1 ${got%% *}, expected ${MY_ROM_SHA1}." die "${MY_ROM} is not the expected ROM" fi local mod path repo sha for mod in "${G64_SUBMODULES[@]}"; do path="${mod%%|*}" repo="${mod#*|}" repo="${repo%%|*}" sha="${mod##*|}" rm -rf "${path}" || die # Only for nested submodules: with no slash this expansion returns # the path itself, which would create the destination and move into it. if [[ ${path} == */* ]]; then mkdir -p "${path%/*}" || die fi mv "${WORKDIR}/${repo##*/}-${sha}" "${path}" || die done # The recompiler reads a decompressed image. The vendored decompilation # ships the tool that produces it, tools/rommy.py, but not the manifest it # needs: lib/mnsg/config/usa/rommy.yaml is absent at the commit this pins, # so the ROM cannot be decompressed here yet. if [[ ! -f lib/mnsg/config/usa/rommy.yaml ]]; then die "lib/mnsg has no config/usa/rommy.yaml, so ${MY_ROM} cannot be decompressed" fi cp "${DISTDIR}/${MY_ROM}" lib/mnsg/config/usa/baserom.z64 || die edo "${EPYTHON}" lib/mnsg/tools/rommy.py decompress \ --input lib/mnsg/config/usa/baserom.z64 \ --output "${MY_ROM_DECOMPRESSED}" \ --manifest lib/mnsg/config/usa/rommy.yaml --pad # RmlUi's bundled robin_hood.h uses the fixed-width integer types without # including , which GCC 16 no longer provides transitively. local hh="lib/RmlUi/Include/RmlUi/Core/Containers/robin_hood.h" grep -q '#include ' "${hh}" || sed -i -e '0,/^#include \n#include ' "${hh}" || die "failed to patch ${hh}" cmake_src_prepare } src_configure() { filter-lto # The recompiler has to be built and run before the main configure rather # than in src_compile: CMakeLists.txt globs its output into the # RecompiledFuncs target, so the generated sources have to exist by the # time CMake runs. # # N64Recomp records functions whose ELF symbol has no real section, then # indexes the section list with that index anyway. GCC on Gentoo defines # _GLIBCXX_ASSERTIONS by default, which turns those reads into aborts, so # build this generator without them, the way upstream builds it. Note that # games-action/zelda64recomp, which shares this recompiler, then fails to # link because the generated functions collide with the patches; expect # the same here. edo cmake -S lib/N64ModernRuntime/N64Recomp -B "${WORKDIR}/recomp-build" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_FLAGS="-U_GLIBCXX_ASSERTIONS" edo cmake --build "${WORKDIR}/recomp-build" --target N64RecompCLI RSPRecomp # The build also invokes ./N64Recomp itself, for the patches, so the tools # have to sit in the source root the way BUILDING.md describes. cp "${WORKDIR}/recomp-build/N64Recomp" \ "${WORKDIR}/recomp-build/RSPRecomp" . || die edo ./N64Recomp mnsg.toml edo ./RSPRecomp aspMain.toml cmake_src_configure } src_install() { newbin "${BUILD_DIR}/Goemon64Recompiled" "${PN}" insinto "/usr/share/${PN}" doins -r assets/. einstalldocs } pkg_postinst() { xdg_pkg_postinst elog "Run ${PN} and point it at a standard, compressed NTSC-U Mystical" elog "Ninja Starring Goemon ROM. Its own assets are installed in" elog "/usr/share/${PN}." }