NesEmulator

NesEmulator

Controls a NES emulator, allowing you to run it frame-by-frame, and get values out of it. Be aware that almost every method on this is asynchronous, and should only be called when prefixed with await, or you may run into timing issues and emulator crashes!

Constructor

# new NesEmulator(romFile)

Create a NesEmulator instance, read to be started and run your tests.

Parameters:
Name Type Description
romFile String

The path to a rom file, relative to the working directory nes-test is called from.

Throws:

Error if the rom file cannot be found.

Type
Error

Methods

# (async) ensureEmulatorAvailable()

Download and prepare the emulator, if required. Not needed if running within nes-test.

# (async) getByteRange(address, length) → {Array.<Number>}

Get a sequence of bytes from the game's memory, of the length requested.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable.

length Number

How many bytes to include in the sequence.

Returns:

An array with the requested bytes.

Type
Array.<Number>

# (async) getByteValue(address) → {Number}

Get the value of a byte from within the NES memory using an address or debug symbol.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

Returns:

The requested byte.

Type
Number

# getNumericAddress(address) → {Number}

Given a string key, this will look up the label/variable mapped to the name and return that numeric value. Numeric values will be returned as-is. Everything else will return null.

Parameters:
Name Type Description
address Number | String

Either a numeric address or a string representing an address.

Throws:

An error if a string address is not found in the game's debug file. (Or the file is not present)

Type
Error
Returns:

A numeric address somewhere in the rom.

Type
Number

# (async) getPpuByteValue(address) → {Number}

Get the value of a bytefrom within the PPU memory.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

Returns:

The requested byte.

Type
Number

# (async) getPpuWordValue(address) → {Number}

Get the value of a word (two consecutive bytes) from within the PPU memory.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

Returns:

The requested word.

Type
Number

# getScreenshotPath(image)

Get the full path to a test image, generally to compare with a prepared image.

Parameters:
Name Type Description
image String

The name of the image given when the screenshot was taken

Returns:

The full path to the image file created, for use in tests.

# (async) getWordValue(address) → {Number}

Get the value of a word (two consecutive bytes) from within the NES memory.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

Returns:

The requested word.

Type
Number

# (async) runCpuFrames(value)

Run a set number of frames in the emulator before handling further input. This can be used to wait for things like title screen rendering, level updates, etc.

Parameters:
Name Type Description
value Number

How many frames to execute

# (async) runLua(string) → {object}

Run the given lua code, and return any values you set with NesTest.writeValue. Note that this is an internal method, and shouldn't be needed for most tests! The documentation of the lua core is also pretty lacking right now. If you use this, please try to help document it!

Parameters:
Name Type Description
string string

The lua code to run. This can be spread across multiple lines.

Returns:

An object containing some internal state used by the tool. Any values you set with NesTest.writeValue() will be available.

Type
object

# (async) sendInput(value, controller)

Press down one or more buttons for the next frame. If you need to do this for multiple frames, you will have to call it multiple times in a loop. Be aware that this command also advances the emulator one frame.

Parameters:
Name Type Default Description
value object

An object with keys for any button on the keyboard, and a true or false value. (True is pressed, false is released.) Available keys:

  • a
  • b
  • up
  • down
  • left
  • right
  • start
  • select
controller number 0

Which controller to use.

  • 0 (player 1)
  • 1 (player 2)
Example

This will hold the up and a buttons for one frame

await emulator.sendInput({up: true, a: true})

# (async) setMemoryByteValue(address, value)

Sets a memory address on the NES to the given value. Note this will have no effect on hardcoded memory addresses.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

value Number

The value to set the given byte to

# (async) setMemoryWordValue(address, value)

Sets a memory address on the NES to the given value. Note this will have no effect on hardcoded memory addresses.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

value Number

The value to set the given word to

# (async) setPpuByteValue(address, value)

Set a byte in ppu memory to a given value.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

value Number

The value to set the given byte to.

# (async) setPpuWordValue(address, value)

Set a word in ppu memory to a given value.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

value Number

The value to set the given word to.

# (async) setPrgByteValue(address, value)

Set a data address on the NES to the given value. This will have no effect on variable memory addresses, only on hardcoded PRG data.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

value Number

The value to set the given byte to

# (async) setPrgWordValue(address, value)

Set a data address on the NES to the given value. This will have no effect on variable memory addresses, only on hardcoded PRG data.

Parameters:
Name Type Description
address Number | String

Either a numeric address, or a string representing a C or assembly variable

value Number

The value to set the given word to

# (async) start()

Start the emulator, so that commands can be run.

# (async) stop(code)

Stop the emulator and clean up all temporary test data.

Parameters:
Name Type Default Description
code number 0

Optional error code to return from Mesen when it exits. You probbably don't want to set this.

# (async) takeScreenshot(filename, options)

Take a screenshot of the emulator and store it for later use in tests. There are also two matchers available:

  • JasmineMatchers#toBeSimilarToImage
  • JasmineMatchers#toBeIdenticalToImage
Parameters:
Name Type Description
filename String

The name of a screenshot to use.

options object

Options for the screenshot

Properties
Name Type Description
copyToLocation String

Local path to copy the screenshot to, for use after the test ends.

Returns:

The full path to the file created

Example

Takes a screenshot, saves it to "example.png" and compares it to a local "example.png"

  // Take a screenshot of the intro screen
  const screenshot = await emulator.takeScreenshot('example.png');

  // Do a comparison that they're similar (at least 80% the same)
  expect(screenshot).toBeSimilarToImage('./example.png');

  // Also test that they're identical. (You'll generally want to do only one of these tests, but both are provided for the example)
  expect(screenshot).toBeIdenticalToImage('./example.png');