Skip to content
Snippets Groups Projects
nes.js 2.06 KiB
import jsnes from "jsnes";

var SCREEN_WIDTH = 256;
var SCREEN_HEIGHT = 240;
var FRAMEBUFFER_SIZE = SCREEN_WIDTH * SCREEN_HEIGHT;

var framebuffer_u8, framebuffer_u32;

var nes = new jsnes.NES({
  onFrame: function (framebuffer_24) {
    for (var i = 0; i < FRAMEBUFFER_SIZE; i++)
      framebuffer_u32[i] = 0xff000000 | framebuffer_24[i];

    postMessage(framebuffer_u8);
  },
});

var pressedKeys = {};

onmessage = (msg) => {
  const keys = {
    up: jsnes.Controller.BUTTON_UP,
    down: jsnes.Controller.BUTTON_DOWN,
    left: jsnes.Controller.BUTTON_LEFT,
    right: jsnes.Controller.BUTTON_RIGHT,
    a: jsnes.Controller.BUTTON_A,
    b: jsnes.Controller.BUTTON_B,
    start: jsnes.Controller.BUTTON_START,
    select: jsnes.Controller.BUTTON_SELECT,
  };

  for (let i = 0; i < Object.keys(keys).length; i++) {
    const key = Object.keys(keys)[i];
    const val = keys[key];
    if (pressedKeys[key] && !msg.data.keys[key]) {
      // key was pressed and no longer is pressed
      nes.buttonUp(1, val);
    } else if (!pressedKeys[key] && msg.data.keys[key]) {
      // key was not pressed but now it is
      nes.buttonDown(1, val);
    }
  }

  pressedKeys = msg.data.keys;
};

function nes_init() {
  // Allocate framebuffer array.
  var buffer = new ArrayBuffer(SCREEN_WIDTH * SCREEN_HEIGHT * 4);
  framebuffer_u8 = new Uint8ClampedArray(buffer);
  framebuffer_u32 = new Uint32Array(buffer);
}

function nes_boot(rom_data) {
  nes.loadROM(rom_data);
}

function nes_load_url(path) {
  nes_init();

  var req = new XMLHttpRequest();
  req.open("GET", path);
  req.overrideMimeType("text/plain; charset=x-user-defined");
  req.onerror = () => console.log(`Error loading ${path}: ${req.statusText}`);

  req.onload = function () {
    if (this.status === 200) {
      nes_boot(this.responseText);

      function doit() {
        setTimeout(() => {
          doit();
          nes.frame();
        }, 1000.0 / 60);
      }

      doit();
    } else if (this.status === 0) {
      // Aborted, so ignore error
    } else {
      req.onerror();
    }
  };

  req.send();
}

nes_load_url("main.rom");