LifestyleCompiling a Spin program correct into a native binary...

Compiling a Spin program correct into a native binary for Nintendo Swap


- Advertisment -

Hajime Hoshi


Right here’s an English translation of my article in Jap.


Previously, we compiled a Spin program correct into a WebAssembly after which transformed it into C++ recordsdata to raze it bustle on Nintendo Swap. Now, I truly beget succeeded in compiling a Spin program correct into a native binary for Nintendo Swap, and furthermore running a sport there. I modified arrangement calls with C goal calls the divulge of the -overlay option. Also, I truly beget developed a new equipment Hitsumabushi to generate JSON direct for this.


This article and the initiating-source initiatives here are essentially based only on publicly accessible data. Hajime is to blame for this text’s direct. Please close no longer quiz of Nintendo about this text.


I truly were developing a 2D sport engine called Ebiten in my spare time. I truly beget succeeded in porting this to Nintendo Swap and the Nintendo Swap model of “Undergo’s Restaurant” change into launched in 2021.

- Advertisement -

Bear's Restaurant

Copyright 2021 Odencat Inc.

The formulation change into to bring collectively a Spin program correct into a WebAssembly (Wasm) binary after which convert it to C++ recordsdata. Glimpse the presentation slides from GoConference 2021 Autumn for added particulars. The benefits were low uncertainty, low upkeep label, and excessive portability. After I developed the tool, its upkeep label change into magnificent puny as Wasm’s specification is exact. On the assorted hand, the disadvantages were inappropriate performance and long compiling time. No longer only that performance change into worse than native, however GC furthermore suspended the sport attributable to a single thread.

Compiling a Spin program correct into a native binary for Nintendo Swap without the divulge of Wasm change into rather unsure and a rocky avenue. Surely, Spin would now not give a fetch to Nintendo Swap formally. And naturally, Nintendo Swap’s source code and binary formats are no longer birth. Even though I hit a agonize, it’d be that that it’s seemingly you’ll well presumably specialize in of that there would no longer be any clues to support me resolve it. On the opposite hand, if I knew that I were to prevail, performance may perhaps well be better than ever, and compiling high-tail may perhaps well be as fleet as Spin. So I believed it change into worth a shot and were doing some experiments intermittently for one 365 days.


The technique is entirely to interchange arrangement calls with C goal calls in the runtime and the fashioned library. The arrangement calls half is OS-dependent, and if I exchange it with one thing transportable, Spin must unexcited work in all places the deliver in belief. It appears to be magnificent straightforward, would now not it? Properly, it change into loads more challenging than I expected…

The graphic below describes what I had to full. The left side is a structure of a structural overview of fashioned Spin compiling. Scheme calls work on explicit systems and naturally, this would now not work on Nintendo Swap. So I had to interchange them with fashioned C goal calls just like the obedient side.

- Advertisement -

Replacing system calls with C function calls

Changing arrangement calls with C goal calls

And, there may perhaps be yet any other whisk merchandise to alter the binary format that the Spin compiler generates to suit with Nintendo Swap. So in summary, the whisk objects were as follows:

  1. Changing arrangement calls with fashioned C goal and/or pthread goal calls
  2. Adjust the ELF format that the Spin compiler generates

For replacing arrangement calls, surely, arrangement calls close no longer correspond one-to-one with C capabilities. And, there are too many arrangement calls to implement. So, I modified arrangement calls one after the opposite by discovering which ones refused to work on an staunch Nintendo Swap utility.

The Spin compiler can generate only formats that the Spin compiler formally helps. As an example, when a target is Linux, the format is ELF. Can Nintendo Swap give a fetch to ELF? To raze a long story quick, yes, I managed it. I would no longer characterize the particulars about 2. here*1.

What I truly must full is raze a .a file by the divulge of the Spin compiler with GOOS=linux GOARCH=arm64 and -buildmode=c-archive, after which hyperlink it with diverse object recordsdata and libraries by the divulge of Nintendo Swap compiler. The motive I produce no longer divulge -buildmode=default is that there are some objects I truly must full round an entry level. IMO, most ceaselessly, it’s extra transportable to depend upon the platform for an entry level.

- Advertisement -

Scheme calls are defined most ceaselessly in the fashioned library, in particular runtime and syscall capabilities. So, how did I rewrite them? In this mission, I adopted the -overlay option.

Hitsumabushi – rewriting the runtime with the -overlay option

whisk form‘s -overlay is an option that overwrites Spin recordsdata to be compiled. I overwrote Spin recordsdata in the runtime with this option. Right here’s the legitimate doc’s rationalization:

-overlay file
    be taught a JSON config file that offers an overlay for form operations.
    The file is a JSON struct with a single self-discipline, named 'Change', that
    maps each and each disk file path (a string) to its backing file path, so that
    a form will bustle as if the disk file path exists with the contents
    given by the backing file paths, or as if the disk file path does no longer
    exist if its backing file path is empty. Support for the -overlay flag
    has some boundaries: importantly, cgo recordsdata included from birth air the
    consist of path needs to be in the identical itemizing because the Spin equipment they're
    included from, and overlays will no longer seem when binaries and assessments are
    bustle by whisk bustle and whisk test respectively.

Right here’s the format to give -overlay:

  "Change": {
    "/usr/native/whisk/src/runtime/os_linux.whisk": "/dwelling/hajimehoshi/my_os_linux.whisk"

Whereas you form a Spin program with this, os_linux.whisk‘s direct in runtime is modified with my_os_linux.whisk‘s. Rather handy, isn’t it?

Managing this JSON file as it’s is no longer transportable. A location where Spin is installed depends on environments, after which the target recordsdata’ locations fluctuate. Plus, you very no longer ceaselessly must exchange the elephantine contents of a file, and most ceaselessly, it’s enough to interchange some capabilities. As such, it’s robust to interchange source recordsdata to examine each and each Spin model exchange.

So, I developed a new equipment to generate a JSON for this mission. Right here’s Hitsumabushi (ひつまぶし)*2. I adopted this title because I wished a title ending with ‘bushi’ as a play on libc (ree-boo-shee (りぶしー) in Jap pronunciation), because this is regarded as one of the important things that Hitsumabushi deals with. There change into yet any other candidate I change into alive to about, Katsuobushi (かつおぶし)*3, however I received’t catch into that…

Hitsumabushi is a extremely straightforward equipment defining an API like this:

// GenOverlayJSON generates JSON direct that shall be handed
// to -overlay in accordance with the given alternatives, or returns an error
// when an error occurs.
// There are some alternatives like specifying repeat arguments
// and specifying the assortment of CPU.
func GenOverlayJSON(alternatives ...Option) ([]byte, error)

Implementation of Hitsumabushi

I truly beget created an fashioned patch format for Hitsumabushi that appears to be like this:

func getRandomData(r []byte) {
    if startupRandomData != nil {
        n := reproduction(r, startupRandomData)
        extendRandom(r, n)
    fd := birth(&urandom_dev[0], 0 /O_RDONLY */, 0)
    n := be taught(fd, unsafe.Pointer(&r[0]), int32(len(r)))
    extendRandom(r, int(n))
// Use getRandomData in os_plan9.whisk.

func getRandomData(r []byte) {
    // inspired by wyrand gaze hash32.whisk for part
    t := nanotime()
    v := getg().m.procid ^ uint64(t)

    for len(r) > 0 {
        v ^= 0xa0761d6478bd642f
        v *= 0xe7037ed1a0b428db
        dimension := 8
        if len(r) < 8 {
            dimension = len(r)
        for i := 0; i < size; i++ {
            r[i] = byte(v >> (8 i))
        r = r[size:]
        v = v>>32 | v<<32

The half after //--from and the half after //--to signify a replacing source and a target respectively. The motive I invented my straightforward format is that the present p

Be a half of the pack! Be a half of 8000+ others registered customers, and catch chat, raze teams, put up updates and raze chums around the field!

- Advertisement -


  1. I absolutely love ebiten, it's gotten me back into game development which was why I initially got into software dev. I've been working through the Game Programming Patterns book and it's been an awesome platform to learn some of the common patterns in game dev. Also the maintainer is incredibly active and constantly pushing the development forward. I'm currently working on a side-scroller and am really excited to see if I can get it running on the switch.

You might also likeRELATED
Recommended to you

Dive into Ethereum signatures with Raku language

The Ethereum blockchain is essentially a transaction-based state machine. We begin with a blank state, before any transactions have happened on the network, and move into some final state when transactions are executed. The state of Ethereum relies on past transactions. These transactions are grouped into blocks and each block is chained together with its…

DirecTV Dumps OAN, Leaving It with No Major TV Distributor

Photo: Chris Delmas / AFP (Getty Images)Former president Donald Trump, known for his gluttonous diet of TV news, is going to have trouble finding one of his favorite far-right channels, One America News Network, in a few months.Satellite TV provider DirecTV, OAN’s largest distributor, said it was dumping the news network on Friday, Bloomberg reported.…

Show HN: OdinCodeBrowser: Navigate Code Like in Your IDE but on a Static Webpage

This project attempts to create a completely static website...

The James Webb Space Telescope – making 300 points of failure reliable

Success through Reliability : Webb Lesson 1The James Webb Space Telescope (JWST) is the largest and most sensitive space...
- Advertisement -

LambdaMART in Depth

LambdaMART is a classic. It’s the endlessly tinkerable classic car of ranking algorithms. If you can grok the algorithm, you can play with the model architecture, coming up with your own variations on this learning to rank staple. Last time I went over the intuition behind how LambdaMART learns to ranks in pseudocode. Now Let’s…

A $3bn bet on finding the fountain of youth

STARTUPS COME and startups go. But few startups start with $3bn in the bank. Yet that is the fortunate position in which Altos Labs finds itself. Though preparations for the launch of what must surely be a candidate for the title of “Best financed startup in history” have been rumoured for months, the firm formally…

Must read

Can 5G be used as surveillance radar? U.S. military funds Binghamton research

5G – the fifth-generation technology standard for broadband cellular networks — has been connecting millions of wireless devices since 2019, offering more pervasive connections, greater bandwidth and higher download speeds than its four predecessors. Two researchers from Binghamton University are researching another use for those ubiquitous signals in addition to watching cat videos and posting…
- Advertisement -