<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Hajime Hoshi</title>
    <description>The latest articles on Forem by Hajime Hoshi (@hajimehoshi).</description>
    <link>https://forem.com/hajimehoshi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F41857%2F78f2a0bb-4b44-41b2-82c6-e39263096718.png</url>
      <title>Forem: Hajime Hoshi</title>
      <link>https://forem.com/hajimehoshi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hajimehoshi"/>
    <language>en</language>
    <item>
      <title>Compiling a Go program into a native binary for Nintendo Switch™</title>
      <dc:creator>Hajime Hoshi</dc:creator>
      <pubDate>Mon, 03 Jan 2022 08:35:41 +0000</pubDate>
      <link>https://forem.com/hajimehoshi/compiling-a-go-program-into-a-native-binary-for-nintendo-switch-17kj</link>
      <guid>https://forem.com/hajimehoshi/compiling-a-go-program-into-a-native-binary-for-nintendo-switch-17kj</guid>
      <description>&lt;h1&gt;
  
  
  This article has been moved to &lt;a href="https://ebiten.org/blog/native_compiling_for_nintendo_switch.html" rel="noopener noreferrer"&gt;ebiten.org&lt;/a&gt; due to some complicated business reasons.
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This is an English translation of &lt;a href="https://zenn.dev/hajimehoshi/articles/72f027db464280" rel="noopener noreferrer"&gt;my article in Japanese&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;Previously, we compiled a Go program into a WebAssembly and then converted it into C++ files to make it run on Nintendo Switch. Now, I have succeeded in compiling a Go program into a native binary for Nintendo Switch, and also running a game there. I replaced system calls with C function calls using the &lt;code&gt;-overlay&lt;/code&gt; option. Also, I have developed a new package &lt;a href="https://github.com/hajimehoshi/hitsumabushi" rel="noopener noreferrer"&gt;Hitsumabushi&lt;/a&gt; to generate JSON content for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caution
&lt;/h2&gt;

&lt;p&gt;This article and the open-source projects in this article are based only on publicly available information. Hajime is responsible for this article's content. Please do not ask Nintendo about this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I have been developing a 2D game engine called &lt;a href="https://ebiten.org" rel="noopener noreferrer"&gt;Ebiten&lt;/a&gt; in my spare time. I have succeeded in porting this to Nintendo Switch and &lt;a href="https://odencat.com/bearsrestaurant/switch/en.html" rel="noopener noreferrer"&gt;the Nintendo Switch version of "Bear's Restaurant"&lt;/a&gt; was released in 2021.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iz6fqqusigk9goikx6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iz6fqqusigk9goikx6y.png" alt="Bear's Restaurant"&gt;&lt;/a&gt;&lt;/p&gt;
Copyright 2021 Odencat Inc.



&lt;p&gt;The method was to compile a Go program into a WebAssembly (Wasm) binary and then convert it to C++ files. See &lt;a href="https://docs.google.com/presentation/d/e/2PACX-1vTMRSmuWjhpOx3DIgetfi72jcOGvlqPU5z0Nps24YN6dxaBbu4dWm0FXS2f--D4G2b1aAvTmfqNA2IG/pub?start=false&amp;amp;loop=false&amp;amp;delayms=3000" rel="noopener noreferrer"&gt;the presentation slides from GoConference 2021 Autumn&lt;/a&gt; for more details. The advantages were low uncertainty, low maintenance cost, and high portability. Once I developed the tool, its maintenance cost was pretty small as Wasm's specification is stable. On the other hand, the disadvantages were bad performance and long compiling time. Not only that performance was worse than native, but GC also suspended the game due to a single thread.&lt;/p&gt;

&lt;p&gt;Compiling a Go program into a native binary for Nintendo Switch without using Wasm was quite uncertain and a rocky road. Of course, Go doesn't support Nintendo Switch officially. And naturally, Nintendo Switch's source code and binary formats are not open. Even if I hit an issue, it'd be possible that there would not be any clues to help me solve it. However, if I knew that I were to succeed, performance would be better than ever, and compiling speed would be as fast as Go. So I thought it was worth a shot and have been doing some experiments intermittently for one year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategy
&lt;/h2&gt;

&lt;p&gt;The strategy is basically to replace system calls with C function calls in the runtime and the standard library. The system calls part is OS-dependent, and if I replace it with something portable, Go should work everywhere in theory. It seems pretty easy, doesn't it? Well, it was a lot more challenging than I expected...&lt;/p&gt;

&lt;p&gt;The graphic below describes what I had to do. The left side is a structure of a structural overview of standard Go compiling. System calls work on specific systems and of course, this doesn't work on Nintendo Switch. So I had to replace them with standard C function calls like the right side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F083w9s2mh16xbmbkq2nl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F083w9s2mh16xbmbkq2nl.png" alt="Replacing system calls with C function calls"&gt;&lt;/a&gt;&lt;/p&gt;
Replacing system calls with C function calls



&lt;p&gt;And, there is another action item to adjust the binary format that the Go compiler generates to fit with Nintendo Switch. So in summary, the action items were as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Replacing system calls with standard C function and/or pthread function calls&lt;/li&gt;
&lt;li&gt;Adjust the ELF format that the Go compiler generates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For replacing system calls, of course, system calls do not correspond one-to-one with C functions. And, there are too many system calls to implement. So, I replaced system calls one by one by finding which ones refused to work on an actual Nintendo Switch device.&lt;/p&gt;

&lt;p&gt;The Go compiler can generate only formats that the Go compiler officially supports. For example, when a target is Linux, the format is ELF. Can Nintendo Switch support ELF? make a long story short, yes, I managed it. I won't describe the details about 2. here &lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;What I have to do is create a &lt;code&gt;.a&lt;/code&gt; file via the Go compiler with &lt;code&gt;GOOS=linux GOARCH=arm64&lt;/code&gt; and &lt;code&gt;-buildmode=c-archive&lt;/code&gt;, and then link it with other object files and libraries via Nintendo Switch compiler. The reason why I don't use &lt;code&gt;-buildmode=default&lt;/code&gt; is that there are some items I have to do around an entry point. IMO, in general, it is more portable to depend on the platform for an entry point.&lt;/p&gt;

&lt;p&gt;System calls are defined basically in the standard library, especially &lt;code&gt;runtime&lt;/code&gt; and &lt;code&gt;syscall&lt;/code&gt; packages. So, how did I rewrite them? In this project, I adopted the &lt;code&gt;-overlay&lt;/code&gt; option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hitsumabushi - rewriting the runtime with the &lt;code&gt;-overlay&lt;/code&gt; option
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;go build&lt;/code&gt;'s &lt;code&gt;-overlay&lt;/code&gt; is an option that overwrites Go files to be compiled. I overwrote Go files in the runtime with this option. This is &lt;a href="https://pkg.go.dev/cmd/go" rel="noopener noreferrer"&gt;the official document's explanation&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

