Created
March 13, 2011 22:56
-
-
Save Themaister/868523 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LIBSNES_HPP | |
#define LIBSNES_HPP | |
#include <stdint.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/////////////////////////////////////////////////////////////////////////////// | |
// LIBSNES Super Nintendo emulation API | |
// | |
// Things you should know: | |
// - Linking against libsnes requires a C++ compiler. It can be compiled with | |
// a C99 compiler if you #include <stdbool.h> and if your C99 compiler's | |
// bool type is compatible with the bool type used by the C++ compiler used | |
// to compile libsnes. | |
// - libsnes supports exactly one emulated SNES; if you want to run two SNESes | |
// in a single process, you'll need to link against or dlopen() two | |
// different copies of the library. | |
// | |
// Typical usage of the libsnes API looks like this: | |
// | |
// 1. Call snes_init() to initialize the library. | |
// 2. Tell libsnes which callback should be called for each event (see the | |
// documentation on the individual callback types below. | |
// 3. Call one of the snes_load_cartridge_* functions to load cartridge data | |
// into the emulated SNES. | |
// 4. If the physical cart had any non-volatile storage, there may be data from | |
// a previous emulation run that needs to be loaded. Find the storage buffer | |
// by calling the snes_get_memory_* functions and load any saved data into | |
// it. | |
// 5. Call snes_set_controller_port_device() to connect appropriate controllers | |
// to the emulated SNES. | |
// 6. Call snes_get_region() to determine the intended screen refresh rate for | |
// this cartridge.. | |
// 7. Call snes_run() to emulate a single frame. Before snes_run() returns, the | |
// installed callbacks will be called - possibly multiple times. | |
// 8. When you're done, call snes_term() to free all memory allocated | |
// associated with the emulated SNES. | |
// | |
/////////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////////// | |
// Constants {{{ | |
// These constants represent the two controller ports on the front of the SNES, | |
// for use with the snes_set_controller_port_device() function and the | |
// snes_input_state_t callback. | |
#define SNES_PORT_1 0 | |
#define SNES_PORT_2 1 | |
// These constants represent the different kinds of controllers that can be | |
// connected to a controller port, for use with the | |
// snes_set_controller_port_device() function and the snes_input_state_t | |
// callback. | |
#define SNES_DEVICE_NONE 0 | |
#define SNES_DEVICE_JOYPAD 1 | |
#define SNES_DEVICE_MULTITAP 2 | |
#define SNES_DEVICE_MOUSE 3 | |
#define SNES_DEVICE_SUPER_SCOPE 4 | |
#define SNES_DEVICE_JUSTIFIER 5 | |
#define SNES_DEVICE_JUSTIFIERS 6 | |
// These constants represent the button and axis inputs on various controllers, | |
// for use with the snes_input_state_t callback. | |
#define SNES_DEVICE_ID_JOYPAD_B 0 | |
#define SNES_DEVICE_ID_JOYPAD_Y 1 | |
#define SNES_DEVICE_ID_JOYPAD_SELECT 2 | |
#define SNES_DEVICE_ID_JOYPAD_START 3 | |
#define SNES_DEVICE_ID_JOYPAD_UP 4 | |
#define SNES_DEVICE_ID_JOYPAD_DOWN 5 | |
#define SNES_DEVICE_ID_JOYPAD_LEFT 6 | |
#define SNES_DEVICE_ID_JOYPAD_RIGHT 7 | |
#define SNES_DEVICE_ID_JOYPAD_A 8 | |
#define SNES_DEVICE_ID_JOYPAD_X 9 | |
#define SNES_DEVICE_ID_JOYPAD_L 10 | |
#define SNES_DEVICE_ID_JOYPAD_R 11 | |
#define SNES_DEVICE_ID_MOUSE_X 0 | |
#define SNES_DEVICE_ID_MOUSE_Y 1 | |
#define SNES_DEVICE_ID_MOUSE_LEFT 2 | |
#define SNES_DEVICE_ID_MOUSE_RIGHT 3 | |
#define SNES_DEVICE_ID_SUPER_SCOPE_X 0 | |
#define SNES_DEVICE_ID_SUPER_SCOPE_Y 1 | |
#define SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER 2 | |
#define SNES_DEVICE_ID_SUPER_SCOPE_CURSOR 3 | |
#define SNES_DEVICE_ID_SUPER_SCOPE_TURBO 4 | |
#define SNES_DEVICE_ID_SUPER_SCOPE_PAUSE 5 | |
#define SNES_DEVICE_ID_JUSTIFIER_X 0 | |
#define SNES_DEVICE_ID_JUSTIFIER_Y 1 | |
#define SNES_DEVICE_ID_JUSTIFIER_TRIGGER 2 | |
#define SNES_DEVICE_ID_JUSTIFIER_START 3 | |
// These constants will be returned by snes_get_region(), representing the | |
// region of the last loaded cartridge. | |
#define SNES_REGION_NTSC 0 | |
#define SNES_REGION_PAL 1 | |
// These constants represent the kinds of non-volatile memory a SNES cartridge | |
// might have, for use with the snes_get_memory_* functions. | |
#define SNES_MEMORY_CARTRIDGE_RAM 0 | |
#define SNES_MEMORY_CARTRIDGE_RTC 1 | |
#define SNES_MEMORY_BSX_RAM 2 | |
#define SNES_MEMORY_BSX_PRAM 3 | |
#define SNES_MEMORY_SUFAMI_TURBO_A_RAM 4 | |
#define SNES_MEMORY_SUFAMI_TURBO_B_RAM 5 | |
#define SNES_MEMORY_GAME_BOY_RAM 6 | |
#define SNES_MEMORY_GAME_BOY_RTC 7 | |
// These constants represent the various kinds of volatile storage the SNES | |
// offers, to allow libsnes clients to implement things like cheat-searching | |
// and certain kinds of debugging. They are for use with the snes_get_memory_* | |
// functions. | |
#define SNES_MEMORY_WRAM 100 | |
#define SNES_MEMORY_APURAM 101 | |
#define SNES_MEMORY_VRAM 102 | |
#define SNES_MEMORY_OAM 103 | |
#define SNES_MEMORY_CGRAM 104 | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Callback types {{{ | |
// | |
// In order to deliver controller input to the emulated SNES, and retrieve | |
// video frames and audio samples, you will need to register callbacks. | |
// snes_audio_sample_t: | |
// | |
// This callback delivers a stereo audio sample pair generated by the | |
// emulated SNES. | |
// | |
// This function is called once for every audio frame (one sample from left | |
// and right channels). The SNES generates audio samples at a rate of about | |
// 32040Hz (varies from unit to unit). | |
// | |
// Because the SNES generates video at exactly 59.94fps and most computer | |
// monitors only support a 60fps refresh rate, real-time emulation needs to | |
// run slightly fast so that each computer frame displays one emulated SNES | |
// frame. Because the emulation runs slightly fast, and because most | |
// consumer audio hardware does not play audio at precisely the requested | |
// sample rate, you'll likely need to let the end-user tweak the effective | |
// sample rate by 100Hz or so in either direction. | |
// | |
// Although the parameters are declared as unsigned for historical reasons, | |
// the data they contain is actually signed. To work with the audio (e.g. | |
// resample), you will need to reinterpret the sample value: | |
// | |
// int16_t real_left = *(int16_t*)(&left); | |
// | |
// Parameters: | |
// | |
// left: | |
// A signed 16-bit integer containing the next audio sample from the | |
// left audio channel. Yes, it's declared as unsigned for historical | |
// reasons. | |
// | |
// right: | |
// A signed 16-bit integer containing the next audio sample from the | |
// right audio channel. Yes, it's declared as unsigned for historical | |
// reasons. | |
// | |
typedef void (*snes_audio_sample_t)(uint16_t left, uint16_t right); | |
// snes_video_refresh_t: | |
// | |
// This callback delivers a single SNES frame, generated by the emulated | |
// SNES. The same memory buffer may be re-used later, so take a copy of the | |
// data if you want to refer to it after your callback returns. | |
// | |
// The framebuffer is an array of unsigned 16-bit pixels, in a somewhat | |
// complicated format. A quick refresher on SNES video modes: | |
// - The basic SNES video-mode renders 256 pixels per scanline for a total | |
// of 224 scanlines. | |
// - When "overscan" mode is enabled, the SNES renders a few extra | |
// scanlines at the end of the frame, for a total of 239 scanlines. | |
// - When "hi-res" mode is enabled, the SNES speeds up its pixel rendering | |
// to fit 512 pixels per scanline. | |
// - Normally the SNES renders its pixels to one field of the interlaced | |
// NTSC signal, but if "interlaced" mode is enabled the SNES renders | |
// a second set of scanlines inbetween the regular set, for a total of | |
// 448 (normal) or 478 (overscan) scanlines. | |
// | |
// Thus, the framebuffer memory layout for a standard 256x240 frame looks | |
// something like this (note that 'height' has been reduced to 4 or 8 for | |
// these examples): | |
// | |
// 0 1024b | |
// ,---------------------------------------. | |
// |====== width ======|...................| -. | |
// |.......................................| | | |
// |===================|...................| | | |
// |.......................................| +- height = 4 | |
// |===================|...................| | | |
// |.......................................| | | |
// |===================|...................| | | |
// |.......................................| -' | |
// `---------------------------------------' | |
// | |
// A hi-res frame would look like this: | |
// | |
// 0 1024b | |
// ,---------------------------------------. | |
// |================ width ================| -. | |
// |.......................................| | | |
// |=======================================| | | |
// |.......................................| +- height = 4 | |
// |=======================================| | | |
// |.......................................| | | |
// |=======================================| | | |
// |.......................................| -' | |
// `---------------------------------------' | |
// | |
// An interlaced frame would look like this: | |
// | |
// 0 1024b | |
// ,---------------------------------------. | |
// |====== width ======|...................| -. | |
// |===================|...................| | | |
// |===================|...................| | | |
// |===================|...................| +- height = 8 | |
// |===================|...................| | | |
// |===================|...................| | | |
// |===================|...................| | | |
// |===================|...................| -' | |
// `---------------------------------------' | |
// | |
// And of course a hi-res, interlaced frame would look like this: | |
// | |
// 0 1024b | |
// ,---------------------------------------. | |
// |================ width ================| -. | |
// |=======================================| | | |
// |=======================================| | | |
// |=======================================| |+- height = 8 | |
// |=======================================| | | |
// |=======================================| | | |
// |=======================================| | | |
// |=======================================| -' | |
// `---------------------------------------' | |
// | |
// More succinctly: | |
// - the buffer begins at the top-left of the frame | |
// - the first "width" bytes contain the first scanline. | |
// - if the emulated SNES is in an interlaced video-mode (that is, if the | |
// "height" parameter" is 448 or 478) then the second scanline begins at | |
// an offset of 1024 bytes (512 pixels) after the first. | |
// - otherwise the second scanline begins at an offset of 2048 bytes (1024 | |
// pixels) after the first. | |
// - there are "height" scanlines in total. | |
// | |
// Each pixel contains a 15-bit RGB tuple: 0RRRRRGGGGGBBBBB (XRGB1555) | |
// | |
// Example code: | |
// | |
// void pack_frame (uint16_t * restrict out, const uint16_t * restrict in, | |
// unsigned width, unsigned height) | |
// { | |
// // Normally our pitch is 2048 bytes. | |
// int pitch_pixels = 1024; | |
// // If we have an interlaced mode, pitch is 1024 bytes. | |
// if ( height == 448 || height == 478 ) | |
// pitch_pixels = 512; | |
// | |
// for ( int y = 0; y < height; y++ ) | |
// { | |
// const uint16_t *src = in + y * pitch_pixels; | |
// uint16_t *dst = out + y * width; | |
// | |
// memcpy(dst, src, width * sizeof(uint16_t)); | |
// } | |
// } | |
// | |
// Parameters: | |
// | |
// data: | |
// a pointer to the beginning of the framebuffer described above. | |
// | |
// width: | |
// the width of the frame, in pixels. | |
// | |
// height: | |
// the number of scanlines in the frame. | |
typedef void (*snes_video_refresh_t)(const uint16_t *data, unsigned width, | |
unsigned height); | |
// snes_input_poll_t: | |
// | |
// This callback requests that you poll your input devices for events, if | |
// required. | |
// | |
// Generally called once per frame before the snes_input_state_t callback is | |
// called. | |
// | |
typedef void (*snes_input_poll_t)(void); | |
// snes_input_state_t: | |
// | |
// This callback asks for information about the state of a particular input. | |
// | |
// The callback may be called multiple times per frame with the same | |
// parameters. | |
// | |
// The callback might not be called at all, if the software running in the | |
// emulated SNES does not try to probe the controllers. | |
// | |
// The callback will not be called for a particular port if DEVICE_NONE is | |
// connected to it. | |
// | |
// If you wish to emulate any kind of turbo-fire, etc. then you will need to | |
// put that logic into this callback. | |
// | |
// Parameters: | |
// | |
// port: | |
// One of the constants SNES_PORT_1 or SNES_PORT_2, describing which | |
// controller port you should report. | |
// | |
// device: | |
// One of the SNES_DEVICE_* constants describing which type of device | |
// is currently connected to the given port. | |
// | |
// index: | |
// A number describing which of the devices connected to the port is | |
// being reported. It's only useful for SNES_DEVICE_MULTITAP and | |
// SNES_DEVICE_JUSTIFIERS - for other device types, this parameter is | |
// always 0. | |
// | |
// id: | |
// One of the SNES_DEVICE_ID_* constants for the given device, | |
// describing which button or axis is being reported (for | |
// SNES_DEVICE_MULTITAP, use the SNES_DEVICE_ID_JOYPAD_* IDs; for | |
// SNES_DEVICE_JUSTIFIERS use the SNES_DEVICE_ID_JUSTIFIER_* IDs.). | |
// | |
// Returns: | |
// | |
// An integer representing the state of the described button or axis. | |
// | |
// - If it represents a digital input such as SNES_DEVICE_ID_JOYPAD_B or | |
// SNES_DEVICE_ID_MOUSE_LEFT), return 1 if the button is pressed, and | |
// 0 otherwise. | |
// - If "id" is SNES_DEVICE_ID_MOUSE_X or SNES_DEVICE_ID_MOUSE_Y then | |
// return the relative movement of the mouse during the current frame; | |
// values outside the range -127 to +127 will be clamped. | |
// - If "id" is one of the light-gun axes (such as | |
// SNES_DEVICE_ID_JUSTIFIER_Y or SNES_DEVICE_ID_SUPER_SCOPE_X), you | |
// should return the relative movement of the pointing device during the | |
// current frame. | |
typedef int16_t (*snes_input_state_t)(bool port, unsigned device, | |
unsigned index, unsigned id); | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// libsnes setup {{{ | |
// | |
// These functions are used to get information about and manipulate the libsnes | |
// library itself, not the emulated SNES it implements. | |
// snes_library_revision_major: | |
// | |
// Returns the major API version of this libsnes implementation. | |
// | |
// This number is increased every time there is a compatibility-breaking | |
// change to the libsnes API. At startup, your program should call this | |
// function and compare the return value to the major API version the | |
// program was designed to work with. If they are different, your program | |
// will (very likely) not work with this libsnes implementation. | |
// | |
// For example, if your program was designed to work with the libsnes API | |
// whose major.minor revision was 1.5, and this function returns a major | |
// version of 2, you have a problem. | |
// | |
// Returns: | |
// | |
// An integer, the major API version of this libsnes implementation. | |
unsigned snes_library_revision_major(void); | |
// snes_library_revision_minor: | |
// | |
// Returns the minor API version of this libsnes implementation. | |
// | |
// This number is increased every time there is a backwards-compatible | |
// change to the libsnes API. At startup, your program should call this | |
// function and compare the return value to the minor API version the | |
// program was designed to work with. If the return value is less than the | |
// expected minor version, your program will (very likely) not work with | |
// this libsnes implementation. | |
// | |
// For example, if your program was designed to work with the libsnes API | |
// whose major.minor revision was 1.5, and this libsnes implementation's | |
// major.minor version is 1.3, it's probably missing features you require. | |
// On the other hand, if this libsnes implementation's major.minor version | |
// is 1.9, it probably has extra fancy features you don't need to worry | |
// about. | |
// | |
// Returns: | |
// | |
// An integer, the minor API version of this libsnes implementation. | |
unsigned snes_library_revision_minor(void); | |
// snes_init: | |
// | |
// Initializes the libsnes implementation. | |
// | |
// This function must be called exactly once before any other library | |
// functions are called. | |
void snes_init(void); | |
// snes_term: | |
// | |
// Shuts down the libsnes implementation. | |
// | |
// This function must be called exactly once. Once called, you should not | |
// call any other libsnes functions besides (perhaps) snes_init(). | |
void snes_term(void); | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Callback registration {{{ | |
// | |
// Note that all callbacks should be set up before snes_run() is called for the | |
// first time. | |
// snes_set_video_refresh: | |
// | |
// Sets the callback that will receive new video frames. | |
// | |
// See the documentation for snes_video_refresh_t for details. | |
// | |
// Parameters: | |
// | |
// A pointer to a function matching the snes_video_refresh_t call | |
// signature. | |
void snes_set_video_refresh(snes_video_refresh_t); | |
// snes_set_audio_sample | |
// | |
// Sets the callback that will receive new audio sample pairs. | |
// | |
// See the documentation for snes_audio_sample_t for details. | |
// | |
// Parameters: | |
// | |
// A pointer to a function matching the snes_audio_sample_t call | |
// signature. | |
void snes_set_audio_sample(snes_audio_sample_t); | |
// snes_set_input_poll: | |
// | |
// Sets the callback that will be notified to poll input devices. | |
// | |
// See the documentation for snes_input_poll_t for details. | |
// | |
// Parameters: | |
// | |
// A pointer to a function matching the snes_input_poll_t call signature. | |
void snes_set_input_poll(snes_input_poll_t); | |
// snes_set_input_state: | |
// | |
// Sets the callback that will be used to read input device state. | |
// | |
// See the documentation for snes_input_state_t for details. | |
// | |
// Parameters: | |
// | |
// A pointer to a function matching the snes_input_state_t call signature. | |
void snes_set_input_state(snes_input_state_t); | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// SNES operation {{{ | |
// | |
// Functions for manipulating the emulated SNES. | |
// snes_set_controller_port_device: | |
// | |
// Sets the input device connected to a given controller port. | |
// | |
// Connecting a device to a port implicitly removes any device previously | |
// connected to that port. To remove a device without connecting a new one, | |
// pass DEVICE_NONE as the device parameter. From this point onward, the | |
// callback passed to set_input_state_cb() will be called with the | |
// appropriate device, index and id parameters. | |
// | |
// If this function is never called, the default is to have a DEVICE_JOYPAD | |
// connected to both ports. | |
// | |
// Calling this callback from inside the set_input_state_cb() has undefined | |
// results, so don't do that. | |
// | |
// Parameters: | |
// | |
// port: | |
// One of the constants SNES_PORT_1 or SNES_PORT_2, describing which | |
// controller port is being configured. | |
// | |
// device: | |
// One of the SNES_DEVICE_* constants describing which type of device | |
// should be connected to the given port. Note that some devices can | |
// only be connected to SNES_PORT_2. Attempting to connect | |
// a port-2-only device to SNES_PORT_1 has undefined results. | |
// | |
// These devices work in either port: | |
// - SNES_DEVICE_NONE: No device is connected to this port. | |
// - SNES_DEVICE_JOYPAD: A standard SNES gamepad. | |
// - SNES_DEVICE_MULTITAP: A multitap controller, which acts like | |
// 4 SNES_DEVICE_JOYPADs. Your input state callback will be | |
// passed "id" parameters between 0 and 3, inclusive. | |
// - SNES_DEVICE_MOUSE: A SNES mouse controller, as shipped with | |
// Mario Paint. | |
// | |
// These devices only work properly when connected to port 2: | |
// - SNES_DEVICE_SUPER_SCOPE: A Nintendo Super Scope light-gun | |
// device. | |
// - SNES_DEVICE_JUSTIFIER: A Konami Justifier light-gun device. | |
// - SNES_DEVICE_JUSTIFIERS: Two Konami Justifier light-gun | |
// devices, daisy-chained together. Your input state callback | |
// will be passed "id" parameters 0 and 1. | |
void snes_set_controller_port_device(bool port, unsigned device); | |
// snes_power: | |
// | |
// Turns the emulated console off and back on. | |
// | |
// This functionality is sometimes called "hard reset" and guarantees that | |
// all hardware state is reset to a reasonable default. | |
// | |
// Before bsnes v070r07, this resets the controller ports to both contain | |
// SNES_DEVICE_JOYPADs. | |
// | |
// This requires that a cartridge is loaded. | |
void snes_power(void); | |
// snes_reset: | |
// | |
// Presses the "reset" button on the emulated SNES. | |
// | |
// This functionality is sometimes called "soft reset". Most hardware state | |
// is reset to a reasonable befault, but not all. | |
// | |
// As of bsnes v073r01, this function (as a side-effect) resets the | |
// controller ports to both contain SNES_DEVICE_JOYPADs. | |
// | |
// This requires that a cartridge is loaded. | |
void snes_reset(void); | |
// snes_run(): | |
// | |
// Runs the emulated SNES until the end of the next video frame. | |
// | |
// Usually causes each registered callback to be called before returning. | |
// | |
// This function will run as fast as possible. It is up to the caller to | |
// make sure that the game runs at the intended speed. | |
// | |
// For optimal A/V sync, make sure that the audio callback never blocks for | |
// longer than a frame (approx 16ms for NTSC, 20ms for PAL) | |
// | |
// Optimally, it should never block for more than a few ms at a time. | |
void snes_run(void); | |
// snes_get_region(): | |
// | |
// Determines the intended frame-rate of the loaded cartridge. | |
// | |
// The two main SNES hardware variants are the US/Japan variant, designed | |
// for NTSC output, and the European variant, designed for PAL output. | |
// However, the world is not quite so tidy as that, and there are countries | |
// like Brazil that use PAL output at NTSC frame-rates. | |
// | |
// For historical reasons this function is named snes_get_region(), but | |
// effectively the only information you can reliably infer is the | |
// frame-rate. | |
// | |
// Returns: | |
// | |
// One of the SNES_REGION_* constants. SNES_REGION_PAL means 50fps, | |
// SNES_REGION_NTSC means 60fps. | |
bool snes_get_region(void); | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Save state support {{{ | |
// | |
// libsnes has the ability to save the current emulation state and restore it | |
// at a later time. | |
// | |
// Note 1: It is impossible to reliably restore the *exact* state, although the | |
// difference is only a few cycles. If you demand the ability to reliably | |
// restore state, call snes_serialize() after each frame to ensure the emulated | |
// SNES is in a state that can be reliably restored. | |
// | |
// Note 2: The save state information is specific to a particular cartridge | |
// loaded into a particular version of a particular libsnes implementation. | |
// Unfortunately, there is not yet a way to determine whether a given save | |
// state is compatible with a given libsnes implementation, other than by | |
// loading it. However, if snes_serialize_size() does not match the size of an | |
// old save state, that's a strong hint that something has incompatibly | |
// changed. | |
// snes_serialize_size: | |
// | |
// Determines the minimum size of a save state. | |
// | |
// This value can change depending on the features used by the loaded | |
// cartridge, and the version of the libsnes implementation used. | |
// | |
// Returns: | |
// | |
// An integer representing the number of bytes required to store the | |
// current emulation state. | |
unsigned snes_serialize_size(void); | |
// snes_serialize: | |
// | |
// Serialize the current emulation state to a buffer. | |
// | |
// If the allocated buffer is smaller than the size returned by | |
// snes_serialize_size(), serialization will fail. If the allocated buffer | |
// is larger, only the first snes_serialize_size() bytes will be written to. | |
// | |
// The resulting buffer may be stored, and later passed to | |
// snes_unserialize() to restore the saved emulation state. | |
// | |
// Parameters: | |
// | |
// data: | |
// A pointer to an allocated buffer of memory. | |
// | |
// size: | |
// The size of the buffer pointed to by "data". Should be greater than | |
// or equal to the value returned by snes_serialize_size(). | |
// | |
// Returns: | |
// | |
// A boolean; True means the emulation state was serialized successfully, | |
// False means a problem was encountered. | |
bool snes_serialize(uint8_t *data, unsigned size); | |
// snes_unserialize: | |
// | |
// Unserialize the emulation state from a buffer. | |
// | |
// If the serialization data in the buffer does not appear to be compatible | |
// with the current libsnes implementation, the function returns False and | |
// the current emulation state is not modified. | |
// | |
// Parameters: | |
// | |
// data: | |
// A pointer to an allocated buffer of memory. | |
// | |
// size: | |
// The size of the buffer pointed to by "data". Should be greater than | |
// or equal to the value returned by snes_serialize_size(). | |
// | |
// Returns: | |
// | |
// A boolean; True means the emulation state was loaded successfully, | |
// False means a problem was encountered. | |
bool snes_unserialize(const uint8_t *data, unsigned size); | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Cheat support {{{ | |
// | |
// libsnes does not include any kind of cheat management API; the intention is | |
// that any change to the set of applied cheats will cause the containing | |
// application to call snes_cheat_reset() then apply the new set of cheats with | |
// snes_cheat_set(). | |
// | |
// Any currently-applied cheats are discarded when a new cartridge is loaded. | |
// snes_cheat_reset: | |
// | |
// Discards all cheat codes applied to the emulated SNES. | |
void snes_cheat_reset(void); | |
// snes_cheat_set: | |
// | |
// Apply a sequence of cheat codes to the emulated SNES. | |
// | |
// Since a "cheat code" is basically an instruction to override the value of | |
// a particular byte in the SNES' memory, more complex cheats may require | |
// several individual codes applied at once. There's no effective difference | |
// between applying these codes in a group with one call to | |
// snes_cheat_set(), or applying them one at a time with individual calls. | |
// However, most cheat databases will have a collection of available cheats | |
// for each game, where each item in the collection has a description and | |
// a sequence of codes to be applied as a unit. This API makes it easy to | |
// present the list of descriptions to the user, and apply each cheat the | |
// user selects. | |
// | |
// Parameters: | |
// | |
// index: | |
// The given cheat code will be stored at this index in the array of | |
// applied cheats. If a cheat already exists at this location, it will | |
// be replaced by the new cheat. If the index is larger than any | |
// previously specififed index, the array will be resized to | |
// accommodate. | |
// | |
// enabled: | |
// True means that the cheat will actually be applied, False means | |
// that the cheat will have no effect. There is no way to enable or | |
// disable a cheat after it has been added, other than to call | |
// snes_cheat_set() a second time with the same values for "index" and | |
// "code". | |
// | |
// code: | |
// A string containing a sequence of cheat codes separated by '+' | |
// characters. Any spaces in the string will be removed before | |
// parsing. | |
// | |
// Each code in the sequence must be in either GameGenie format | |
// ("1234-ABCD") or ProActionReplay format ("1234AB:CD" or | |
// "1234ABCD"). | |
void snes_cheat_set(unsigned index, bool enabled, const char *code); | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Cartridge loading and unloading {{{ | |
// | |
// Before calling snes_run(), a cartridge must be loaded into the emulated SNES | |
// so that it has code to run. | |
// | |
// Loading a cartridge of any kind calls snes_cheat_reset() as a side-effect. | |
// snes_load_cartridge_normal: | |
// | |
// Load a normal ROM image into the emulated SNES. | |
// | |
// Parameters: | |
// | |
// rom_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes where the ROM image is mapped into the SNES address | |
// space, what special chips it uses (and where they're mapped), etc. | |
// | |
// If NULL, libsnes will guess a memory map. The guessed memory map | |
// should be correct for all licenced games in all regions. | |
// | |
// rom_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless ROM image. | |
// | |
// rom_size: | |
// The length of the rom_data array, in bytes. | |
// | |
// Returns: | |
// | |
// A boolean; True means the cartridge was loaded correctly, False means | |
// an error occurred. | |
bool snes_load_cartridge_normal( | |
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size | |
); | |
// snes_load_cartridge_bsx: | |
// | |
// Load a BS-X base cart image, optionally with a memory pack. | |
// | |
// The Satellaview system, abbreviated "BS-X" for unclear reasons, was an | |
// addon for the Super Famicom that connected it to the St. GIGA satellite | |
// network. The network would broadcast games at a particular time, and | |
// users could download them to replaceable memory packs. | |
// | |
// For more information, see http://en.wikipedia.org/wiki/Satellaview | |
// | |
// Parameters: | |
// | |
// rom_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes where the BS-X base cartridge ROM image is mapped | |
// into the SNES address space. | |
// | |
// If NULL, libsnes will guess a memory map. The guessed memory map | |
// should be correct for all known BS-X base cartridge images. | |
// | |
// rom_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless ROM image of the BS-X base cartridge. | |
// | |
// The BS-X base cartridge is named "BS-X - Sore wa Namae o Nusumareta | |
// Machi no Monogatari" in some SNES game databases. | |
// | |
// rom_size: | |
// The length of the rom_data array, in bytes. | |
// | |
// bsx_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes the BS-X memory pack. | |
// | |
// This parameter is currently ignored and should be passed as NULL. | |
// | |
// bsx_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless image of the BS-X memory-pack. | |
// | |
// If NULL, libsnes will behave as though no memory-pack were inserted | |
// into the base cartridge. | |
// | |
// bsx_size: | |
// The length of the bsx_data array, in bytes. | |
// | |
// Returns: | |
// | |
// A boolean; True means the cartridge was loaded correctly, False means | |
// an error occurred. | |
bool snes_load_cartridge_bsx( | |
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, | |
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size | |
); | |
// snes_load_cartridge_bsx_slotted: | |
// | |
// Load a BS-X slotted cartridge, optionally with a memory pack. | |
// | |
// A BS-X slotted cartridge is an ordinary SNES cartridge, with a slot in | |
// the top that accepts the same memory packs used by the BS-X base | |
// cartridge. | |
// | |
// Parameters: | |
// | |
// rom_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes where the ROM image is mapped into the SNES address | |
// space, what special chips it uses (and where they're mapped), etc. | |
// | |
// If NULL, libsnes will guess a memory map. The guessed memory map | |
// should be correct for all licenced games in all regions. | |
// | |
// rom_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless ROM image. | |
// | |
// rom_size: | |
// The length of the rom_data array, in bytes. | |
// | |
// bsx_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes the BS-X memory pack. | |
// | |
// This parameter is currently ignored and should be passed as NULL. | |
// | |
// bsx_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless image of the BS-X memory-pack. | |
// | |
// If NULL, libsnes will behave as though no memory-pack were inserted | |
// into the base cartridge. | |
// | |
// bsx_size: | |
// The length of the bsx_data array, in bytes. | |
// | |
// Returns: | |
// | |
// A boolean; True means the cartridge was loaded correctly, False means | |
// an error occurred. | |
bool snes_load_cartridge_bsx_slotted( | |
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, | |
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size | |
); | |
// snes_load_cartridge_sufami_turbo: | |
// | |
// Load a SuFami Turbo base cart image, optionally with game packs. | |
// | |
// The SuFami Turbo was a cartridge available for the Super Famicom, created | |
// by Bandai, with two slots in the top designed to accept special | |
// mini-cartridges. The cartridge in Slot A was the cartridge that actually | |
// ran, while the cartridge in Slot B was made available to the Slot | |
// A cartridge, enabling sharing of save-game data or using characters from | |
// one game in another. | |
// | |
// For more information, see: http://en.wikipedia.org/wiki/Sufami_Turbo | |
// | |
// Parameters: | |
// | |
// rom_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes where the SuFami Turbo base cartridge ROM image is | |
// mapped into the SNES address space. | |
// | |
// If NULL, libsnes will guess a memory map. The guessed memory map | |
// should be correct for all known SuFami Turbo base cartridge images. | |
// | |
// rom_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless ROM image of the SuFami Turbo base | |
// cartridge. | |
// | |
// The SuFami Turbo base cartridge is named "Sufami Turbo" in some | |
// SNES game databases. | |
// | |
// rom_size: | |
// The length of the rom_data array, in bytes. | |
// | |
// sta_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes the Sufami Turbo cartridge in Slot A. | |
// | |
// This parameter is currently ignored and should be passed as NULL. | |
// | |
// sta_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless ROM image of the SuFami Turbo cartridge | |
// in Slot A. | |
// | |
// This is the cartridge that will be executed by the SNES. | |
// | |
// If NULL, libsnes will behave as though no cartridge were inserted | |
// into the Slot A. | |
// | |
// sta_size: | |
// The length of the sta_data array, in bytes. | |
// | |
// stb_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes the Sufami Turbo cartridge in Slot B. | |
// | |
// This parameter is currently ignored and should be passed as NULL. | |
// | |
// stb_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless ROM image of the SuFami Turbo cartridge | |
// in Slot B. | |
// | |
// The data in this cartridge will be made available to the cartridge | |
// in Slot A. | |
// | |
// If NULL, libsnes will behave as though no cartridge were inserted | |
// into Slot B. | |
// | |
// stb_size: | |
// The length of the stb_data array, in bytes. | |
// | |
// Returns: | |
// | |
// A boolean; True means the cartridge was loaded correctly, False means | |
// an error occurred. | |
bool snes_load_cartridge_sufami_turbo( | |
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, | |
const char *sta_xml, const uint8_t *sta_data, unsigned sta_size, | |
const char *stb_xml, const uint8_t *stb_data, unsigned stb_size | |
); | |
// snes_load_cartridge_super_game_boy: | |
// | |
// Load a Super Game Boy base cart, optionally with a Gameboy cartridge. | |
// | |
// The Super Game Boy was a cartridge available for the Super Famicom and | |
// Super Nintendo that accepted ordinary (original) Gameboy cartridges and | |
// allowed the user to play them with a Super Nintendo controller, on a TV. | |
// It extended the orginal Gameboy hardware in a few ways, including the | |
// ability to display games in various palettes (rather than strictly | |
// monochrome), to display a full-colour border image around the Gameboy | |
// video output, or even run native SNES code to enhance the game. | |
// | |
// For more information, see: http://en.wikipedia.org/wiki/Super_Game_Boy | |
// | |
// Up until bsnes v073, loading Super Game Boy cartridges only works if the | |
// libsupergameboy library from the bsnes release is installed. bsnes v074 | |
// includes a custom Gameboy emulation core, and external code is no longer | |
// required. | |
// | |
// Parameters: | |
// | |
// rom_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes where the Super Game Boy base cartridge ROM image is | |
// mapped into the SNES address space. | |
// | |
// If NULL, libsnes will guess a memory map. The guessed memory map | |
// should be correct for all known Super Game Boy base cartridge | |
// images. | |
// | |
// rom_data: | |
// A pointer to a byte array containing the uncompressed, | |
// de-interleaved, headerless ROM image of the Super Game Boy base | |
// cartridge. | |
// | |
// Appropriate base cartridge images are named "Super Game Boy" or | |
// "Super Game Boy 2" in some SNES game databases. | |
// | |
// rom_size: | |
// The length of the rom_data array, in bytes. | |
// | |
// dmg_xml: | |
// A pointer to a null-terminated string containing an XML memory map | |
// that describes the inserted Gameboy cartridge. | |
// | |
// If NULL, libsnes will guess a memory map. The guesed memory map | |
// should be correct for all licensed original Gameboy games in all | |
// regions. | |
// | |
// dmg_data: | |
// A pointer to a byte array containing the uncompressed, headerless | |
// ROM image of the inserted Gameboy cartridge. | |
// | |
// If NULL, libsnes will behave as though no cartridge were inserted. | |
// | |
// dmg_size: | |
// The length of the dmg_size array, in bytes. | |
// | |
// Returns: | |
// | |
// A boolean; True means the cartridge was loaded correctly, False means | |
// an error occurred. | |
bool snes_load_cartridge_super_game_boy( | |
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, | |
const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size | |
); | |
// snes_set_cartridge_basename: | |
// | |
// Set the location and name of the loaded cartridge. | |
// | |
// libsnes uses this information to locate additional resources the | |
// cartridge might require. Currently, these resources include: | |
// | |
// - The MSU-1 data pack and associated audio tracks, if the cartridge makes | |
// use of bsnes' MSU-1 special-chip. | |
// - The serial-port data receiving library, if the cartridge makes uses of | |
// bsnes' serial-data-over-controller-port feature. | |
// | |
// Parameters: | |
// | |
// basename: | |
// The path and basename of the loaded cartridge. For example, if the | |
// full path to the loaded cartridge is "/path/to/filename.sfc", this | |
// parameter should be set to "/path/to/filename". | |
void snes_set_cartridge_basename(const char *basename); | |
// snes_unload_cartridge: | |
// | |
// Unloads the currently loaded cartridge from the emulated SNES. | |
// | |
// You will be unable to call snes_run() until another cartridge is loaded. | |
void snes_unload_cartridge(void); | |
////////////////////////////////////////////////////////////////////////////}}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Volatile and non-volatile storage {{{ | |
// | |
// Certain SNES cartridges include non-volatile storage or other kinds of data | |
// that would persist after the SNES is turned off. libsnes exposes this | |
// information via the snes_get_memory_data() and snes_get_memory_size() | |
// functions. Since version 1.2 of the libsnes API, libsnes also exposes the | |
// contents of volatile storage such as WRAM and VRAM. | |
// | |
// After a cartridge is loaded, call snes_get_memory_size() and | |
// snes_get_memory_data() with the various SNES_MEMORY_* constants to determine | |
// which kinds of non-volatile storage the cartridge supports - unsupported | |
// storage types will have a size of 0 and the data pointer NULL. | |
// | |
// If you have non-volatile storage data from a previous run, you can memcpy() | |
// the data from your storage into the buffer described by the data and size | |
// values before calling snes_run(). Do not load non-volatile storage data if | |
// the size of the data you have is different from the size returned by | |
// snes_get_memory_size(). | |
// | |
// Before calling snes_unload_cartridge(), you should copy the contents of the | |
// relevant storage buffers into a file (or some non-volatile storage of your | |
// own) so that you can load it the next time you load the same cartridge into | |
// the emulated SNES. Do not call free() on the storage buffers; they will be | |
// handled by libsnes. Note: It is not necessary to store the contents of | |
// volatile storage; the emulated SNES expects information in volatile storage | |
// to be lost (hence the name 'volatile'). | |
// | |
// Because non-volatile storage is read and written by the software running on | |
// the emulated SNES, it should be compatible between different versions of | |
// different emulators running on different platforms, unlike save states. | |
// | |
// The various kinds of non-volatile storage and their uses are: | |
// | |
// SNES_MEMORY_CARTRIDGE_RAM: | |
// Standard battery-backed static RAM (SRAM). Traditionally, the SRAM for | |
// a ROM image named "foo.sfc" is stored in a file named "foo.srm" beside | |
// it. | |
// | |
// SNES_MEMORY_CARTRIDGE_RTC: | |
// Real-time clock data. Traditionally, the RTC data for a ROM image named | |
// "foo.sfc" is stored in a file named "foo.rtc" beside it. | |
// | |
// SNES_MEMORY_BSX_RAM: | |
// RAM data used with the BS-X base cartridge. | |
// | |
// SNES_MEMORY_BSX_PRAM: | |
// PRAM data used with the BS-X base cartridge. | |
// | |
// SNES_MEMORY_SUFAMI_TURBO_A_RAM: | |
// RAM data stored in the mini-cartridge inserted into Slot A of the | |
// SuFami Turbo base cartridge. | |
// | |
// SNES_MEMORY_SUFAMI_TURBO_B_RAM: | |
// RAM data stored in the mini-cartridge inserted into Slot B of the | |
// SuFami Turbo base cartridge. | |
// | |
// SNES_MEMORY_GAME_BOY_RAM: | |
// Standard battery-backed static RAM (SRAM) in the Gameboy cartridge | |
// inserted into the Super Game Boy base cartridge. Not all Gameboy games | |
// have SRAM. | |
// | |
// SNES_MEMORY_GAME_BOY_RTC: | |
// Real-time clock data in the Gameboy cartridge inserted into the Super | |
// Game Boy base cartridge. Not all Gameboy games have an RTC. | |
// | |
// The various kinds of volatile storage are: | |
// | |
// SNES_MEMORY_WRAM: | |
// Working RAM, accessible by the CPU. SNES software tends to keep runtime | |
// information in here; games' life-bars and inventory contents and so | |
// forth are in here somewhere. | |
// | |
// SNES_MEMORY_APURAM: | |
// RAM accessible by the Audio Processing Unit. Contains audio samples, | |
// music data and the code responsible for feeding the right notes to the | |
// DSP at the right times. | |
// | |
// SNES_MEMORY_VRAM: | |
// Video RAM. Stores almost everything related to video output, including | |
// the patterns used for each tile and sprite, tilemaps for each | |
// background. The exact format used depends on the current video mode of | |
// the emulated SNES. | |
// | |
// SNES_MEMORY_OAM: | |
// Object Attribute Memory. Stores the location, orientation and priority | |
// of all the sprites the SNES displays. | |
// | |
// SNES_MEMORY_CGRAM: | |
// Color Generator RAM. Contains the colour palettes used by tiles and | |
// sprites. Each palette entry is stored in a 16-bit int, in the standard | |
// XBGR1555 format. | |
// snes_get_memory_data: | |
// | |
// Returns a pointer to the given non-volatile storage buffer. | |
// | |
// This requires that a cartridge is loaded. | |
// | |
// Parameters: | |
// | |
// id: | |
// One of the SNES_MEMORY_* constants. | |
// | |
// Returns: | |
// | |
// A pointer to the memory buffer used for storing the given type of data. | |
// The size of the buffer can be obtained from snes_get_memory_size(). | |
// | |
// If NULL, the loaded cartridge does not store the given type of data. | |
uint8_t* snes_get_memory_data(unsigned id); | |
// snes_get_memory_size: | |
// | |
// Returns the size of the given non-volatile storage buffer. | |
// | |
// This requires that a cartridge is loaded. | |
// | |
// Parameters: | |
// | |
// id: | |
// One of the SNES_MEMORY_* constants. | |
// | |
// Returns: | |
// | |
// The size of the memory buffer used for storing the given type of data. | |
// A pointer to the buffer can be obtained from snes_get_memory_data(). | |
// | |
// If 0, the loaded cartridge does not store the given type of data. | |
unsigned snes_get_memory_size(unsigned id); | |
////////////////////////////////////////////////////////////////////////////}}} | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment