<?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>DEV Community: bokuweb</title>
    <description>The latest articles on DEV Community by bokuweb (@bokuweb17).</description>
    <link>https://dev.to/bokuweb17</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%2F57201%2Fb4d31487-f684-43b5-b427-3d2aaf685c86.png</url>
      <title>DEV Community: bokuweb</title>
      <link>https://dev.to/bokuweb17</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bokuweb17"/>
    <language>en</language>
    <item>
      <title>Writing An NES Emulator with Rust and WebAssembly</title>
      <dc:creator>bokuweb</dc:creator>
      <pubDate>Wed, 11 Apr 2018 14:30:56 +0000</pubDate>
      <link>https://dev.to/bokuweb17/writing-an-nes-emulator-with-rust-and-webassembly-30jd</link>
      <guid>https://dev.to/bokuweb17/writing-an-nes-emulator-with-rust-and-webassembly-30jd</guid>
      <description>&lt;p&gt;I wrote the NES emulator with Rust and WebAssembly to learn Rust. It’s not perfect and have some audio bugs, but it’s good enough to play Super Mario bros.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NGf4IFZm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/759/1%2AFeNjHAjDRrgLw9w5PJ0GgQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NGf4IFZm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/759/1%2AFeNjHAjDRrgLw9w5PJ0GgQ.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;TL;DR&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/bokuweb/rustynes"&gt;Here&lt;/a&gt; is the source code. Also, you can play the game in the canvas below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bokuweb.github.io/rustynes/"&gt;rustynes&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Nintendo Entertainment System (NES)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Nintendo Entertainment System (NES) was the world’s most widely used video games.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU 6502(RP2A03), 8bit 1.79MHz&lt;/li&gt;
&lt;li&gt;PPU Picture Processing Unit RP2C02&lt;/li&gt;
&lt;li&gt;ROM ProgramROM:32KiB + CharactorROM:8KiB&lt;/li&gt;
&lt;li&gt;WRAM WorkingRAM 2KiB&lt;/li&gt;
&lt;li&gt;VRAM VideoRAM 2KiB&lt;/li&gt;
&lt;li&gt;Color 52color&lt;/li&gt;
&lt;li&gt;Resolution 256x240pixles&lt;/li&gt;
&lt;li&gt;Sound Square1/2, Triangle, Noise, DPCM&lt;/li&gt;
&lt;li&gt;Controller Up, Down, Left, Right, A, B, Start, Select&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had to emulate the above specs with WebAssembly and browser features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Emulator Structure
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yuev5qzm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANudS1Jxt1STmldYF9n88sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yuev5qzm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANudS1Jxt1STmldYF9n88sg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building WebAssembly with Rust
&lt;/h3&gt;

&lt;p&gt;I used wasm32-unknown-emscripten to convert Rust to WebAssembly. Because I did not have wasm32-unknown-unknown when I started this project, since there are now great libraries such as &lt;a href="https://github.com/koute/stdweb"&gt;stdweb&lt;/a&gt; and &lt;a href="https://github.com/rustwasm/wasm-bindgen"&gt;wasm-bindgen&lt;/a&gt; with wasm32-unknown-unknown consider using them It might be good, too.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The most important of these are NO_EXIT_RUNTIME and EXPORTED_FUNCTIONS. NO_EXIT_RUNTIME is used to freeze the memory on the Rust side to use it from the JavaScript side. Without this setting, memory will be freed and unexpected behavior will occur.&lt;/p&gt;

&lt;p&gt;EXPORTED_FUNCTIONS is used to specify the function to export to the Javascript side. Actually it is invoked from JavaScript side as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bokuweb/rustynes/blob/master/main.js#L63"&gt;bokuweb/rustynes&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Game loop
&lt;/h3&gt;