-overlay file
    read a JSON config file that provides an overlay for build operations.
    The file is a JSON struct with a single field, named 'Replace', that
    maps each disk file path (a string) to its backing file path, so that
    a build will run as if the disk file path exists with the contents
    given by the backing file paths, or as if the disk file path does not
    exist if its backing file path is empty. Support for the -overlay flag
    has some limitations: importantly, cgo files included from outside the
    include path must be in the same directory as the Go package they are
    included from, and overlays will not appear when binaries and tests are
    run through go run and go test respectively.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This is the format to give &lt;code&gt;-overlay&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Replace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"/usr/local/go/src/runtime/os_linux.go"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/home/hajimehoshi/my_os_linux.go"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you build a Go program with this, &lt;code&gt;os_linux.go&lt;/code&gt;'s content in &lt;code&gt;runtime&lt;/code&gt; is replaced with &lt;code&gt;my_os_linux.go&lt;/code&gt;'s. Pretty handy, isn’t it?&lt;/p&gt;

&lt;p&gt;Managing this JSON file as it is is not portable. A location where Go is installed depends on environments, and then the target files' locations vary. Plus, you very rarely have to replace the full contents of a file, and in most cases, it is enough to replace some functions. As such, it is troublesome to update source files to match each Go version update.&lt;/p&gt;

&lt;p&gt;So, I developed a new package to generate a JSON for this project. This is &lt;a href="https://github.com/hajimehoshi/hitsumabushi" rel="noopener noreferrer"&gt;Hitsumabushi (ひつまぶし)&lt;/a&gt; &lt;sup id="fnref2"&gt;2&lt;/sup&gt;. I adopted this name because I wanted a name ending with 'bushi' as a play on libc (ree-boo-shee (りぶしー) in Japanese pronunciation), because this is one of the primary things that Hitsumabushi deals with. There was another candidate I was considering, Katsuobushi (かつおぶし) &lt;sup id="fnref3"&gt;3&lt;/sup&gt;, but I won’t get into that...&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/hajimehoshi" rel="noopener noreferrer"&gt;
        hajimehoshi
      &lt;/a&gt; / &lt;a href="https://github.com/hajimehoshi/hitsumabushi" rel="noopener noreferrer"&gt;
        hitsumabushi
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Run Go programs (almost) everywhere
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Hitsumabushi is a very simple package defining an API like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="c"&gt;// GenOverlayJSON generates JSON content that can be passed&lt;/span&gt;
&lt;span class="c"&gt;// to -overlay based on the given options, or returns an error&lt;/span&gt;
&lt;span class="c"&gt;// when an error occurs.&lt;/span&gt;
&lt;span class="c"&gt;//&lt;/span&gt;
&lt;span class="c"&gt;// There are some options like specifying command arguments&lt;/span&gt;
&lt;span class="c"&gt;// and specifying the number of CPU.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GenOverlayJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;Option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Implementation of Hitsumabushi
&lt;/h2&gt;

&lt;p&gt;I have created an original patch format for Hitsumabushi that looks like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="c"&gt;//--from&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getRandomData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;startupRandomData&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;startupRandomData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;extendRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;urandom_dev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="c"&gt;/* O_RDONLY */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;closefd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;extendRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;//--to&lt;/span&gt;
&lt;span class="c"&gt;// Use getRandomData in os_plan9.go.&lt;/span&gt;

&lt;span class="c"&gt;//go:nosplit&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getRandomData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// inspired by wyrand see hash32.go for detail&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;nanotime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;procid&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="m"&gt;0xa0761d6478bd642f&lt;/span&gt;
        &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="m"&gt;0xe7037ed1a0b428db&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The part after &lt;code&gt;//--from&lt;/code&gt; and the part after &lt;code&gt;//--to&lt;/code&gt; represent a replacing source and a target respectively. The reason why I invented my simple format is that the existing patch formats don't assume to be modified by a human being. In the above example, Linux's &lt;code&gt;getRandomData&lt;/code&gt; implementation is replaced with Plan 9's. Linux's &lt;code&gt;getRandomData&lt;/code&gt; uses &lt;code&gt;/dev/urandom&lt;/code&gt; and this is not potable&lt;sup id="fnref4"&gt;4&lt;/sup&gt;. This patch format saves some amount of work to manage the differences I want to replace. Of course, the cost to keep up with the Go version updates doesn't become zero even with this, but it should help a lot.&lt;/p&gt;

&lt;p&gt;Hitsumabushi creates modified files with this format and puts them in a temporary directory. It uses the files as the content of JSON (the replacing source file names).&lt;/p&gt;

&lt;p&gt;Note that Hitsumabushi rewrites the standard library and the runtime, and the Go compiler is not the target to rewrite. In other words, the regular Go compiler is used as is.&lt;/p&gt;

&lt;p&gt;The replacements by Hitsumabushi are only the standard C function calls and pthread function calls. It never deals with platform-specific APIs&lt;sup id="fnref5"&gt;5&lt;/sup&gt;. So, ideally, &lt;strong&gt;Hitsumabushi should enable a Go program to run on any platform, regardless of whether or not the Go compiler originally supports it&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replacements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Calling C functions from &lt;code&gt;runtime&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;It is not an easy task to call a C function from &lt;code&gt;runtime&lt;/code&gt;. In a usual Go program, you can call a C function easily with Cgo. However, &lt;code&gt;runtime&lt;/code&gt; cannot use Cgo. Using Cgo means to depend on &lt;code&gt;runtime/cgo&lt;/code&gt;, and &lt;code&gt;runtime/cgo&lt;/code&gt; depends on &lt;code&gt;runtime&lt;/code&gt;, so this would be a circular dependency.&lt;/p&gt;

&lt;p&gt;To get straight to the point, &lt;code&gt;libcCall&lt;/code&gt; makes it possible to call a C function from &lt;code&gt;runtime&lt;/code&gt;. Some environments like &lt;code&gt;GOOS=darwin&lt;/code&gt; already do this.&lt;/p&gt;

