C interface
This commit is contained in:
parent
76c9599369
commit
1d72c3c4f8
17 changed files with 2107 additions and 56 deletions
|
@ -92,7 +92,7 @@ struct loaded_rom
|
|||
* returns: The saved state.
|
||||
* throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
std::vector<char> save_core_state(bool nochecksum = false) throw(std::bad_alloc);
|
||||
std::vector<char> save_core_state(bool nochecksum = false) throw(std::bad_alloc, std::runtime_error);
|
||||
|
||||
/**
|
||||
* Loads core state from buffer.
|
||||
|
|
822
include/interface/c-interface.h
Normal file
822
include/interface/c-interface.h
Normal file
|
@ -0,0 +1,822 @@
|
|||
#ifndef _interface__c_interface__h__included__
|
||||
#define _interface__c_interface__h__included__
|
||||
|
||||
/*
|
||||
|
||||
Copyright (c) 2013 Ilari Liusvaara
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Some general information about the interface:
|
||||
* - The parameter type for LSNES_CORE_FOO is struct lsnes_core_foo*
|
||||
* - There are also some other enumerations/structures.
|
||||
* - The only exposed entry point (lsnes_core_entrypoint) has fp type of lsnes_core_func_t.
|
||||
* - By nature, this interface does not reference any symbols (exception is lsnes_register_builtin_core).
|
||||
* - Some fields may be conditional on API version.
|
||||
* - The following functions are required:
|
||||
* * LSNES_CORE_ENUMERATE_CORES
|
||||
* * LSNES_CORE_GET_CORE_INFO
|
||||
* * LSNES_CORE_GET_TYPE_INFO
|
||||
* * LSNES_CORE_GET_REGION_INFO
|
||||
* * LSNES_CORE_GET_SYSREGION_INFO
|
||||
* * LSNES_CORE_GET_AV_STATE
|
||||
* * LSNES_CORE_EMULATE
|
||||
* * LSNES_CORE_SAVESTATE
|
||||
* * LSNES_CORE_LOADSTATE
|
||||
* * LSNES_CORE_GET_CONTROLLERCONFIG
|
||||
* * LSNES_CORE_LOAD_ROM
|
||||
* - Scratch buffers from emulator side last for duration of the call.
|
||||
* - Scratch buffers form core side last until next call.
|
||||
* - Never free buffer from emulator in core or vice versa.
|
||||
* - The spaces for Core, Type, Region and Sysregion IDs are distinct.
|
||||
* - If you only have one region, use ID of 0 for that and GET_REGION/SET_REGION are not needed.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//API version.
|
||||
#define LSNES_CORE_API 0
|
||||
|
||||
/** Constants. **/
|
||||
//VMA is read-only.
|
||||
#define LSNES_CORE_VMA_READONLY 1
|
||||
//VMA has special semantics (no read/write consistency).
|
||||
#define LSNES_CORE_VMA_SPECIAL 2
|
||||
//VMA is volatile (and uninitialized on poweron).
|
||||
#define LSNES_CORE_VMA_VOLATILE 4
|
||||
|
||||
/** Capabilities. **/
|
||||
//Core supports multiple regions (By supporting LSNES_CORE_GET_REGION/LSNES_CORE_SET_REGION).
|
||||
#define LSNES_CORE_CAP1_MULTIREGION 0x00000001U
|
||||
//Core supports poll flags (By supporting LSNES_CORE_GET_PFLAG/LSNES_CORE_SET_PFLAG).
|
||||
#define LSNES_CORE_CAP1_PFLAG 0x00000002U
|
||||
//Core supports actions (By supporting LSNES_CORE_GET_ACTION_FLAGS/LSNES_CORE_EXECUTE_ACTION).
|
||||
#define LSNES_CORE_CAP1_ACTION 0x00000004U
|
||||
//Core supports bus map (By supporting LSNES_CORE_GET_BUS_MAPPING).
|
||||
#define LSNES_CORE_CAP1_BUSMAP 0x00000008U
|
||||
//Core supports SRAM (By supporting LSNES_CORE_ENUMERATE_SRAM/LSNES_CORE_LOAD_SRAM/LSNES_CORE_SAVE_SRAM).
|
||||
#define LSNES_CORE_CAP1_SRAM 0x00000010U
|
||||
//Core supports resets (By supporting LSNES_CORE_GET_RESET_ACTION). LSNES_CORE_CAP1_ACTION is required.
|
||||
#define LSNES_CORE_CAP1_RESET 0x00000020U
|
||||
//Core supports custom scale computation (By supporting LSNES_CORE_COMPUTE_SCALE).
|
||||
#define LSNES_CORE_CAP1_SCALE 0x00000040U
|
||||
//Core supports explicit save points (By supporting LSNES_CORE_RUNTOSAVE).
|
||||
#define LSNES_CORE_CAP1_RUNTOSAVE 0x00000080U
|
||||
//Core supports powerons (By supporting LSNES_CORE_POWERON).
|
||||
#define LSNES_CORE_CAP1_POWERON 0x00000100U
|
||||
//Core supports cartridge unload (By supporting LSNES_CORE_UNLOAD_CARTRIDGE).
|
||||
#define LSNES_CORE_CAP1_UNLOAD 0x00000200U
|
||||
//Core supports debugging (By supporting LSNES_CORE_DEBUG_RESET and LSNES_CORE_SET_DEBUG_FLAGS[breakpoints]).
|
||||
//LSNES_CORE_CAP1_MEMWATCH is required.
|
||||
#define LSNES_CORE_CAP1_DEBUG 0x00000400U
|
||||
//Core supports tracing (By supporting LSNES_CORE_DEBUG_RESET and LSNES_CORE_SET_DEBUG_FLAGS[tracing]).
|
||||
//LSNES_CORE_CAP1_MEMWATCH is required.
|
||||
#define LSNES_CORE_CAP1_TRACE 0x00000800U
|
||||
//Core supports cheating (By supporting LSNES_CORE_DEBUG_RESET and LSNES_CORE_SET_CHEAT).
|
||||
//LSNES_CORE_CAP1_MEMWATCH is required.
|
||||
#define LSNES_CORE_CAP1_CHEAT 0x00001000U
|
||||
//Core supports cover pages (By supporting LSNES_CORE_DRAW_COVER).
|
||||
#define LSNES_CORE_CAP1_COVER 0x00002000U
|
||||
//Core supports pre-emulate (By supporting LSNES_CORE_PRE_EMULATE).
|
||||
#define LSNES_CORE_CAP1_PREEMULATE 0x00004000U
|
||||
//Core supports registers (By supporting LSNES_CORE_GET_DEVICE_REGS).
|
||||
#define LSNES_CORE_CAP1_REGISTERS 0x00008000U
|
||||
//Core supports memory watch (By supporting LSNES_CORE_GET_VMA_LIST).
|
||||
#define LSNES_CORE_CAP1_MEMWATCH 0x00010000U
|
||||
//Core supports lightguns (By setting lightgun_height/lightgun_width in LSNES_CORE_GET_AV_STATE).
|
||||
#define LSNES_CORE_CAP1_LIGHTGUN 0x00020000U
|
||||
//Reserved capabilities.
|
||||
#define LSNES_CORE_CAP1_RESERVED18 0x00040000U
|
||||
#define LSNES_CORE_CAP1_RESERVED19 0x00080000U
|
||||
#define LSNES_CORE_CAP1_RESERVED20 0x00100000U
|
||||
#define LSNES_CORE_CAP1_RESERVED21 0x00200000U
|
||||
#define LSNES_CORE_CAP1_RESERVED22 0x00400000U
|
||||
#define LSNES_CORE_CAP1_RESERVED23 0x00800000U
|
||||
#define LSNES_CORE_CAP1_RESERVED24 0x01000000U
|
||||
#define LSNES_CORE_CAP1_RESERVED25 0x02000000U
|
||||
#define LSNES_CORE_CAP1_RESERVED26 0x04000000U
|
||||
#define LSNES_CORE_CAP1_RESERVED27 0x08000000U
|
||||
#define LSNES_CORE_CAP1_RESERVED28 0x10000000U
|
||||
#define LSNES_CORE_CAP1_RESERVED29 0x20000000U
|
||||
#define LSNES_CORE_CAP1_RESERVED30 0x40000000U
|
||||
#define LSNES_CORE_CAP1_CAPS2 0x80000000U
|
||||
|
||||
#define LSNES_END_OF_LIST 0xFFFFFFFFU
|
||||
|
||||
//Do action <action> on item <item> with parameters <params>.
|
||||
//If successful, return 0.
|
||||
//If supported but unsuccessful, return -1 and fill <error> (will not be released, only needs to be stable to next
|
||||
//call).
|
||||
//In dynamic libs, this is looked up as lsnes_core_fn.
|
||||
typedef int(*lsnes_core_func_t)(unsigned action, unsigned item, void* params, const char** error);
|
||||
|
||||
//Pixel format.
|
||||
enum lsnes_core_pixel_format
|
||||
{
|
||||
LSNES_CORE_PIXFMT_RGB15,
|
||||
LSNES_CORE_PIXFMT_BGR15,
|
||||
LSNES_CORE_PIXFMT_RGB16,
|
||||
LSNES_CORE_PIXFMT_BGR16,
|
||||
LSNES_CORE_PIXFMT_RGB24,
|
||||
LSNES_CORE_PIXFMT_BGR24,
|
||||
LSNES_CORE_PIXFMT_RGB32,
|
||||
LSNES_CORE_PIXFMT_LRGB
|
||||
};
|
||||
|
||||
//Framebuffer.
|
||||
struct lsnes_core_framebuffer_info
|
||||
{
|
||||
//Pixel format of framebuffer.
|
||||
enum lsnes_core_pixel_format type;
|
||||
//The physical memory backing the framebuffer.
|
||||
const char* mem;
|
||||
//Physical width of framebuffer.
|
||||
size_t physwidth;
|
||||
//Physical height of framebuffer.
|
||||
size_t physheight;
|
||||
//Physical stride of framebuffer (in bytes).
|
||||
size_t physstride;
|
||||
//Visible width of framebuffer.
|
||||
size_t width;
|
||||
//Visible height of framebuffer.
|
||||
size_t height;
|
||||
//Visible stride of framebuffer (in bytes).
|
||||
size_t stride;
|
||||
//Visible X offset of framebuffer.
|
||||
size_t offset_x;
|
||||
//Visible Y offset of framebuffer.
|
||||
size_t offset_y;
|
||||
};
|
||||
|
||||
struct lsnes_core_sram
|
||||
{
|
||||
//Name.
|
||||
const char* name;
|
||||
//Content size.
|
||||
size_t size;
|
||||
//Data.
|
||||
const char* data;
|
||||
};
|
||||
|
||||
struct lsnes_core_system_setting
|
||||
{
|
||||
//Name.
|
||||
const char* name;
|
||||
//Value.
|
||||
const char* value;
|
||||
};
|
||||
|
||||
struct lsnes_core_disassembler
|
||||
{
|
||||
//Name.
|
||||
const char* name;
|
||||
//Routine.
|
||||
const char* (*fn)(uint64_t base, unsigned char(*fetch)(void* ctx), void* ctx);
|
||||
};
|
||||
|
||||
//Request 0: Initialize and enumerate cores.
|
||||
//Item: 0.
|
||||
//Default action: (required)
|
||||
//Called as the first call. Do the needed initialization and return list of core IDs.
|
||||
#define LSNES_CORE_ENUMERATE_CORES 0
|
||||
struct lsnes_core_enumerate_cores
|
||||
{
|
||||
//Output: List of sysregion ids. Terminated by 0xFFFFFFFF.
|
||||
unsigned* sysregions;
|
||||
//Input: Emulator capability flags 1.
|
||||
unsigned emu_flags1;
|
||||
//Input: Function to print message line.
|
||||
void (*message)(const char* msg, size_t length);
|
||||
//Input: Get input.
|
||||
short (*get_input)(unsigned port, unsigned index, unsigned control);
|
||||
//Input: Notify that state of action has updated.
|
||||
void (*notify_action_update)();
|
||||
//Input: Notify that time has ticked.
|
||||
void (*timer_tick)(uint32_t increment, uint32_t per_second);
|
||||
//Input: Get firmware path. The return value is temporary.
|
||||
const char* (*get_firmware_path)();
|
||||
//Input: Get cartridge base path. The return value is temporary.
|
||||
const char* (*get_base_path)();
|
||||
//Input: Get current time.
|
||||
time_t (*get_time)();
|
||||
//Input: Get random seed.
|
||||
time_t (*get_randomseed)();
|
||||
//Input: Notify that memory has been read.
|
||||
void (*memory_read)(uint64_t addr, uint64_t value);
|
||||
//Input: Notify that memory is about to be written.
|
||||
void (*memory_write)(uint64_t addr, uint64_t value);
|
||||
//Input: Notify that memory is about to be executed.
|
||||
void (*memory_execute)(uint64_t addr, uint64_t cpunum);
|
||||
//Input: Notify memory trace event. Str needs to be valid during call.
|
||||
void (*memory_trace)(uint64_t proc, const char* str, int insn);
|
||||
//Input: Submit sound.
|
||||
void (*submit_sound)(const int16_t* samples, size_t count, int stereo, double rate);
|
||||
//Input: Notify latch event. Parameters are NULL-terminated and need to be remain during call.
|
||||
void (*notify_latch)(const char** params);
|
||||
//Input: Output a frame.
|
||||
void (*submit_frame)(struct lsnes_core_framebuffer_info* fb, uint32_t fps_n, uint32_t fps_d);
|
||||
//Input: Add disassembler. Only available if emu_flags1>=1.
|
||||
void* (*add_disasm)(struct lsnes_core_disassembler* disasm);
|
||||
//Input: Remove disassembler. Only available if emu_flags1>=1.
|
||||
void (*remove_disasm)(void* handle);
|
||||
};
|
||||
|
||||
//Request 1: Request information about core.
|
||||
//Item id: Core ID.
|
||||
//Default action: (required)
|
||||
//Obtain information about core.
|
||||
#define LSNES_CORE_GET_CORE_INFO 1
|
||||
struct lsnes_core_get_core_info_aparam
|
||||
{
|
||||
//Name of the parameter.
|
||||
const char* name;
|
||||
//Model:
|
||||
//bool: boolean
|
||||
//int:<val>,<val>: Integer in specified range.
|
||||
//string[:<regex>]: String with regex.
|
||||
//enum:<json-array-of-strings>: Enumeration.
|
||||
//toggle: Not a real parameter, boolean toggle, must be the first.
|
||||
const char* model;
|
||||
};
|
||||
struct lsnes_core_get_core_info_action
|
||||
{
|
||||
//Internal id of the action.
|
||||
int id;
|
||||
//Internal name of the action.
|
||||
const char* iname;
|
||||
//Human-readable Name of the action
|
||||
const char* hname;
|
||||
//Array of parameters. Terminated by parameter with NULL name.
|
||||
struct lsnes_core_get_core_info_aparam* parameters;
|
||||
};
|
||||
struct lsnes_core_get_core_info
|
||||
{
|
||||
//Output: The JSON text.
|
||||
const char* json;
|
||||
//Output: JSON pointer to root of the port array.
|
||||
const char* root_ptr;
|
||||
//Output: Short core name.
|
||||
const char* shortname;
|
||||
//Output: Full core name.
|
||||
const char* fullname;
|
||||
//Output: Capability flags #1 (LSNES_CORE_CAP1_*).
|
||||
unsigned cap_flags1;
|
||||
//Output: Array of actions. Terminated by action with NUL iname. Only if LSNES_CORE_CAP1_ACTION is set.
|
||||
struct lsnes_core_get_core_info_action* actions;
|
||||
//Output: List of trace CPUs. Terminated by NULL. Only if LSNES_CORE_CAP1_TRACE is set.
|
||||
const char** trace_cpu_list;
|
||||
};
|
||||
|
||||
//Request 2: Request information about system type.
|
||||
//Item id: Type ID.
|
||||
//Default action: (required)
|
||||
//Obtain information about system type.
|
||||
#define LSNES_CORE_GET_TYPE_INFO 2
|
||||
struct lsnes_core_get_type_info_paramval
|
||||
{
|
||||
const char* iname;
|
||||
const char* hname;
|
||||
signed index;
|
||||
};
|
||||
struct lsnes_core_get_type_info_param
|
||||
{
|
||||
//Internal name.
|
||||
const char* iname;
|
||||
//Human-readable name.
|
||||
const char* hname;
|
||||
//Default value.
|
||||
const char* dflt;
|
||||
//Enumeration of values (if enumerated, ended by value with NULL iname).
|
||||
//If values are false and true, this is boolean.
|
||||
struct lsnes_core_get_type_info_paramval* values;
|
||||
//Validation regex (only for non-enumerated).
|
||||
const char* regex;
|
||||
};
|
||||
struct lsnes_core_get_type_info_romimage
|
||||
{
|
||||
//Internal name.
|
||||
const char* iname;
|
||||
//Human-readable name.
|
||||
const char* hname;
|
||||
//Mandatory mask (OR of all preset ones must equal OR of all).
|
||||
unsigned mandatory;
|
||||
//Pass mode: 0 => Content. 1 => Filename, 2 => Directory.
|
||||
int pass_mode;
|
||||
//Optional header size.
|
||||
unsigned headersize;
|
||||
//Standard extensions (split by ;).
|
||||
const char* extensions;
|
||||
};
|
||||
struct lsnes_core_get_type_info
|
||||
{
|
||||
//Output: ID of core emulating this.
|
||||
unsigned core;
|
||||
//Output: internal name.
|
||||
const char* iname;
|
||||
//Output: human-readable name.
|
||||
const char* hname;
|
||||
//Output: Short System name (e.g. SNES).
|
||||
const char* sysname;
|
||||
//Output: BIOS name.
|
||||
const char* bios;
|
||||
//Output: List of regions. Terminated by 0xFFFFFFFF.
|
||||
unsigned* regions;
|
||||
//Output: List of images. Terminated by image with NULL iname.
|
||||
struct lsnes_core_get_type_info_romimage* images;
|
||||
//Output: List of settings. Terminated by setting with NULL iname.
|
||||
struct lsnes_core_get_type_info_param* settings;
|
||||
};
|
||||
|
||||
//Request 3: Request information about region.
|
||||
//Item id: Region ID.
|
||||
//Default action: (required)
|
||||
//Obtain information about region.
|
||||
#define LSNES_CORE_GET_REGION_INFO 3
|
||||
struct lsnes_core_get_region_info
|
||||
{
|
||||
//Output: Internal name.
|
||||
const char* iname;
|
||||
//Output: Human-readable name.
|
||||
const char* hname;
|
||||
//Output: Priority
|
||||
unsigned priority;
|
||||
//Output: Multi-region flag.
|
||||
int multi;
|
||||
//Output: Fps numerator.
|
||||
uint32_t fps_n;
|
||||
//Output: Fps denomerator.
|
||||
uint32_t fps_d;
|
||||
//Output: Compatible run regions, ended with 0xFFFFFFFF.
|
||||
unsigned* compatible_runs;
|
||||
};
|
||||
|
||||
//Request 4: Get sysregion info.
|
||||
//Item id: Sysregion ID.
|
||||
//Default action: (required)
|
||||
//Get information about specific sysregion.
|
||||
#define LSNES_CORE_GET_SYSREGION_INFO 4
|
||||
struct lsnes_core_get_sysregion_info
|
||||
{
|
||||
//Output: The name of sysregion.
|
||||
const char* name;
|
||||
//Output: The type ID.
|
||||
unsigned type;
|
||||
//Output: The region ID.
|
||||
unsigned region;
|
||||
//Output: The system name this is for.
|
||||
const char* for_system;
|
||||
};
|
||||
|
||||
|
||||
//Request 5: Get current A/V state.
|
||||
//Item: Core ID.
|
||||
//Default action: (required)
|
||||
//Fill the structure with current A/V state.
|
||||
#define LSNES_CORE_GET_AV_STATE 5
|
||||
struct lsnes_core_get_av_state
|
||||
{
|
||||
uint32_t fps_n;
|
||||
uint32_t fps_d;
|
||||
double par;
|
||||
uint32_t rate_n;
|
||||
uint32_t rate_d;
|
||||
unsigned lightgun_width;
|
||||
unsigned lightgun_height;
|
||||
};
|
||||
|
||||
|
||||
//Request 6: Emulate a frame
|
||||
//Item: Core ID.
|
||||
//Default action: (required).
|
||||
//Emulate a frame and output the video and audio data resulting.
|
||||
#define LSNES_CORE_EMULATE 6
|
||||
struct lsnes_core_emulate
|
||||
{
|
||||
};
|
||||
|
||||
//Request 7: Save state.
|
||||
//Item: Core ID.
|
||||
//Default action: (required).
|
||||
//Save core state.
|
||||
#define LSNES_CORE_SAVESTATE 7
|
||||
struct lsnes_core_savestate
|
||||
{
|
||||
//Output: Size of the savestate.
|
||||
size_t size;
|
||||
//Output: Savestate data. Only needs to be stable to next call.
|
||||
const char* data;
|
||||
};
|
||||
|
||||
//Request 8: Load state.
|
||||
//Item: Core ID.
|
||||
//Default action: (required).
|
||||
//Load core state.
|
||||
#define LSNES_CORE_LOADSTATE 8
|
||||
struct lsnes_core_loadstate
|
||||
{
|
||||
//Input: Size of the savestate.
|
||||
size_t size;
|
||||
//Input: Savestate data. Only stable during call.
|
||||
const char* data;
|
||||
};
|
||||
|
||||
//Request 9: Get controller set.
|
||||
//Item id: Type ID.
|
||||
//Default action: (required).
|
||||
//Get the controller set.
|
||||
#define LSNES_CORE_GET_CONTROLLERCONFIG 9
|
||||
struct lsnes_core_get_controllerconfig_logical_entry
|
||||
{
|
||||
//port
|
||||
unsigned port;
|
||||
//controller
|
||||
unsigned controller;
|
||||
};
|
||||
struct lsnes_core_get_controllerconfig
|
||||
{
|
||||
//Input: System settings. Ended by entry with NULL name.
|
||||
struct lsnes_core_system_setting* settings;
|
||||
//Output: Port types, indexed by 0-based ID to port type root JSON array. Ended by 0xFFFFFFFF.
|
||||
unsigned* controller_types;
|
||||
//Output: Logical map (ended by 0,0).
|
||||
struct lsnes_core_get_controllerconfig_logical_entry* logical_map;
|
||||
};
|
||||
|
||||
//Request 10: Load ROM.
|
||||
//Item id: Type ID.
|
||||
//Default action: (required).
|
||||
//Load given ROM.
|
||||
#define LSNES_CORE_LOAD_ROM 10
|
||||
struct lsnes_core_load_rom_image
|
||||
{
|
||||
//ROM image (or filename thereof)
|
||||
const char* data;
|
||||
//Size of ROM image.
|
||||
size_t size;
|
||||
//Markup.
|
||||
const char* markup;
|
||||
};
|
||||
struct lsnes_core_load_rom
|
||||
{
|
||||
//Input: The image set.
|
||||
struct lsnes_core_load_rom_image* images;
|
||||
//Input: System settings. Ended by entry with NULL name.
|
||||
struct lsnes_core_system_setting* settings;
|
||||
//Input: RTC second.
|
||||
uint64_t rtc_sec;
|
||||
//Input: RTC subsecond.
|
||||
uint64_t rtc_subsec;
|
||||
};
|
||||
|
||||
//Request 11: Get region.
|
||||
//Item: Core ID.
|
||||
//Default action: Fill region 0.
|
||||
//Return the current region.
|
||||
#define LSNES_CORE_GET_REGION 11
|
||||
struct lsnes_core_get_region
|
||||
{
|
||||
//Output: The region.
|
||||
unsigned region;
|
||||
};
|
||||
|
||||
//Request 12: Set region.
|
||||
//Item: Core ID.
|
||||
//Default action: If region is 0, succeed, otherwise fail.
|
||||
//Set current region.
|
||||
#define LSNES_CORE_SET_REGION 12
|
||||
struct lsnes_core_set_region
|
||||
{
|
||||
//Input: The region ID.
|
||||
unsigned region;
|
||||
};
|
||||
|
||||
//Request 13: Deinitialize
|
||||
//Item: 0.
|
||||
//Default action: No-op
|
||||
//Deinitialize the state.
|
||||
#define LSNES_CORE_DEINITIALIZE 13
|
||||
struct lsnes_core_deinitialize
|
||||
{
|
||||
};
|
||||
|
||||
//Request 14: Get poll flag state.
|
||||
//Item: Core ID.
|
||||
//Default action: Return flag inferred from polls.
|
||||
//Return the poll flag state.
|
||||
//The poll flag gets automatically set to 1 if core reads controllers.
|
||||
#define LSNES_CORE_GET_PFLAG 14
|
||||
struct lsnes_core_get_pflag
|
||||
{
|
||||
//Output: The poll flag state.
|
||||
int pflag;
|
||||
};
|
||||
|
||||
//Request 15: Set poll flag state.
|
||||
//Item: Core ID.
|
||||
//Default action: Set flag inferred from polls.
|
||||
//Sets the poll flag state.
|
||||
#define LSNES_CORE_SET_PFLAG 15
|
||||
struct lsnes_core_set_pflag
|
||||
{
|
||||
//Input: The poll flag state.
|
||||
int pflag;
|
||||
};
|
||||
|
||||
//Request 16: Get action flags.
|
||||
//Item: Core ID.
|
||||
//Default action: Act as if flags was 1.
|
||||
//Get flags for given action.
|
||||
#define LSNES_CORE_GET_ACTION_FLAGS 16
|
||||
struct lsnes_core_get_action_flags
|
||||
{
|
||||
//Input: The ID of action.
|
||||
unsigned action;
|
||||
//Output: The flags.
|
||||
//Bit 0: Enabled.
|
||||
//Bit 1: Checked.
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
//Request 17: Execute action.
|
||||
//Item: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Execute given action.
|
||||
#define LSNES_CORE_EXECUTE_ACTION 17
|
||||
struct lsnes_core_execute_action_param
|
||||
{
|
||||
union {
|
||||
int boolean;
|
||||
int64_t integer;
|
||||
struct {
|
||||
const char* base;
|
||||
size_t length;
|
||||
} string;
|
||||
};
|
||||
};
|
||||
struct lsnes_core_execute_action
|
||||
{
|
||||
//Input: The ID of action.
|
||||
unsigned action;
|
||||
//Parameters block (length is set by action info).
|
||||
struct lsnes_core_execute_action_param* params;
|
||||
};
|
||||
|
||||
//Request 18: Get bus mapping.
|
||||
//Item: Core ID.
|
||||
//Default action: base=0, size=0 (no mapping).
|
||||
//Get the base and size of bus mapping.
|
||||
#define LSNES_CORE_GET_BUS_MAPPING 18
|
||||
struct lsnes_core_get_bus_mapping
|
||||
{
|
||||
//Output: The base address of the mapping.
|
||||
uint64_t base;
|
||||
//Output: The size of the mapping.
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
//Request 19: Enumerate SRAMs.
|
||||
//Item iD: Core ID.
|
||||
//Default action: Return empty set.
|
||||
//Get the set of SRAMs available.
|
||||
#define LSNES_CORE_ENUMERATE_SRAM 19
|
||||
struct lsnes_core_enumerate_sram
|
||||
{
|
||||
//Output: List of SRAMs, NULL terminated (valid until next call).
|
||||
const char** srams;
|
||||
};
|
||||
|
||||
//Request 20: Save SRAMs.
|
||||
//Item id: Core ID.
|
||||
//Default action: Return empty set.
|
||||
//Save the contents of SRAMs.
|
||||
#define LSNES_CORE_SAVE_SRAM 20
|
||||
struct lsnes_core_save_sram
|
||||
{
|
||||
//Output: The SRAMs, terminated by entry with NULL name. Valid until next call.
|
||||
struct lsnes_core_sram* srams;
|
||||
};
|
||||
|
||||
//Request 21: Load SRAMs.
|
||||
//Item id: Core ID.
|
||||
//Default action: Warn about any SRAMs present.
|
||||
//Load the contents of SRAMs.
|
||||
#define LSNES_CORE_LOAD_SRAM 21
|
||||
struct lsnes_core_load_sram
|
||||
{
|
||||
//Intput: The SRAMs, terminated by entry with NULL name. Valid during call.
|
||||
struct lsnes_core_sram* srams;
|
||||
};
|
||||
|
||||
//Request 22: Get reset action number.
|
||||
//Item id: Core ID.
|
||||
//Default action: Return -1 for both (not supported).
|
||||
//Return the IDs for reset actions.
|
||||
#define LSNES_CORE_GET_RESET_ACTION 22
|
||||
struct lsnes_core_get_reset_action
|
||||
{
|
||||
//Output: Soft reset action (-1 if not supported).
|
||||
int softreset;
|
||||
//Output: Hard reset action (-1 if not supported).
|
||||
int hardreset;
|
||||
};
|
||||
|
||||
//Request 23: Get scale factors.
|
||||
//Item id: Core ID.
|
||||
//Default action: Scale to at least 360 width, 320 height.
|
||||
//Compute scale factors for given resolution.
|
||||
#define LSNES_CORE_COMPUTE_SCALE 23
|
||||
struct lsnes_core_compute_scale
|
||||
{
|
||||
//Input: Width
|
||||
unsigned width;
|
||||
//Input: Height.
|
||||
unsigned height;
|
||||
//Output: Horizontal scale factor.
|
||||
uint32_t hfactor;
|
||||
//Output: Vertical scale factor.
|
||||
uint32_t vfactor;
|
||||
};
|
||||
|
||||
//Request 24: Run to save.
|
||||
//Item id: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Run to next save point (can be at most frame).
|
||||
#define LSNES_CORE_RUNTOSAVE 24
|
||||
struct lsnes_core_runtosave
|
||||
{
|
||||
};
|
||||
|
||||
//Request 25: Poweron the system
|
||||
//Item id: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Powers on the emulate system.
|
||||
#define LSNES_CORE_POWERON 25
|
||||
struct lsnes_core_poweron
|
||||
{
|
||||
};
|
||||
|
||||
//Request 26: Unload the ROM.
|
||||
//Item id: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Signals that the ROM is no longer needed and can be unloaded.
|
||||
#define LSNES_CORE_UNLOAD_CARTRIDGE 26
|
||||
struct lsnes_core_unload_cartridge
|
||||
{
|
||||
};
|
||||
|
||||
//Request 27: Reset debugging.
|
||||
//Item id: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Signals that debugging system should discard all breakpoints, cheats and tracks.
|
||||
#define LSNES_CORE_DEBUG_RESET 27
|
||||
struct lsnes_core_debug_reset
|
||||
{
|
||||
};
|
||||
|
||||
//Request 28: Set debug flags.
|
||||
//Item id: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Set debugging flags.
|
||||
#define LSNES_CORE_SET_DEBUG_FLAGS 28
|
||||
struct lsnes_core_set_debug_flags
|
||||
{
|
||||
//Input: Address or CPU id.
|
||||
uint64_t addr;
|
||||
//Input: Flags to set.
|
||||
//1 => Break on read.
|
||||
//2 => Break on write.
|
||||
//4 => Break on execute.
|
||||
//8 => Trace.
|
||||
unsigned set;
|
||||
//Input: Flags to clear.
|
||||
unsigned clear;
|
||||
};
|
||||
|
||||
//Request 29: Set cheat.
|
||||
//Item id: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Set or clear cheat.
|
||||
#define LSNES_CORE_SET_CHEAT 29
|
||||
struct lsnes_core_set_cheat
|
||||
{
|
||||
//Input: Address to set on.
|
||||
uint64_t addr;
|
||||
//Input: Value to set.
|
||||
uint64_t value;
|
||||
//Input: If nonzero, set cheat, else clear it.
|
||||
int set;
|
||||
};
|
||||
|
||||
//Request 30: Draw cover page.
|
||||
//Item id: Core ID.
|
||||
//Default action: Draw black screen.
|
||||
//Draw the cover page.
|
||||
#define LSNES_CORE_DRAW_COVER 30
|
||||
struct lsnes_core_draw_cover
|
||||
{
|
||||
//Output: The cover page. Needs to stay valid to next call.
|
||||
struct lsnes_core_framebuffer_info* coverpage;
|
||||
};
|
||||
|
||||
//Request 31: Set system controls before emulating frame.
|
||||
//Item id: Core ID.
|
||||
//Default action: Do nothing.
|
||||
//Set the system controls before frame is emulated.
|
||||
#define LSNES_CORE_PRE_EMULATE 31
|
||||
struct lsnes_core_pre_emulate
|
||||
{
|
||||
//Input: Context to pass to the function.
|
||||
void* context;
|
||||
//Input: Set input function.
|
||||
void (*set_input)(void* context, unsigned port, unsigned controller, unsigned index, short value);
|
||||
};
|
||||
|
||||
//Request 32: Get list of device registers.
|
||||
//Item id: Core ID.
|
||||
//Default action: Return no registers.
|
||||
//Return list of device registers.
|
||||
#define LSNES_CORE_GET_DEVICE_REGS 32
|
||||
struct lsnes_core_get_device_regs_reg
|
||||
{
|
||||
//Name of the register.
|
||||
const char* name;
|
||||
//Read function.
|
||||
uint64_t (*read)();
|
||||
//Write function.
|
||||
void (*write)(uint64_t v);
|
||||
//Is boolean?
|
||||
int boolean;
|
||||
};
|
||||
struct lsnes_core_get_device_regs
|
||||
{
|
||||
//Output: List of registers. Terminated with register with NULL name.
|
||||
struct lsnes_core_get_device_regs_reg* regs;
|
||||
};
|
||||
|
||||
//Request 33: Get VMA list.
|
||||
//Item id: Core ID.
|
||||
//Default action: Return no VMAs.
|
||||
//Get the list of VMAs.
|
||||
#define LSNES_CORE_GET_VMA_LIST 33
|
||||
struct lsnes_core_get_vma_list_vma
|
||||
{
|
||||
//Name of region.
|
||||
const char* name;
|
||||
//Base address.
|
||||
uint64_t base;
|
||||
//Size of region.
|
||||
uint64_t size;
|
||||
//Endianess of region (-1 => little, 0 => host, 1 => big).
|
||||
int endian;
|
||||
//flags (LSNES_CORE_VMA_*).
|
||||
int flags;
|
||||
//Direct mapping for the region. If not NULL, read/write will not be used, instead all operations directly
|
||||
//manipulate this buffer (faster). Must be NULL for special regions.
|
||||
unsigned char* direct_map;
|
||||
//Function to read region (if direct_map is NULL).
|
||||
uint8_t (*read)(uint64_t offset);
|
||||
//Function to write region (if direct_map is NULL and readonly is 0).
|
||||
void (*write)(uint64_t offset, uint8_t value);
|
||||
};
|
||||
struct lsnes_core_get_vma_list
|
||||
{
|
||||
//Output: List of VMAs. NULL-terminated.
|
||||
struct lsnes_core_get_vma_list_vma** vmas;
|
||||
};
|
||||
|
||||
|
||||
#ifdef LSNES_BUILD_AS_BUILTIN_CORE
|
||||
void lsnes_register_builtin_core(lsnes_core_func_t fn);
|
||||
#else
|
||||
int lsnes_core_entrypoint(unsigned action, unsigned item, void* params, const char** error);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
13
include/interface/c-interface.hpp
Normal file
13
include/interface/c-interface.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef _interface__c_interface__hpp__included__
|
||||
#define _interface__c_interface__hpp__included__
|
||||
|
||||
#define LSNES_BUILD_AS_BUILTIN_CORE
|
||||
#include "c-interface.h"
|
||||
#include <library/loadlib.hpp>
|
||||
|
||||
void try_init_c_module(const loadlib::module& module);
|
||||
void initialize_all_builtin_c_cores();
|
||||
|
||||
template<typename T> struct ccore_call_param_map { static int id; static const char* name; };
|
||||
|
||||
#endif
|
|
@ -70,7 +70,7 @@ public:
|
|||
/**
|
||||
* Notify trace event.
|
||||
*/
|
||||
virtual void memory_trace(uint64_t proc, const char* str) = 0;
|
||||
virtual void memory_trace(uint64_t proc, const char* str, bool insn) = 0;
|
||||
};
|
||||
|
||||
extern struct emucore_callbacks* ecore_callbacks;
|
||||
|
|
|
@ -159,7 +159,9 @@ struct core_romimage_info
|
|||
*/
|
||||
struct core_romimage_info_collection
|
||||
{
|
||||
core_romimage_info_collection();
|
||||
core_romimage_info_collection(std::initializer_list<core_romimage_info_params> idata);
|
||||
core_romimage_info_collection(std::vector<core_romimage_info_params> idata);
|
||||
std::vector<core_romimage_info> get() const { return data; }
|
||||
private:
|
||||
std::vector<core_romimage_info> data;
|
||||
|
@ -177,7 +179,9 @@ struct core_vma_info
|
|||
backing_ram = NULL;
|
||||
readonly = false;
|
||||
volatile_flag = false;
|
||||
iospace_rw = NULL;
|
||||
special = false;
|
||||
read = NULL;
|
||||
write = NULL;
|
||||
}
|
||||
/**
|
||||
* Name of the VMA.
|
||||
|
@ -199,6 +203,10 @@ struct core_vma_info
|
|||
* If true, the VMA can't be written to.
|
||||
*/
|
||||
bool readonly;
|
||||
/**
|
||||
* If true, the VMA has special read/write semantics (no consistency assumed).
|
||||
*/
|
||||
bool special;
|
||||
/**
|
||||
* Default endianess. -1 => Little endian, 0 => The same as host system, 1 => Big endian.
|
||||
*/
|
||||
|
@ -211,11 +219,16 @@ struct core_vma_info
|
|||
* If backing_ram is NULL, this routine is used to access the memory one byte at a time.
|
||||
*
|
||||
* Parameter offset: The offset into VMA to access.
|
||||
* Parameter data: Byte to write. Ignored if write = false.
|
||||
* Parameter write: If true, do write, otherwise do read.
|
||||
* Returns: The read value. Only valid if write = false.
|
||||
* Returns: The read value.
|
||||
*/
|
||||
uint8_t (*iospace_rw)(uint64_t offset, uint8_t data, bool write);
|
||||
uint8_t (*read)(uint64_t offset);
|
||||
/**
|
||||
* If backing_ram is NULL, this routine is used to access the memory one byte at a time.
|
||||
*
|
||||
* Parameter offset: The offset into VMA to access.
|
||||
* Parameter data: Byte to write.
|
||||
*/
|
||||
void (*write)(uint64_t offset, uint8_t data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -298,6 +311,7 @@ struct core_romimage
|
|||
struct core_core
|
||||
{
|
||||
core_core(std::initializer_list<port_type*> ports, std::initializer_list<interface_action> actions);
|
||||
core_core(std::vector<port_type*> ports, std::vector<interface_action> actions);
|
||||
~core_core() throw();
|
||||
bool set_region(core_region& region);
|
||||
std::pair<uint32_t, uint32_t> get_video_rate();
|
||||
|
|
|
@ -117,6 +117,7 @@ struct core_setting
|
|||
*/
|
||||
struct core_setting_group
|
||||
{
|
||||
core_setting_group();
|
||||
/**
|
||||
* Create a new group of settings.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "core/loadlib.hpp"
|
||||
#include "interface/c-interface.hpp"
|
||||
#include "interface/romtype.hpp"
|
||||
#include "core/command.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
|
@ -83,6 +84,11 @@ void with_loaded_library(const loadlib::module& l)
|
|||
} catch(...) {
|
||||
//This wasn't libopus.
|
||||
}
|
||||
try {
|
||||
try_init_c_module(l);
|
||||
} catch(...) {
|
||||
//Ignored.
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "core/romloader.hpp"
|
||||
#include "core/settings.hpp"
|
||||
#include "core/window.hpp"
|
||||
#include "interface/c-interface.hpp"
|
||||
#include "interface/callbacks.hpp"
|
||||
#include "interface/romtype.hpp"
|
||||
#include "library/framebuffer.hpp"
|
||||
|
@ -527,9 +528,9 @@ public:
|
|||
debug_fire_callback_exec(addr, proc);
|
||||
}
|
||||
|
||||
void memory_trace(uint64_t proc, const char* str)
|
||||
void memory_trace(uint64_t proc, const char* str, bool insn)
|
||||
{
|
||||
debug_fire_callback_trace(proc, str);
|
||||
debug_fire_callback_trace(proc, str, insn);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1184,6 +1185,7 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_
|
|||
our_rom = rom;
|
||||
lsnes_callbacks lsnes_callbacks_obj;
|
||||
ecore_callbacks = &lsnes_callbacks_obj;
|
||||
initialize_all_builtin_c_cores();
|
||||
core_core::install_all_handlers();
|
||||
|
||||
//Load our given movie.
|
||||
|
|
|
@ -22,22 +22,22 @@ memory_space lsnes_memory;
|
|||
|
||||
namespace
|
||||
{
|
||||
uint8_t lsnes_mmio_iospace_handler(uint64_t offset, uint8_t data, bool write)
|
||||
uint8_t lsnes_mmio_iospace_read(uint64_t offset)
|
||||
{
|
||||
try {
|
||||
if(offset >= 0 && offset < 8 && !write) {
|
||||
if(offset >= 0 && offset < 8) {
|
||||
//Frame counter.
|
||||
uint64_t x = movb.get_movie().get_current_frame();
|
||||
return x >> (8 * (offset & 7));
|
||||
} else if(offset >= 8 && offset < 16 && !write) {
|
||||
} else if(offset >= 8 && offset < 16) {
|
||||
//Movie length.
|
||||
uint64_t x = movb.get_movie().get_frame_count();
|
||||
return x >> (8 * (offset & 7));
|
||||
} else if(offset >= 16 && offset < 24 && !write) {
|
||||
} else if(offset >= 16 && offset < 24) {
|
||||
//Lag counter.
|
||||
uint64_t x = movb.get_movie().get_lag_frames();
|
||||
return x >> (8 * (offset & 7));
|
||||
} else if(offset >= 24 && offset < 32 && !write) {
|
||||
} else if(offset >= 24 && offset < 32) {
|
||||
//Rerecord counter.
|
||||
uint64_t x = movb.get_rrdata().count();
|
||||
return x >> (8 * (offset & 7));
|
||||
|
@ -48,19 +48,25 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void lsnes_mmio_iospace_write(uint64_t offset, uint8_t data)
|
||||
{
|
||||
//Ignore.
|
||||
}
|
||||
|
||||
class iospace_region : public memory_region
|
||||
{
|
||||
public:
|
||||
iospace_region(const std::string& _name, uint64_t _base, uint64_t _size,
|
||||
uint8_t (*_iospace_rw)(uint64_t offset, uint8_t data, bool write))
|
||||
iospace_region(const std::string& _name, uint64_t _base, uint64_t _size, bool _special,
|
||||
uint8_t (*_read)(uint64_t offset), void (*_write)(uint64_t offset, uint8_t data))
|
||||
{
|
||||
name = _name;
|
||||
base = _base;
|
||||
size = _size;
|
||||
iospace_rw = _iospace_rw;
|
||||
Xread = _read;
|
||||
Xwrite = _write;
|
||||
endian = -1;
|
||||
readonly = false;
|
||||
special = true;
|
||||
readonly = (_write == NULL);
|
||||
special = _special;
|
||||
direct_map = NULL;
|
||||
}
|
||||
~iospace_region() throw() {}
|
||||
|
@ -68,16 +74,17 @@ namespace
|
|||
{
|
||||
uint8_t* _buffer = reinterpret_cast<uint8_t*>(buffer);
|
||||
for(size_t i = 0; i < rsize; i++)
|
||||
_buffer[i] = iospace_rw(offset + i, 0, false);
|
||||
_buffer[i] = Xread(offset + i);
|
||||
}
|
||||
bool write(uint64_t offset, const void* buffer, size_t rsize)
|
||||
{
|
||||
const uint8_t* _buffer = reinterpret_cast<const uint8_t*>(buffer);
|
||||
for(size_t i = 0; i < rsize; i++)
|
||||
iospace_rw(offset + i, _buffer[i], true);
|
||||
Xwrite(offset + i, _buffer[i]);
|
||||
return offset + rsize <= size;
|
||||
}
|
||||
uint8_t (*iospace_rw)(uint64_t offset, uint8_t data, bool write);
|
||||
uint8_t (*Xread)(uint64_t offset);
|
||||
void (*Xwrite)(uint64_t offset, uint8_t data);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -90,12 +97,13 @@ void refresh_cart_mappings() throw(std::bad_alloc)
|
|||
memory_region* tmp = NULL;
|
||||
auto vmalist = our_rom.rtype->vma_list();
|
||||
try {
|
||||
tmp = new iospace_region("LSNESMMIO", 0xFFFFFFFF00000000ULL, 32, lsnes_mmio_iospace_handler);
|
||||
tmp = new iospace_region("LSNESMMIO", 0xFFFFFFFF00000000ULL, 32, true, lsnes_mmio_iospace_read,
|
||||
lsnes_mmio_iospace_write);
|
||||
regions.push_back(tmp);
|
||||
tmp = NULL;
|
||||
for(auto i : vmalist) {
|
||||
if(i.iospace_rw)
|
||||
tmp = new iospace_region(i.name, i.base, i.size, i.iospace_rw);
|
||||
if(!i.backing_ram)
|
||||
tmp = new iospace_region(i.name, i.base, i.size, i.special, i.read, i.write);
|
||||
else
|
||||
tmp = new memory_region_direct(i.name, i.base, i.endian,
|
||||
reinterpret_cast<uint8_t*>(i.backing_ram), i.size, i.readonly);
|
||||
|
|
|
@ -294,12 +294,8 @@ namespace
|
|||
void populate_volatile_ram(moviefile& mf, std::list<core_vma_info>& vmas)
|
||||
{
|
||||
for(auto i : vmas) {
|
||||
if(!i.volatile_flag)
|
||||
continue;
|
||||
if(i.readonly)
|
||||
continue;
|
||||
//FIXME: The special flag might have to be split.
|
||||
if(i.iospace_rw)
|
||||
//Only regions that are marked as volatile, readwrite not special are initializable.
|
||||
if(!i.volatile_flag || i.readonly || i.special)
|
||||
continue;
|
||||
if(!mf.ramcontent.count(i.name))
|
||||
continue;
|
||||
|
@ -308,7 +304,7 @@ namespace
|
|||
memcpy(i.backing_ram, &mf.ramcontent[i.name][0], csize);
|
||||
else
|
||||
for(uint64_t o = 0; o < csize; o++)
|
||||
i.iospace_rw(o, mf.ramcontent[i.name][o], true);
|
||||
i.write(o, mf.ramcontent[i.name][o]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -626,7 +626,7 @@ std::map<std::string, std::vector<char>> load_sram_commandline(const std::vector
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::vector<char> loaded_rom::save_core_state(bool nochecksum) throw(std::bad_alloc)
|
||||
std::vector<char> loaded_rom::save_core_state(bool nochecksum) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
std::vector<char> ret;
|
||||
rtype->serialize(ret);
|
||||
|
|
|
@ -738,7 +738,7 @@ namespace
|
|||
if(trace_cpu_enable) {
|
||||
char buffer[1024];
|
||||
SNES::cpu.disassemble_opcode(buffer, SNES::cpu.regs.pc);
|
||||
ecore_callbacks->memory_trace(0, buffer);
|
||||
ecore_callbacks->memory_trace(0, buffer, true);
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
|
@ -749,7 +749,7 @@ namespace
|
|||
if(trace_smp_enable) {
|
||||
nall::string _disasm = SNES::smp.disassemble_opcode(SNES::smp.regs.pc);
|
||||
std::string disasm(_disasm, _disasm.length());
|
||||
ecore_callbacks->memory_trace(1, disasm.c_str());
|
||||
ecore_callbacks->memory_trace(1, disasm.c_str(), true);
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
|
@ -806,23 +806,26 @@ namespace
|
|||
return id.substr(1);
|
||||
}
|
||||
|
||||
uint8_t snes_bus_iospace_rw(uint64_t offset, uint8_t data, bool write)
|
||||
uint8_t snes_bus_iospace_read(uint64_t offset)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
disable_breakpoints = true;
|
||||
if(write)
|
||||
SNES::bus.write(offset, data);
|
||||
else
|
||||
#ifdef BSNES_SUPPORTS_ADV_BREAKPOINTS
|
||||
val = SNES::bus.read(offset, false);
|
||||
uint8_t val = SNES::bus.read(offset, false);
|
||||
#else
|
||||
val = SNES::bus.read(offset);
|
||||
uint8_t val = SNES::bus.read(offset);
|
||||
#endif
|
||||
disable_breakpoints = false;
|
||||
return val;
|
||||
}
|
||||
|
||||
uint8_t ptrtable_iospace_rw(uint64_t offset, uint8_t data, bool write)
|
||||
void snes_bus_iospace_write(uint64_t offset, uint8_t data)
|
||||
{
|
||||
disable_breakpoints = true;
|
||||
SNES::bus.write(offset, data);
|
||||
disable_breakpoints = false;
|
||||
}
|
||||
|
||||
uint8_t ptrtable_iospace_read(uint64_t offset)
|
||||
{
|
||||
uint16_t entry = offset >> 4;
|
||||
if(!ptrmap.count(entry))
|
||||
|
@ -834,7 +837,8 @@ namespace
|
|||
}
|
||||
|
||||
void create_region(std::list<core_vma_info>& inf, const std::string& name, uint64_t base, uint64_t size,
|
||||
uint8_t (*iospace_rw)(uint64_t offset, uint8_t data, bool write)) throw(std::bad_alloc)
|
||||
uint8_t (*readfn)(uint64_t offset), void (*writefn)(uint64_t offset, uint8_t data))
|
||||
throw(std::bad_alloc)
|
||||
{
|
||||
if(size == 0)
|
||||
return;
|
||||
|
@ -843,7 +847,10 @@ namespace
|
|||
i.base = base;
|
||||
i.size = size;
|
||||
i.endian = -1;
|
||||
i.iospace_rw = iospace_rw;
|
||||
i.special = true;
|
||||
i.readonly = (writefn == NULL);
|
||||
i.read = readfn;
|
||||
i.write = writefn;
|
||||
inf.push_back(i);
|
||||
}
|
||||
|
||||
|
@ -1595,8 +1602,8 @@ again2:
|
|||
}
|
||||
create_region(ret, "SRAM", 0x10000000, SNES::cartridge.ram, false);
|
||||
create_region(ret, "ROM", 0x80000000, SNES::cartridge.rom, true);
|
||||
create_region(ret, "BUS", 0x1000000, 0x1000000, snes_bus_iospace_rw);
|
||||
create_region(ret, "PTRTABLE", 0x100000000, 0x100000, ptrtable_iospace_rw);
|
||||
create_region(ret, "BUS", 0x1000000, 0x1000000, snes_bus_iospace_read, snes_bus_iospace_write);
|
||||
create_region(ret, "PTRTABLE", 0x100000000, 0x100000, ptrtable_iospace_read, NULL);
|
||||
map_internal(ret, "CPU_STATE", 0, &SNES::cpu, sizeof(SNES::cpu));
|
||||
map_internal(ret, "PPU_STATE", 1, &SNES::ppu, sizeof(SNES::ppu));
|
||||
map_internal(ret, "SMP_STATE", 2, &SNES::smp, sizeof(SNES::smp));
|
||||
|
|
|
@ -268,4 +268,4 @@ namespace
|
|||
}
|
||||
return o.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -306,7 +306,7 @@ namespace
|
|||
*(buffer_ptr++) = instance->get_cpureg(gambatte::GB::REG_HF1) ? '1' : '-';
|
||||
*(buffer_ptr++) = instance->get_cpureg(gambatte::GB::REG_HF2) ? '2' : '-';
|
||||
*(buffer_ptr++) = '\0';
|
||||
ecore_callbacks->memory_trace(0, buffer);
|
||||
ecore_callbacks->memory_trace(0, buffer, true);
|
||||
}
|
||||
|
||||
void basic_init()
|
||||
|
@ -413,17 +413,20 @@ namespace
|
|||
}
|
||||
|
||||
#ifdef GAMBATTE_SUPPORTS_ADV_DEBUG
|
||||
uint8_t gambatte_bus_iospace_rw(uint64_t offset, uint8_t data, bool write)
|
||||
uint8_t gambatte_bus_read(uint64_t offset)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
disable_breakpoints = true;
|
||||
if(write)
|
||||
instance->bus_write(offset, data);
|
||||
else
|
||||
val = instance->bus_read(offset);
|
||||
uint8_t val = instance->bus_read(offset);
|
||||
disable_breakpoints = false;
|
||||
return val;
|
||||
}
|
||||
|
||||
void gambatte_bus_write(uint64_t offset, uint8_t data)
|
||||
{
|
||||
disable_breakpoints = true;
|
||||
instance->bus_write(offset, data);
|
||||
disable_breakpoints = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::list<core_vma_info> get_VMAlist()
|
||||
|
@ -483,7 +486,9 @@ namespace
|
|||
bus.name = "BUS";
|
||||
bus.base = 0x1000000;
|
||||
bus.size = 0x10000;
|
||||
bus.iospace_rw = gambatte_bus_iospace_rw;
|
||||
bus.backing_ram = NULL;
|
||||
bus.read = gambatte_bus_read;
|
||||
bus.write = gambatte_bus_write;
|
||||
bus.endian = -1;
|
||||
vmas.push_back(bus);
|
||||
#endif
|
||||
|
|
1150
src/interface/c-interface.cpp
Normal file
1150
src/interface/c-interface.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -382,6 +382,19 @@ core_core::core_core(std::initializer_list<port_type*> ports, std::initializer_l
|
|||
new_core_flag = true;
|
||||
}
|
||||
|
||||
core_core::core_core(std::vector<port_type*> ports, std::vector<interface_action> x_actions)
|
||||
{
|
||||
for(auto i : ports)
|
||||
port_types.push_back(i);
|
||||
for(auto i : x_actions)
|
||||
actions[i._symbol] = i;
|
||||
|
||||
hidden = false;
|
||||
uninitialized_cores_set().insert(this);
|
||||
all_cores_set().insert(this);
|
||||
new_core_flag = true;
|
||||
}
|
||||
|
||||
core_core::~core_core() throw()
|
||||
{
|
||||
all_cores().erase(this);
|
||||
|
@ -566,12 +579,22 @@ emucore_callbacks::~emucore_callbacks() throw()
|
|||
{
|
||||
}
|
||||
|
||||
core_romimage_info_collection::core_romimage_info_collection()
|
||||
{
|
||||
}
|
||||
|
||||
core_romimage_info_collection::core_romimage_info_collection(std::initializer_list<core_romimage_info_params> idata)
|
||||
{
|
||||
for(auto i : idata)
|
||||
data.push_back(core_romimage_info(i));
|
||||
}
|
||||
|
||||
core_romimage_info_collection::core_romimage_info_collection(std::vector<core_romimage_info_params> idata)
|
||||
{
|
||||
for(auto i : idata)
|
||||
data.push_back(core_romimage_info(i));
|
||||
}
|
||||
|
||||
std::set<core_sysregion*> core_sysregion::find_matching(const std::string& name)
|
||||
{
|
||||
std::set<core_sysregion*> ret;
|
||||
|
|
|
@ -41,6 +41,10 @@ bool core_setting::validate(const std::string& value) const
|
|||
return regex_match(regex, value);
|
||||
}
|
||||
|
||||
core_setting_group::core_setting_group()
|
||||
{
|
||||
}
|
||||
|
||||
core_setting_group::core_setting_group(std::initializer_list<core_setting_param> _settings)
|
||||
{
|
||||
for(auto i : _settings)
|
||||
|
|
Loading…
Add table
Reference in a new issue