Move core-specific code to core bindings
This is probably quite buggy...
This commit is contained in:
parent
59a822d023
commit
008536d21c
16 changed files with 1028 additions and 1243 deletions
|
@ -8,10 +8,8 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "library/framebuffer.hpp"
|
#include "library/framebuffer.hpp"
|
||||||
|
#include "core/romtype.hpp"
|
||||||
|
|
||||||
#define EC_REGION_AUTO -1
|
|
||||||
#define EC_REGION_NTSC 0
|
|
||||||
#define EC_REGION_PAL 1
|
|
||||||
|
|
||||||
//Get the CPU rate.
|
//Get the CPU rate.
|
||||||
uint32_t get_snes_cpu_rate();
|
uint32_t get_snes_cpu_rate();
|
||||||
|
@ -30,32 +28,19 @@ void do_basic_core_init();
|
||||||
//Get set of SRAMs.
|
//Get set of SRAMs.
|
||||||
std::set<std::string> get_sram_set();
|
std::set<std::string> get_sram_set();
|
||||||
//Get region.
|
//Get region.
|
||||||
bool core_get_region();
|
core_region& core_get_region();
|
||||||
//Get the current video rate.
|
//Get the current video rate.
|
||||||
std::pair<uint32_t, uint32_t> get_video_rate();
|
std::pair<uint32_t, uint32_t> get_video_rate();
|
||||||
//Get the current audio rate.
|
//Get the current audio rate.
|
||||||
std::pair<uint32_t, uint32_t> get_audio_rate();
|
std::pair<uint32_t, uint32_t> get_audio_rate();
|
||||||
//Set preload settings.
|
//Set preload settings.
|
||||||
void set_preload_settings();
|
void set_preload_settings();
|
||||||
//Load SNES cartridge.
|
|
||||||
bool core_load_cartridge_normal(const char* rom_markup, const unsigned char* rom, size_t romsize);
|
|
||||||
//Load BS-X cartridge.
|
|
||||||
bool core_load_cartridge_bsx(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* rom_markup, const unsigned char* rom, size_t romsize);
|
|
||||||
//Load slotted BS-X cartridge.
|
|
||||||
bool core_load_cartridge_bsx_slotted(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* rom_markup, const unsigned char* rom, size_t romsize);
|
|
||||||
//Load Super Game Boy cartridge.
|
|
||||||
bool core_load_cartridge_super_game_boy(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* rom_markup, const unsigned char* rom, size_t romsize);
|
|
||||||
//Load Sufami turbo cartridge.
|
|
||||||
bool core_load_cartridge_sufami_turbo(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* romA_markup, const unsigned char* romA, size_t romAsize, const char* romB_markup,
|
|
||||||
const unsigned char* romB, size_t romBsize);
|
|
||||||
//Set the region.
|
//Set the region.
|
||||||
void core_set_region(int region);
|
bool core_set_region(core_region& region);
|
||||||
//Power the core.
|
//Power the core.
|
||||||
void core_power();
|
void core_power();
|
||||||
|
//Unload the cartridge.
|
||||||
|
void core_unload_cartridge();
|
||||||
//Save SRAM set.
|
//Save SRAM set.
|
||||||
std::map<std::string, std::vector<char>> save_sram() throw(std::bad_alloc);
|
std::map<std::string, std::vector<char>> save_sram() throw(std::bad_alloc);
|
||||||
//Load SRAM set.
|
//Load SRAM set.
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct moviefile
|
||||||
/**
|
/**
|
||||||
* What is the ROM type and region?
|
* What is the ROM type and region?
|
||||||
*/
|
*/
|
||||||
gametype_t gametype;
|
core_sysregion* gametype;
|
||||||
/**
|
/**
|
||||||
* What's in port #1?
|
* What's in port #1?
|
||||||
*/
|
*/
|
||||||
|
@ -73,29 +73,13 @@ struct moviefile
|
||||||
*/
|
*/
|
||||||
std::string rerecords;
|
std::string rerecords;
|
||||||
/**
|
/**
|
||||||
* SHA-256 of main ROM (empty string if none).
|
* SHA-256 of ROM (empty string if none).
|
||||||
*/
|
*/
|
||||||
std::string rom_sha256; //SHA-256 of main ROM.
|
std::string romimg_sha256[27];
|
||||||
/**
|
/**
|
||||||
* SHA-256 of main ROM XML (empty string if none).
|
* SHA-256 of ROM XML (empty string if none).
|
||||||
*/
|
*/
|
||||||
std::string romxml_sha256; //SHA-256 of main ROM XML.
|
std::string romxml_sha256[27];
|
||||||
/**
|
|
||||||
* SHA-256 of slot A ROM (empty string if none).
|
|
||||||
*/
|
|
||||||
std::string slota_sha256; //SHA-256 of SLOT A ROM.
|
|
||||||
/**
|
|
||||||
* SHA-256 of slot A XML (empty string if none).
|
|
||||||
*/
|
|
||||||
std::string slotaxml_sha256; //SHA-256 of SLOT A XML.
|
|
||||||
/**
|
|
||||||
* SHA-256 of slot B ROM (empty string if none).
|
|
||||||
*/
|
|
||||||
std::string slotb_sha256; //SHA-256 of SLOT B ROM.
|
|
||||||
/**
|
|
||||||
* SHA-256 of slot B XML (empty string if none).
|
|
||||||
*/
|
|
||||||
std::string slotbxml_sha256; //SHA-256 of SLOT B XML.
|
|
||||||
/**
|
/**
|
||||||
* Authors of the run, first in each pair is full name, second is nickname.
|
* Authors of the run, first in each pair is full name, second is nickname.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,178 +5,10 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "misc.hpp"
|
#include "core/misc.hpp"
|
||||||
|
#include "core/romtype.hpp"
|
||||||
|
|
||||||
/**
|
|
||||||
* Region of ROM.
|
|
||||||
*/
|
|
||||||
enum rom_region
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Autodetect region
|
|
||||||
*/
|
|
||||||
REGION_AUTO = 0,
|
|
||||||
/**
|
|
||||||
* (force) PAL region
|
|
||||||
*/
|
|
||||||
REGION_PAL,
|
|
||||||
/**
|
|
||||||
* (force) NTSC region
|
|
||||||
*/
|
|
||||||
REGION_NTSC
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Major type of ROM
|
|
||||||
*/
|
|
||||||
enum rom_type
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Ordinary SNES ROM
|
|
||||||
*/
|
|
||||||
ROMTYPE_SNES,
|
|
||||||
/**
|
|
||||||
* BS-X Slotted ROM.
|
|
||||||
*/
|
|
||||||
ROMTYPE_BSXSLOTTED,
|
|
||||||
/**
|
|
||||||
* BS-X (non-slotted) ROM.
|
|
||||||
*/
|
|
||||||
ROMTYPE_BSX,
|
|
||||||
/**
|
|
||||||
* Sufami Turbo ROM.
|
|
||||||
*/
|
|
||||||
ROMTYPE_SUFAMITURBO,
|
|
||||||
/**
|
|
||||||
* Super Game Boy ROM.
|
|
||||||
*/
|
|
||||||
ROMTYPE_SGB,
|
|
||||||
/**
|
|
||||||
* No ROM.
|
|
||||||
*/
|
|
||||||
ROMTYPE_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This enumeration enumerates possible ROM types and regions for those.
|
|
||||||
*/
|
|
||||||
enum gametype_t
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* NTSC-region SNES game
|
|
||||||
*/
|
|
||||||
GT_SNES_NTSC = 0,
|
|
||||||
/**
|
|
||||||
* PAL-region SNES game
|
|
||||||
*/
|
|
||||||
GT_SNES_PAL = 1,
|
|
||||||
/**
|
|
||||||
* NTSC-region BSX slotted game
|
|
||||||
*/
|
|
||||||
GT_BSX_SLOTTED = 2,
|
|
||||||
/**
|
|
||||||
* NTSC-region BSX (non-slotted) game
|
|
||||||
*/
|
|
||||||
GT_BSX = 3,
|
|
||||||
/**
|
|
||||||
* NTSC-region sufami turbo game
|
|
||||||
*/
|
|
||||||
GT_SUFAMITURBO = 4,
|
|
||||||
/**
|
|
||||||
* NTSC-region Super Game Boy game
|
|
||||||
*/
|
|
||||||
GT_SGB_NTSC = 5,
|
|
||||||
/**
|
|
||||||
* PAL-region Super Game Boy game
|
|
||||||
*/
|
|
||||||
GT_SGB_PAL = 6,
|
|
||||||
/**
|
|
||||||
* Invalid game type
|
|
||||||
*/
|
|
||||||
GT_INVALID = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translations between diffrent representations of type.
|
|
||||||
*/
|
|
||||||
class gtype
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Translate from major ROM type and region to string representation of the type.
|
|
||||||
*
|
|
||||||
* parameter rtype: The major ROM type.
|
|
||||||
* parameter region: Region.
|
|
||||||
* returns: String representation of combined type/region.
|
|
||||||
* throws std::bad_alloc: Not enough memory.
|
|
||||||
* throws std::runtime_error: Invalid type.
|
|
||||||
*/
|
|
||||||
static std::string tostring(rom_type rtype, rom_region region) throw(std::bad_alloc, std::runtime_error);
|
|
||||||
/**
|
|
||||||
* Translate major/region combination to string representation.
|
|
||||||
*
|
|
||||||
* This function produces the same IDs as the other tostring(), except that it can't produce arbitrary-region ones.
|
|
||||||
*
|
|
||||||
* parameter gametype: Type of the game.
|
|
||||||
* returns: String representation of the type.
|
|
||||||
* throws std::bad_alloc: Not enough memory.
|
|
||||||
* throws std::runtime_error: Invalid type.
|
|
||||||
*/
|
|
||||||
static std::string tostring(gametype_t gametype) throw(std::bad_alloc, std::runtime_error);
|
|
||||||
/**
|
|
||||||
* Combine major/region into game type.
|
|
||||||
*
|
|
||||||
* For arbitrary-region types, this gives NTSC types.
|
|
||||||
*
|
|
||||||
* parameter rtype: Major type.
|
|
||||||
* parameter region: The region.
|
|
||||||
* returns: The combined game type.
|
|
||||||
* throws std::bad_alloc: Not enough memory.
|
|
||||||
* throws std::runtime_error: Invalid type.
|
|
||||||
*/
|
|
||||||
static gametype_t togametype(rom_type rtype, rom_region region) throw(std::bad_alloc, std::runtime_error);
|
|
||||||
/**
|
|
||||||
* Parse string representation to game type.
|
|
||||||
*
|
|
||||||
* parameter gametype: The game type to parse.
|
|
||||||
* returns: The parsed game type.
|
|
||||||
* throws std::bad_alloc: Not enough memory.
|
|
||||||
* throws std::runtime_error: Invalid type.
|
|
||||||
*/
|
|
||||||
static gametype_t togametype(const std::string& gametype) throw(std::bad_alloc, std::runtime_error);
|
|
||||||
/**
|
|
||||||
* Parse string representation into major type.
|
|
||||||
*
|
|
||||||
* parameter gametype: The game type to parse.
|
|
||||||
* returns: The major type.
|
|
||||||
* throws std::bad_alloc: Not enough memory.
|
|
||||||
* throws std::runtime_error: Invalid type.
|
|
||||||
*/
|
|
||||||
static rom_type toromtype(const std::string& gametype) throw(std::bad_alloc, std::runtime_error);
|
|
||||||
/**
|
|
||||||
* Extract major type out of game type.
|
|
||||||
*
|
|
||||||
* parameter gametype: the game type to parse.
|
|
||||||
* returns: The major type.
|
|
||||||
*/
|
|
||||||
static rom_type toromtype(gametype_t gametype) throw();
|
|
||||||
/**
|
|
||||||
* Extract region out of game type.
|
|
||||||
*
|
|
||||||
* parameter gametype: the game type to parse.
|
|
||||||
* returns: The region.
|
|
||||||
* throws std::bad_alloc: Not enough memory.
|
|
||||||
* throws std::runtime_error: Invalid type.
|
|
||||||
*/
|
|
||||||
static rom_region toromregion(const std::string& gametype) throw(std::bad_alloc, std::runtime_error);
|
|
||||||
/**
|
|
||||||
* Extract region out of game type.
|
|
||||||
*
|
|
||||||
* parameter gametype: the game type to parse.
|
|
||||||
* returns: The region.
|
|
||||||
*/
|
|
||||||
static rom_region toromregion(gametype_t gametype) throw();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This structure gives all files associated with given ROM image.
|
* This structure gives all files associated with given ROM image.
|
||||||
|
@ -212,35 +44,19 @@ struct rom_files
|
||||||
/**
|
/**
|
||||||
* Major ROM type.
|
* Major ROM type.
|
||||||
*/
|
*/
|
||||||
enum rom_type rtype;
|
core_type* rtype;
|
||||||
/**
|
/**
|
||||||
* Game region (the region ROM is to be loaded as)
|
* Game region (the region ROM is to be loaded as)
|
||||||
*/
|
*/
|
||||||
enum rom_region region;
|
core_region* region;
|
||||||
/**
|
/**
|
||||||
* Relative filename of main ROM file.
|
* Relative filename of main ROM file.
|
||||||
*/
|
*/
|
||||||
std::string rom;
|
std::string romimg[27];
|
||||||
/**
|
/**
|
||||||
* Relative filename of main ROM XML file.
|
* Relative filename of main ROM XML file.
|
||||||
*/
|
*/
|
||||||
std::string rom_xml;
|
std::string romxml[27];
|
||||||
/**
|
|
||||||
* Relative filename of slot A ROM file (non-SNES only).
|
|
||||||
*/
|
|
||||||
std::string slota;
|
|
||||||
/**
|
|
||||||
* Relative filename of slot A XML file (non-SNES only).
|
|
||||||
*/
|
|
||||||
std::string slota_xml;
|
|
||||||
/**
|
|
||||||
* Relative filename of slot B ROM file (Sufami Turbo only).
|
|
||||||
*/
|
|
||||||
std::string slotb;
|
|
||||||
/**
|
|
||||||
* Relative filename of slot B XML file (Sufami Turbo only).
|
|
||||||
*/
|
|
||||||
std::string slotb_xml;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -343,39 +159,23 @@ struct loaded_rom
|
||||||
/**
|
/**
|
||||||
* ROM type
|
* ROM type
|
||||||
*/
|
*/
|
||||||
enum rom_type rtype;
|
core_type* rtype;
|
||||||
/**
|
/**
|
||||||
* ROM region (this is the currently active region).
|
* ROM region (this is the currently active region).
|
||||||
*/
|
*/
|
||||||
enum rom_region region;
|
core_region* region;
|
||||||
/**
|
/**
|
||||||
* ROM original region (this is the region ROM is loaded as).
|
* ROM original region (this is the region ROM is loaded as).
|
||||||
*/
|
*/
|
||||||
enum rom_region orig_region;
|
core_region* orig_region;
|
||||||
/**
|
/**
|
||||||
* Loaded main ROM
|
* Loaded main ROM
|
||||||
*/
|
*/
|
||||||
loaded_slot rom;
|
loaded_slot romimg[27];
|
||||||
/**
|
/**
|
||||||
* Loaded main ROM XML
|
* Loaded main ROM XML
|
||||||
*/
|
*/
|
||||||
loaded_slot rom_xml;
|
loaded_slot romxml[27];
|
||||||
/**
|
|
||||||
* Loaded slot A ROM (.bs, .st or .dmg)
|
|
||||||
*/
|
|
||||||
loaded_slot slota;
|
|
||||||
/**
|
|
||||||
* Loaded slot A XML (.bs, .st or .dmg)
|
|
||||||
*/
|
|
||||||
loaded_slot slota_xml;
|
|
||||||
/**
|
|
||||||
* Loaded slot B ROM (.st)
|
|
||||||
*/
|
|
||||||
loaded_slot slotb;
|
|
||||||
/**
|
|
||||||
* Loaded slot B XML (.st).
|
|
||||||
*/
|
|
||||||
loaded_slot slotb_xml;
|
|
||||||
/**
|
/**
|
||||||
* MSU-1 base.
|
* MSU-1 base.
|
||||||
*/
|
*/
|
||||||
|
@ -399,26 +199,6 @@ struct loaded_rom
|
||||||
void load() throw(std::bad_alloc, std::runtime_error);
|
void load() throw(std::bad_alloc, std::runtime_error);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognize the slot this ROM goes to.
|
|
||||||
*
|
|
||||||
* parameter major: The major type.
|
|
||||||
* parameter romname: Name of the ROM type.
|
|
||||||
* returns: Even if this is main rom, odd if XML. 0/1 for main slot, 2/3 for slot A, 4/5 for slot B. -1 if not valid
|
|
||||||
* rom type.
|
|
||||||
* throws std::bad_alloc: Not enough memory
|
|
||||||
*/
|
|
||||||
int recognize_commandline_rom(enum rom_type major, const std::string& romname) throw(std::bad_alloc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recognize major type from flags.
|
|
||||||
*
|
|
||||||
* parameter flags: Flags telling what ROM parameters are present.
|
|
||||||
* returns: The recognzed major type.
|
|
||||||
* throws std::bad_alloc: Not enough memory
|
|
||||||
* throws std::runtime_error: Illegal flags.
|
|
||||||
*/
|
|
||||||
rom_type recognize_platform(unsigned long flags) throw(std::bad_alloc, std::runtime_error);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name a sub-ROM.
|
* Name a sub-ROM.
|
||||||
|
@ -427,14 +207,14 @@ rom_type recognize_platform(unsigned long flags) throw(std::bad_alloc, std::runt
|
||||||
* parameter romnumber: ROM number to name (as returned by recognize_commandline_rom).
|
* parameter romnumber: ROM number to name (as returned by recognize_commandline_rom).
|
||||||
* throws std::bad_alloc: Not enough memory
|
* throws std::bad_alloc: Not enough memory
|
||||||
*/
|
*/
|
||||||
std::string name_subrom(enum rom_type major, unsigned romnumber) throw(std::bad_alloc);
|
std::string name_subrom(core_type& major, unsigned romnumber) throw(std::bad_alloc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get major type and region of loaded ROM.
|
* Get major type and region of loaded ROM.
|
||||||
*
|
*
|
||||||
* returns: Tuple (ROM type, ROM region) of currently loaded ROM.
|
* returns: Tuple (ROM type, ROM region) of currently loaded ROM.
|
||||||
*/
|
*/
|
||||||
std::pair<enum rom_type, enum rom_region> get_current_rom_info() throw();
|
std::pair<core_type*, core_region*> get_current_rom_info() throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take current values of all SRAMs in current system and save their contents.
|
* Take current values of all SRAMs in current system and save their contents.
|
||||||
|
|
115
include/core/romtype.hpp
Normal file
115
include/core/romtype.hpp
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
#ifndef _romtype__hpp__included__
|
||||||
|
#define _romtype__hpp__included__
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct core_region;
|
||||||
|
struct core_type;
|
||||||
|
struct core_sysregion;
|
||||||
|
|
||||||
|
struct core_region
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
core_region(const std::string& iname, const std::string& hname, unsigned priority, unsigned handle,
|
||||||
|
bool multi, uint64_t* fmagic, int (*compatible)(unsigned rom, unsigned run));
|
||||||
|
static core_region& lookup(const std::string& name);
|
||||||
|
const std::string& get_iname();
|
||||||
|
const std::string& get_hname();
|
||||||
|
unsigned get_priority();
|
||||||
|
bool is_multi();
|
||||||
|
void fill_framerate_magic(uint64_t* magic); //4 elements filled.
|
||||||
|
double approx_framerate();
|
||||||
|
bool compatible_with(core_region& run);
|
||||||
|
private:
|
||||||
|
core_region(const core_region&);
|
||||||
|
core_region& operator=(const core_region&);
|
||||||
|
std::string iname;
|
||||||
|
std::string hname;
|
||||||
|
bool multi;
|
||||||
|
unsigned handle;
|
||||||
|
unsigned priority;
|
||||||
|
uint64_t magic[4];
|
||||||
|
int (*compatible)(unsigned rom, unsigned run);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct core_romimage_info
|
||||||
|
{
|
||||||
|
core_romimage_info(const std::string& iname, const std::string& hname, unsigned mandatory,
|
||||||
|
unsigned (*headersize)(size_t imagesize));
|
||||||
|
std::string iname;
|
||||||
|
std::string hname;
|
||||||
|
unsigned mandatory;
|
||||||
|
unsigned (*headersize)(size_t imagesize);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct core_romimage
|
||||||
|
{
|
||||||
|
const char* markup;
|
||||||
|
const unsigned char* data;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct core_type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
core_type(const std::string& iname, const std::string& hname, int (*_load)(core_romimage* images));
|
||||||
|
static std::set<core_type*> get_core_types();
|
||||||
|
void add_region(core_region& reg);
|
||||||
|
void add_romimage(core_romimage_info& info, unsigned index);
|
||||||
|
core_region& get_preferred_region();
|
||||||
|
std::set<core_region*> get_regions();
|
||||||
|
core_sysregion& combine_region(core_region& reg);
|
||||||
|
const std::string& get_iname();
|
||||||
|
const std::string& get_hname();
|
||||||
|
unsigned get_image_count();
|
||||||
|
core_romimage_info get_image_info(unsigned index);
|
||||||
|
bool load(core_romimage* images);
|
||||||
|
private:
|
||||||
|
int (*loadimg)(core_romimage* images);
|
||||||
|
core_type(const core_type&);
|
||||||
|
core_type& operator=(const core_type&);
|
||||||
|
std::string iname;
|
||||||
|
std::string hname;
|
||||||
|
std::set<core_region*> regions;
|
||||||
|
std::vector<core_romimage_info*> imageinfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct core_type_region_bind
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
core_type_region_bind(core_type& type, core_region& region);
|
||||||
|
private:
|
||||||
|
core_type_region_bind(const core_type_region_bind&);
|
||||||
|
core_type_region_bind& operator=(const core_type_region_bind&);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct core_type_image_bind
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
core_type_image_bind(core_type& type, core_romimage_info& imageinfo, unsigned index);
|
||||||
|
private:
|
||||||
|
core_type_image_bind(const core_type_image_bind&);
|
||||||
|
core_type_image_bind& operator=(const core_type_image_bind&);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct core_sysregion
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
core_sysregion(const std::string& name, core_type& type, core_region& region);
|
||||||
|
static core_sysregion& lookup(const std::string& name);
|
||||||
|
const std::string& get_name();
|
||||||
|
core_region& get_region();
|
||||||
|
core_type& get_type();
|
||||||
|
void fill_framerate_magic(uint64_t* magic); //4 elements filled.
|
||||||
|
private:
|
||||||
|
core_sysregion(const core_sysregion&);
|
||||||
|
core_sysregion& operator=(const core_sysregion&);
|
||||||
|
std::string name;
|
||||||
|
core_type& type;
|
||||||
|
core_region& region;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
10
include/fonts/wrapper.hpp
Normal file
10
include/fonts/wrapper.hpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef _fonts__wrapper__hpp__included__
|
||||||
|
#define _fonts__wrapper__hpp__included__
|
||||||
|
|
||||||
|
#include "library/framebuffer.hpp"
|
||||||
|
|
||||||
|
extern bitmap_font main_font;
|
||||||
|
|
||||||
|
void do_init_font();
|
||||||
|
|
||||||
|
#endif
|
|
@ -51,37 +51,119 @@
|
||||||
#define LOGICAL_BUTTON_TURBO 14
|
#define LOGICAL_BUTTON_TURBO 14
|
||||||
#define LOGICAL_BUTTON_PAUSE 15
|
#define LOGICAL_BUTTON_PAUSE 15
|
||||||
|
|
||||||
//Set controller type to none.
|
|
||||||
void set_core_controller_none(unsigned port) throw();
|
|
||||||
//Set controller type to gamepad.
|
|
||||||
void set_core_controller_gamepad(unsigned port) throw();
|
|
||||||
//Set controller type to mouse.
|
|
||||||
void set_core_controller_mouse(unsigned port) throw();
|
|
||||||
//Set controller type to multitap.
|
|
||||||
void set_core_controller_multitap(unsigned port) throw();
|
|
||||||
//Set controller type to superscope.
|
|
||||||
void set_core_controller_superscope(unsigned port) throw();
|
|
||||||
//Set controller type to justifier.
|
|
||||||
void set_core_controller_justifier(unsigned port) throw();
|
|
||||||
//Set controller type to justifiers.
|
|
||||||
void set_core_controller_justifiers(unsigned port) throw();
|
|
||||||
//Button ID function for none.
|
|
||||||
int get_button_id_none(unsigned controller, unsigned lbid) throw();
|
|
||||||
//Button ID function for gamepad.
|
|
||||||
int get_button_id_gamepad(unsigned controller, unsigned lbid) throw();
|
|
||||||
//Button ID function for mouse.
|
|
||||||
int get_button_id_mouse(unsigned controller, unsigned lbid) throw();
|
|
||||||
//Button ID function for multitap.
|
|
||||||
int get_button_id_multitap(unsigned controller, unsigned lbid) throw();
|
|
||||||
//Button ID function for superscope.
|
|
||||||
int get_button_id_superscope(unsigned controller, unsigned lbid) throw();
|
|
||||||
//Button ID function for justifier.
|
|
||||||
int get_button_id_justifier(unsigned controller, unsigned lbid) throw();
|
|
||||||
//Button ID function for justifiers.
|
|
||||||
int get_button_id_justifiers(unsigned controller, unsigned lbid) throw();
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
int regions_compatible(unsigned rom, unsigned run)
|
||||||
|
{
|
||||||
|
return (!rom || rom == run);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned header_fn(size_t r)
|
||||||
|
{
|
||||||
|
if((r % 1024) == 512)
|
||||||
|
return 512;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
core_type* internal_rom;
|
||||||
|
extern core_type type_snes;
|
||||||
|
extern core_type type_bsx;
|
||||||
|
extern core_type type_bsxslotted;
|
||||||
|
extern core_type type_sufamiturbo;
|
||||||
|
extern core_type type_sgb;
|
||||||
|
|
||||||
|
int load_rom_snes(core_romimage* img)
|
||||||
|
{
|
||||||
|
bool r = snes_load_cartridge_normal(img[0].markup, img[0].data, img[0].size);
|
||||||
|
if(r)
|
||||||
|
internal_rom = &type_snes;
|
||||||
|
return r ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_rom_bsx(core_romimage* img)
|
||||||
|
{
|
||||||
|
bool r = snes_load_cartridge_bsx(img[0].markup, img[0].data, img[0].size,
|
||||||
|
img[1].markup, img[1].data, img[1].size);
|
||||||
|
if(r)
|
||||||
|
internal_rom = &type_bsx;
|
||||||
|
return r ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_rom_bsxslotted(core_romimage* img)
|
||||||
|
{
|
||||||
|
bool r = snes_load_cartridge_bsx_slotted(img[0].markup, img[0].data, img[0].size,
|
||||||
|
img[1].markup, img[1].data, img[1].size);
|
||||||
|
if(r)
|
||||||
|
internal_rom = &type_bsxslotted;
|
||||||
|
return r ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_rom_sgb(core_romimage* img)
|
||||||
|
{
|
||||||
|
bool r = snes_load_cartridge_super_game_boy(img[0].markup, img[0].data, img[0].size,
|
||||||
|
img[1].markup, img[1].data, img[1].size);
|
||||||
|
if(r)
|
||||||
|
internal_rom = &type_sgb;
|
||||||
|
return r ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_rom_sufamiturbo(core_romimage* img)
|
||||||
|
{
|
||||||
|
bool r = snes_load_cartridge_sufami_turbo(img[0].markup, img[0].data, img[0].size,
|
||||||
|
img[1].markup, img[1].data, img[1].size, img[2].markup, img[2].data, img[2].size);
|
||||||
|
if(r)
|
||||||
|
internal_rom = &type_sufamiturbo;
|
||||||
|
return r ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ntsc_magic[4] = {178683, 10738636, 16639264, 596096};
|
||||||
|
uint64_t pal_magic[4] = {6448, 322445, 19997208, 266440};
|
||||||
|
|
||||||
|
core_region region_auto("autodetect", "Autodetect", 1, 0, true, ntsc_magic, regions_compatible);
|
||||||
|
core_region region_ntsc("ntsc", "NTSC", 0, 1, true, ntsc_magic, regions_compatible);
|
||||||
|
core_region region_pal("pal", "PAL", 0, 2, true, pal_magic, regions_compatible);
|
||||||
|
core_romimage_info image_snescart("rom", "Cartridge ROM", 1, header_fn);
|
||||||
|
core_romimage_info image_bsxbios("rom", "BS-X BIOS", 1, header_fn);
|
||||||
|
core_romimage_info image_bsxflash("bsx", "BS-X Flash", 2, header_fn);
|
||||||
|
core_romimage_info image_bsxsflash("bsxslotted", "BS-X Flash", 2, header_fn);
|
||||||
|
core_romimage_info image_sgbbios("rom", "SGB BIOS", 1, header_fn);
|
||||||
|
core_romimage_info image_dmg("dmg", "DMG ROM", 2, header_fn);
|
||||||
|
core_romimage_info image_stbios("rom", "ST BIOS", 1, header_fn);
|
||||||
|
core_romimage_info image_stslota("slot-a", "ST Slot A ROM", 2, header_fn);
|
||||||
|
core_romimage_info image_stslotb("slot-b", "ST Slot B ROM", 2, header_fn);
|
||||||
|
core_type type_snes("snes", "SNES", load_rom_snes);
|
||||||
|
core_type type_bsx("bsx", "BS-X (non-slotted)", load_rom_bsx);
|
||||||
|
core_type type_bsxslotted("bsxslotted", "BS-X (slotted)", load_rom_bsxslotted);
|
||||||
|
core_type type_sufamiturbo("sufamiturbo", "Sufami Turbo", load_rom_sufamiturbo);
|
||||||
|
core_type type_sgb("sgb", "Super Game Boy", load_rom_sgb);
|
||||||
|
core_type_region_bind bind_A(type_snes, region_auto);
|
||||||
|
core_type_region_bind bind_B(type_snes, region_ntsc);
|
||||||
|
core_type_region_bind bind_C(type_snes, region_pal);
|
||||||
|
core_type_region_bind bind_D(type_bsx, region_ntsc);
|
||||||
|
core_type_region_bind bind_E(type_bsxslotted, region_ntsc);
|
||||||
|
core_type_region_bind bind_F(type_sufamiturbo, region_ntsc);
|
||||||
|
core_type_region_bind bind_G(type_sgb, region_auto);
|
||||||
|
core_type_region_bind bind_H(type_sgb, region_ntsc);
|
||||||
|
core_type_region_bind bind_I(type_sgb, region_pal);
|
||||||
|
core_type_image_bind bind_J(type_snes, image_snescart, 0);
|
||||||
|
core_type_image_bind bind_K(type_bsx, image_bsxbios, 0);
|
||||||
|
core_type_image_bind bind_L(type_bsx, image_bsxflash, 1);
|
||||||
|
core_type_image_bind bind_M(type_bsxslotted, image_bsxbios, 0);
|
||||||
|
core_type_image_bind bind_N(type_bsxslotted, image_bsxsflash, 1);
|
||||||
|
core_type_image_bind bind_O(type_sufamiturbo, image_stbios, 0);
|
||||||
|
core_type_image_bind bind_P(type_sufamiturbo, image_stslota, 1);
|
||||||
|
core_type_image_bind bind_Q(type_sufamiturbo, image_stslotb, 2);
|
||||||
|
core_type_image_bind bind_R(type_sgb, image_sgbbios, 0);
|
||||||
|
core_type_image_bind bind_S(type_sgb, image_dmg, 1);
|
||||||
|
core_sysregion sr1("snes_ntsc", type_snes, region_ntsc);
|
||||||
|
core_sysregion sr2("snes_pal", type_snes, region_pal);
|
||||||
|
core_sysregion sr3("bsx", type_bsx, region_ntsc);
|
||||||
|
core_sysregion sr4("bsxslotted", type_bsxslotted, region_ntsc);
|
||||||
|
core_sysregion sr5("sufamiturbo", type_sufamiturbo, region_ntsc);
|
||||||
|
core_sysregion sr6("sgb_ntsc", type_sgb, region_ntsc);
|
||||||
|
core_sysregion sr7("sgb_pal", type_sgb, region_pal);
|
||||||
|
|
||||||
bool last_hires = false;
|
bool last_hires = false;
|
||||||
bool last_interlace = false;
|
bool last_interlace = false;
|
||||||
bool stepping_into_save;
|
bool stepping_into_save;
|
||||||
|
@ -91,7 +173,6 @@ namespace
|
||||||
unsigned long long delayreset_cycles_target;
|
unsigned long long delayreset_cycles_target;
|
||||||
|
|
||||||
bool p1disable = false;
|
bool p1disable = false;
|
||||||
unsigned internal_rom = ROM_TYPE_NONE;
|
|
||||||
std::map<int16_t, std::pair<uint64_t, uint64_t>> ptrmap;
|
std::map<int16_t, std::pair<uint64_t, uint64_t>> ptrmap;
|
||||||
|
|
||||||
const char* buttonnames[] = {
|
const char* buttonnames[] = {
|
||||||
|
@ -242,7 +323,7 @@ namespace
|
||||||
{
|
{
|
||||||
last_hires = hires;
|
last_hires = hires;
|
||||||
last_interlace = interlace;
|
last_interlace = interlace;
|
||||||
bool region = core_get_region();
|
bool region = (&core_get_region() == ®ion_pal);
|
||||||
if(stepping_into_save)
|
if(stepping_into_save)
|
||||||
messages << "Got video refresh in runtosave, expect desyncs!" << std::endl;
|
messages << "Got video refresh in runtosave, expect desyncs!" << std::endl;
|
||||||
video_refresh_done = true;
|
video_refresh_done = true;
|
||||||
|
@ -290,6 +371,146 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void set_core_controller_generic(unsigned port, unsigned id, bool p2only)
|
||||||
|
{
|
||||||
|
if(port > 1)
|
||||||
|
return;
|
||||||
|
if(port == 1)
|
||||||
|
snes_set_controller_port_device(true, id);
|
||||||
|
if(port == 0) {
|
||||||
|
snes_set_controller_port_device(false, p2only ? SNES_DEVICE_NONE : id);
|
||||||
|
p1disable = p2only;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_core_controller_none(unsigned port) throw()
|
||||||
|
{
|
||||||
|
set_core_controller_generic(port, SNES_DEVICE_NONE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_core_controller_gamepad(unsigned port) throw()
|
||||||
|
{
|
||||||
|
set_core_controller_generic(port, SNES_DEVICE_JOYPAD, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_core_controller_mouse(unsigned port) throw()
|
||||||
|
{
|
||||||
|
set_core_controller_generic(port, SNES_DEVICE_MOUSE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_core_controller_multitap(unsigned port) throw()
|
||||||
|
{
|
||||||
|
set_core_controller_generic(port, SNES_DEVICE_MULTITAP, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_core_controller_superscope(unsigned port) throw()
|
||||||
|
{
|
||||||
|
set_core_controller_generic(port, SNES_DEVICE_SUPER_SCOPE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_core_controller_justifier(unsigned port) throw()
|
||||||
|
{
|
||||||
|
set_core_controller_generic(port, SNES_DEVICE_JUSTIFIER, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_core_controller_justifiers(unsigned port) throw()
|
||||||
|
{
|
||||||
|
set_core_controller_generic(port, SNES_DEVICE_JUSTIFIERS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_button_id_none(unsigned controller, unsigned lbid) throw()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_button_id_gamepad(unsigned controller, unsigned lbid) throw()
|
||||||
|
{
|
||||||
|
if(controller > 0)
|
||||||
|
return -1;
|
||||||
|
switch(lbid) {
|
||||||
|
case LOGICAL_BUTTON_LEFT: return SNES_DEVICE_ID_JOYPAD_LEFT;
|
||||||
|
case LOGICAL_BUTTON_RIGHT: return SNES_DEVICE_ID_JOYPAD_RIGHT;
|
||||||
|
case LOGICAL_BUTTON_UP: return SNES_DEVICE_ID_JOYPAD_UP;
|
||||||
|
case LOGICAL_BUTTON_DOWN: return SNES_DEVICE_ID_JOYPAD_DOWN;
|
||||||
|
case LOGICAL_BUTTON_A: return SNES_DEVICE_ID_JOYPAD_A;
|
||||||
|
case LOGICAL_BUTTON_B: return SNES_DEVICE_ID_JOYPAD_B;
|
||||||
|
case LOGICAL_BUTTON_X: return SNES_DEVICE_ID_JOYPAD_X;
|
||||||
|
case LOGICAL_BUTTON_Y: return SNES_DEVICE_ID_JOYPAD_Y;
|
||||||
|
case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_JOYPAD_L;
|
||||||
|
case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_JOYPAD_R;
|
||||||
|
case LOGICAL_BUTTON_SELECT: return SNES_DEVICE_ID_JOYPAD_SELECT;
|
||||||
|
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JOYPAD_START;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_button_id_mouse(unsigned controller, unsigned lbid) throw()
|
||||||
|
{
|
||||||
|
if(controller > 0)
|
||||||
|
return -1;
|
||||||
|
switch(lbid) {
|
||||||
|
case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_MOUSE_LEFT;
|
||||||
|
case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_MOUSE_RIGHT;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_button_id_multitap(unsigned controller, unsigned lbid) throw()
|
||||||
|
{
|
||||||
|
if(controller > 3)
|
||||||
|
return -1;
|
||||||
|
switch(lbid) {
|
||||||
|
case LOGICAL_BUTTON_LEFT: return SNES_DEVICE_ID_JOYPAD_LEFT;
|
||||||
|
case LOGICAL_BUTTON_RIGHT: return SNES_DEVICE_ID_JOYPAD_RIGHT;
|
||||||
|
case LOGICAL_BUTTON_UP: return SNES_DEVICE_ID_JOYPAD_UP;
|
||||||
|
case LOGICAL_BUTTON_DOWN: return SNES_DEVICE_ID_JOYPAD_DOWN;
|
||||||
|
case LOGICAL_BUTTON_A: return SNES_DEVICE_ID_JOYPAD_A;
|
||||||
|
case LOGICAL_BUTTON_B: return SNES_DEVICE_ID_JOYPAD_B;
|
||||||
|
case LOGICAL_BUTTON_X: return SNES_DEVICE_ID_JOYPAD_X;
|
||||||
|
case LOGICAL_BUTTON_Y: return SNES_DEVICE_ID_JOYPAD_Y;
|
||||||
|
case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_JOYPAD_L;
|
||||||
|
case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_JOYPAD_R;
|
||||||
|
case LOGICAL_BUTTON_SELECT: return SNES_DEVICE_ID_JOYPAD_SELECT;
|
||||||
|
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JOYPAD_START;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_button_id_superscope(unsigned controller, unsigned lbid) throw()
|
||||||
|
{
|
||||||
|
if(controller > 0)
|
||||||
|
return -1;
|
||||||
|
switch(lbid) {
|
||||||
|
case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER;
|
||||||
|
case LOGICAL_BUTTON_CURSOR: return SNES_DEVICE_ID_SUPER_SCOPE_CURSOR;
|
||||||
|
case LOGICAL_BUTTON_TURBO: return SNES_DEVICE_ID_SUPER_SCOPE_TURBO;
|
||||||
|
case LOGICAL_BUTTON_PAUSE: return SNES_DEVICE_ID_SUPER_SCOPE_PAUSE;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_button_id_justifier(unsigned controller, unsigned lbid) throw()
|
||||||
|
{
|
||||||
|
if(controller > 0)
|
||||||
|
return -1;
|
||||||
|
switch(lbid) {
|
||||||
|
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JUSTIFIER_START;
|
||||||
|
case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_button_id_justifiers(unsigned controller, unsigned lbid) throw()
|
||||||
|
{
|
||||||
|
if(controller > 1)
|
||||||
|
return -1;
|
||||||
|
switch(lbid) {
|
||||||
|
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JUSTIFIER_START;
|
||||||
|
case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct porttype_gamepad : public porttype_info
|
struct porttype_gamepad : public porttype_info
|
||||||
{
|
{
|
||||||
porttype_gamepad() : porttype_info("gamepad", "Gamepad", generic_port_size<1, 0, 12>())
|
porttype_gamepad() : porttype_info("gamepad", "Gamepad", generic_port_size<1, 0, 12>())
|
||||||
|
@ -447,6 +668,13 @@ namespace
|
||||||
SNES::Interface* old;
|
SNES::Interface* old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_logical_button_name(unsigned lbid) throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
if(lbid >= sizeof(buttonnames) / sizeof(buttonnames[0]))
|
||||||
|
return "";
|
||||||
|
return buttonnames[lbid];
|
||||||
|
}
|
||||||
|
|
||||||
void core_install_handler()
|
void core_install_handler()
|
||||||
{
|
{
|
||||||
old = SNES::interface;
|
old = SNES::interface;
|
||||||
|
@ -516,203 +744,12 @@ void set_preload_settings()
|
||||||
SNES::config.expansion_port = SNES::System::ExpansionPortDevice::None;
|
SNES::config.expansion_port = SNES::System::ExpansionPortDevice::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_core_controller_generic(unsigned port, unsigned id, bool p2only)
|
core_region& core_get_region()
|
||||||
{
|
{
|
||||||
if(port > 1)
|
if(SNES::system.region() == SNES::System::Region::PAL)
|
||||||
return;
|
return region_pal;
|
||||||
if(port == 1)
|
else
|
||||||
snes_set_controller_port_device(true, id);
|
return region_ntsc;
|
||||||
if(port == 0) {
|
|
||||||
snes_set_controller_port_device(false, p2only ? SNES_DEVICE_NONE : id);
|
|
||||||
p1disable = p2only;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_core_controller_none(unsigned port) throw()
|
|
||||||
{
|
|
||||||
set_core_controller_generic(port, SNES_DEVICE_NONE, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_core_controller_gamepad(unsigned port) throw()
|
|
||||||
{
|
|
||||||
set_core_controller_generic(port, SNES_DEVICE_JOYPAD, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_core_controller_mouse(unsigned port) throw()
|
|
||||||
{
|
|
||||||
set_core_controller_generic(port, SNES_DEVICE_MOUSE, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_core_controller_multitap(unsigned port) throw()
|
|
||||||
{
|
|
||||||
set_core_controller_generic(port, SNES_DEVICE_MULTITAP, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_core_controller_superscope(unsigned port) throw()
|
|
||||||
{
|
|
||||||
set_core_controller_generic(port, SNES_DEVICE_SUPER_SCOPE, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_core_controller_justifier(unsigned port) throw()
|
|
||||||
{
|
|
||||||
set_core_controller_generic(port, SNES_DEVICE_JUSTIFIER, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_core_controller_justifiers(unsigned port) throw()
|
|
||||||
{
|
|
||||||
set_core_controller_generic(port, SNES_DEVICE_JUSTIFIERS, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_button_id_none(unsigned controller, unsigned lbid) throw()
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_button_id_gamepad(unsigned controller, unsigned lbid) throw()
|
|
||||||
{
|
|
||||||
if(controller > 0)
|
|
||||||
return -1;
|
|
||||||
switch(lbid) {
|
|
||||||
case LOGICAL_BUTTON_LEFT: return SNES_DEVICE_ID_JOYPAD_LEFT;
|
|
||||||
case LOGICAL_BUTTON_RIGHT: return SNES_DEVICE_ID_JOYPAD_RIGHT;
|
|
||||||
case LOGICAL_BUTTON_UP: return SNES_DEVICE_ID_JOYPAD_UP;
|
|
||||||
case LOGICAL_BUTTON_DOWN: return SNES_DEVICE_ID_JOYPAD_DOWN;
|
|
||||||
case LOGICAL_BUTTON_A: return SNES_DEVICE_ID_JOYPAD_A;
|
|
||||||
case LOGICAL_BUTTON_B: return SNES_DEVICE_ID_JOYPAD_B;
|
|
||||||
case LOGICAL_BUTTON_X: return SNES_DEVICE_ID_JOYPAD_X;
|
|
||||||
case LOGICAL_BUTTON_Y: return SNES_DEVICE_ID_JOYPAD_Y;
|
|
||||||
case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_JOYPAD_L;
|
|
||||||
case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_JOYPAD_R;
|
|
||||||
case LOGICAL_BUTTON_SELECT: return SNES_DEVICE_ID_JOYPAD_SELECT;
|
|
||||||
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JOYPAD_START;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_button_id_mouse(unsigned controller, unsigned lbid) throw()
|
|
||||||
{
|
|
||||||
if(controller > 0)
|
|
||||||
return -1;
|
|
||||||
switch(lbid) {
|
|
||||||
case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_MOUSE_LEFT;
|
|
||||||
case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_MOUSE_RIGHT;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_button_id_multitap(unsigned controller, unsigned lbid) throw()
|
|
||||||
{
|
|
||||||
if(controller > 3)
|
|
||||||
return -1;
|
|
||||||
switch(lbid) {
|
|
||||||
case LOGICAL_BUTTON_LEFT: return SNES_DEVICE_ID_JOYPAD_LEFT;
|
|
||||||
case LOGICAL_BUTTON_RIGHT: return SNES_DEVICE_ID_JOYPAD_RIGHT;
|
|
||||||
case LOGICAL_BUTTON_UP: return SNES_DEVICE_ID_JOYPAD_UP;
|
|
||||||
case LOGICAL_BUTTON_DOWN: return SNES_DEVICE_ID_JOYPAD_DOWN;
|
|
||||||
case LOGICAL_BUTTON_A: return SNES_DEVICE_ID_JOYPAD_A;
|
|
||||||
case LOGICAL_BUTTON_B: return SNES_DEVICE_ID_JOYPAD_B;
|
|
||||||
case LOGICAL_BUTTON_X: return SNES_DEVICE_ID_JOYPAD_X;
|
|
||||||
case LOGICAL_BUTTON_Y: return SNES_DEVICE_ID_JOYPAD_Y;
|
|
||||||
case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_JOYPAD_L;
|
|
||||||
case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_JOYPAD_R;
|
|
||||||
case LOGICAL_BUTTON_SELECT: return SNES_DEVICE_ID_JOYPAD_SELECT;
|
|
||||||
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JOYPAD_START;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_button_id_superscope(unsigned controller, unsigned lbid) throw()
|
|
||||||
{
|
|
||||||
if(controller > 0)
|
|
||||||
return -1;
|
|
||||||
switch(lbid) {
|
|
||||||
case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER;
|
|
||||||
case LOGICAL_BUTTON_CURSOR: return SNES_DEVICE_ID_SUPER_SCOPE_CURSOR;
|
|
||||||
case LOGICAL_BUTTON_TURBO: return SNES_DEVICE_ID_SUPER_SCOPE_TURBO;
|
|
||||||
case LOGICAL_BUTTON_PAUSE: return SNES_DEVICE_ID_SUPER_SCOPE_PAUSE;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_button_id_justifier(unsigned controller, unsigned lbid) throw()
|
|
||||||
{
|
|
||||||
if(controller > 0)
|
|
||||||
return -1;
|
|
||||||
switch(lbid) {
|
|
||||||
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JUSTIFIER_START;
|
|
||||||
case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_button_id_justifiers(unsigned controller, unsigned lbid) throw()
|
|
||||||
{
|
|
||||||
if(controller > 1)
|
|
||||||
return -1;
|
|
||||||
switch(lbid) {
|
|
||||||
case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JUSTIFIER_START;
|
|
||||||
case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_logical_button_name(unsigned lbid) throw(std::bad_alloc)
|
|
||||||
{
|
|
||||||
if(lbid >= sizeof(buttonnames) / sizeof(buttonnames[0]))
|
|
||||||
return "";
|
|
||||||
return buttonnames[lbid];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool core_get_region()
|
|
||||||
{
|
|
||||||
bool r = (SNES::system.region() == SNES::System::Region::PAL);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool core_load_cartridge_normal(const char* rom_markup, const unsigned char* rom, size_t romsize)
|
|
||||||
{
|
|
||||||
bool r = snes_load_cartridge_normal(rom_markup, rom, romsize);
|
|
||||||
if(r)
|
|
||||||
internal_rom = ROM_TYPE_SNES;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool core_load_cartridge_bsx(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* rom_markup, const unsigned char* rom, size_t romsize)
|
|
||||||
{
|
|
||||||
bool r = snes_load_cartridge_bsx(bios_markup, bios, biossize, rom_markup, rom, romsize);
|
|
||||||
if(r)
|
|
||||||
internal_rom = ROM_TYPE_BSX;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool core_load_cartridge_bsx_slotted(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* rom_markup, const unsigned char* rom, size_t romsize)
|
|
||||||
{
|
|
||||||
bool r = snes_load_cartridge_bsx_slotted(bios_markup, bios, biossize, rom_markup, rom, romsize);
|
|
||||||
if(r)
|
|
||||||
internal_rom = ROM_TYPE_BSXSLOTTED;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool core_load_cartridge_super_game_boy(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* rom_markup, const unsigned char* rom, size_t romsize)
|
|
||||||
{
|
|
||||||
bool r = snes_load_cartridge_super_game_boy(bios_markup, bios, biossize, rom_markup, rom, romsize);
|
|
||||||
if(r)
|
|
||||||
internal_rom = ROM_TYPE_SGB;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool core_load_cartridge_sufami_turbo(const char* bios_markup, const unsigned char* bios, size_t biossize,
|
|
||||||
const char* romA_markup, const unsigned char* romA, size_t romAsize, const char* romB_markup,
|
|
||||||
const unsigned char* romB, size_t romBsize)
|
|
||||||
{
|
|
||||||
bool r = snes_load_cartridge_sufami_turbo(bios_markup, bios, biossize, romA_markup, romA, romAsize,
|
|
||||||
romB_markup, romB, romBsize);
|
|
||||||
if(r)
|
|
||||||
internal_rom = ROM_TYPE_SUFAMITURBO;
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_power()
|
void core_power()
|
||||||
|
@ -720,6 +757,12 @@ void core_power()
|
||||||
snes_power();
|
snes_power();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void core_unload_cartridge()
|
||||||
|
{
|
||||||
|
snes_term();
|
||||||
|
snes_unload_cartridge();
|
||||||
|
}
|
||||||
|
|
||||||
//Get the current video rate.
|
//Get the current video rate.
|
||||||
std::pair<uint32_t, uint32_t> get_video_rate()
|
std::pair<uint32_t, uint32_t> get_video_rate()
|
||||||
{
|
{
|
||||||
|
@ -774,13 +817,14 @@ void load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_al
|
||||||
messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge." << std::endl;
|
messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_set_region(int region)
|
bool core_set_region(core_region& region)
|
||||||
{
|
{
|
||||||
switch(region) {
|
if(®ion == ®ion_auto) SNES::config.region = SNES::System::Region::Autodetect;
|
||||||
case EC_REGION_AUTO: SNES::config.region = SNES::System::Region::Autodetect; break;
|
else if(®ion == ®ion_ntsc) SNES::config.region = SNES::System::Region::NTSC;
|
||||||
case EC_REGION_NTSC: SNES::config.region = SNES::System::Region::NTSC; break;
|
else if(®ion == ®ion_pal) SNES::config.region = SNES::System::Region::PAL;
|
||||||
case EC_REGION_PAL: SNES::config.region = SNES::System::Region::PAL; break;
|
else
|
||||||
}
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_serialize(std::vector<char>& out)
|
void core_serialize(std::vector<char>& out)
|
||||||
|
@ -835,7 +879,7 @@ void core_runtosave()
|
||||||
std::list<vma_info> get_vma_list()
|
std::list<vma_info> get_vma_list()
|
||||||
{
|
{
|
||||||
std::list<vma_info> ret;
|
std::list<vma_info> ret;
|
||||||
if(internal_rom == ROM_TYPE_NONE)
|
if(!internal_rom)
|
||||||
return ret;
|
return ret;
|
||||||
create_region(ret, "WRAM", 0x007E0000, SNES::cpu.wram, 131072, false);
|
create_region(ret, "WRAM", 0x007E0000, SNES::cpu.wram, 131072, false);
|
||||||
create_region(ret, "APURAM", 0x00000000, SNES::smp.apuram, 65536, false);
|
create_region(ret, "APURAM", 0x00000000, SNES::smp.apuram, 65536, false);
|
||||||
|
@ -860,27 +904,21 @@ std::list<vma_info> get_vma_list()
|
||||||
map_internal(ret, "PPU_STATE", 1, &SNES::ppu, sizeof(SNES::ppu));
|
map_internal(ret, "PPU_STATE", 1, &SNES::ppu, sizeof(SNES::ppu));
|
||||||
map_internal(ret, "SMP_STATE", 2, &SNES::smp, sizeof(SNES::smp));
|
map_internal(ret, "SMP_STATE", 2, &SNES::smp, sizeof(SNES::smp));
|
||||||
map_internal(ret, "DSP_STATE", 3, &SNES::dsp, sizeof(SNES::dsp));
|
map_internal(ret, "DSP_STATE", 3, &SNES::dsp, sizeof(SNES::dsp));
|
||||||
switch(internal_rom) {
|
if(internal_rom == &type_bsx || internal_rom == &type_bsxslotted) {
|
||||||
case ROM_TYPE_BSX:
|
|
||||||
case ROM_TYPE_BSXSLOTTED:
|
|
||||||
create_region(ret, "BSXFLASH", 0x90000000, SNES::bsxflash.memory, true);
|
create_region(ret, "BSXFLASH", 0x90000000, SNES::bsxflash.memory, true);
|
||||||
create_region(ret, "BSX_RAM", 0x20000000, SNES::bsxcartridge.sram, false);
|
create_region(ret, "BSX_RAM", 0x20000000, SNES::bsxcartridge.sram, false);
|
||||||
create_region(ret, "BSX_PRAM", 0x30000000, SNES::bsxcartridge.psram, false);
|
create_region(ret, "BSX_PRAM", 0x30000000, SNES::bsxcartridge.psram, false);
|
||||||
break;
|
}
|
||||||
case ROM_TYPE_SUFAMITURBO:
|
if(internal_rom == &type_sufamiturbo) {
|
||||||
create_region(ret, "SLOTA_ROM", 0x90000000, SNES::sufamiturbo.slotA.rom, true);
|
create_region(ret, "SLOTA_ROM", 0x90000000, SNES::sufamiturbo.slotA.rom, true);
|
||||||
create_region(ret, "SLOTB_ROM", 0xA0000000, SNES::sufamiturbo.slotB.rom, true);
|
create_region(ret, "SLOTB_ROM", 0xA0000000, SNES::sufamiturbo.slotB.rom, true);
|
||||||
create_region(ret, "SLOTA_RAM", 0x20000000, SNES::sufamiturbo.slotA.ram, false);
|
create_region(ret, "SLOTA_RAM", 0x20000000, SNES::sufamiturbo.slotA.ram, false);
|
||||||
create_region(ret, "SLOTB_RAM", 0x30000000, SNES::sufamiturbo.slotB.ram, false);
|
create_region(ret, "SLOTB_RAM", 0x30000000, SNES::sufamiturbo.slotB.ram, false);
|
||||||
break;
|
}
|
||||||
case ROM_TYPE_SGB:
|
if(internal_rom == &type_sgb) {
|
||||||
create_region(ret, "GBROM", 0x90000000, GameBoy::cartridge.romdata, GameBoy::cartridge.romsize, true);
|
create_region(ret, "GBROM", 0x90000000, GameBoy::cartridge.romdata, GameBoy::cartridge.romsize, true);
|
||||||
create_region(ret, "GBRAM", 0x20000000, GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize, false);
|
create_region(ret, "GBRAM", 0x20000000, GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize, false);
|
||||||
break;
|
}
|
||||||
case ROM_TYPE_SNES:
|
|
||||||
case ROM_TYPE_NONE:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ void refresh_cart_mappings() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
linear_ram_size = 0;
|
linear_ram_size = 0;
|
||||||
memory_regions.clear();
|
memory_regions.clear();
|
||||||
if(get_current_rom_info().first == ROMTYPE_NONE)
|
if(!get_current_rom_info().first)
|
||||||
return;
|
return;
|
||||||
auto vmalist = get_vma_list();
|
auto vmalist = get_vma_list();
|
||||||
for(auto i : vmalist) {
|
for(auto i : vmalist) {
|
||||||
|
|
|
@ -106,16 +106,13 @@ struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) th
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
throw std::runtime_error(std::string("Can't resolve ROM files: ") + e.what());
|
throw std::runtime_error(std::string("Can't resolve ROM files: ") + e.what());
|
||||||
}
|
}
|
||||||
messages << "ROM type: " << gtype::tostring(f.rtype, f.region) << std::endl;
|
messages << "ROM type: " << f.rtype->get_hname() << " (" << f.region->get_hname() << ")" << std::endl;
|
||||||
if(f.rom != "") messages << name_subrom(f.rtype, 0) << " file: '" << f.rom << "'" << std::endl;
|
for(size_t i = 0; i < sizeof(f.romimg)/sizeof(f.romimg[0]); i++) {
|
||||||
if(f.rom_xml != "") messages << name_subrom(f.rtype, 1) << " file: '" << f.rom_xml << "'"
|
if(f.romimg[i] != "") messages << name_subrom(*f.rtype, 2 * i + 0) << " file: '" << f.romimg[i]
|
||||||
<< std::endl;
|
<< "'" << std::endl;
|
||||||
if(f.slota != "") messages << name_subrom(f.rtype, 2) << " file: '" << f.slota << "'" << std::endl;
|
if(f.romxml[i] != "") messages << name_subrom(*f.rtype, 2 * i + 1) << " file: '" << f.romxml[i]
|
||||||
if(f.slota_xml != "") messages << name_subrom(f.rtype, 3) << " file: '" << f.slota_xml << "'"
|
<< "'" << std::endl;
|
||||||
<< std::endl;
|
}
|
||||||
if(f.slotb != "") messages << name_subrom(f.rtype, 4) << " file: '" << f.slotb << "'" << std::endl;
|
|
||||||
if(f.slotb_xml != "") messages << name_subrom(f.rtype, 5) << " file: '" << f.slotb_xml << "'"
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
struct loaded_rom r;
|
struct loaded_rom r;
|
||||||
try {
|
try {
|
||||||
|
@ -128,14 +125,12 @@ struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) th
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string not_present = "N/A";
|
std::string not_present = "N/A";
|
||||||
if(r.rom.valid) messages << name_subrom(f.rtype, 0) << " hash: " << r.rom.sha256 << std::endl;
|
for(size_t i = 0; i < sizeof(r.romimg)/sizeof(r.romimg[0]); i++) {
|
||||||
if(r.rom_xml.valid) messages << name_subrom(f.rtype, 1) << " hash: " << r.rom_xml.sha256 << std::endl;
|
if(r.romimg[i].valid) messages << name_subrom(*f.rtype, 2 * i + 0) << " hash: "
|
||||||
if(r.slota.valid) messages << name_subrom(f.rtype, 2) << " hash: " << r.slota.sha256 << std::endl;
|
<< r.romimg[i].sha256 << std::endl;
|
||||||
if(r.slota_xml.valid) messages << name_subrom(f.rtype, 3) << " hash: " << r.slota_xml.sha256
|
if(r.romxml[i].valid) messages << name_subrom(*f.rtype, 2 * i + 1) << " hash: "
|
||||||
<< std::endl;
|
<< r.romxml[i].sha256 << std::endl;
|
||||||
if(r.slotb.valid) messages << name_subrom(f.rtype, 4) << " hash: " << r.slotb.sha256 << std::endl;
|
}
|
||||||
if(r.slotb_xml.valid) messages << name_subrom(f.rtype, 5) << " hash: " << r.slotb_xml.sha256
|
|
||||||
<< std::endl;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,12 +220,10 @@ void do_save_state(const std::string& filename) throw(std::bad_alloc,
|
||||||
our_movie.prefix = sanitize_prefix(mprefix.prefix);
|
our_movie.prefix = sanitize_prefix(mprefix.prefix);
|
||||||
our_movie.is_savestate = true;
|
our_movie.is_savestate = true;
|
||||||
our_movie.sram = save_sram();
|
our_movie.sram = save_sram();
|
||||||
our_movie.rom_sha256 = our_rom->rom.sha256;
|
for(size_t i = 0; i < sizeof(our_rom->romimg)/sizeof(our_rom->romimg[0]); i++) {
|
||||||
our_movie.romxml_sha256 = our_rom->rom_xml.sha256;
|
our_movie.romimg_sha256[i] = our_rom->romimg[i].sha256;
|
||||||
our_movie.slota_sha256 = our_rom->slota.sha256;
|
our_movie.romxml_sha256[i] = our_rom->romxml[i].sha256;
|
||||||
our_movie.slotaxml_sha256 = our_rom->slota_xml.sha256;
|
}
|
||||||
our_movie.slotb_sha256 = our_rom->slotb.sha256;
|
|
||||||
our_movie.slotbxml_sha256 = our_rom->slotb_xml.sha256;
|
|
||||||
our_movie.savestate = save_core_state();
|
our_movie.savestate = save_core_state();
|
||||||
get_framebuffer().save(our_movie.screenshot);
|
get_framebuffer().save(our_movie.screenshot);
|
||||||
movb.get_movie().save_state(our_movie.projectid, our_movie.save_frame, our_movie.lagged_frames,
|
movb.get_movie().save_state(our_movie.projectid, our_movie.save_frame, our_movie.lagged_frames,
|
||||||
|
@ -306,13 +304,9 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
||||||
if(_movie.force_corrupt)
|
if(_movie.force_corrupt)
|
||||||
throw std::runtime_error("Movie file invalid");
|
throw std::runtime_error("Movie file invalid");
|
||||||
bool will_load_state = _movie.is_savestate && lmode != LOAD_STATE_MOVIE;
|
bool will_load_state = _movie.is_savestate && lmode != LOAD_STATE_MOVIE;
|
||||||
if(gtype::toromtype(_movie.gametype) != our_rom->rtype) {
|
if(&(_movie.gametype->get_type()) != our_rom->rtype)
|
||||||
messages << "_movie.gametype = " << _movie.gametype << std::endl;
|
|
||||||
messages << "gtype::toromtype(_movie.gametype) = " << gtype::toromtype(_movie.gametype) << std::endl;
|
|
||||||
messages << "our_rom->rtype = " << our_rom->rtype << std::endl;
|
|
||||||
throw std::runtime_error("ROM types of movie and loaded ROM don't match");
|
throw std::runtime_error("ROM types of movie and loaded ROM don't match");
|
||||||
}
|
if(!our_rom->orig_region->compatible_with(_movie.gametype->get_region()))
|
||||||
if(gtype::toromregion(_movie.gametype) != our_rom->orig_region && our_rom->orig_region != REGION_AUTO)
|
|
||||||
throw std::runtime_error("NTSC/PAL select of movie and loaded ROM don't match");
|
throw std::runtime_error("NTSC/PAL select of movie and loaded ROM don't match");
|
||||||
|
|
||||||
if(_movie.coreversion != bsnes_core_version) {
|
if(_movie.coreversion != bsnes_core_version) {
|
||||||
|
@ -328,12 +322,12 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
||||||
<< "\tFile is from: " << _movie.coreversion << std::endl;
|
<< "\tFile is from: " << _movie.coreversion << std::endl;
|
||||||
}
|
}
|
||||||
bool rom_ok = true;
|
bool rom_ok = true;
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.rom_sha256, our_rom->rom, "ROM #1", will_load_state);
|
for(size_t i = 0; i < sizeof(our_rom->romimg)/sizeof(our_rom->romimg[0]); i++) {
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.romxml_sha256, our_rom->rom_xml, "XML #1", will_load_state);
|
rom_ok = rom_ok & warn_hash_mismatch(_movie.romimg_sha256[i], our_rom->romimg[i],
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slota_sha256, our_rom->slota, "ROM #2", will_load_state);
|
(stringfmt() << "ROM #" << (i + 1)).str(), will_load_state);
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slotaxml_sha256, our_rom->slota_xml, "XML #2", will_load_state);
|
rom_ok = rom_ok & warn_hash_mismatch(_movie.romxml_sha256[i], our_rom->romxml[i],
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slotb_sha256, our_rom->slotb, "ROM #3", will_load_state);
|
(stringfmt() << "XML #" << (i + 1)).str(), will_load_state);
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slotbxml_sha256, our_rom->slotb_xml, "XML #3", will_load_state);
|
}
|
||||||
if(!rom_ok)
|
if(!rom_ok)
|
||||||
throw std::runtime_error("Incorrect ROM");
|
throw std::runtime_error("Incorrect ROM");
|
||||||
|
|
||||||
|
@ -354,7 +348,7 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
||||||
rrdata::read(_movie.c_rrdata);
|
rrdata::read(_movie.c_rrdata);
|
||||||
rrdata::add_internal();
|
rrdata::add_internal();
|
||||||
try {
|
try {
|
||||||
our_rom->region = gtype::toromregion(_movie.gametype);
|
our_rom->region = &(_movie.gametype->get_region());
|
||||||
random_seed_value = _movie.rtc_second;
|
random_seed_value = _movie.rtc_second;
|
||||||
our_rom->load();
|
our_rom->load();
|
||||||
|
|
||||||
|
@ -407,40 +401,8 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
||||||
if(lmode == LOAD_STATE_CURRENT && !current_mode)
|
if(lmode == LOAD_STATE_CURRENT && !current_mode)
|
||||||
movb.get_movie().readonly_mode(false);
|
movb.get_movie().readonly_mode(false);
|
||||||
information_dispatch::do_mode_change(movb.get_movie().readonly_mode());
|
information_dispatch::do_mode_change(movb.get_movie().readonly_mode());
|
||||||
messages << "ROM Type ";
|
messages << "ROM Type " << our_rom->rtype->get_hname() << " region " << our_rom->region->get_hname()
|
||||||
switch(our_rom->rtype) {
|
<< std::endl;
|
||||||
case ROMTYPE_SNES:
|
|
||||||
messages << "SNES";
|
|
||||||
break;
|
|
||||||
case ROMTYPE_BSX:
|
|
||||||
messages << "BS-X";
|
|
||||||
break;
|
|
||||||
case ROMTYPE_BSXSLOTTED:
|
|
||||||
messages << "BS-X slotted";
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SUFAMITURBO:
|
|
||||||
messages << "Sufami Turbo";
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
messages << "Super Game Boy";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
messages << "Unknown";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
messages << " region ";
|
|
||||||
switch(our_rom->region) {
|
|
||||||
case REGION_PAL:
|
|
||||||
messages << "PAL";
|
|
||||||
break;
|
|
||||||
case REGION_NTSC:
|
|
||||||
messages << "NTSC";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
messages << "Unknown";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
messages << std::endl;
|
|
||||||
uint64_t mlength = _movie.get_movie_length();
|
uint64_t mlength = _movie.get_movie_length();
|
||||||
{
|
{
|
||||||
mlength += 999999;
|
mlength += 999999;
|
||||||
|
|
|
@ -296,7 +296,7 @@ porttype_info& parse_controller_type(const std::string& type, unsigned port) thr
|
||||||
moviefile::moviefile() throw(std::bad_alloc)
|
moviefile::moviefile() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
force_corrupt = false;
|
force_corrupt = false;
|
||||||
gametype = GT_INVALID;
|
gametype = NULL;
|
||||||
port1 = &porttype_info::default_type();
|
port1 = &porttype_info::default_type();
|
||||||
port2 = &porttype_info::default_type();
|
port2 = &porttype_info::default_type();
|
||||||
coreversion = "";
|
coreversion = "";
|
||||||
|
@ -323,7 +323,7 @@ moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtim
|
||||||
throw std::runtime_error("Can't decode movie data");
|
throw std::runtime_error("Can't decode movie data");
|
||||||
read_linefile(r, "gametype", tmp);
|
read_linefile(r, "gametype", tmp);
|
||||||
try {
|
try {
|
||||||
gametype = gtype::togametype(tmp);
|
gametype = &core_sysregion::lookup(tmp);
|
||||||
} catch(std::bad_alloc& e) {
|
} catch(std::bad_alloc& e) {
|
||||||
throw;
|
throw;
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
|
@ -340,12 +340,14 @@ moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtim
|
||||||
read_linefile(r, "projectid", projectid);
|
read_linefile(r, "projectid", projectid);
|
||||||
rerecords = read_rrdata(r, c_rrdata);
|
rerecords = read_rrdata(r, c_rrdata);
|
||||||
read_linefile(r, "coreversion", coreversion);
|
read_linefile(r, "coreversion", coreversion);
|
||||||
read_linefile(r, "rom.sha256", rom_sha256, true);
|
read_linefile(r, "rom.sha256", romimg_sha256[0], true);
|
||||||
read_linefile(r, "romxml.sha256", romxml_sha256, true);
|
read_linefile(r, "romxml.sha256", romxml_sha256[0], true);
|
||||||
read_linefile(r, "slota.sha256", slota_sha256, true);
|
for(size_t i = 0; i < 26; i++) {
|
||||||
read_linefile(r, "slotaxml.sha256", slotaxml_sha256, true);
|
read_linefile(r, (stringfmt() << "slot" << (char)(96 + i) << ".sha256").str(), romimg_sha256[i + 1],
|
||||||
read_linefile(r, "slotb.sha256", slotb_sha256, true);
|
true);
|
||||||
read_linefile(r, "slotbxml.sha256", slotbxml_sha256, true);
|
read_linefile(r, (stringfmt() << "slot" << (char)(96 + i) << "xml.sha256").str(),
|
||||||
|
romxml_sha256[i + 1], true);
|
||||||
|
}
|
||||||
read_linefile(r, "prefix", prefix, true);
|
read_linefile(r, "prefix", prefix, true);
|
||||||
prefix = sanitize_prefix(prefix);
|
prefix = sanitize_prefix(prefix);
|
||||||
movie_rtc_second = DEFAULT_RTC_SECOND;
|
movie_rtc_second = DEFAULT_RTC_SECOND;
|
||||||
|
@ -388,7 +390,7 @@ moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtim
|
||||||
void moviefile::save(const std::string& movie, unsigned compression) throw(std::bad_alloc, std::runtime_error)
|
void moviefile::save(const std::string& movie, unsigned compression) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
zip_writer w(movie, compression);
|
zip_writer w(movie, compression);
|
||||||
write_linefile(w, "gametype", gtype::tostring(gametype));
|
write_linefile(w, "gametype", gametype->get_name());
|
||||||
if(port1->name != porttype_info::port_default(0).name)
|
if(port1->name != porttype_info::port_default(0).name)
|
||||||
write_linefile(w, "port1", port1->name);
|
write_linefile(w, "port1", port1->name);
|
||||||
if(port2->name != porttype_info::port_default(1).name)
|
if(port2->name != porttype_info::port_default(1).name)
|
||||||
|
@ -400,12 +402,14 @@ void moviefile::save(const std::string& movie, unsigned compression) throw(std::
|
||||||
write_linefile(w, "coreversion", coreversion);
|
write_linefile(w, "coreversion", coreversion);
|
||||||
write_linefile(w, "projectid", projectid);
|
write_linefile(w, "projectid", projectid);
|
||||||
write_rrdata(w);
|
write_rrdata(w);
|
||||||
write_linefile(w, "rom.sha256", rom_sha256, true);
|
write_linefile(w, "rom.sha256", romimg_sha256[0], true);
|
||||||
write_linefile(w, "romxml.sha256", romxml_sha256, true);
|
write_linefile(w, "romxml.sha256", romxml_sha256[0], true);
|
||||||
write_linefile(w, "slota.sha256", slota_sha256, true);
|
for(size_t i = 0; i < 26; i++) {
|
||||||
write_linefile(w, "slotaxml.sha256", slotaxml_sha256, true);
|
write_linefile(w, (stringfmt() << "slot" << (char)(96 + i) << ".sha256").str(), romimg_sha256[i + 1],
|
||||||
write_linefile(w, "slotb.sha256", slotb_sha256, true);
|
true);
|
||||||
write_linefile(w, "slotbxml.sha256", slotbxml_sha256, true);
|
write_linefile(w, (stringfmt() << "slot" << (char)(96 + i) << "xml.sha256").str(),
|
||||||
|
romxml_sha256[i + 1], true);
|
||||||
|
}
|
||||||
write_linefile(w, "prefix", prefix, true);
|
write_linefile(w, "prefix", prefix, true);
|
||||||
for(auto i : movie_sram)
|
for(auto i : movie_sram)
|
||||||
write_raw_file(w, "moviesram." + i.first, i.second);
|
write_raw_file(w, "moviesram." + i.first, i.second);
|
||||||
|
@ -454,62 +458,14 @@ uint64_t moviefile::get_movie_length(uint64_t framebias) throw()
|
||||||
frames -= framebias;
|
frames -= framebias;
|
||||||
else
|
else
|
||||||
frames = 0;
|
frames = 0;
|
||||||
uint64_t* _magic = magic[(gametype == GT_SNES_PAL || gametype == GT_SGB_PAL) ? 1 : 0];
|
uint64_t _magic[4];
|
||||||
|
gametype->fill_framerate_magic(_magic);
|
||||||
uint64_t t = _magic[BLOCK_SECONDS] * 1000000000ULL * (frames / _magic[BLOCK_FRAMES]);
|
uint64_t t = _magic[BLOCK_SECONDS] * 1000000000ULL * (frames / _magic[BLOCK_FRAMES]);
|
||||||
frames %= _magic[BLOCK_FRAMES];
|
frames %= _magic[BLOCK_FRAMES];
|
||||||
t += frames * _magic[STEP_W] + (frames * _magic[STEP_N] / _magic[BLOCK_FRAMES]);
|
t += frames * _magic[STEP_W] + (frames * _magic[STEP_N] / _magic[BLOCK_FRAMES]);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
gametype_t gametype_compose(rom_type type, rom_region region)
|
|
||||||
{
|
|
||||||
switch(type) {
|
|
||||||
case ROMTYPE_SNES:
|
|
||||||
return (region == REGION_PAL) ? GT_SNES_PAL : GT_SNES_NTSC;
|
|
||||||
case ROMTYPE_BSX:
|
|
||||||
return GT_BSX;
|
|
||||||
case ROMTYPE_BSXSLOTTED:
|
|
||||||
return GT_BSX_SLOTTED;
|
|
||||||
case ROMTYPE_SUFAMITURBO:
|
|
||||||
return GT_SUFAMITURBO;
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
return (region == REGION_PAL) ? GT_SGB_PAL : GT_SGB_NTSC;
|
|
||||||
default:
|
|
||||||
return GT_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rom_region gametype_region(gametype_t type)
|
|
||||||
{
|
|
||||||
switch(type) {
|
|
||||||
case GT_SGB_PAL:
|
|
||||||
case GT_SNES_PAL:
|
|
||||||
return REGION_PAL;
|
|
||||||
default:
|
|
||||||
return REGION_NTSC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rom_type gametype_romtype(gametype_t type)
|
|
||||||
{
|
|
||||||
switch(type) {
|
|
||||||
case GT_SNES_NTSC:
|
|
||||||
case GT_SNES_PAL:
|
|
||||||
return ROMTYPE_SNES;
|
|
||||||
case GT_BSX:
|
|
||||||
return ROMTYPE_BSX;
|
|
||||||
case GT_BSX_SLOTTED:
|
|
||||||
return ROMTYPE_BSXSLOTTED;
|
|
||||||
case GT_SUFAMITURBO:
|
|
||||||
return ROMTYPE_SUFAMITURBO;
|
|
||||||
case GT_SGB_PAL:
|
|
||||||
case GT_SGB_NTSC:
|
|
||||||
return ROMTYPE_SGB;
|
|
||||||
default:
|
|
||||||
return ROMTYPE_NONE;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string sanitize_prefix(const std::string& in) throw(std::bad_alloc)
|
std::string sanitize_prefix(const std::string& in) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
|
|
519
src/core/rom.cpp
519
src/core/rom.cpp
|
@ -39,156 +39,26 @@
|
||||||
#define SGB_PAL "sgb_pal"
|
#define SGB_PAL "sgb_pal"
|
||||||
#define SGB_NTSC "sgb_ntsc"
|
#define SGB_NTSC "sgb_ntsc"
|
||||||
|
|
||||||
std::string gtype::tostring(rom_type rtype, rom_region region) throw(std::bad_alloc, std::runtime_error)
|
/**
|
||||||
{
|
* Recognize the slot this ROM goes to.
|
||||||
switch(rtype) {
|
*
|
||||||
case ROMTYPE_SNES:
|
* parameter major: The major type.
|
||||||
switch(region) {
|
* parameter romname: Name of the ROM type.
|
||||||
case REGION_AUTO: return "snes";
|
* returns: Even if this is main rom, odd if XML. 0/1 for main slot, 2/3 for slot A, 4/5 for slot B. -1 if not valid
|
||||||
case REGION_NTSC: return "snes_ntsc";
|
* rom type.
|
||||||
case REGION_PAL: return "snes_pal";
|
* throws std::bad_alloc: Not enough memory
|
||||||
};
|
*/
|
||||||
case ROMTYPE_SGB:
|
int recognize_commandline_rom(core_type& major, const std::string& romname) throw(std::bad_alloc);
|
||||||
switch(region) {
|
|
||||||
case REGION_AUTO: return "sgb";
|
|
||||||
case REGION_NTSC: return "sgb_ntsc";
|
|
||||||
case REGION_PAL: return "sgb_pal";
|
|
||||||
};
|
|
||||||
case ROMTYPE_BSX: return "bsx";
|
|
||||||
case ROMTYPE_BSXSLOTTED: return "bsxslotted";
|
|
||||||
case ROMTYPE_SUFAMITURBO: return "sufamiturbo";
|
|
||||||
default: throw std::runtime_error("tostring: ROMTYPE_NONE");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string gtype::tostring(gametype_t gametype) throw(std::bad_alloc, std::runtime_error)
|
/**
|
||||||
{
|
* Recognize major type from flags.
|
||||||
switch(gametype) {
|
*
|
||||||
case GT_SNES_NTSC: return "snes_ntsc";
|
* parameter flags: Flags telling what ROM parameters are present.
|
||||||
case GT_SNES_PAL: return "snes_pal";
|
* returns: The recognzed major type.
|
||||||
case GT_SGB_NTSC: return "sgb_ntsc";
|
* throws std::bad_alloc: Not enough memory
|
||||||
case GT_SGB_PAL: return "sgb_pal";
|
* throws std::runtime_error: Illegal flags.
|
||||||
case GT_BSX: return "bsx";
|
*/
|
||||||
case GT_BSX_SLOTTED: return "bsxslotted";
|
core_type& recognize_platform(const std::set<std::string>& present) throw(std::bad_alloc, std::runtime_error);
|
||||||
case GT_SUFAMITURBO: return "sufamiturbo";
|
|
||||||
default: throw std::runtime_error("tostring: GT_INVALID");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
gametype_t gtype::togametype(rom_type rtype, rom_region region) throw(std::bad_alloc, std::runtime_error)
|
|
||||||
{
|
|
||||||
switch(rtype) {
|
|
||||||
case ROMTYPE_SNES:
|
|
||||||
switch(region) {
|
|
||||||
case REGION_AUTO: return GT_SGB_NTSC;
|
|
||||||
case REGION_NTSC: return GT_SNES_NTSC;
|
|
||||||
case REGION_PAL: return GT_SNES_PAL;
|
|
||||||
};
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
switch(region) {
|
|
||||||
case REGION_AUTO: return GT_SGB_NTSC;
|
|
||||||
case REGION_NTSC: return GT_SGB_NTSC;
|
|
||||||
case REGION_PAL: return GT_SGB_PAL;
|
|
||||||
};
|
|
||||||
case ROMTYPE_BSX: return GT_BSX;
|
|
||||||
case ROMTYPE_BSXSLOTTED: return GT_BSX_SLOTTED;
|
|
||||||
case ROMTYPE_SUFAMITURBO: return GT_SUFAMITURBO;
|
|
||||||
default: throw std::runtime_error("togametype: ROMTYPE_NONE");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
gametype_t gtype::togametype(const std::string& gametype) throw(std::bad_alloc, std::runtime_error)
|
|
||||||
{
|
|
||||||
if(gametype == "snes_ntsc")
|
|
||||||
return GT_SNES_NTSC;
|
|
||||||
if(gametype == "snes_pal")
|
|
||||||
return GT_SNES_PAL;
|
|
||||||
if(gametype == "sgb_ntsc")
|
|
||||||
return GT_SGB_NTSC;
|
|
||||||
if(gametype == "sgb_pal")
|
|
||||||
return GT_SGB_PAL;
|
|
||||||
if(gametype == "bsx")
|
|
||||||
return GT_BSX;
|
|
||||||
if(gametype == "bsxslotted")
|
|
||||||
return GT_BSX_SLOTTED;
|
|
||||||
if(gametype == "sufamiturbo")
|
|
||||||
return GT_SUFAMITURBO;
|
|
||||||
throw std::runtime_error("Unknown game type '" + gametype + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
rom_type gtype::toromtype(const std::string& gametype) throw(std::bad_alloc, std::runtime_error)
|
|
||||||
{
|
|
||||||
if(gametype == "snes_ntsc")
|
|
||||||
return ROMTYPE_SNES;
|
|
||||||
if(gametype == "snes_pal")
|
|
||||||
return ROMTYPE_SNES;
|
|
||||||
if(gametype == "snes")
|
|
||||||
return ROMTYPE_SNES;
|
|
||||||
if(gametype == "sgb_ntsc")
|
|
||||||
return ROMTYPE_SGB;
|
|
||||||
if(gametype == "sgb_pal")
|
|
||||||
return ROMTYPE_SGB;
|
|
||||||
if(gametype == "sgb")
|
|
||||||
return ROMTYPE_SGB;
|
|
||||||
if(gametype == "bsx")
|
|
||||||
return ROMTYPE_BSX;
|
|
||||||
if(gametype == "bsxslotted")
|
|
||||||
return ROMTYPE_BSXSLOTTED;
|
|
||||||
if(gametype == "sufamiturbo")
|
|
||||||
return ROMTYPE_SUFAMITURBO;
|
|
||||||
throw std::runtime_error("Unknown game type '" + gametype + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
rom_type gtype::toromtype(gametype_t gametype) throw()
|
|
||||||
{
|
|
||||||
switch(gametype) {
|
|
||||||
case GT_SNES_NTSC: return ROMTYPE_SNES;
|
|
||||||
case GT_SNES_PAL: return ROMTYPE_SNES;
|
|
||||||
case GT_SGB_NTSC: return ROMTYPE_SGB;
|
|
||||||
case GT_SGB_PAL: return ROMTYPE_SGB;
|
|
||||||
case GT_BSX: return ROMTYPE_BSX;
|
|
||||||
case GT_BSX_SLOTTED: return ROMTYPE_BSXSLOTTED;
|
|
||||||
case GT_SUFAMITURBO: return ROMTYPE_SUFAMITURBO;
|
|
||||||
case GT_INVALID: throw std::runtime_error("toromtype: GT_INVALID");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
rom_region gtype::toromregion(const std::string& gametype) throw(std::bad_alloc, std::runtime_error)
|
|
||||||
{
|
|
||||||
if(gametype == "snes_ntsc")
|
|
||||||
return REGION_NTSC;
|
|
||||||
if(gametype == "snes_pal")
|
|
||||||
return REGION_PAL;
|
|
||||||
if(gametype == "snes")
|
|
||||||
return REGION_AUTO;
|
|
||||||
if(gametype == "sgb_ntsc")
|
|
||||||
return REGION_NTSC;
|
|
||||||
if(gametype == "sgb_pal")
|
|
||||||
return REGION_PAL;
|
|
||||||
if(gametype == "sgb")
|
|
||||||
return REGION_AUTO;
|
|
||||||
if(gametype == "bsx")
|
|
||||||
return REGION_NTSC;
|
|
||||||
if(gametype == "bsxslotted")
|
|
||||||
return REGION_NTSC;
|
|
||||||
if(gametype == "sufamiturbo")
|
|
||||||
return REGION_NTSC;
|
|
||||||
throw std::runtime_error("Unknown game type '" + gametype + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
rom_region gtype::toromregion(gametype_t gametype) throw()
|
|
||||||
{
|
|
||||||
switch(gametype) {
|
|
||||||
case GT_SNES_NTSC: return REGION_NTSC;
|
|
||||||
case GT_SNES_PAL: return REGION_PAL;
|
|
||||||
case GT_SGB_NTSC: return REGION_NTSC;
|
|
||||||
case GT_SGB_PAL: return REGION_PAL;
|
|
||||||
case GT_BSX: return REGION_NTSC;
|
|
||||||
case GT_BSX_SLOTTED: return REGION_NTSC;
|
|
||||||
case GT_SUFAMITURBO: return REGION_NTSC;
|
|
||||||
case GT_INVALID: throw std::runtime_error("toromregion: GT_INVALID");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -201,13 +71,8 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* romtypes_to_recognize[] = {
|
core_type* current_rom_type = NULL;
|
||||||
"rom", "bsx", "bsxslotted", "dmg", "slot-a", "slot-b",
|
core_region* current_region = NULL;
|
||||||
"rom-xml", "bsx-xml", "bsxslotted-xml", "dmg-xml", "slot-a-xml", "slot-b-xml"
|
|
||||||
};
|
|
||||||
|
|
||||||
enum rom_type current_rom_type = ROMTYPE_NONE;
|
|
||||||
enum rom_region current_region = REGION_NTSC;
|
|
||||||
|
|
||||||
std::string findoption(const std::vector<std::string>& cmdline, const std::string& option)
|
std::string findoption(const std::vector<std::string>& cmdline, const std::string& option)
|
||||||
{
|
{
|
||||||
|
@ -226,6 +91,21 @@ namespace
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<std::string> find_present_roms(const std::vector<std::string>& cmdline)
|
||||||
|
{
|
||||||
|
std::set<std::string> p;
|
||||||
|
std::set<core_type*> types = core_type::get_core_types();
|
||||||
|
for(auto i : types) {
|
||||||
|
for(unsigned j = 0; j < i->get_image_count(); j++) {
|
||||||
|
std::string iname = i->get_image_info(j).iname;
|
||||||
|
if(findoption(cmdline, iname) != "")
|
||||||
|
p.insert(iname);
|
||||||
|
if(findoption(cmdline, iname + "-xml") != "")
|
||||||
|
p.insert(iname + "-xml");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded_slot::loaded_slot() throw(std::bad_alloc)
|
loaded_slot::loaded_slot() throw(std::bad_alloc)
|
||||||
|
@ -288,159 +168,128 @@ void loaded_slot::patch(const std::vector<char>& patch, int32_t offset) throw(st
|
||||||
|
|
||||||
rom_files::rom_files() throw()
|
rom_files::rom_files() throw()
|
||||||
{
|
{
|
||||||
rtype = ROMTYPE_NONE;
|
rtype = NULL;
|
||||||
region = REGION_AUTO;
|
region = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rom_files::rom_files(const std::vector<std::string>& cmdline) throw(std::bad_alloc, std::runtime_error)
|
rom_files::rom_files(const std::vector<std::string>& cmdline) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
rom = rom_xml = slota = slota_xml = slotb = slotb_xml = "";
|
for(size_t i = 0; i < sizeof(romimg) / sizeof(romimg[0]); i++) {
|
||||||
std::string arr[sizeof(romtypes_to_recognize) / sizeof(romtypes_to_recognize[0])];
|
romimg[i] = "";
|
||||||
unsigned long flags = 0;
|
romxml[i] = "";
|
||||||
for(size_t i = 0; i < sizeof(romtypes_to_recognize) / sizeof(romtypes_to_recognize[0]); i++) {
|
|
||||||
arr[i] = findoption(cmdline, romtypes_to_recognize[i]);
|
|
||||||
if(arr[i] != "")
|
|
||||||
flags |= (1L << i);
|
|
||||||
}
|
}
|
||||||
rtype = recognize_platform(flags);
|
|
||||||
for(size_t i = 0; i < sizeof(romtypes_to_recognize) / sizeof(romtypes_to_recognize[0]); i++) {
|
|
||||||
if(arr[i] != "")
|
|
||||||
switch(recognize_commandline_rom(rtype, romtypes_to_recognize[i])) {
|
|
||||||
case 0: rom = arr[i]; break;
|
|
||||||
case 1: rom_xml = arr[i]; break;
|
|
||||||
case 2: slota = arr[i]; break;
|
|
||||||
case 3: slota_xml = arr[i]; break;
|
|
||||||
case 4: slotb = arr[i]; break;
|
|
||||||
case 5: slotb_xml = arr[i]; break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
region = (rtype == ROMTYPE_SGB || rtype == ROMTYPE_SNES) ? REGION_AUTO : REGION_NTSC;
|
|
||||||
if(option_set(cmdline, "--ntsc"))
|
|
||||||
region = REGION_NTSC;
|
|
||||||
else if(option_set(cmdline, "--pal"))
|
|
||||||
region = REGION_PAL;
|
|
||||||
|
|
||||||
|
auto opts = find_present_roms(cmdline);
|
||||||
|
rtype = &recognize_platform(opts);
|
||||||
|
for(auto i : opts) {
|
||||||
|
std::string o = findoption(cmdline, i);
|
||||||
|
if(o != "") {
|
||||||
|
int j = recognize_commandline_rom(*rtype, i);
|
||||||
|
if(j >= 0 && j & 1)
|
||||||
|
romxml[j / 2] = o;
|
||||||
|
else if(j >= 0)
|
||||||
|
romimg[j / 2] = o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
region = &rtype->get_preferred_region();
|
||||||
|
std::string _region = findoption(cmdline, "region");
|
||||||
|
if(_region != "") {
|
||||||
|
bool isset = false;
|
||||||
|
for(auto i : rtype->get_regions()) {
|
||||||
|
if(i->get_iname() == _region) {
|
||||||
|
region = i;
|
||||||
|
isset = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!isset)
|
||||||
|
throw std::runtime_error("Unknown region for system type");
|
||||||
|
}
|
||||||
base_file = "";
|
base_file = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void rom_files::resolve_relative() throw(std::bad_alloc, std::runtime_error)
|
void rom_files::resolve_relative() throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
rom = resolve_file_relative(rom, base_file);
|
for(size_t i = 0; i < sizeof(romimg)/sizeof(romimg[0]); i++) {
|
||||||
rom_xml = resolve_file_relative(rom_xml, base_file);
|
romimg[i] = resolve_file_relative(romimg[i], base_file);
|
||||||
slota = resolve_file_relative(slota, base_file);
|
romxml[i] = resolve_file_relative(romxml[i], base_file);
|
||||||
slota_xml = resolve_file_relative(slota_xml, base_file);
|
}
|
||||||
slotb = resolve_file_relative(slotb, base_file);
|
|
||||||
slotb_xml = resolve_file_relative(slotb_xml, base_file);
|
|
||||||
base_file = "";
|
base_file = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair<enum rom_type, enum rom_region> get_current_rom_info() throw()
|
std::pair<core_type*, core_region*> get_current_rom_info() throw()
|
||||||
{
|
{
|
||||||
return std::make_pair(current_rom_type, current_region);
|
return std::make_pair(current_rom_type, current_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded_rom::loaded_rom() throw()
|
loaded_rom::loaded_rom() throw()
|
||||||
{
|
{
|
||||||
rtype = ROMTYPE_NONE;
|
rtype = NULL;
|
||||||
region = orig_region = REGION_AUTO;
|
region = orig_region = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded_rom::loaded_rom(const rom_files& files) throw(std::bad_alloc, std::runtime_error)
|
loaded_rom::loaded_rom(const rom_files& files) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
std::string _slota = files.slota;
|
std::string cromimg[sizeof(files.romimg)/sizeof(files.romimg[0])];
|
||||||
std::string _slota_xml = files.slota_xml;
|
std::string cromxml[sizeof(files.romimg)/sizeof(files.romimg[0])];
|
||||||
std::string _slotb = files.slotb;
|
for(size_t i = 0; i < sizeof(files.romimg)/sizeof(files.romimg[0]); i++) {
|
||||||
std::string _slotb_xml = files.slotb_xml;
|
cromimg[i] = files.romimg[i];
|
||||||
if(files.rtype == ROMTYPE_NONE) {
|
cromxml[i] = files.romxml[i];
|
||||||
rtype = ROMTYPE_NONE;
|
}
|
||||||
|
if(!files.rtype) {
|
||||||
|
rtype = NULL;
|
||||||
region = orig_region = files.region;
|
region = orig_region = files.region;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if((_slota != "" || _slota_xml != "") && files.rtype == ROMTYPE_SNES) {
|
for(size_t i = 0; i < sizeof(files.romimg)/sizeof(files.romimg[0]); i++) {
|
||||||
messages << "WARNING: SNES takes only 1 ROM image" << std::endl;
|
if((cromimg[i] != "" || cromxml[i] != "") && i > rtype->get_image_count()) {
|
||||||
_slota = "";
|
messages << "Warning: ROM slot #" << (i + 1) << " is not used for this console" << std::endl;
|
||||||
_slota_xml = "";
|
cromimg[i] = "";
|
||||||
|
cromxml[i] = "";
|
||||||
|
}
|
||||||
|
if(cromimg[i] == "" && cromxml[i] != "") {
|
||||||
|
messages << "WARNING: " << name_subrom(*files.rtype, 2 * i + 1) << " specified without "
|
||||||
|
<< "corresponding " << name_subrom(*files.rtype, 2 * i + 0) << std::endl;
|
||||||
|
cromxml[i] = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if((_slotb != "" || _slotb_xml != "") && files.rtype != ROMTYPE_SUFAMITURBO) {
|
|
||||||
messages << "WARNING: Only Sufami Turbo takes 3 ROM images" << std::endl;
|
|
||||||
_slotb = "";
|
|
||||||
_slotb_xml = "";
|
|
||||||
}
|
|
||||||
if(files.rom_xml != "" && files.rom == "")
|
|
||||||
messages << "WARNING: " << name_subrom(files.rtype, 0) << " specified without corresponding "
|
|
||||||
<< name_subrom(files.rtype, 1) << std::endl;
|
|
||||||
if(_slota_xml != "" && _slota == "")
|
|
||||||
messages << "WARNING: " << name_subrom(files.rtype, 2) << " specified without corresponding "
|
|
||||||
<< name_subrom(files.rtype, 3) << std::endl;
|
|
||||||
if(_slotb_xml != "" && _slotb == "")
|
|
||||||
messages << "WARNING: " << name_subrom(files.rtype, 4) << " specified without corresponding "
|
|
||||||
<< name_subrom(files.rtype, 5) << std::endl;
|
|
||||||
|
|
||||||
rtype = files.rtype;
|
rtype = files.rtype;
|
||||||
rom = loaded_slot(files.rom, files.base_file, false);
|
for(size_t i = 0; i < sizeof(romimg) / sizeof(romimg[0]); i++) {
|
||||||
rom_xml = loaded_slot(files.rom_xml, files.base_file, true);
|
romimg[i] = loaded_slot(cromimg[i], files.base_file, false);
|
||||||
slota = loaded_slot(_slota, files.base_file, false);
|
romxml[i] = loaded_slot(cromxml[i], files.base_file, true);
|
||||||
slota_xml = loaded_slot(_slota_xml, files.base_file, true);
|
}
|
||||||
slotb = loaded_slot(_slotb, files.base_file, false);
|
|
||||||
slotb_xml = loaded_slot(_slotb_xml, files.base_file, true);
|
|
||||||
orig_region = region = files.region;
|
orig_region = region = files.region;
|
||||||
if(files.rtype == ROMTYPE_SNES)
|
if(cromimg[1] != "")
|
||||||
msu1_base = resolve_file_relative(files.rom, files.base_file);
|
msu1_base = resolve_file_relative(cromimg[1], files.base_file);
|
||||||
else
|
else
|
||||||
msu1_base = resolve_file_relative(_slota, files.base_file);
|
msu1_base = resolve_file_relative(cromimg[0], files.base_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loaded_rom::load() throw(std::bad_alloc, std::runtime_error)
|
void loaded_rom::load() throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
current_rom_type = ROMTYPE_NONE;
|
if(!rtype)
|
||||||
if(region == REGION_AUTO && orig_region != REGION_AUTO)
|
|
||||||
region = orig_region;
|
|
||||||
if(region != orig_region && orig_region != REGION_AUTO)
|
|
||||||
throw std::runtime_error("Trying to force incompatible region");
|
|
||||||
if(rtype == ROMTYPE_NONE)
|
|
||||||
throw std::runtime_error("Can't insert cartridge of type NONE!");
|
throw std::runtime_error("Can't insert cartridge of type NONE!");
|
||||||
switch(region) {
|
current_rom_type = NULL;
|
||||||
case REGION_AUTO: core_set_region(EC_REGION_AUTO); break;
|
if(!orig_region)
|
||||||
case REGION_NTSC: core_set_region(EC_REGION_NTSC); break;
|
orig_region = &rtype->get_preferred_region();
|
||||||
case REGION_PAL: core_set_region(EC_REGION_PAL); break;
|
if(!region)
|
||||||
default:
|
region = orig_region;
|
||||||
|
if(!orig_region->compatible_with(*region))
|
||||||
|
throw std::runtime_error("Trying to force incompatible region");
|
||||||
|
if(!core_set_region(*region))
|
||||||
throw std::runtime_error("Trying to force unknown region");
|
throw std::runtime_error("Trying to force unknown region");
|
||||||
|
|
||||||
|
core_romimage images[sizeof(romimg)/sizeof(romimg[0])];
|
||||||
|
for(size_t i = 0; i < sizeof(romimg)/sizeof(romimg[0]); i++) {
|
||||||
|
images[i].markup = (const char*)romxml[i];
|
||||||
|
images[i].data = (const unsigned char*)romimg[i];
|
||||||
|
images[i].size = (size_t)romimg[i];
|
||||||
}
|
}
|
||||||
switch(rtype) {
|
if(!rtype->load(images))
|
||||||
case ROMTYPE_SNES:
|
throw std::runtime_error("Can't load cartridge ROM");
|
||||||
if(!core_load_cartridge_normal(rom_xml, rom, rom))
|
|
||||||
throw std::runtime_error("Can't load cartridge ROM");
|
region = &core_get_region();
|
||||||
break;
|
|
||||||
case ROMTYPE_BSX:
|
|
||||||
if(region == REGION_PAL)
|
|
||||||
throw std::runtime_error("BSX can't be PAL");
|
|
||||||
if(!core_load_cartridge_bsx(rom_xml, rom, rom, slota_xml, slota, slota))
|
|
||||||
throw std::runtime_error("Can't load cartridge ROM");
|
|
||||||
break;
|
|
||||||
case ROMTYPE_BSXSLOTTED:
|
|
||||||
if(region == REGION_PAL)
|
|
||||||
throw std::runtime_error("Slotted BSX can't be PAL");
|
|
||||||
if(!core_load_cartridge_bsx_slotted(rom_xml, rom, rom, slota_xml, slota, slota))
|
|
||||||
throw std::runtime_error("Can't load cartridge ROM");
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
if(!core_load_cartridge_super_game_boy(rom_xml, rom, rom, slota_xml, slota, slota))
|
|
||||||
throw std::runtime_error("Can't load cartridge ROM");
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SUFAMITURBO:
|
|
||||||
if(region == REGION_PAL)
|
|
||||||
throw std::runtime_error("Sufami Turbo can't be PAL");
|
|
||||||
if(!core_load_cartridge_sufami_turbo(rom_xml, rom, rom, slota_xml, slota, slota, slotb_xml, slotb,
|
|
||||||
slotb))
|
|
||||||
throw std::runtime_error("Can't load cartridge ROM");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unknown cartridge type");
|
|
||||||
}
|
|
||||||
if(region == REGION_AUTO)
|
|
||||||
region = core_get_region() ? REGION_PAL : REGION_NTSC;
|
|
||||||
core_power();
|
core_power();
|
||||||
auto nominal_fps = get_video_rate();
|
auto nominal_fps = get_video_rate();
|
||||||
auto nominal_hz = get_audio_rate();
|
auto nominal_hz = get_audio_rate();
|
||||||
|
@ -476,16 +325,13 @@ void loaded_rom::do_patch(const std::vector<std::string>& cmdline) throw(std::ba
|
||||||
throw std::runtime_error("Can't read IPS '" + opt[2] + "': " + e.what());
|
throw std::runtime_error("Can't read IPS '" + opt[2] + "': " + e.what());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
switch(recognize_commandline_rom(rtype, opt[1])) {
|
int r_id = recognize_commandline_rom(*rtype, opt[1]);
|
||||||
case 0: rom.patch(ips, offset); break;
|
if(r_id < 0 || r_id > 2 * sizeof(romimg) / sizeof(romimg[0]))
|
||||||
case 1: rom_xml.patch(ips, offset); break;
|
|
||||||
case 2: slota.patch(ips, offset); break;
|
|
||||||
case 3: slota_xml.patch(ips, offset); break;
|
|
||||||
case 4: slotb.patch(ips, offset); break;
|
|
||||||
case 5: slotb_xml.patch(ips, offset); break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid subROM '" + opt[1] + "' to patch");
|
throw std::runtime_error("Invalid subROM '" + opt[1] + "' to patch");
|
||||||
}
|
if(r_id & 1)
|
||||||
|
romxml[r_id / 2].patch(ips, offset);
|
||||||
|
else
|
||||||
|
romimg[r_id / 2].patch(ips, offset);
|
||||||
} catch(std::bad_alloc& e) {
|
} catch(std::bad_alloc& e) {
|
||||||
OOM_panic();
|
OOM_panic();
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
|
@ -563,84 +409,59 @@ void load_core_state(const std::vector<char>& buf, bool nochecksum) throw(std::r
|
||||||
core_unserialize(&buf[0], buf.size() - 32);;
|
core_unserialize(&buf[0], buf.size() - 32);;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name_subrom(enum rom_type major, unsigned romnumber) throw(std::bad_alloc)
|
std::string name_subrom(core_type& major, unsigned romnumber) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
if(romnumber == 0)
|
std::string name = "UNKNOWN";
|
||||||
|
if(romnumber < 2 * major.get_image_count())
|
||||||
|
name = major.get_image_info(romnumber / 2).hname;
|
||||||
|
if(romnumber % 2)
|
||||||
|
return name + " XML";
|
||||||
|
else if(name != "ROM")
|
||||||
|
return name + " ROM";
|
||||||
|
else
|
||||||
return "ROM";
|
return "ROM";
|
||||||
else if(romnumber == 1)
|
|
||||||
return "ROM XML";
|
|
||||||
else if(major == ROMTYPE_BSX && romnumber == 2)
|
|
||||||
return "BSX ROM";
|
|
||||||
else if(major == ROMTYPE_BSX && romnumber == 3)
|
|
||||||
return "BSX XML";
|
|
||||||
else if(major == ROMTYPE_BSXSLOTTED && romnumber == 2)
|
|
||||||
return "BSX ROM";
|
|
||||||
else if(major == ROMTYPE_BSXSLOTTED && romnumber == 3)
|
|
||||||
return "BSX XML";
|
|
||||||
else if(major == ROMTYPE_SGB && romnumber == 2)
|
|
||||||
return "DMG ROM";
|
|
||||||
else if(major == ROMTYPE_SGB && romnumber == 3)
|
|
||||||
return "DMG XML";
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 2)
|
|
||||||
return "SLOT A ROM";
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 3)
|
|
||||||
return "SLOT A XML";
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 4)
|
|
||||||
return "SLOT B ROM";
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 5)
|
|
||||||
return "SLOT B XML";
|
|
||||||
else if(romnumber % 2)
|
|
||||||
return "UNKNOWN XML";
|
|
||||||
else
|
|
||||||
return "UNKNOWN ROM";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int recognize_commandline_rom(enum rom_type major, const std::string& romname) throw(std::bad_alloc)
|
int recognize_commandline_rom(core_type& major, const std::string& romname) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
if(romname == romtypes_to_recognize[0])
|
for(unsigned i = 0; i < major.get_image_count(); i++) {
|
||||||
return 0;
|
std::string iname = major.get_image_info(i).iname;
|
||||||
else if(romname == romtypes_to_recognize[6])
|
if(romname == iname)
|
||||||
return 1;
|
return 2 * i + 0;
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[1])
|
if(romname == iname + "-xml")
|
||||||
return 2;
|
return 2 * i + 1;
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[7])
|
}
|
||||||
return 3;
|
return -1;
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[2])
|
|
||||||
return 2;
|
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[8])
|
|
||||||
return 3;
|
|
||||||
else if(major == ROMTYPE_SGB && romname == romtypes_to_recognize[3])
|
|
||||||
return 2;
|
|
||||||
else if(major == ROMTYPE_SGB && romname == romtypes_to_recognize[9])
|
|
||||||
return 3;
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romname == romtypes_to_recognize[4])
|
|
||||||
return 2;
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romname == romtypes_to_recognize[10])
|
|
||||||
return 3;
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romname == romtypes_to_recognize[5])
|
|
||||||
return 4;
|
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romname == romtypes_to_recognize[11])
|
|
||||||
return 5;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rom_type recognize_platform(unsigned long flags) throw(std::bad_alloc, std::runtime_error)
|
core_type& recognize_platform(const std::set<std::string>& present) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
if((flags & 07700) >> 6 & ~(flags & 077))
|
std::set<core_type*> possible = core_type::get_core_types();
|
||||||
throw std::runtime_error("SubROM XML specified without corresponding subROM");
|
unsigned total = 0;
|
||||||
if((flags & 1) == 0)
|
for(auto i : present) {
|
||||||
throw std::runtime_error("No SNES main cartridge ROM specified");
|
regex_results r;
|
||||||
if((flags & 077) == 1)
|
std::string base = i;
|
||||||
return ROMTYPE_SNES;
|
if(r = regex("(.*)-xml", base)) {
|
||||||
if((flags & 077) == 3)
|
if(!present.count(r[1]))
|
||||||
return ROMTYPE_BSX;
|
throw std::runtime_error("SubROM XML specified without corresponding subROM");
|
||||||
if((flags & 077) == 5)
|
} else
|
||||||
return ROMTYPE_BSXSLOTTED;
|
total++;
|
||||||
if((flags & 077) == 9)
|
}
|
||||||
return ROMTYPE_SGB;
|
for(auto i : possible) {
|
||||||
if((flags & 060) != 0 && (flags & 017) == 1)
|
unsigned pmask = 0;
|
||||||
return ROMTYPE_SUFAMITURBO;
|
unsigned rmask = 0;
|
||||||
throw std::runtime_error("Not valid combination of rom/bsx/bsxslotted/dmg/slot-a/slot-b");
|
unsigned found = 0;
|
||||||
|
for(unsigned j = 0; j < i->get_image_count(); j++) {
|
||||||
|
std::string iname = i->get_image_info(j).iname;
|
||||||
|
if(present.count(iname)) {
|
||||||
|
pmask |= i->get_image_info(j).mandatory;
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
rmask |= i->get_image_info(j).mandatory;
|
||||||
|
}
|
||||||
|
if(pmask == rmask && found == total)
|
||||||
|
return *i;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Invalid combination of subROMs");
|
||||||
}
|
}
|
||||||
|
|
259
src/core/romtype.cpp
Normal file
259
src/core/romtype.cpp
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
#include "core/romtype.hpp"
|
||||||
|
#include "library/minmax.hpp"
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::map<std::string, core_sysregion*>& sysregions()
|
||||||
|
{
|
||||||
|
static std::map<std::string, core_sysregion*> x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, core_type*>& types()
|
||||||
|
{
|
||||||
|
static std::map<std::string, core_type*> x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, core_region*>& regionss()
|
||||||
|
{
|
||||||
|
static std::map<std::string, core_region*> x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::pair<core_type*, core_region*>>& reglist1()
|
||||||
|
{
|
||||||
|
static std::list<std::pair<core_type*, core_region*>> x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::pair<core_type*, std::pair<core_romimage_info*, unsigned>>>& reglist2()
|
||||||
|
{
|
||||||
|
static std::list<std::pair<core_type*, std::pair<core_romimage_info*, unsigned>>> x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_registrations()
|
||||||
|
{
|
||||||
|
auto& l = reglist1();
|
||||||
|
for(auto i = l.begin(); i != l.end();) {
|
||||||
|
auto& m = types();
|
||||||
|
bool done = false;
|
||||||
|
for(auto j : m)
|
||||||
|
if(j.second == i->first) {
|
||||||
|
auto iold = i;
|
||||||
|
i->first->add_region(*i->second);
|
||||||
|
i++;
|
||||||
|
l.erase(iold);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
if(!done)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
auto& l2 = reglist2();
|
||||||
|
for(auto i = l2.begin(); i != l2.end();) {
|
||||||
|
auto& m = types();
|
||||||
|
bool done = false;
|
||||||
|
for(auto j : m)
|
||||||
|
if(j.second == i->first) {
|
||||||
|
auto iold = i;
|
||||||
|
i->first->add_romimage(*i->second.first, i->second.second);
|
||||||
|
i++;
|
||||||
|
l2.erase(iold);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
if(!done)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
core_region::core_region(const std::string& _iname, const std::string& _hname, unsigned _priority, unsigned _handle,
|
||||||
|
bool _multi, uint64_t* _fmagic, int (*_compatible)(unsigned rom, unsigned run))
|
||||||
|
: iname(_iname), hname(_hname), priority(_priority), handle(_handle), compatible(_compatible),
|
||||||
|
multi(_multi)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < 4; i++)
|
||||||
|
magic[i] = _fmagic[i];
|
||||||
|
regionss()[_iname] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool core_region::compatible_with(core_region& run)
|
||||||
|
{
|
||||||
|
return (compatible(handle, run.handle) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
core_region& core_region::lookup(const std::string& name)
|
||||||
|
{
|
||||||
|
if(regionss().count(name))
|
||||||
|
return *(regionss()[name]);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Bad region");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool core_region::is_multi()
|
||||||
|
{
|
||||||
|
return multi;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& core_region::get_iname()
|
||||||
|
{
|
||||||
|
return iname;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& core_region::get_hname()
|
||||||
|
{
|
||||||
|
return hname;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned core_region::get_priority()
|
||||||
|
{
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_region::fill_framerate_magic(uint64_t* _magic)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < 4; i++)
|
||||||
|
_magic[i] = magic[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
double core_region::approx_framerate()
|
||||||
|
{
|
||||||
|
return (double)magic[1] / magic[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
core_sysregion::core_sysregion(const std::string& _name, core_type& _type, core_region& _region)
|
||||||
|
: name(_name), type(_type), region(_region)
|
||||||
|
{
|
||||||
|
sysregions()[_name] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
core_sysregion& core_sysregion::lookup(const std::string& _name)
|
||||||
|
{
|
||||||
|
if(sysregions().count(_name))
|
||||||
|
return *(sysregions()[_name]);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Bad system-region type");
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& core_sysregion::get_name()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
core_region& core_sysregion::get_region()
|
||||||
|
{
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
core_type& core_sysregion::get_type()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_sysregion::fill_framerate_magic(uint64_t* magic)
|
||||||
|
{
|
||||||
|
region.fill_framerate_magic(magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_type::add_region(core_region& reg)
|
||||||
|
{
|
||||||
|
regions.insert(®);
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_type::add_romimage(core_romimage_info& info, unsigned index)
|
||||||
|
{
|
||||||
|
if(imageinfo.size() <= index)
|
||||||
|
imageinfo.resize(index + 1);
|
||||||
|
imageinfo[index] = &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& core_type::get_iname()
|
||||||
|
{
|
||||||
|
return iname;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& core_type::get_hname()
|
||||||
|
{
|
||||||
|
return hname;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned core_type::get_image_count()
|
||||||
|
{
|
||||||
|
return imageinfo.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
core_romimage_info::core_romimage_info(const std::string& _iname, const std::string& _hname, unsigned _mandatory,
|
||||||
|
unsigned (*_headersize)(size_t imagesize))
|
||||||
|
: iname(_iname), hname(_hname), headersize(_headersize), mandatory(_mandatory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
core_romimage_info core_type::get_image_info(unsigned index)
|
||||||
|
{
|
||||||
|
if(index >= imageinfo.size())
|
||||||
|
throw std::runtime_error("Requested invalid image index");
|
||||||
|
return *imageinfo[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<core_type*> core_type::get_core_types()
|
||||||
|
{
|
||||||
|
std::set<core_type*> ret;
|
||||||
|
for(auto i : types())
|
||||||
|
ret.insert(i.second);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<core_region*> core_type::get_regions()
|
||||||
|
{
|
||||||
|
return regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
core_region& core_type::get_preferred_region()
|
||||||
|
{
|
||||||
|
core_region* p = NULL;
|
||||||
|
unsigned cutoff = 0;
|
||||||
|
for(auto i : regions) {
|
||||||
|
unsigned pri = i->get_priority();
|
||||||
|
if(pri >= cutoff) {
|
||||||
|
cutoff = max(pri + 1, pri);
|
||||||
|
p = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool core_type::load(core_romimage* images)
|
||||||
|
{
|
||||||
|
return (loadimg(images) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
core_sysregion& core_type::combine_region(core_region& reg)
|
||||||
|
{
|
||||||
|
for(auto i : sysregions())
|
||||||
|
if(&(i.second->get_type()) == this && &(i.second->get_region()) == ®)
|
||||||
|
return *(i.second);
|
||||||
|
throw std::runtime_error("Invalid region for system type");
|
||||||
|
}
|
||||||
|
|
||||||
|
core_type::core_type(const std::string& _iname, const std::string& _hname, int (*_load)(core_romimage* images))
|
||||||
|
: iname(_iname), hname(_hname), loadimg(_load)
|
||||||
|
{
|
||||||
|
types()[iname] = this;
|
||||||
|
process_registrations();
|
||||||
|
}
|
||||||
|
|
||||||
|
core_type_region_bind::core_type_region_bind(core_type& type, core_region& region)
|
||||||
|
{
|
||||||
|
reglist1().push_back(std::make_pair(&type, ®ion));
|
||||||
|
process_registrations();
|
||||||
|
}
|
||||||
|
|
||||||
|
core_type_image_bind::core_type_image_bind(core_type& type, core_romimage_info& imageinfo, unsigned index)
|
||||||
|
{
|
||||||
|
reglist2().push_back(std::make_pair(&type, std::make_pair(&imageinfo, index)));
|
||||||
|
process_registrations();
|
||||||
|
}
|
|
@ -29,13 +29,11 @@ struct moviefile generate_movie_template(std::vector<std::string> cmdline, loade
|
||||||
movie.port2 = &porttype_info::port_default(1);
|
movie.port2 = &porttype_info::port_default(1);
|
||||||
movie.coreversion = bsnes_core_version;
|
movie.coreversion = bsnes_core_version;
|
||||||
movie.projectid = get_random_hexstring(40);
|
movie.projectid = get_random_hexstring(40);
|
||||||
movie.gametype = gtype::togametype(r.rtype, r.region);
|
movie.gametype = &r.rtype->combine_region(*r.region);
|
||||||
movie.rom_sha256 = r.rom.sha256;
|
for(size_t i = 0; i < sizeof(r.romimg)/sizeof(r.romimg[0]); i++) {
|
||||||
movie.romxml_sha256 = r.rom_xml.sha256;
|
movie.romimg_sha256[i] = r.romimg[i].sha256;
|
||||||
movie.slota_sha256 = r.slota.sha256;
|
movie.romxml_sha256[i] = r.romxml[i].sha256;
|
||||||
movie.slotaxml_sha256 = r.slota_xml.sha256;
|
}
|
||||||
movie.slotb_sha256 = r.slotb.sha256;
|
|
||||||
movie.slotbxml_sha256 = r.slotb_xml.sha256;
|
|
||||||
movie.movie_sram = load_sram_commandline(cmdline);
|
movie.movie_sram = load_sram_commandline(cmdline);
|
||||||
for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
|
for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
|
||||||
std::string o = *i;
|
std::string o = *i;
|
||||||
|
@ -180,11 +178,8 @@ int main(int argc, char** argv)
|
||||||
fatal_error();
|
fatal_error();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
|
messages << "Detected region: " << r.rtype->combine_region(*r.region).get_name() << std::endl;
|
||||||
if(r.region == REGION_PAL)
|
set_nominal_framerate(r.region->approx_framerate());
|
||||||
set_nominal_framerate(322445.0/6448.0);
|
|
||||||
else if(r.region == REGION_NTSC)
|
|
||||||
set_nominal_framerate(10738636.0/178683.0);
|
|
||||||
|
|
||||||
messages << "--- Internal memory mappings ---" << std::endl;
|
messages << "--- Internal memory mappings ---" << std::endl;
|
||||||
dump_region_map();
|
dump_region_map();
|
||||||
|
|
|
@ -20,37 +20,12 @@
|
||||||
#define ASK_SRAMS_BASE (wxID_HIGHEST + 129)
|
#define ASK_SRAMS_BASE (wxID_HIGHEST + 129)
|
||||||
#define ASK_SRAMS_LAST (wxID_HIGHEST + 255)
|
#define ASK_SRAMS_LAST (wxID_HIGHEST + 255)
|
||||||
|
|
||||||
#define CONTROLLERTYPES_P1 4
|
|
||||||
#define CONTROLLERTYPES 7
|
|
||||||
#define CNAME_NONE "None"
|
|
||||||
#define CNAME_GAMEPAD "Gamepad"
|
|
||||||
#define CNAME_MULTITAP "Multitap"
|
|
||||||
#define CNAME_MOUSE "Mouse"
|
|
||||||
#define CNAME_SUPERSCOPE "Superscope"
|
|
||||||
#define CNAME_JUSTIFIER "Justifier"
|
|
||||||
#define CNAME_JUSTIFIERS "2 Justifiers"
|
|
||||||
#define TNAME_SNES "SNES"
|
|
||||||
#define TNAME_BSX_NS "BS-X (non-slotted)"
|
|
||||||
#define TNAME_BSX_S "BS-X (slotted)"
|
|
||||||
#define TNAME_SUFAMITURBO "Sufami Turbo"
|
|
||||||
#define TNAME_SGB "SGB"
|
|
||||||
#define RNAME_AUTO "Autodetect"
|
|
||||||
#define RNAME_NTSC "NTSC"
|
|
||||||
#define RNAME_PAL "PAL"
|
|
||||||
#define WNAME_SNES_MAIN "Cartridge ROM"
|
|
||||||
#define WNAME_BS_MAIN "BS-X BIOS"
|
|
||||||
#define WNAME_BS_SLOTA "BS FLASH"
|
|
||||||
#define WNAME_ST_MAIN "Sufami Turbo BIOS"
|
|
||||||
#define WNAME_ST_SLOTA "SLOT A ROM"
|
|
||||||
#define WNAME_ST_SLOTB "SLOT B ROM"
|
|
||||||
#define WNAME_SGB_MAIN "SGB BIOS"
|
|
||||||
#define WNAME_SGB_SLOTA "DMG ROM"
|
|
||||||
#define MARKUP_POSTFIX " Markup"
|
#define MARKUP_POSTFIX " Markup"
|
||||||
|
|
||||||
|
|
||||||
void patching_done(struct loaded_rom& rom, wxWindow* modwin);
|
void patching_done(struct loaded_rom& rom, wxWindow* modwin);
|
||||||
|
|
||||||
#define ROMSELECT_ROM_COUNT 3
|
#define ROMSELECT_ROM_COUNT 27
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -79,96 +54,56 @@ namespace
|
||||||
|
|
||||||
struct loaded_slot& get_rom_slot(struct loaded_rom& rom, unsigned index)
|
struct loaded_slot& get_rom_slot(struct loaded_rom& rom, unsigned index)
|
||||||
{
|
{
|
||||||
switch(index) {
|
if(index >= 2 * sizeof(rom.romimg) / sizeof(rom.romimg[0]))
|
||||||
case 0: return rom.rom;
|
return rom.romimg[0];
|
||||||
case 1: return rom.rom_xml;
|
if(index & 1)
|
||||||
case 2: return rom.slota;
|
return rom.romxml[index / 2];
|
||||||
case 3: return rom.slota_xml;
|
else
|
||||||
case 4: return rom.slotb;
|
return rom.romimg[index / 2];
|
||||||
case 5: return rom.slotb_xml;
|
}
|
||||||
|
|
||||||
|
core_region& region_from_string(core_type& rtype, const std::string& str)
|
||||||
|
{
|
||||||
|
core_region* x = NULL;
|
||||||
|
for(auto i : rtype.get_regions())
|
||||||
|
if(i->get_hname() == str)
|
||||||
|
return *i;
|
||||||
|
return *x;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned populate_region_choices(std::vector<wxString>& array)
|
||||||
|
{
|
||||||
|
array.push_back(wxT("(Default)"));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned populate_system_choices(std::vector<wxString>& array)
|
||||||
|
{
|
||||||
|
for(auto i : core_type::get_core_types())
|
||||||
|
array.push_back(i->get_hname());
|
||||||
|
return array.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_present_roms(core_type& rtype, unsigned flags)
|
||||||
|
{
|
||||||
|
unsigned a = 0;
|
||||||
|
unsigned b = 0;
|
||||||
|
for(size_t i = 0; i < ROMSELECT_ROM_COUNT && i < rtype.get_image_count(); i++) {
|
||||||
|
if((flags >> i) & 1)
|
||||||
|
a |= rtype.get_image_info(i).mandatory;
|
||||||
|
b |= rtype.get_image_info(i).mandatory;
|
||||||
}
|
}
|
||||||
return rom.rom;
|
return (a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum rom_region region_from_string(const std::string& str)
|
std::string romname(core_type& rtype, unsigned index)
|
||||||
{
|
{
|
||||||
if(str == RNAME_NTSC)
|
if(index >= rtype.get_image_count())
|
||||||
return REGION_NTSC;
|
return "";
|
||||||
if(str == RNAME_PAL)
|
return rtype.get_image_info(index).hname;
|
||||||
return REGION_PAL;
|
|
||||||
return REGION_AUTO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned populate_region_choices(wxString* array)
|
unsigned romname_to_index(core_type& rtype, const wxString& _name)
|
||||||
{
|
|
||||||
array[0] = wxT(RNAME_AUTO);
|
|
||||||
array[1] = wxT(RNAME_NTSC);
|
|
||||||
array[2] = wxT(RNAME_PAL);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned populate_system_choices(wxString* array)
|
|
||||||
{
|
|
||||||
array[0] = wxT(TNAME_SNES);
|
|
||||||
array[1] = wxT(TNAME_BSX_NS);
|
|
||||||
array[2] = wxT(TNAME_BSX_S);
|
|
||||||
array[3] = wxT(TNAME_SUFAMITURBO);
|
|
||||||
array[4] = wxT(TNAME_SGB);
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check_present_roms(enum rom_type rtype, unsigned flags)
|
|
||||||
{
|
|
||||||
switch(rtype)
|
|
||||||
{
|
|
||||||
case ROMTYPE_SNES:
|
|
||||||
return ((flags & 1) == 1);
|
|
||||||
case ROMTYPE_BSX:
|
|
||||||
case ROMTYPE_BSXSLOTTED:
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
return ((flags & 3) == 3);
|
|
||||||
case ROMTYPE_SUFAMITURBO:
|
|
||||||
return ((flags & 1) == 1) && ((flags & 6) != 0);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string romname(enum rom_type rtype, unsigned index)
|
|
||||||
{
|
|
||||||
switch(rtype) {
|
|
||||||
case ROMTYPE_SNES:
|
|
||||||
switch(index) {
|
|
||||||
case 0: return WNAME_SNES_MAIN;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case ROMTYPE_BSX:
|
|
||||||
case ROMTYPE_BSXSLOTTED:
|
|
||||||
switch(index) {
|
|
||||||
case 0: return WNAME_BS_MAIN;
|
|
||||||
case 1: return WNAME_BS_SLOTA;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SUFAMITURBO:
|
|
||||||
switch(index) {
|
|
||||||
case 0: return WNAME_ST_MAIN;
|
|
||||||
case 1: return WNAME_ST_SLOTA;
|
|
||||||
case 2: return WNAME_ST_SLOTB;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
switch(index) {
|
|
||||||
case 0: return WNAME_SGB_MAIN;
|
|
||||||
case 1: return WNAME_SGB_SLOTA;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case ROMTYPE_NONE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned romname_to_index(enum rom_type rtype, const wxString& _name)
|
|
||||||
{
|
{
|
||||||
std::string name = tostdstring(_name);
|
std::string name = tostdstring(_name);
|
||||||
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++) {
|
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++) {
|
||||||
|
@ -180,7 +115,7 @@ namespace
|
||||||
return 2 * ROMSELECT_ROM_COUNT;
|
return 2 * ROMSELECT_ROM_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned fill_rom_names(enum rom_type rtype, std::string* array)
|
unsigned fill_rom_names(core_type& rtype, std::string* array)
|
||||||
{
|
{
|
||||||
unsigned r = 0;
|
unsigned r = 0;
|
||||||
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++) {
|
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++) {
|
||||||
|
@ -191,25 +126,19 @@ namespace
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum rom_type romtype_from_string(const std::string& str)
|
core_type& romtype_from_string(const std::string& str)
|
||||||
{
|
{
|
||||||
if(str == TNAME_SNES)
|
core_type* x = NULL;
|
||||||
return ROMTYPE_SNES;
|
for(auto i : core_type::get_core_types())
|
||||||
if(str == TNAME_BSX_NS)
|
if(i->get_hname() == str)
|
||||||
return ROMTYPE_BSX;
|
return *i;
|
||||||
if(str == TNAME_BSX_S)
|
return *x;
|
||||||
return ROMTYPE_BSXSLOTTED;
|
|
||||||
if(str == TNAME_SUFAMITURBO)
|
|
||||||
return ROMTYPE_SUFAMITURBO;
|
|
||||||
if(str == TNAME_SGB)
|
|
||||||
return ROMTYPE_SGB;
|
|
||||||
return ROMTYPE_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_forced_region(const std::string& str)
|
bool has_forced_region(const std::string& str)
|
||||||
{
|
{
|
||||||
enum rom_type rtype = romtype_from_string(str);
|
core_type& rtype = romtype_from_string(str);
|
||||||
return (rtype != ROMTYPE_SNES && rtype != ROMTYPE_SGB);
|
return (rtype.get_regions().size() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
class textboxloadfilename : public wxFileDropTarget
|
class textboxloadfilename : public wxFileDropTarget
|
||||||
|
@ -396,7 +325,6 @@ private:
|
||||||
wxButton* open_rom;
|
wxButton* open_rom;
|
||||||
wxButton* quit_button;
|
wxButton* quit_button;
|
||||||
std::string current_rtype;
|
std::string current_rtype;
|
||||||
std::string remembered_region;
|
|
||||||
void set_rtype(std::string rtype);
|
void set_rtype(std::string rtype);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -465,8 +393,8 @@ wxwin_romselect::wxwin_romselect()
|
||||||
: wxFrame(NULL, wxID_ANY, wxT("Select ROM"), wxDefaultPosition, wxSize(-1, -1),
|
: wxFrame(NULL, wxID_ANY, wxT("Select ROM"), wxDefaultPosition, wxSize(-1, -1),
|
||||||
wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxCLOSE_BOX)
|
wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxCLOSE_BOX)
|
||||||
{
|
{
|
||||||
wxString rtchoices[32];
|
std::vector<wxString> rtchoices;
|
||||||
wxString rrchoices[32];
|
std::vector<wxString> rrchoices;
|
||||||
size_t systems = populate_system_choices(rtchoices);
|
size_t systems = populate_system_choices(rtchoices);
|
||||||
size_t regions = populate_region_choices(rrchoices);
|
size_t regions = populate_region_choices(rrchoices);
|
||||||
|
|
||||||
|
@ -483,10 +411,10 @@ wxwin_romselect::wxwin_romselect()
|
||||||
wxBoxSizer* selects = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* selects = new wxBoxSizer(wxHORIZONTAL);
|
||||||
selects->Add(new wxStaticText(this, wxID_ANY, wxT("ROM type:")), 0, wxGROW);
|
selects->Add(new wxStaticText(this, wxID_ANY, wxT("ROM type:")), 0, wxGROW);
|
||||||
selects->Add(romtype_combo = new wxComboBox(this, wxID_ANY, rtchoices[0], wxDefaultPosition, wxDefaultSize,
|
selects->Add(romtype_combo = new wxComboBox(this, wxID_ANY, rtchoices[0], wxDefaultPosition, wxDefaultSize,
|
||||||
systems, rtchoices, wxCB_READONLY), 0, wxGROW);
|
systems, &rtchoices[0], wxCB_READONLY), 0, wxGROW);
|
||||||
selects->Add(new wxStaticText(this, wxID_ANY, wxT("Region:")), 0, wxGROW);
|
selects->Add(new wxStaticText(this, wxID_ANY, wxT("Region:")), 0, wxGROW);
|
||||||
selects->Add(region_combo = new wxComboBox(this, wxID_ANY, rrchoices[0], wxDefaultPosition, wxDefaultSize,
|
selects->Add(region_combo = new wxComboBox(this, wxID_ANY, rrchoices[0], wxDefaultPosition, wxDefaultSize,
|
||||||
regions, rrchoices, wxCB_READONLY), 0, wxGROW);
|
regions, &rrchoices[0], wxCB_READONLY), 0, wxGROW);
|
||||||
romtype_combo->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED,
|
romtype_combo->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED,
|
||||||
wxCommandEventHandler(wxwin_romselect::on_romtype_change), NULL, this);
|
wxCommandEventHandler(wxwin_romselect::on_romtype_change), NULL, this);
|
||||||
region_combo->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED,
|
region_combo->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED,
|
||||||
|
@ -536,15 +464,14 @@ void wxwin_romselect::set_rtype(std::string rtype)
|
||||||
rtype = tostdstring(romtype_combo->GetValue());
|
rtype = tostdstring(romtype_combo->GetValue());
|
||||||
if(rtype == current_rtype)
|
if(rtype == current_rtype)
|
||||||
return;
|
return;
|
||||||
if(has_forced_region(rtype)) {
|
region_combo->Clear();
|
||||||
|
for(auto i : romtype_from_string(rtype).get_regions())
|
||||||
|
region_combo->Append(i->get_hname());
|
||||||
|
region_combo->SetSelection(0);
|
||||||
|
if(has_forced_region(rtype))
|
||||||
region_combo->Disable();
|
region_combo->Disable();
|
||||||
remembered_region = tostdstring(region_combo->GetValue());
|
else
|
||||||
} else {
|
|
||||||
if(remembered_region != "")
|
|
||||||
region_combo->SetValue(towxstring(remembered_region));
|
|
||||||
remembered_region = "";
|
|
||||||
region_combo->Enable();
|
region_combo->Enable();
|
||||||
}
|
|
||||||
std::string tmp[ROMSELECT_ROM_COUNT];
|
std::string tmp[ROMSELECT_ROM_COUNT];
|
||||||
unsigned c = fill_rom_names(romtype_from_string(rtype), tmp);
|
unsigned c = fill_rom_names(romtype_from_string(rtype), tmp);
|
||||||
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++)
|
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++)
|
||||||
|
@ -561,7 +488,7 @@ void wxwin_romselect::set_rtype(std::string rtype)
|
||||||
void wxwin_romselect::on_file_change()
|
void wxwin_romselect::on_file_change()
|
||||||
{
|
{
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
enum rom_type rtype = romtype_from_string(tostdstring(romtype_combo->GetValue()));
|
core_type& rtype = romtype_from_string(tostdstring(romtype_combo->GetValue()));
|
||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++)
|
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++)
|
||||||
flags |= ((slots[i]->get_filename() != "") ? (1 << i) : 0);
|
flags |= ((slots[i]->get_filename() != "") ? (1 << i) : 0);
|
||||||
|
@ -595,22 +522,20 @@ void wxwin_romselect::on_openapply_rom(wxCommandEvent& e, bool apply)
|
||||||
{
|
{
|
||||||
rom_files rfiles;
|
rom_files rfiles;
|
||||||
rfiles.base_file = "";
|
rfiles.base_file = "";
|
||||||
rfiles.rtype = romtype_from_string(tostdstring(romtype_combo->GetValue()));
|
rfiles.rtype = &romtype_from_string(tostdstring(romtype_combo->GetValue()));
|
||||||
rfiles.region = region_from_string(tostdstring(region_combo->GetValue()));
|
rfiles.region = ®ion_from_string(*rfiles.rtype, tostdstring(region_combo->GetValue()));
|
||||||
rfiles.rom = slots[0]->get_filename();
|
for(size_t i = 0; i < ROMSELECT_ROM_COUNT && i < sizeof(rfiles.romimg) / sizeof(rfiles.romimg[0]); i++) {
|
||||||
rfiles.rom_xml = slots[0]->get_markup();
|
rfiles.romimg[i] = slots[i]->get_filename();
|
||||||
rfiles.slota = slots[1]->get_filename();
|
rfiles.romxml[i] = slots[i]->get_markup();
|
||||||
rfiles.slota_xml = slots[1]->get_markup();
|
}
|
||||||
rfiles.slotb = slots[2]->get_filename();
|
|
||||||
rfiles.slotb_xml = slots[2]->get_markup();
|
|
||||||
try {
|
try {
|
||||||
our_rom = new loaded_rom(rfiles);
|
our_rom = new loaded_rom(rfiles);
|
||||||
if(our_rom->slota.valid)
|
our_rom_name = "";
|
||||||
our_rom_name = our_rom->slota.sha256;
|
for(size_t i = 1; i < sizeof(our_rom->romimg) / sizeof(our_rom->romimg[0]); i++)
|
||||||
else if(our_rom->slotb.valid)
|
if(our_rom->romimg[i].valid && our_rom_name == "")
|
||||||
our_rom_name = our_rom->slotb.sha256;
|
our_rom_name = our_rom->romimg[i].sha256;
|
||||||
else
|
if(our_rom_name == "")
|
||||||
our_rom_name = our_rom->rom.sha256;
|
our_rom_name = our_rom->romimg[0].sha256;
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
show_message_ok(this, "Error loading ROM", e.what(), wxICON_EXCLAMATION);
|
show_message_ok(this, "Error loading ROM", e.what(), wxICON_EXCLAMATION);
|
||||||
return;
|
return;
|
||||||
|
@ -631,7 +556,7 @@ wxwin_patch::wxwin_patch(loaded_rom& rom)
|
||||||
our_rom = &rom;
|
our_rom = &rom;
|
||||||
wxString targets[2 * ROMSELECT_ROM_COUNT];
|
wxString targets[2 * ROMSELECT_ROM_COUNT];
|
||||||
std::string _targets[ROMSELECT_ROM_COUNT];
|
std::string _targets[ROMSELECT_ROM_COUNT];
|
||||||
size_t _target_count = fill_rom_names(rom.rtype, _targets);
|
size_t _target_count = fill_rom_names(*rom.rtype, _targets);
|
||||||
size_t target_count = 0;
|
size_t target_count = 0;
|
||||||
for(auto i = 0; i < _target_count; i++) {
|
for(auto i = 0; i < _target_count; i++) {
|
||||||
targets[2 * i] = towxstring(_targets[i]);
|
targets[2 * i] = towxstring(_targets[i]);
|
||||||
|
@ -749,7 +674,7 @@ void wxwin_patch::on_do_patch(wxCommandEvent& e)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto patch_contents = read_file_relative(tostdstring(patchfile->GetValue()), "");
|
auto patch_contents = read_file_relative(tostdstring(patchfile->GetValue()), "");
|
||||||
size_t patch_index = romname_to_index(our_rom->rtype, patch_what->GetValue());
|
size_t patch_index = romname_to_index(*our_rom->rtype, patch_what->GetValue());
|
||||||
if(patch_index > 2 * ROMSELECT_ROM_COUNT)
|
if(patch_index > 2 * ROMSELECT_ROM_COUNT)
|
||||||
throw std::runtime_error("Internal error: Patch WHAT?");
|
throw std::runtime_error("Internal error: Patch WHAT?");
|
||||||
loaded_slot& s = get_rom_slot(*our_rom, patch_index);
|
loaded_slot& s = get_rom_slot(*our_rom, patch_index);
|
||||||
|
@ -774,22 +699,19 @@ void patching_done(struct loaded_rom& rom, wxWindow* modwin)
|
||||||
struct loaded_rom* our_rom = &rom;
|
struct loaded_rom* our_rom = &rom;
|
||||||
try {
|
try {
|
||||||
do_basic_core_init();
|
do_basic_core_init();
|
||||||
if(our_rom->slota.valid)
|
our_rom_name = "";
|
||||||
our_rom_name = our_rom->slota.sha256;
|
for(size_t i = 1; i < sizeof(our_rom->romimg) / sizeof(our_rom->romimg[0]); i++)
|
||||||
else if(our_rom->slotb.valid)
|
if(our_rom->romimg[i].valid && our_rom_name == "")
|
||||||
our_rom_name = our_rom->slotb.sha256;
|
our_rom_name = our_rom->romimg[i].sha256;
|
||||||
else
|
if(our_rom_name == "")
|
||||||
our_rom_name = our_rom->rom.sha256;
|
our_rom_name = our_rom->romimg[0].sha256;
|
||||||
our_rom->load();
|
our_rom->load();
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
show_message_ok(modwin, "Error loading ROM", e.what(), wxICON_EXCLAMATION);
|
show_message_ok(modwin, "Error loading ROM", e.what(), wxICON_EXCLAMATION);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
messages << "Detected region: " << gtype::tostring(our_rom->rtype, our_rom->region) << std::endl;
|
messages << "Detected region: " << our_rom->rtype->combine_region(*our_rom->region).get_name() << std::endl;
|
||||||
if(our_rom->region == REGION_PAL)
|
set_nominal_framerate(our_rom->region->approx_framerate());
|
||||||
set_nominal_framerate(322445.0/6448.0);
|
|
||||||
else if(our_rom->region == REGION_NTSC)
|
|
||||||
set_nominal_framerate(10738636.0/178683.0);
|
|
||||||
|
|
||||||
messages << "--- Internal memory mappings ---" << std::endl;
|
messages << "--- Internal memory mappings ---" << std::endl;
|
||||||
dump_region_map();
|
dump_region_map();
|
||||||
|
@ -1028,7 +950,7 @@ struct moviefile wxwin_project::make_movie()
|
||||||
{
|
{
|
||||||
moviefile f;
|
moviefile f;
|
||||||
f.force_corrupt = false;
|
f.force_corrupt = false;
|
||||||
f.gametype = gtype::togametype(our_rom->rtype, our_rom->region);
|
f.gametype = &our_rom->rtype->combine_region(*our_rom->region);
|
||||||
f.port1 = &get_controller_type(tostdstring(controller1type->GetValue()));
|
f.port1 = &get_controller_type(tostdstring(controller1type->GetValue()));
|
||||||
f.port2 = &get_controller_type(tostdstring(controller2type->GetValue()));
|
f.port2 = &get_controller_type(tostdstring(controller2type->GetValue()));
|
||||||
f.coreversion = bsnes_core_version;
|
f.coreversion = bsnes_core_version;
|
||||||
|
@ -1036,12 +958,10 @@ struct moviefile wxwin_project::make_movie()
|
||||||
f.prefix = sanitize_prefix(tostdstring(prefix->GetValue()));
|
f.prefix = sanitize_prefix(tostdstring(prefix->GetValue()));
|
||||||
f.projectid = get_random_hexstring(40);
|
f.projectid = get_random_hexstring(40);
|
||||||
f.rerecords = "0";
|
f.rerecords = "0";
|
||||||
f.rom_sha256 = our_rom->rom.sha256;
|
for(size_t i = 0; i < sizeof(our_rom->romimg)/sizeof(our_rom->romimg[0]); i++) {
|
||||||
f.romxml_sha256 = our_rom->rom_xml.sha256;
|
f.romimg_sha256[i] = our_rom->romimg[i].sha256;
|
||||||
f.slota_sha256 = our_rom->slota.sha256;
|
f.romxml_sha256[i] = our_rom->romxml[i].sha256;
|
||||||
f.slotaxml_sha256 = our_rom->slota_xml.sha256;
|
}
|
||||||
f.slotb_sha256 = our_rom->slotb.sha256;
|
|
||||||
f.slotbxml_sha256 = our_rom->slotb_xml.sha256;
|
|
||||||
size_t lines = authors->GetNumberOfLines();
|
size_t lines = authors->GetNumberOfLines();
|
||||||
for(size_t i = 0; i < lines; i++) {
|
for(size_t i = 0; i < lines; i++) {
|
||||||
std::string l = tostdstring(authors->GetLineText(i));
|
std::string l = tostdstring(authors->GetLineText(i));
|
||||||
|
|
|
@ -257,11 +257,8 @@ int main(int argc, char** argv)
|
||||||
fatal_error();
|
fatal_error();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
|
messages << "Detected region: " << r.rtype->combine_region(*r.region).get_name() << std::endl;
|
||||||
if(r.region == REGION_PAL)
|
set_nominal_framerate(r.region->approx_framerate());
|
||||||
set_nominal_framerate(322445.0/6448.0);
|
|
||||||
else if(r.region == REGION_NTSC)
|
|
||||||
set_nominal_framerate(10738636.0/178683.0);
|
|
||||||
|
|
||||||
messages << "--- Internal memory mappings ---" << std::endl;
|
messages << "--- Internal memory mappings ---" << std::endl;
|
||||||
dump_region_map();
|
dump_region_map();
|
||||||
|
@ -290,7 +287,7 @@ int main(int argc, char** argv)
|
||||||
throw std::runtime_error("Can't load any of the movies specified");
|
throw std::runtime_error("Can't load any of the movies specified");
|
||||||
//Load ROM before starting the dumper.
|
//Load ROM before starting the dumper.
|
||||||
our_rom = &r;
|
our_rom = &r;
|
||||||
our_rom->region = gtype::toromregion(movie.gametype);
|
our_rom->region = &movie.gametype->get_region();
|
||||||
our_rom->load();
|
our_rom->load();
|
||||||
startup_lua_scripts(cmdline);
|
startup_lua_scripts(cmdline);
|
||||||
dumper_startup(dumper, mode, prefix, length);
|
dumper_startup(dumper, mode, prefix, length);
|
||||||
|
|
|
@ -6,23 +6,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
std::string name_romtype(rom_type r)
|
|
||||||
{
|
|
||||||
if(r == ROMTYPE_SNES) return "SNES";
|
|
||||||
if(r == ROMTYPE_BSX) return "BS-X (non-slotted)";
|
|
||||||
if(r == ROMTYPE_BSXSLOTTED) return "BS-X (slotted)";
|
|
||||||
if(r == ROMTYPE_SUFAMITURBO) return "Sufami turbo";
|
|
||||||
if(r == ROMTYPE_SGB) return "SGB";
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name_region(rom_region r)
|
|
||||||
{
|
|
||||||
if(r == REGION_PAL) return "PAL";
|
|
||||||
if(r == REGION_NTSC) return "NTSC";
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string escape_string(std::string x)
|
std::string escape_string(std::string x)
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
|
@ -48,10 +31,10 @@ int main(int argc, char** argv)
|
||||||
try {
|
try {
|
||||||
uint64_t starting_point = 0;
|
uint64_t starting_point = 0;
|
||||||
struct moviefile m(argv[1]);
|
struct moviefile m(argv[1]);
|
||||||
rom_type rtype = gtype::toromtype(m.gametype);
|
core_type* rtype = &m.gametype->get_type();
|
||||||
rom_region reg = gtype::toromregion(m.gametype);
|
core_region* reg = &m.gametype->get_region();
|
||||||
std::cout << "Console: " << name_romtype(rtype) << std::endl;
|
std::cout << "Console: " << rtype->get_hname() << std::endl;
|
||||||
std::cout << "Region: " << name_region(reg) << std::endl;
|
std::cout << "Region: " << reg->get_hname() << std::endl;
|
||||||
std::cout << "Port #1: " << m.port1->hname << std::endl;
|
std::cout << "Port #1: " << m.port1->hname << std::endl;
|
||||||
std::cout << "Port #2: " << m.port2->hname << std::endl;
|
std::cout << "Port #2: " << m.port2->hname << std::endl;
|
||||||
std::cout << "Used emulator core: " << escape_string(m.coreversion) << std::endl;
|
std::cout << "Used emulator core: " << escape_string(m.coreversion) << std::endl;
|
||||||
|
@ -60,32 +43,17 @@ int main(int argc, char** argv)
|
||||||
else
|
else
|
||||||
std::cout << "No game name available" << std::endl;
|
std::cout << "No game name available" << std::endl;
|
||||||
std::cout << "Project ID: " << escape_string(m.projectid) << std::endl;
|
std::cout << "Project ID: " << escape_string(m.projectid) << std::endl;
|
||||||
if(m.rom_sha256 != "") {
|
for(size_t i = 0; i < sizeof(m.romimg_sha256)/sizeof(m.romimg_sha256[0]); i++) {
|
||||||
std::cout << "ROM checksum: " << escape_string(m.rom_sha256) << std::endl;
|
if(m.romimg_sha256[i] != "") {
|
||||||
if(m.romxml_sha256 != "")
|
std::cout << name_subrom(*rtype, 2 * i + 0) << " checksum: "
|
||||||
std::cout << "ROM XML checksum: " << escape_string(m.romxml_sha256) << std::endl;
|
<< escape_string(m.romimg_sha256[i]) << std::endl;
|
||||||
else
|
if(m.romxml_sha256[i] != "") {
|
||||||
std::cout << "Using default settings for ROM" << std::endl;
|
std::cout << name_subrom(*rtype, 2 * i + 1) << " checksum: "
|
||||||
} else
|
<< escape_string(m.romimg_sha256[i]) << std::endl;
|
||||||
std::cout << "No main ROM present" << std::endl;
|
}
|
||||||
if(m.slota_sha256 != "") {
|
} else
|
||||||
std::cout << "BS/ST-A/DMG checksum: " << escape_string(m.slota_sha256) << std::endl;
|
std::cout << "No " << name_subrom(*rtype, 2 * i + 0) << " present" << std::endl;
|
||||||
if(m.slotaxml_sha256 != "")
|
}
|
||||||
std::cout << "BS/ST-A/DMG XML checksum: " << escape_string(m.slotaxml_sha256)
|
|
||||||
<< std::endl;
|
|
||||||
else
|
|
||||||
std::cout << "Using default settings for BS/ST-A/DMG" << std::endl;
|
|
||||||
} else
|
|
||||||
std::cout << "No BS/ST-A/DMG present" << std::endl;
|
|
||||||
if(m.slotb_sha256 != "") {
|
|
||||||
std::cout << "ST-B checksum: " << escape_string(m.slotb_sha256) << std::endl;
|
|
||||||
if(m.slotbxml_sha256 != "")
|
|
||||||
std::cout << "ST-B XML checksum: " << escape_string(m.slotbxml_sha256)
|
|
||||||
<< std::endl;
|
|
||||||
else
|
|
||||||
std::cout << "Using default settings for BS/ST-A/DMG" << std::endl;
|
|
||||||
} else
|
|
||||||
std::cout << "No ST-B present" << std::endl;
|
|
||||||
for(auto i = m.authors.begin(); i != m.authors.end(); i++) {
|
for(auto i = m.authors.begin(); i != m.authors.end(); i++) {
|
||||||
if(i->first != "" && i->second != "")
|
if(i->first != "" && i->second != "")
|
||||||
std::cout << "Author: " << escape_string(i->first) << " (" << escape_string(i->second)
|
std::cout << "Author: " << escape_string(i->first) << " (" << escape_string(i->second)
|
||||||
|
|
Loading…
Add table
Reference in a new issue