&lt;p&gt;In addition, various &lt;a href="https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives" rel="noopener noreferrer"&gt;compiler directives&lt;/a&gt; are required.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;//go:nosplit&lt;/code&gt;: Skips an overflow in the stack.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;//go:cgo_unsafe_args&lt;/code&gt;: Treats Go arguments as C arguments.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;//go:linkname&lt;/code&gt;: Treats something defined in another package as if it was defined in this package. Or, it treats something defined in this package as if it was defined in another package. It ignores whether the symbol is exported or not. Very useful!&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;//go:cgo_import_static&lt;/code&gt;: Static-links a C function and makes it possible to treat the symbol value in Go.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see an actual example. To call the &lt;code&gt;write&lt;/code&gt; system call from &lt;code&gt;runtime&lt;/code&gt;, a function called &lt;code&gt;write1&lt;/code&gt; is defined on the Go side.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="c"&gt;// An excerpt from runtime/stubs2.go in Go 1.17.5&lt;/span&gt;

&lt;span class="c"&gt;//go:noescape&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;write1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// An excerpt from runtime/sys_linux_arm64.s in Go 1.17.5

TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
    MOVD    fd+0(FP), R0
    MOVD    p+8(FP), R1
    MOVW    n+16(FP), R2
    MOVD    $SYS_write, R8
    SVC
    MOVW    R0, ret+24(FP)
    RET


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the case of 64bit ARM, &lt;code&gt;SVC&lt;/code&gt; is used to invoke a system call.&lt;/p&gt;

&lt;p&gt;Let's replace this with a C function call by &lt;code&gt;libcCall&lt;/code&gt; and compiler directives.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="c"&gt;// An excerpt from runtime/stubs2.go after Hitsumabushi's replacement&lt;/span&gt;

&lt;span class="c"&gt;//go:nosplit&lt;/span&gt;
&lt;span class="c"&gt;//go:cgo_unsafe_args&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;write1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;libcCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FuncPCABI0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;write1_trampoline&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;write1_trampoline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="c"&gt;// An excerpt from runtime/os_linux.go after Hitsumabushi's replacement&lt;/span&gt;

&lt;span class="c"&gt;//go:linkname c_write1 c_write1&lt;/span&gt;
&lt;span class="c"&gt;//go:cgo_import_static c_write1&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;c_write1&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// An excerpt from runtime/sys_linux_arm64.s after Hitsumabushi's replacement

TEXT runtime·write1_trampoline(SB),NOSPLIT,$0-28
    MOVD    8(R0), R1   // p
    MOVW    16(R0), R2  // n
    MOVD    0(R0), R0   // fd
    BL  c_write1(SB)
    RET


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// An excerpt from runtime/cgo/gcc_linux_arm64.c after Hitsumabushi's replacement&lt;/span&gt;

&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;c_write1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uintptr_t&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;pthread_mutex_t&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PTHREAD_MUTEX_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;pthread_mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fflush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fflush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;default:&lt;/span&gt;
    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"syscall write(%lu, %p, %d) is not implemented&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By the way, &lt;code&gt;libcCall&lt;/code&gt; is not defined on &lt;code&gt;GOOS=linux&lt;/code&gt;. I had to rewrite &lt;code&gt;//go:build&lt;/code&gt; in &lt;code&gt;runtime/sys_libc.go&lt;/code&gt; properly.&lt;/p&gt;

&lt;p&gt;If you forcibly call a C function using assembly without &lt;code&gt;libcCall&lt;/code&gt;, a C stack will be on the current Goroutine's stack. Then, you might find very mysterious errors. I don't recommend invoking a C function without &lt;code&gt;libcCall&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ignoring signals
&lt;/h3&gt;

&lt;p&gt;Hitsumabushi ignores all signals. For example, &lt;a href="https://github.com/hajimehoshi/hitsumabushi/blob/033f91b0b848e44349a91ccd28d6436bc22d0c44/1.17/runtime/os_linux.go.patch#L165-L180" rel="noopener noreferrer"&gt;&lt;code&gt;sigaltstack&lt;/code&gt; and &lt;code&gt;sigprocmask&lt;/code&gt; in &lt;code&gt;runtime&lt;/code&gt; are empty&lt;/a&gt;. There are standard C functions that deal with signals, but they are not implemented in some environments.&lt;/p&gt;

&lt;p&gt;As a side effect, accessing a nil pointer caused SEGV, and &lt;code&gt;recover&lt;/code&gt;-ing it became impossible. A program dies without panic messages, even. This is inconvenient to some extent, but we have to put in the effort to avoid this issue in production environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing a pseudo file system
&lt;/h3&gt;

&lt;p&gt;Even when a Go program does nothing, the runtime might access the file system. On Linux, apparently these files are read from the runtime:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/proc/self/auxv&lt;/code&gt; (Information about e.g. a page size)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/sys/kernel/mm/transparent_hugepage/hpage_pmd_size&lt;/code&gt; (Huge Page Size)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hand-crafted some content for both. For example, I used &lt;code&gt;0&lt;/code&gt; for Huge Page Size since it worked. For the implementation, see &lt;a href="https://github.com/hajimehoshi/hitsumabushi/blob/033f91b0b848e44349a91ccd28d6436bc22d0c44/1.17/runtime/cgo/gcc_linux_arm64.c.patch#L437-L454" rel="noopener noreferrer"&gt;Hitsumabushi's &lt;code&gt;c_open&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For writing files, I implemented only a standard output and a standard error. Both just use &lt;code&gt;fprintf&lt;/code&gt;. Without them, even &lt;code&gt;println&lt;/code&gt; doesn't work. I decided not to implement reading and writing other files for now. For the implementation, see &lt;a href="https://github.com/hajimehoshi/hitsumabushi/blob/033f91b0b848e44349a91ccd28d6436bc22d0c44/1.17/runtime/cgo/gcc_linux_arm64.c.patch#L480-L499" rel="noopener noreferrer"&gt;Hitsumabushi's &lt;code&gt;c_write1&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing a pseudo memory system
&lt;/h3&gt;

&lt;p&gt;In Go's heap memory management, &lt;a href="https://man7.org/linux/man-pages/man2/mmap.2.html" rel="noopener noreferrer"&gt;&lt;code&gt;mmap&lt;/code&gt;&lt;/a&gt; system call is the bottom layer on Linux. Go manages virtual memory allocated there. &lt;code&gt;munmap&lt;/code&gt; is called for unused regions.&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/runtime/malloc.go;l=349-360" rel="noopener noreferrer"&gt;4 states&lt;/a&gt; of a heap memory region and these states transition as in the diagram below. When the state is 'Ready', the region is available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vxhb0t1twu5qs0p6v0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vxhb0t1twu5qs0p6v0x.png" alt="The state transition diagram of Go's memory"&gt;&lt;/a&gt;&lt;/p&gt;
The state transition diagram of Go's memory



&lt;p&gt;Go specifies an address in virtual memory and uses an allocated memory region with the address. However, there is no standard C function to allocate memory with a specific address. That's unfortunate.&lt;/p&gt;

