tinygo icon indicating copy to clipboard operation
tinygo copied to clipboard

Nintendo Switch Basic Support

Open racerxdl opened this issue 4 years ago • 22 comments

I added basic Nintendo Switch support to TinyGo.

It still relies on devKitPro and libnx to interact with Horizon OS (The Nintendo Switch Operating System), I hope that changes soon.

Still, that does work. At first I added the libnx calls here, but I found out its easier to make an external library to that. So I created this:

https://github.com/racerxdl/gonx

Without gonx the application can run inside nintendo switch, but can't use the display or anything until we implement full golang calls for the Switch IPCs.

I also created this: https://github.com/racerxdl/go-switch-examples

I will port each example from the switchbrew examples repo ( https://github.com/switchbrew/switch-examples/ ) and implement the nescessary calls on gonx as needed.

For compiling to nintendo switch its simple by using:

tinygo build -target nintendo-switch -o hello-world.elf

For running on real devices a NRO file needs to be generated, that can be done with elf2nro (which is inside devKitPro) or with linkle:

linkle nro hello-world.elf hello-world.nro

Here is a video of working: https://twitter.com/lucasteske/status/1259650256897298432

And the vt52-example inside examples folder prints this: image

racerxdl avatar May 13 '20 04:05 racerxdl

Wow!

trevor403 avatar May 13 '20 06:05 trevor403

I did a first pass over the PR.

There is a bit of code in builder/build.go that I'm not so happy about, I wonder how that can best be fixed? Ideally no environment variable is needed (apart from making sure the compiler is included in $PATH), but otherwise the best place to configure this would be compileopts, not builder.

The issue is that there still need to have the devkitpro env to get the libnx include path. It's always inside devkitpro folder, but you dont know where is installed. All devKitPro projects expect a DEVKITPRO environment to build.

racerxdl avatar May 13 '20 15:05 racerxdl

The issue is that there still need to have the devkitpro env to get the libnx include path. It's always inside devkitpro folder, but you dont know where is installed. All devKitPro projects expect a DEVKITPRO environment to build.

I was playing around with it and you're right, even the bundled compilers haven't been configured to include libnx by default. Which makes things a whole lot more complicated.


I tried running examples/nintendoswitch in Yuzu but it doesn't work for me. That may also because of my Yuzu build (which I only barely managed to get to work). Does the example work in Yuzu?

aykevl avatar May 13 '20 21:05 aykevl

The example does work on Yuzu (the screenshot is from yuzu). But I don't remember if you need the basic Nintendo Switch dump to make it work.

To avoid legal issues with Nintendo proprietary assets, to run commercial games on yuzu you need to dump keys from your console and some content from the NAND flash. That's a requirement for commercial games because they're signed and encrypted. The NRO files are neither, so I don't know what's the minimum requirements to run. I will check here (since I have everything) what's the minimum setup to get it working.

racerxdl avatar May 13 '20 21:05 racerxdl

Can you maybe share a working .nro file that I can test? To determine which is the cause (the build or Yuzu).

aykevl avatar May 13 '20 21:05 aykevl

Sure, this one works here:

vt52-demo.nro.zip image

racerxdl avatar May 13 '20 21:05 racerxdl

Well that version sadly doesn't run, so I'm afraid my Yuzu build still doesn't work. One time it even crashed:

Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
dynarmic: POSIX SigHandler: Exception was not in registered code blocks (rip 0x007f596a4da8bb)
fish: “yuzu tmp/vt52-demo.nro” terminated by signal SIGSEGV (Address boundary error)

(fish is my shell)

aykevl avatar May 13 '20 22:05 aykevl

Hmm thats odd. As I remember it gives a message box saying what you need to run, not crashing. Maybe its some issue with wayland? Here I'm using Xorg instead, I never tested on wayland.

racerxdl avatar May 13 '20 22:05 racerxdl

This is what it says on startup, is that a problem?

Screenshot from 2020-05-14 00-19-49

aykevl avatar May 13 '20 22:05 aykevl

That's the thing, for commercial games I'm 100% sure you need everything. Homebrew need only a subset. In about an hour I can confirm what's needed.

racerxdl avatar May 13 '20 22:05 racerxdl

I have also managed to produce a test.nro that works in yuzu, so I have all the tools I need for local testing.

aykevl avatar May 14 '20 00:05 aykevl

Played around a bit with avoiding libnx, but all I got was a panic in linkle:

thread 'main' panicked at 'Invalid module offset 3531603969', <::std::macros::panic macros>:5:6
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

aykevl avatar May 14 '20 00:05 aykevl

@racerxdl can you please rebase this branch against dev to resolve the merge conflicts? Thank you.

deadprogram avatar May 22 '20 11:05 deadprogram

Done @deadprogram ! I also squashed all commits.

racerxdl avatar May 22 '20 19:05 racerxdl

We recently changed compiler/compiler.go in #941 so I'm afraid this will need another conflict resolution.

aykevl avatar May 28 '20 00:05 aykevl

@aykevl just changed the way the PIC stuff reaches the compiler. Now it goes on TargetSpec and comes from json spec. I modified the original NewTargetMachine to read the RelocationModel from TargetSpec and select the appropriate one (or static if invalid defined)

racerxdl avatar May 31 '20 19:05 racerxdl

Hello, everyone. I would love to help get this PR merged before the next release. Seems like there are again (or still?) some merge conflicts to resolve.

After that, what else will be needed to get it into a mergeable state? Thank you.

deadprogram avatar Jun 20 '20 10:06 deadprogram

Done @deadprogram. Not sure what's next.

racerxdl avatar Jun 21 '20 00:06 racerxdl

If possible, please add a smoke test for this PR. It will make it obvious when there is a compile-time breaking change.

Yes, please, @racerxdl is this possible? Ideally something with no external dependencies. Does not have to do much, just shows that the core compiler itself is working.

deadprogram avatar Jul 08 '20 20:07 deadprogram

Hi @deadprogram / @aykevl - sorry I didn't had much time to look these days. This weekend I will try to get a look in all comments and do the nescessary fixes / comments.

About the smoke test, yes I can put a very small program just to test that everything is compiling. The thing is that the only change for Nintendo Switch is basically the devKitpro call for libnx linking, otherwise is just a normal arm64. So If I remove the devKitPro dependency for a smoke test, it will just test the ARM64 compiler part. Is that what's intended?

The last time I was working on that, I tried to make the libnx linkage externally to the tinygo (by doing this https://github.com/racerxdl/gonx/blob/dev/base.go#L6-L7 ) but that does seen to trigger a bug in CGO ( #1148 ) which @aykevl wasn't able to simulate. (I think because he is importing from a local folder and not a external library).

If I manage to do a external linkage, I can put a very small CRT for nintendo switch inside tinygo so it works as a application inside the nintendo switch. Also I think in that case, the lld can link it (just not link when using libnx).

racerxdl avatar Jul 08 '20 20:07 racerxdl

Thanks @racerxdl that sounds great!

deadprogram avatar Jul 08 '20 20:07 deadprogram

Hi @deadprogram / @aykevl while I work on the external integration of libnx for this branch, I did another setup that does not require devKitPro or anything, but can only print to Nintendo Switch emulator debug console.

https://github.com/tinygo-org/tinygo/pull/1226

But this will serve as a base for external linkage of libnx. I will change this PR (#1108) to draft and then when its ready again I switch to a PR again.

racerxdl avatar Jul 10 '20 05:07 racerxdl