Skip to main content

In node.js

In this tutorial we will run Digger game in Node.js and save game screenshot to the image.

Let's start with creating empty project:

npm init

In node environment you can only use emulators package, because emulators-ui is made for browser integrations. For creating screenshot we will use jimp library. So let's install them.

npm install --save emulators jimp

Next we need to download Digger js-dos bundle:

curl https://cdn.dos.zone/original/2X/2/24b00b14f118580763440ecaddcc948f8cb94f14.jsdos -o digger.jsdos

Let's create source file digger.js. We can run it with this command node digger.js

Use require to import all libraries

const fs = require("fs");
const jimp = require("jimp");
require("emulators");
const emulators = global.emulators;
emulators.pathPrefix = "./";

info

emulators package does not use exports system. It injects itself into global object. pathPrefix is used to locate wasm files it relative to require path.

Now we need to read contents of jsdos bundle and start emulation

const bundle = fs.readFileSync("digger.jsdos");
emulators
.dosDirect(bundle)
.then((ci) => {
// ...
});

When dos emulation starts, we will receive Command Interface, we can use it to subscribe on frame updates and to send key/mouse events.

ci.events().onFrame((rgb, rgba) => {
// use rgb or rgba image data
});

info

onFrame method have two arguments rgb and rgba image data. One of them is always null whilte other is UInt8ClampedArray. It depends on used emulator which data it uses rgb or rgba. js-dos for browsers return rgba data with transparent alpha channel.


In browser we have frame in RGBA format with transparent alpha, let's fix this and save screenshot:

const width = ci.width();
const height = ci.height();
for (let next = 3; next < width * height * 4; next = next + 4) {
rgba[next] = 255;
}
new jimp({ data: rgba, width, height }, (err, image) => {
image.write("./screenshot.png", () => {
ci.exit();
});
});

If you execute node digger.js it will save the screenshot to ./screenshot.png.

Full code of digger.js:

const fs = require("fs");
const jimp = require("jimp");
require("emulators");
const emulators = global.emulators;
emulators.pathPrefix = "./";
const bundle = fs.readFileSync("digger.jsdos");
emulators
.dosDirect(bundle)
.then((ci) => {
let rgba = new Uint8Array(0);
ci.events().onFrame((_, _rgba) => {
rgba = _rgba;
});
// capture the screen after 3 sec
console.log("Will capture screen after 3 sec...");
setTimeout(() => {
const width = ci.width();
const height = ci.height();
for (let next = 3; next < width * height * 4; next = next + 4) {
rgba[next] = 255;
}
new jimp({ data: rgba, width, height }, (err, image) => {
image.write("./screenshot.png", () => {
ci.exit();
});
});
}, 3000);
})
.catch(console.error);