&lt;p&gt;There are some platforms where it is impossible to allocate memory with a specific address: Plan 9 and Wasm. Hitsumabushi referred to them and implemented a 'corner-cutting' memory system. It referred to &lt;a href="https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/runtime/mem_js.go" rel="noopener noreferrer"&gt;the Wasm version&lt;/a&gt; in particular, which is the simplest implementation. I won't describe the details here, but basically, the implementation is as shown in the following list. For an actual source, see &lt;a href="https://github.com/hajimehoshi/hitsumabushi/blob/033f91b0b848e44349a91ccd28d6436bc22d0c44/1.17/runtime/mem_linux.go" rel="noopener noreferrer"&gt;Hitsumabushi's &lt;code&gt;mem_linux.go&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sysAlloc&lt;/code&gt;: Calls &lt;code&gt;sysReserve&lt;/code&gt; and &lt;code&gt;sysMap&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sysMap&lt;/code&gt;: Increments the total size record of heap memory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sysFree&lt;/code&gt;: Decrements the total size record of heap memory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sysReserve&lt;/code&gt;: Calls &lt;code&gt;calloc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The other functions do nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, there is a call of &lt;code&gt;calloc&lt;/code&gt; but no call of &lt;code&gt;free&lt;/code&gt;. It is impossible to &lt;code&gt;free&lt;/code&gt; a part of a region allocated by &lt;code&gt;calloc&lt;/code&gt;. This means that memory usage is monotonically increased. Originally, the method to make an Ebiten application work on Nintendo Switch was to convert Go to C++ via Wasm, and memory usage was also monotonically increased there&lt;sup id="fnref6"&gt;6&lt;/sup&gt;. It didn’t end up making things worse, at the very least, so I’ve compromised with this solution so far, but I would like to fix this in the future…&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing pseudo &lt;code&gt;futex&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://man7.org/linux/man-pages/man2/futex.2.html" rel="noopener noreferrer"&gt;&lt;code&gt;futex&lt;/code&gt;&lt;/a&gt; is the bottom layer of the part that handles sleeping and waking up threads. Of course, the standard C functions and pthread functions cannot invoke &lt;code&gt;futex&lt;/code&gt; directly. So, I had to mimic the behavior of &lt;code&gt;futex&lt;/code&gt; with pthread. Originally, pthread itself is implemented with &lt;code&gt;futex&lt;/code&gt;, so I had to do the opposite thing.&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/runtime/os_linux.go;l=17-24" rel="noopener noreferrer"&gt;two ways&lt;/a&gt; to use &lt;code&gt;futex&lt;/code&gt; via Go.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;futexsleep(uint32 *addr, uint32 val)&lt;/code&gt;: Makes the thread sleep when &lt;code&gt;addr&lt;/code&gt; is &lt;code&gt;val&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;futexwake(uint32 *addr)&lt;/code&gt;: Wakes up the thread which sleeps with &lt;code&gt;addr&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Hitsumabushi, I added a simple implementation like this. For an actual source, see &lt;a href="https://github.com/hajimehoshi/hitsumabushi/blob/033f91b0b848e44349a91ccd28d6436bc22d0c44/1.17/runtime/cgo/gcc_linux_arm64.c.patch#L321-L385" rel="noopener noreferrer"&gt;Hitsumabushi's &lt;code&gt;pseudo_futex&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// A pseudo code&lt;/span&gt;
&lt;span class="n"&gt;pseudo_futex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;uaddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;pthread_cond_t&lt;/span&gt; &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// A condition variable&lt;/span&gt;

  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;uaddr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;cond_wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Sleep&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;wake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cond_broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Wake up all the threads sleeping with cond.&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When &lt;code&gt;wake&lt;/code&gt; is called, it will wake up not only the necessary threads, but all the threads. If you want to wake up only necessary threads, you would need to manage multiple condition variables for each &lt;code&gt;uaddr&lt;/code&gt;, which would be cumbersome. Such unnecessary waking up is called &lt;a href="https://en.wikipedia.org/wiki/Spurious_wakeup" rel="noopener noreferrer"&gt;spurious wakeup&lt;/a&gt;. &lt;a href="https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/runtime/os_linux.go;l=41-42" rel="noopener noreferrer"&gt;This is explicitly expected in Go source code&lt;/a&gt;, so this is not problematic. However, performance might be degraded.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adjusting the number of CPU cores
&lt;/h3&gt;

&lt;p&gt;The number of CPU cores is determined by the result of the  &lt;a href="https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html" rel="noopener noreferrer"&gt;&lt;code&gt;sched_getaffinity&lt;/code&gt;&lt;/a&gt; system call. There is no corresponding standard C function, so I gave Hitsumabushi an option to specify the number of cores to &lt;code&gt;GenOverlayJSON&lt;/code&gt;. For the actual source, see &lt;a href="https://github.com/hajimehoshi/hitsumabushi/blob/033f91b0b848e44349a91ccd28d6436bc22d0c44/overlay.go#L177-L208" rel="noopener noreferrer"&gt;Hitsumabushi's &lt;code&gt;c_sched_getaffinity&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There were some environments where an application froze with 2 or more CPU cores specified. It's because a thread could use only one core by default. Thus, I had to call &lt;a href="https://man7.org/linux/man-pages/man3/pthread_setaffinity_np.3.html" rel="noopener noreferrer"&gt;&lt;code&gt;pthread_setaffinity_np&lt;/code&gt;&lt;/a&gt; explicitly. In Hitsumabushi, I added a hack to call &lt;code&gt;pthread_setaffinity_np&lt;/code&gt; just after &lt;a href="https://man7.org/linux/man-pages/man3/pthread_create.3.html" rel="noopener noreferrer"&gt;&lt;code&gt;pthread_create&lt;/code&gt;&lt;/a&gt;. For the actual source, see &lt;a href="https://github.com/hajimehoshi/hitsumabushi/blob/033f91b0b848e44349a91ccd28d6436bc22d0c44/overlay.go#L217-L247" rel="noopener noreferrer"&gt;Hitsumabushi's overlay.go&lt;/a&gt;. As an aside, it was quite hard to find this solution. I can’t tell you how happy I was to finally solve this conundrum.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entry point
&lt;/h3&gt;

