2. docs
  3. higan
  4. interface


Important Notice: I have moved to a new domain. This site is no longer being updated. Read more here.

Interface2019-12-17 13:46:08

Every emulation core implemented in higan inherits from the Interface class. All cores can be controlled using this API.

To put it another way, GUIs call Interface functions.


struct Interface {
  virtual auto name() -> string;

  virtual auto root() -> Node::Object;
  virtual auto load(string tree = {}) -> void;
  virtual auto power() -> void;
  virtual auto run() -> void;
  virtual auto save() -> void;
  virtual auto unload() -> void;

  virtual auto serialize() -> serializer;
  virtual auto unserialize(serializer&) -> bool;

  virtual auto cheats(const vector<string>& = {}) -> void;

name() -> string;

Returns a unique string identifier to indicate which emulation core is currently being used.

This string is typically in English, and is generally the first name of a released system. For instance, Japan released the Super Famicom first, followed by the US and Europe releasing the Super Nintendo. As the original, first model was labeled the Super Famicom, that is the string returned for the SNES emulation core.

root() -> Node

Returns a Node::System object representing the tree root of the emulated system. All Node::Objects contain zero or more child nodes. The tree represents the complete hardware state of a system: all available hardware properties, settings, ports, connected peripherals, their associated connections, etc.

This tree can and must be parsed to enumerate cartridge and controller ports. When Node::Port objects are found, Node::Port::connect() may be called to connect a Node::Peripheral to it. For instance, a controller may be connected to a controller port.

load(string tree = {}) -> void;

This function is used to initialize an emulation core to a known state. The tree parameter is optional, so on first run, the emulator will be initialized to its default state, with no connected peripherals.

After the user has connected eg controllers to the system, and then closed the emulator, the user interface should save the tree via Node::serialize(root()), which it can then restore on next run using load() here.

Note that Interface::load() is not the same as Node::unserialize(). This function will walk the provided tree while creating a new root tree, copying in only properties that are safe and valid to copy. This guarantees that even if the tree becomes corrupted or outdated due to changes, the emulator will be in a fully operational state after the tree is restored.

It will also call out to Node::Port::connect() as each peripheral is located in the provided tree.

power() -> void;

This function performs a hard reset of the emulated system.

run() -> void;

This function runs the emulated system until a frame of video has been generated, which is typically ~16-20 milliseconds of emulated time. If the emulation core is faster than the host hardware, it will take less time. If it is slower, it will take more time and techniques such as dynamic rate control should be used on the audio output.

save() -> void;

Calling this function triggers the emulation core to attempt to save all non-volatile memory to disk. For instance, all connected cartridges with save RAM will call Platform::open() in write mode, and attempt to write the RAM contents to disk.

unload() -> void;

Calling this function will implicitly invoke save() first, and then it will release and free all allocated memory for eg cartridge ROM and save RAM data, the entire tree, etc.

After calling this function, load() must be used to re-initialize the emulation core.

serialize() -> serializer;

Captures and returns a nall/serializer object that holds the current emulated system state. In other words, this produces a save state. Note that due to the cooperative threading model employed by higan, this function may run the emulation core for up to one video frame before returning. This is especially important to consider when a user attempts to save a state while the emulator is paused within the user interface.

unserialize(serializer&) -> bool;

Attempts to restore a serialized system state. If the state is corrupted or in an incompatible (eg older) format, this function will fail.

Generally, states between emulator releases aren't compatible, unless the core in question has not undergone any internal state changes since the last version.

cheats(const vector<string>& = {}) -> void;

Loads a list of strings into the cheat code system for a given system. Call this function with no parameters to disable all cheats.

There is no per-cheat API. To disable a cheat code, call this function again with said cheat code excluded from the list.

There is no universal format for these codes, as every system is unique. But in general, higan uses two types of codes here:

address=data codes will assign the data value to a given address.

address=compare?data codes will assign the data value to a given address, only when the given address originally contains the compare value. This type of code is used to support systems that use bank-switching mechanisms. For instance, the Famicom and Game Boy.