tinygo
tinygo copied to clipboard
Nintendo Switch Basic Support
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:
Wow!
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.
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?
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.
Can you maybe share a working .nro file that I can test? To determine which is the cause (the build or Yuzu).
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)
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.
This is what it says on startup, is that a problem?
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.
I have also managed to produce a test.nro that works in yuzu, so I have all the tools I need for local testing.
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
@racerxdl can you please rebase this branch against dev
to resolve the merge conflicts? Thank you.
Done @deadprogram ! I also squashed all commits.
We recently changed compiler/compiler.go in #941 so I'm afraid this will need another conflict resolution.
@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)
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.
Done @deadprogram. Not sure what's next.
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.
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).
Thanks @racerxdl that sounds great!
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.