&lt;p&gt;Hitsumabushi is assumed to be used with &lt;code&gt;-buildmode=c-archive&lt;/code&gt;. The generated file is a C library, and even &lt;code&gt;main&lt;/code&gt; is not called. If you want to call &lt;code&gt;main&lt;/code&gt;, you have to define a C function and call &lt;code&gt;main&lt;/code&gt; explicitly inside. Calling &lt;code&gt;main&lt;/code&gt; explicitly does not make sense usually, but I think it is practical for &lt;code&gt;c-archive&lt;/code&gt;.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c"&gt;//export GoMain&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GoMain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c1"&gt;// Call the entry point in Go in the entry point in C.&lt;/span&gt;&lt;br&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="n"&gt;GoMain&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;br&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Results&lt;br&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I managed to get a game called "&lt;a href="https://github.com/hajimehoshi/go-inovation" rel="noopener noreferrer"&gt;Innovation 2007&lt;/a&gt;" working on an actual Nintendo Switch device&lt;/strong&gt;. Controller support, touch inputting, and audio all work perfectly. Innovation 2007 uses most of Ebiten's features, so I'm sure other games would work as well.&lt;/li&gt;
&lt;li&gt;Compiling speed became much faster. Before this solution, it took 5 to 10 minutes to full-build a C++ project, but now it only takes less than 10 seconds. This is awesome!&lt;/li&gt;
&lt;li&gt;Suspensions by GC seem to have disappeared.&lt;/li&gt;
&lt;li&gt;I now have to update whenever a new version of Go is released. This is an acceptable compromise to me. From my past experiments, I don’t expect any major changes anyway.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Remarks
&lt;/h2&gt;

&lt;p&gt;This is a side note, but the implementation of Go's runtime has ample accumulation of knowledge about modern OSes and is very insightful. I think it can teach you a significant amount about computer science. That said, it can be quite daunting to read it without a purpose, so I recommend doing so with some sort of modification project in mind.&lt;/p&gt;

&lt;p&gt;Thanks to the near-success of this project, the method I presented in the Go Conference is now becoming outdated. This was inevitable, obviously, but it still makes me feel a little sad to see that hard work go obsolete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future works
&lt;/h2&gt;

&lt;p&gt;I'll continue polishing this so that a proper game can be released for Nintendo Switch. As I described first, there is a high level of uncertainty in this project. Until a game is released, I cannot anticipate what kind of issues will occur, and I always have to be on high alert. Even in the worst case scenario, however, I know we can continue to release the game with the help of &lt;a href="https://github.com/hajimehoshi/go2cpp" rel="noopener noreferrer"&gt;go2cpp&lt;/a&gt;, which is reassuring. Still, with all the hard work I’ve put into this already, I really want to release a game with Hitsumabushi and see it achieve some actual results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;Thanks to the kind folks over in the PySpa community for all their technical advice. I’d also like to express my gratitude to Daigo, &lt;a href="https://odencat.com/" rel="noopener noreferrer"&gt;President of Odencat Inc.&lt;/a&gt;, who kindly uses Ebiten for Nintendo Switch. Thank you very much.&lt;/p&gt;

&lt;p&gt;Happy new year!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;It's due to complicated business reasons. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Hitsumabushi is &lt;a href="https://en.wikipedia.org/wiki/Unadon#Variations" rel="noopener noreferrer"&gt;Japanese food&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Katsuobushi is &lt;a href="https://en.wikipedia.org/wiki/Katsuobushi" rel="noopener noreferrer"&gt;yet another Japanese food&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;There is another solution, making a pseudo &lt;code&gt;/dev/urandom&lt;/code&gt; file, but I didn't adopt this. There is no other good way than using a platform-specific API. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;The main reason is portability, but there is also another compelling reason: I wouldn't be able to make it open-source if it used a platform-specific API. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;To be exact, about 2G of memory was allocated first and was used without additional allocations. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>go</category>
      <category>ebiten</category>
      <category>gamedev</category>
      <category>nintendoswitch</category>
    </item>
    <item>
      <title>GopherJS vs WebAssembly for Go</title>
      <dc:creator>Hajime Hoshi</dc:creator>
      <pubDate>Fri, 15 Jun 2018 19:49:51 +0000</pubDate>
      <link>https://forem.com/hajimehoshi/gopherjs-vs-webassembly-for-go-148m</link>
      <guid>https://forem.com/hajimehoshi/gopherjs-vs-webassembly-for-go-148m</guid>
      <description>&lt;p&gt;&lt;strong&gt;EDIT&lt;/strong&gt;: For the latest of GopherJS/Wasm comparison, see &lt;a href="https://github.com/hajimehoshi/wasm-bench" rel="noopener noreferrer"&gt;Wasm benchmark result&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Hi all!&lt;/p&gt;

&lt;p&gt;This article describes about my experiment of &lt;a href="https://github.com/golang/go/issues/18892" rel="noopener noreferrer"&gt;the new WebAssembly port of Go&lt;/a&gt;. WebAssembly port is now available on the master branch of Go, and you'd need to compile Go yourself.&lt;/p&gt;

&lt;h1&gt;
  
  
  tl;dr
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;I have created &lt;a href="https://github.com/hajimehoshi/gopherwasm" rel="noopener noreferrer"&gt;GopherWasm&lt;/a&gt;, an agnostic WebAssembly wrapper that works both on GopherJS and WebAssembly port.&lt;/li&gt;
&lt;li&gt;Performance of GopherJS and WebAssembly depends on browsers. GopherJS is faster than WebAssembly on some environments, and slower on other environments. For Ebiten 'sprite' example, &lt;code&gt;(GopherJS on Chrome) &amp;gt; (WebAssembly on Firefox) &amp;gt; (GopherJS on Firefox) &amp;gt; (WebAssembly on Chrome)&lt;/code&gt; with 5000 sprites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Go on browsers
&lt;/h1&gt;

&lt;p&gt;Running Go applications on web browsers must be awesome. Needless to say, Go is an awesome language. I don't discuss how good Go is in this article :-)&lt;/p&gt;

&lt;p&gt;There is a transpiler from Go to JavaScript - &lt;a href="https://github.com/gopherjs/gopherjs/" rel="noopener noreferrer"&gt;GopherJS&lt;/a&gt; by &lt;a href="https://github.com/neelance" rel="noopener noreferrer"&gt;Richard Musiol&lt;/a&gt;. This also enables Go programs to run both on browsers and Node.js. You can use all the features of Go. The compilation result is reasonably readable JavaScript. The performance is so-so due to some overhead. To emulate Go behaviors precisely, GopherJS adds some overhead like boundary check of index access to slices. Instead of emulating Go behavior by JavaScript, executing binaries like WebAssembly on browsers seems much more efficient.&lt;/p&gt;

