diff --git a/README.md b/README.md index 24e437b..8235df6 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,6 @@ The exefs ROM used is the one by [meliodas2255] which was based on or inspired b Both ROMs are supported as they use the same romfs structure for specifying which NRO to load from the microSD card. Simply replace the assets in the `/assets/exefs` folder with the [original ROM][ROM]'s exefs files. -**Note**: Direct RetroArch game forwarding is not yet supported. - ## Changes 1. The script was completely rewritten in Python. @@ -37,7 +35,7 @@ Simply replace the assets in the `/assets/exefs` folder with the [original ROM][ 3. Place your `prod.keys` at the root of the project folder or at `%USERPROFILE/.switch/prod.keys`. Make sure it's up-to-date for the firmware version you're switch is on. You can get this file using [Lockpick_RCM]. 4. Run `pip install nton`. If you see any warnings about a path not being in your PATH environment variable, add it - or you wont be able to run `nton`. + or you won't be able to run `nton`. [ImageMagick]: [winget]: @@ -60,14 +58,25 @@ E.g., to make a forwarder for the Homebrew Menu that's on your Switch's microSD Take a look at `nton build --help` for advanced usage like changing the Icon, Title Name, and so on. +### Direct RetroArch Game forwarding + +Use a RetroArch Game Core as the NRO path and provide the path to the ROM on your Switch's microSD card with `--rom`. +This will then load the Core directly under RetroArch and provide the path to the ROM as a startup argument to the +RetroArch Core. + +Note: + +- You must use a path to a RetroArch Game Core NRO, not the path to the RetroArch NRO itself. +- Do not move, delete, or rename the ROM or the Core NRO files that are on your microSD card, or it will break. + ## To-do - [X] Rewrite as a Python script to heavily improve the user experience and code. - [X] Combine the Drive letter and Path arguments and manually split them when they need to be separate instead. - [X] Automate name and publisher by extracting from the extracted `control.nacp`. - [X] Force enable video capture and screenshots in the extracted `control.nacp`. +- [x] Add support for direct RetroArch Game Forwarding. - [ ] Force disable save data allocation. Fixed in [v3.3.5 of Nro2NSP](https://github.com/Root-MtX/Nro2Nsp/releases/tag/3.3.5). -- [ ] Add support for direct RetroArch Game Forwarding. - [ ] Maybe a new GUI one day, and let you override the icons and such? ## Troubleshooting diff --git a/nton/main.py b/nton/main.py index 36071de..2ff70e7 100644 --- a/nton/main.py +++ b/nton/main.py @@ -40,7 +40,15 @@ def main(version: bool, debug: bool) -> None: @click.option("-p", "--publisher", type=str, default=None, help="Title Publisher.") @click.option("-i", "--icon", type=Path, default=None, help="Title Icon (256x256px recommended, supports any image).") @click.option("--id", "id_", type=str, default=None, help="Title ID.") -def build(path: Path, name: str | None, publisher: str | None, icon: Path | None, id_: str | None) -> int: +@click.option("--rom", type=Path, default=None, help="ROM path for Direct RetroArch Game Forwarding.") +def build( + path: Path, + name: str | None, + publisher: str | None, + icon: Path | None, + id_: str | None, + rom: Path | None +) -> int: """ Build an NSP that loads an NRO on the Switch's microSD card. @@ -53,7 +61,8 @@ def build(path: Path, name: str | None, publisher: str | None, icon: Path | None resolution. A 256x256px image is recommended. id_: Set a specific Title ID, otherwise a Random Title ID is used. There's a miniscule chance it could get the same Title ID as another installed Title, but it's so miniscule you shouldn't realistically worry about it. - + rom: Path to a ROM file to create a forwarder that boots directly into the game using RetroArch. The NRO path + must be to a RetroArch Core. """ log = logging.getLogger("build") log.info("Building!") @@ -88,6 +97,15 @@ def build(path: Path, name: str | None, publisher: str | None, icon: Path | None else: id_ = "01%s000" % os.urandom(6).hex()[:-1] + if rom: + if not rom.is_file(): + log.error(f"The ROM path \"{rom}\" does not exist, or is not a file.") + return 1 + if not str(path).lower().startswith(f"{path.drive.lower()}:/retroarch/cores/"): + log.error(f"Setting a ROM path for the forwarder requires the NRO path to be to a RetroArch Core.") + log.error(f"Make sure you set it to a RetroArch Core and not to RetroArch itself or any other NRO.") + return 1 + log.info(f"Title ID: %s", id_) build_dir = Directories.temp / id_ @@ -179,9 +197,13 @@ def build(path: Path, name: str | None, publisher: str | None, icon: Path | None log.critical(f"Failed to convert and strip the Icon, {e.output} [{e.returncode}]") return 2 - sdmc_path = f"sdmc:{str(path.resolve().absolute()).split(':', maxsplit=1)[1]}" - next_argv_file.write_text(sdmc_path) - next_nro_path_file.write_text(sdmc_path) + next_nro_path = str(path.resolve().absolute()).replace(f"{path.drive}:/", "sdmc:/") + next_nro_path_file.write_text(next_nro_path) + + next_argv = next_nro_path + if rom: + next_argv += " " + str(rom.resolve().absolute()).replace(f"{rom.drive}:/", "sdmc:/") + next_argv_file.write_text(next_argv) # only make this directory at this point because we have a high chance of success Directories.output.mkdir(parents=True, exist_ok=True)