&lt;p&gt;NES works at 60 FPS. It means that It is necessary to refresh the screen every 16 ms. So I used emscripten_set_main_loop for this. If 0 or negative value is used as the second argument, requestAnimationFrame will be used internally. (See. &lt;a href="https://kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html#c.emscripten_set_main_loop"&gt;https://kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html#c.emscripten_set_main_loop&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I wanted to use closure so I struggled and finally wrote it as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  The CPU
&lt;/h3&gt;

&lt;p&gt;The NES used the MOS6502 (at 1.79 MHz) as its CPU. The 6502 is an 8bit microprocessor.The 6502 had relatively few registers (A, X &amp;amp; Y) and they were special-purpose registers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Registers
&lt;/h4&gt;

&lt;p&gt;The stack pointer needs to point to a 16bit address space, but the upper 8 bits are fixed to 0x01. 256 bytes are available for the stack( 0x0100 to 0x01FF) in WRAM is allocated. That is, if the stack pointer register is 0xA0, the stack pointer is 0x01A0.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This is expressed as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Memory map
&lt;/h4&gt;

&lt;p&gt;The Program ROM is 0x8000~, The WRAM is mapped from 0x0000~0x07FF, and the PPU register is mapped to 0x2000~.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  How to emulate CPU
&lt;/h4&gt;

&lt;p&gt;The 6502 does not have a pipeline structure like a recent CPU, and can be emulated simply by repeating fetching, decoding, and execution from Program ROM.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In addition, the opcode dictionary is created using lazy_static. That is a very good library.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  The PPU (Picture Processing Unit)
&lt;/h3&gt;

&lt;p&gt;The PPU reads the sprite information from the cartridge and constructs the screen. So the data bus of the PPU is directly connected to the cartridge.&lt;/p&gt;

&lt;p&gt;Sprites are 8 x 8 or 8 x16 pixels as follows, PPU places sprites based on data set in VRAM. (Below is the output of Super Mario Bros. sprite data).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ViwO5Eb7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AP5Dg-Vr49SgwL31xxI62gg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ViwO5Eb7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AP5Dg-Vr49SgwL31xxI62gg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please refer to the following article for details about the NES graphic.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.dustmop.io/blog/2015/04/28/nes-graphics-part-1/"&gt;NES Graphics - Part 1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After generating data for one screen from VRAM data and sprite information, I emulated game screen by drawing on Canvas.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;canvas_render is Javascript side code. If you are using emscriptenyou will be able to call on the Rust side via mergeInto.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  The game Pad
&lt;/h3&gt;

&lt;p&gt;The game pad emulated using keydownEvent. Specifically, the following handlers are registered at initialization, and specific bytes of ArrayBuffer are written at keyDown / keyUp. This is because, from the viewpoint of Browser, the memory on the Rust side can be handled as ArrayBuffer.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  The Sound
&lt;/h3&gt;

&lt;p&gt;Just like Canvas, we used mergeInto to invoke Javascript code using WebAudio API from Rust side.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As an example, the waveform is generated using the WebAudio API as follows&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Although we omitted it considerably, we implemented NES Emulator with Rust and WebAssembly like this. The whole code please see the following repositry.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bokuweb/rustynes"&gt;bokuweb/rustynes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to know deeply, you may want to look at the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://nesdev.com/NESDoc.pdf"&gt;NES Documentation (PDF)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.nesdev.com/w/index.php/NES_reference_guide"&gt;NES Reference Guide (Wiki)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.obelisk.demon.co.uk/6502/"&gt;6502 CPU Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusions
&lt;/h3&gt;

&lt;p&gt;I’ve been really impressed with Rust, and I think that it is one very good choice for building on the WebAssembly. A framework for an advanced browser front end like &lt;a href="https://github.com/DenisKolodin/yew"&gt;yew&lt;/a&gt; has also been developed and I think that it is also a remarkable language for developers who usually write Javascript.&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>rust</category>
      <category>javascript</category>
      <category>emulator</category>
    </item>
  </channel>
</rss>