&lt;p&gt;WebAssembly is a performance-wise format compared to JavaScript. WebAssembly is supported by &lt;a href="https://caniuse.com/#feat=wasm" rel="noopener noreferrer"&gt;most of modern browsers&lt;/a&gt;. WebAssembly is a low-level language as the name says, and it is expected that WebAssembly binary is generated from other languages. Actually C, C++ and Rust already support WebAssembly port.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tip.golang.org/doc/go1.11" rel="noopener noreferrer"&gt;The latest Go version 1.11&lt;/a&gt; supports WebAssembly port by Richard Musiol, the same author of GopherJS. Now Go 1.11 is on the way releasing, but you can test WebAssembly APIs with the latest Go by compiling yourself. Your compiled program for WebAssembly is available both on browsers and Node.js. You can use full features of Go including goroutines. You can call any JavaScript functions from Go, and you can pass Go function as a JavaScript callback. The API is defined at &lt;a href="https://tip.golang.org/pkg/syscall/js/?GOOS=js&amp;amp;GOARCH=wasm" rel="noopener noreferrer"&gt;&lt;code&gt;syscall/js&lt;/code&gt; package&lt;/a&gt;. The environment variables for WebAssembly are &lt;code&gt;GOOS=js&lt;/code&gt; and &lt;code&gt;GOARCH=wasm&lt;/code&gt;. As WebAssembly is performance-wise format, this should be faster than GopherJS, right? Unfortunately, this was not true. I'll describe this later.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ebiten
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://hajimehoshi.github.io/ebiten/" rel="noopener noreferrer"&gt;Ebiten&lt;/a&gt; is a dead simple 2D game library by me. This is basically an OpenGL wrapper. This works on browsers with WebGL by GopherJS, and actually you can see some examples work on &lt;a href="https://hajimehoshi.github.io/ebiten/" rel="noopener noreferrer"&gt;the website&lt;/a&gt; and &lt;a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/flappy" rel="noopener noreferrer"&gt;the jsgo playground&lt;/a&gt; by &lt;a href="https://github.com/dave" rel="noopener noreferrer"&gt;Dave Brophy&lt;/a&gt;. Recently (actually today!) I fixed Ebiten (master branch) to accept WebAssembly compilation of the latest Go compiler except for the audio part. Thus, Ebiten now works both on GopherJS and WebAssembly!&lt;/p&gt;

&lt;h1&gt;
  
  
  Port GopherJS library to WebAssembly
&lt;/h1&gt;

&lt;p&gt;As I said, Ebiten can already work with GopherJS. GopherJS's API is similar to WebAssembly, but different. For example, the counterpart of &lt;code&gt;js.Object&lt;/code&gt; of GopherJS is &lt;code&gt;js.Value&lt;/code&gt; of &lt;code&gt;syscall/js&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://godoc.org/github.com/gopherjs/gopherjs/js" rel="noopener noreferrer"&gt;GopherJS API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tip.golang.org/pkg/syscall/js/?GOOS=js&amp;amp;GOARCH=wasm" rel="noopener noreferrer"&gt;&lt;code&gt;syscall/js&lt;/code&gt; API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, how can I write libraries to accept both GopherJS and WebAssembly? Of course it is easily possible to write similar duplicated code, but isn't there a more elegant way?&lt;/p&gt;

&lt;p&gt;I've created &lt;a href="https://github.com/hajimehoshi/gopherwasm" rel="noopener noreferrer"&gt;GopherWasm&lt;/a&gt;, an agnostic WebAssembly wrapper. If you use GopherWasm, your library automatically works both on GopherJS and WebAssembly port! &lt;a href="https://godoc.org/github.com/hajimehoshi/gopherwasm/js" rel="noopener noreferrer"&gt;GopherWasm API&lt;/a&gt; is almost same as &lt;code&gt;syscall/js&lt;/code&gt;. The only one difference is &lt;code&gt;js.ValueOf&lt;/code&gt; accepts &lt;code&gt;[]float32&lt;/code&gt; or other slices in GopherWasm, not in &lt;code&gt;syscall/js&lt;/code&gt;. I have already &lt;a href="https://github.com/golang/go/issues/25532" rel="noopener noreferrer"&gt;filed&lt;/a&gt; to fix &lt;code&gt;syscall/js.ValueOf&lt;/code&gt; to accept such slices, so the situation might change in near future.&lt;/p&gt;

&lt;h1&gt;
  
  
  Performance comparison
&lt;/h1&gt;

&lt;p&gt;I've compared the performances between GopherJS and WebAssembly port with my Ebiten example 'sprites'.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jsgo.io/github.com/hajimehoshi/ebiten/examples/sprites" rel="noopener noreferrer"&gt;Sprites (GopherJS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://storage.googleapis.com/ebiten-test/index.html" rel="noopener noreferrer"&gt;Sprites (WebAssembly)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79rdcl0sqxq400pbquao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79rdcl0sqxq400pbquao.png" alt="Sprites" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By pressing left or right arrow keys, you can change the number of sprites and see how FPS (frames per second) changes.&lt;/p&gt;

&lt;p&gt;On my MacBook Pro 2014, I took very rough measurements by showing 5000 sprites:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GopherJS on Chrome:     55-60 FPS
GopherJS on Firefox:    20-25 FPS
WebAssembly on Chrome:  15-20 FPS
WebAssembly on Firefox: 40-45 FPS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Chrome: Version 67.0.3396.87 (Official Build) (64-bit)&lt;/li&gt;
&lt;li&gt;Firefox: 60.0.2 (64-bit)&lt;/li&gt;
&lt;li&gt;Ebiten: 460c47a9ebaa21bcce730a460a7f87fa6cbe56ed&lt;/li&gt;
&lt;li&gt;Go: 534ddf741f6a5fc38fb0bb3e3547d3231c51a7be&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a very interesting result. Before this experiment, I thought WebAssembly should always be faster than GopherJS. However, the result depended on browsers. For 5000 sprites, the result was &lt;code&gt;(GopherJS on Chrome) &amp;gt; (WebAssembly on Firefox) &amp;gt; (GopherJS on Firefox) &amp;gt; (WebAssembly on Chrome)&lt;/code&gt;. I guess optimization way is different among browsers.&lt;/p&gt;

&lt;p&gt;I took rough profile and it looks like allocation (&lt;code&gt;runtime.mallocgc&lt;/code&gt;) was the heaviest task on WebAssembly. This is different tendency from GopherJS. I'm not sure the details how objects are allocated on WebAssembly, but at least WebAssembly requires different optimization from GopherJS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92b0qhoc81swki5y734u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92b0qhoc81swki5y734u.png" alt="Profiling" width="800" height="850"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I plan to do optimization to keep 60 FPS as much as possible. Stay tuned!&lt;/p&gt;

&lt;h1&gt;
  
  
  Binary size comparison
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-rw-r--r--    1 hajimehoshi  staff  7310436 Jun 16 05:23 sprites.js
-rw-r--r--    1 hajimehoshi  staff   278394 Jun 16 05:23 sprites.js.map
-rwxr-xr-x    1 hajimehoshi  staff  8303883 Jun 16 04:03 sprites.wasm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like WebAssembly binary is slightly bigger.&lt;/p&gt;

&lt;h1&gt;
  
  
  Appendix - How to do experiments
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Install Ebiten and other libraries
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/hajimehoshi/ebiten/...
go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/hajimehoshi/gopherwasm
go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/gopherjs/gopherjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Get the latest Go and compile it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd
&lt;/span&gt;git clone https://go.googlesource.com/go go-code
&lt;span class="nb"&gt;cd &lt;/span&gt;go-code/src

&lt;span class="c"&gt;# Compile Go. ./all.bash is also fine if you want to run tests.&lt;/span&gt;
./make.bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Compile an Ebiten example for WebAssembly
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/your/wasm/project

&lt;span class="c"&gt;# Compile 'sprites' example for WebAssembly&lt;/span&gt;
&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;js &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wasm ~/go-code/bin/go build &lt;span class="nt"&gt;-tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;example &lt;span class="nt"&gt;-o&lt;/span&gt; sprites.wasm github.com/hajimehoshi/ebiten/examples/sprites

&lt;span class="c"&gt;# Copy wasm_exec.js&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; ~/go-code/misc/wasm/wasm_exec.js &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prepare an HTML file to run the wasm file. This file is based on &lt;code&gt;~/go-code/misc/wasm/index.html&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"wasm_exec.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// Polyfill&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instantiateStreaming&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instantiateStreaming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;go&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Go&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiateStreaming&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sprites.wasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;go&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;importObject&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;go&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run an HTTP server as you like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run GopherJS server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gopherjs serve &lt;span class="nt"&gt;--tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then access &lt;code&gt;http://localhost:8080/github.com/hajimehoshi/ebiten/examples/sprites/&lt;/code&gt; to see the example.&lt;/p&gt;

</description>
      <category>go</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Go Packages we developed for our games</title>
      <dc:creator>Hajime Hoshi</dc:creator>
      <pubDate>Sat, 17 Feb 2018 06:54:08 +0000</pubDate>
      <link>https://forem.com/hajimehoshi/go-packages-we-developed-for-our-games--4cl9</link>
      <guid>https://forem.com/hajimehoshi/go-packages-we-developed-for-our-games--4cl9</guid>
      <description>&lt;p&gt;We have released some games in Go like &lt;a href="http://blockbros.net/tsugunai/" rel="noopener noreferrer"&gt;Clock of Atonement&lt;/a&gt; and &lt;a href="http://blockbros.net/bluebird/" rel="noopener noreferrer"&gt;Bluebird of Happiness&lt;/a&gt;. Unfortunately, we haven't made them open-source yet for some business reasons. However, we're now splitting the code into some public packages for games gradually so that Go game developers can utilize them, and game developing in Go would get more popular. In this article, I'd like to list the public Go packages we developed and used for the games!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fux6sxr77fg5vzv1mjzbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fux6sxr77fg5vzv1mjzbg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://github.com/hajimehoshi/ebiten" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/hajimehoshi/ebiten&lt;/code&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A dead simple 2D game library. Basically this is an OpenGL wrapper. This works on multiple platforms, not only desktop but also mobiles and even web browsers by &lt;a href="https://github.com/gopherjs/gopherjs" rel="noopener noreferrer"&gt;GopherJS&lt;/a&gt;! Actually we were able to develop the games on desktops and browsers, and released for mobiles.&lt;/p&gt;

&lt;p&gt;Ebiten (海老天) means a tempura of shrimp, which is one of my favorite Japanese food :-)&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://github.com/hajimehoshi/go-mp3" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/hajimehoshi/go-mp3&lt;/code&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;An MP3 decoder in pure Go. This is a port of &lt;a href="https://github.com/technosaurus/PDMP3" rel="noopener noreferrer"&gt;PDMP3&lt;/a&gt;, an MP3 decoder in Public Domain license. As I just ported this automatically without understanding the spec, I am still struggling to understand what is going on in my lib :-)&lt;/p&gt;

&lt;p&gt;The motivation I developed MP3 decoder instead of other decoder like Ogg is that we wanted to make games work on browsers. Now &lt;a href="https://caniuse.com/#feat=mp3" rel="noopener noreferrer"&gt;MP3 is supported by most modern browsers&lt;/a&gt; but others are not supported well (e.g. &lt;a href="https://caniuse.com/#search=ogg" rel="noopener noreferrer"&gt;Ogg&lt;/a&gt;). We could utilize the browser-native decoder on browsers instead of MP3 decoder in Go for performance. MP3 had patent problems, but the patents were expired in 2017.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://github.com/hajimehoshi/oto" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/hajimehoshi/oto&lt;/code&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A lower level audio lib. The great thing of this is portability: this works on Windows, macOS, Linux, Android, iOS and Web browsers. This just offers an &lt;code&gt;io.Writer&lt;/code&gt; and you can play any sound by writing bytes to the writer. With &lt;code&gt;go-mp3&lt;/code&gt;, you can play an MP3 file with &lt;a href="https://golang.org/pkg/io/#Copy" rel="noopener noreferrer"&gt;&lt;code&gt;io.Copy&lt;/code&gt;&lt;/a&gt; (&lt;a href="https://github.com/hajimehoshi/go-mp3/blob/master/example/main.go" rel="noopener noreferrer"&gt;Example&lt;/a&gt;)!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"classic.mp3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Decode MP3 stream and the result is an `io.Reader`&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mp3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Create an oto's player, which is an `io.Writer`&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;oto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SampleRate&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// With `io.Copy`, you can play the decoded MP3 on your machine!&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oto (音) means 'sound' in Japanese.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://github.com/hajimehoshi/file2byteslice" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/hajimehoshi/file2byteslice&lt;/code&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Yet another tool to embed binary to Go file, just like &lt;a href="https://github.com/jteeuwen/go-bindata" rel="noopener noreferrer"&gt;go-bindata&lt;/a&gt;. &lt;code&gt;file2bytesslice&lt;/code&gt; is dead simple compared to other similar packages. This just converts one binary to one byte slice literal. That's it! The motivation I developed this is that there was an &lt;a href="https://www.reddit.com/r/golang/comments/7vv9zz/popular_lib_gobindata_removed_from_github_or_why/" rel="noopener noreferrer"&gt;incident&lt;/a&gt;: go-bindata's original author deleted their GitHub account and another person used the same GitHub account again, and I thought the repository is no longer trusty. Thus, I tried to develop it myself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Usage of file2byteslice:
  -compress
        use gzip compression
  -input string
        input filename
  -output string
        output filename
  -package string
        package name (default "main")
  -var string
        variable name (default "_")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;a href="https://github.com/hajimehoshi/go-mplusbitmap" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/hajimehoshi/go-mplusbitmap&lt;/code&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A package to offer &lt;a href="https://godoc.org/golang.org/x/image/font#Face" rel="noopener noreferrer"&gt;&lt;code&gt;font.Face&lt;/code&gt;&lt;/a&gt; object of &lt;a href="http://mplus-fonts.osdn.jp/mplus-bitmap-fonts/" rel="noopener noreferrer"&gt;M+ Bitmap font&lt;/a&gt; for 8/16 bitty style Japanese texts. &lt;code&gt;font.Face&lt;/code&gt; is a semi-standard interface to represent a font face, and there is &lt;a href="https://github.com/golang/freetype" rel="noopener noreferrer"&gt;a TrueType parser&lt;/a&gt; in Go to make &lt;code&gt;font.Face&lt;/code&gt; instances. You can draw the text with &lt;a href="https://godoc.org/github.com/hajimehoshi/ebiten/text" rel="noopener noreferrer"&gt;Ebiten's text package&lt;/a&gt; very easily! Of course, this can be used with (semi-)standard rendering package (&lt;a href="https://github.com/hajimehoshi/go-mplusbitmap/blob/master/example/main.go" rel="noopener noreferrer"&gt;Example&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;`Hello, World!

こんにちは世界!`&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;
        &lt;span class="n"&gt;oy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRGBA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;240&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c"&gt;// Initialize the destination image dst by filling with white.&lt;/span&gt;
    &lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bounds&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewUniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;White&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mplusbitmap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Gothic12r&lt;/span&gt;

    &lt;span class="c"&gt;// golang.org/x/image/font's Drawer draws a text on a specified image.&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Drawer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Dst&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewUniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Black&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Face&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Dot&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;fixed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;oy&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DrawString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fixed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Metrics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Height&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Now the text is drawn to the image dst.&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;a href="https://github.com/hajimehoshi/chinesegamefonts" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/hajimehoshi/chinesegamefonts&lt;/code&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;This offers (compressed) TTF binaries of &lt;a href="https://www.google.com/get/noto/help/cjk/" rel="noopener noreferrer"&gt;Noto CJK fonts&lt;/a&gt;. This package's fonts are different from original Noto CJK fonts in some points.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The fonts are TrueType, not OpenType since there is no actually-usable Go package to parse OpenType fonts so far (&lt;a href="https://github.com/golang/go/issues/22451" rel="noopener noreferrer"&gt;&lt;code&gt;golang.org/x/image/font/sfnt&lt;/code&gt; is under development&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Many glyphs are removed from the originals' and &lt;code&gt;chinesegamefonts&lt;/code&gt; fonts include only common CJK glyphs to reduce file size. The original file sizes are 46.1 MB (both Simplified and Traditional), and the reduced ones are 4.4 MB (Simplified) and 7.6 MB (Traditional)!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our games don't have Chinese support so far, but we're now implementing that with this font package.&lt;/p&gt;




&lt;p&gt;Besides above packges, we are now developing packages e.g. for user interface. Stay tuned!&lt;/p&gt;

</description>
      <category>go</category>
      <category>ebiten</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>New Ebiten package inpututil</title>
      <dc:creator>Hajime Hoshi</dc:creator>
      <pubDate>Mon, 12 Feb 2018 15:14:53 +0000</pubDate>
      <link>https://forem.com/hajimehoshi/new-ebiten-package-inpututil--e5b</link>
      <guid>https://forem.com/hajimehoshi/new-ebiten-package-inpututil--e5b</guid>
      <description>&lt;p&gt;Hi all,&lt;/p&gt;

&lt;p&gt;This is the very first post for &lt;a href="https://hajimehoshi.github.io/ebiten/"&gt;Ebiten&lt;/a&gt;, my own game library in Go. I didn't have any places to announce the recent updates of Ebiten until now, and I started that here now!&lt;/p&gt;

&lt;p&gt;I'd like to announce that I have introduced a new package, &lt;a href="https://godoc.org/github.com/hajimehoshi/ebiten/inpututil"&gt;&lt;code&gt;inpututil&lt;/code&gt;&lt;/a&gt;! With this package, for example, you can detect the key is pressed just in the current frame (&lt;code&gt;IsKeyJustPressed&lt;/code&gt;). This is a very common idiom, and the package would help you do such things.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>go</category>
      <category>ebiten</category>
    </item>
    <item>
      <title>摩訶般若波羅蜜多心経</title>
      <dc:creator>Hajime Hoshi</dc:creator>
      <pubDate>Wed, 15 Nov 2017 14:22:48 +0000</pubDate>
      <link>https://forem.com/hajimehoshi/scriptalerthiscript-3pb</link>
      <guid>https://forem.com/hajimehoshi/scriptalerthiscript-3pb</guid>
      <description>&lt;p&gt;観自在菩薩　行深般若波羅蜜多時　照見五蘊皆空　度一切苦厄&lt;br&gt;
舎利子　色不異空　空不異色　色即是空　空即是色　受想行識亦復如是&lt;br&gt;
舎利子　是諸法空相　不生不滅　不垢不浄　不増不減&lt;br&gt;
是故空中 無色　無受想行識　無眼耳鼻舌身意　無色声香味触法&lt;br&gt;
無眼界　乃至無意識界　無無明亦　無無明尽　乃至無老死　亦無老死尽&lt;br&gt;
無苦集滅道　無智亦無得　以無所得故　菩提薩埵　依般若波羅蜜多故&lt;br&gt;
心無罣礙　無罣礙故　無有恐怖　遠離一切顛倒夢想　究竟涅槃&lt;br&gt;
三世諸仏　依般若波羅蜜多故　得阿耨多羅三藐三菩提&lt;br&gt;
故知般若波羅蜜多　是大神呪　是大明呪　是無上呪　是無等等呪&lt;br&gt;
能除一切苦　真実不虚　故説般若波羅蜜多呪　即説呪曰&lt;br&gt;
羯諦　羯諦　波羅羯諦　波羅僧羯諦　菩提薩婆訶&lt;br&gt;
般若心経&lt;/p&gt;

</description>
      <category>摩訶般若波羅蜜多心経</category>
    </item>
    <item>
      <title>Oreo</title>
      <dc:creator>Hajime Hoshi</dc:creator>
      <pubDate>Wed, 15 Nov 2017 06:31:04 +0000</pubDate>
      <link>https://forem.com/hajimehoshi/oreo-bk7</link>
      <guid>https://forem.com/hajimehoshi/oreo-bk7</guid>
      <description>&lt;p&gt;Oreo&lt;/p&gt;

</description>
      <category>oreo</category>
    </item>
  </channel>
</rss>
