Refactor ROM slots handling
Refactor ROM slot behaviour to bsnes-specific code
This commit is contained in:
parent
baf53174ca
commit
4f9dfd513c
16 changed files with 773 additions and 1101 deletions
|
@ -37,26 +37,6 @@ void set_random_seed(const std::string& seed) throw(std::bad_alloc);
|
||||||
*/
|
*/
|
||||||
void set_random_seed() throw(std::bad_alloc);
|
void set_random_seed() throw(std::bad_alloc);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Load a ROM.
|
|
||||||
*
|
|
||||||
* Given commandline arguments, load a ROM.
|
|
||||||
*
|
|
||||||
* \param cmdline The command line.
|
|
||||||
* \return The loaded ROM set.
|
|
||||||
* \throws std::bad_alloc Not enough memory.
|
|
||||||
* \throws std::runtime_error Can't load the ROMset.
|
|
||||||
*/
|
|
||||||
struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) throw(std::bad_alloc,
|
|
||||||
std::runtime_error);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Dump listing of regions to graphics system messages.
|
|
||||||
*
|
|
||||||
* \throws std::bad_alloc Not enough memory.
|
|
||||||
*/
|
|
||||||
void dump_region_map() throw(std::bad_alloc);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Fatal error.
|
* \brief Fatal error.
|
||||||
*
|
*
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct moviefile
|
||||||
/**
|
/**
|
||||||
* What is the ROM type and region?
|
* What is the ROM type and region?
|
||||||
*/
|
*/
|
||||||
gametype_t gametype;
|
std::string gametype;
|
||||||
/**
|
/**
|
||||||
* What's in port #1?
|
* What's in port #1?
|
||||||
*/
|
*/
|
||||||
|
@ -73,13 +73,13 @@ struct moviefile
|
||||||
*/
|
*/
|
||||||
std::string rerecords;
|
std::string rerecords;
|
||||||
/**
|
/**
|
||||||
* SHA-256 of main ROM (empty string if none).
|
* SHA-256 of main ROMs (empty string if none).
|
||||||
*/
|
*/
|
||||||
std::string rom_sha256; //SHA-256 of main ROM.
|
std::vector<std::string> main_checksums;
|
||||||
/**
|
/**
|
||||||
* SHA-256 of main ROM XML (empty string if none).
|
* SHA-256 of main ROM XMLs (empty string if none).
|
||||||
*/
|
*/
|
||||||
std::string romxml_sha256; //SHA-256 of main ROM XML.
|
std::vector<std::string> markup_checksums;
|
||||||
/**
|
/**
|
||||||
* SHA-256 of slot A ROM (empty string if none).
|
* SHA-256 of slot A ROM (empty string if none).
|
||||||
*/
|
*/
|
||||||
|
@ -181,5 +181,7 @@ struct moviefile
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string sanitize_prefix(const std::string& in) throw(std::bad_alloc);
|
std::string sanitize_prefix(const std::string& in) throw(std::bad_alloc);
|
||||||
|
void copy_romdata_to_movie(struct moviefile& movie, const struct loaded_rom& r);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,179 +5,9 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include "interface/core.hpp"
|
||||||
#include "misc.hpp"
|
#include "misc.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 +42,19 @@ struct rom_files
|
||||||
/**
|
/**
|
||||||
* Major ROM type.
|
* Major ROM type.
|
||||||
*/
|
*/
|
||||||
enum rom_type rtype;
|
struct systype_info_structure* 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;
|
struct region_info_structure* region;
|
||||||
/**
|
/**
|
||||||
* Relative filename of main ROM file.
|
* ROM slots.
|
||||||
*/
|
*/
|
||||||
std::string rom;
|
std::vector<std::string> main_slots;
|
||||||
/**
|
/**
|
||||||
* Relative filename of main ROM XML file.
|
* ROM markup slots.
|
||||||
*/
|
*/
|
||||||
std::string rom_xml;
|
std::vector<std::string> markup_slots;
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,12 +74,13 @@ struct loaded_slot
|
||||||
*
|
*
|
||||||
* parameter filename: The filename to read. If "", empty slot is constructed.
|
* parameter filename: The filename to read. If "", empty slot is constructed.
|
||||||
* parameter base: Base filename to interpret the filename against. If "", no base filename is used.
|
* parameter base: Base filename to interpret the filename against. If "", no base filename is used.
|
||||||
|
* parameter slot: The rom slot this is for.
|
||||||
* parameter xml_flag: If set, always keep trailing NUL.
|
* parameter xml_flag: If set, always keep trailing NUL.
|
||||||
* throws std::bad_alloc: Not enough memory.
|
* throws std::bad_alloc: Not enough memory.
|
||||||
* throws std::runtime_error: Can't load the data.
|
* throws std::runtime_error: Can't load the data.
|
||||||
*/
|
*/
|
||||||
loaded_slot(const std::string& filename, const std::string& base, bool xml_flag = false)
|
loaded_slot(const std::string& filename, const std::string& base, struct rom_info_structure& slot,
|
||||||
throw(std::bad_alloc, std::runtime_error);
|
bool xml_flag = false) throw(std::bad_alloc, std::runtime_error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method patches this slot using specified IPS patch.
|
* This method patches this slot using specified IPS patch.
|
||||||
|
@ -343,42 +158,25 @@ struct loaded_rom
|
||||||
/**
|
/**
|
||||||
* ROM type
|
* ROM type
|
||||||
*/
|
*/
|
||||||
enum rom_type rtype;
|
struct systype_info_structure* rtype;
|
||||||
/**
|
/**
|
||||||
* ROM region (this is the currently active region).
|
* ROM region (this is the currently active region).
|
||||||
*/
|
*/
|
||||||
enum rom_region region;
|
struct region_info_structure* 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;
|
struct region_info_structure* orig_region;
|
||||||
/**
|
/**
|
||||||
* Loaded main ROM
|
* Loaded main ROMs
|
||||||
*/
|
*/
|
||||||
loaded_slot rom;
|
std::vector<loaded_slot> main_slots;
|
||||||
/**
|
/**
|
||||||
* Loaded main ROM XML
|
* Loaded ROM markups
|
||||||
*/
|
*/
|
||||||
loaded_slot rom_xml;
|
std::vector<loaded_slot> markup_slots;
|
||||||
/**
|
/**
|
||||||
* Loaded slot A ROM (.bs, .st or .dmg)
|
* Patch the ROMs.
|
||||||
*/
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Patch the ROM.
|
|
||||||
*
|
*
|
||||||
* parameter cmdline: The command line.
|
* parameter cmdline: The command line.
|
||||||
* throws std::bad_alloc: Not enough memory.
|
* throws std::bad_alloc: Not enough memory.
|
||||||
|
@ -396,43 +194,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.
|
|
||||||
*
|
|
||||||
* parameter major: The major type.
|
|
||||||
* parameter romnumber: ROM number to name (as returned by recognize_commandline_rom).
|
|
||||||
* throws std::bad_alloc: Not enough memory
|
|
||||||
*/
|
|
||||||
std::string name_subrom(enum rom_type major, unsigned romnumber) throw(std::bad_alloc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get major type and region of 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();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*
|
*
|
||||||
|
@ -461,22 +222,21 @@ std::map<std::string, std::vector<char>> load_sram_commandline(const std::vector
|
||||||
throw(std::bad_alloc, std::runtime_error);
|
throw(std::bad_alloc, std::runtime_error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read index of ROMs and add ROMs found to content-searchable storage.
|
* Given commandline arguments, load a ROM.
|
||||||
*
|
*
|
||||||
* parameter filename: The filename of index file.
|
* parameter cmdline: The command line.
|
||||||
|
* returns: The loaded ROM set.
|
||||||
* throws std::bad_alloc: Not enough memory.
|
* throws std::bad_alloc: Not enough memory.
|
||||||
* throws std::runtime_error: Loading index failed.
|
* throws std::runtime_error: Can't load the ROMset.
|
||||||
*/
|
*/
|
||||||
void load_index_file(const std::string& filename) throw(std::bad_alloc, std::runtime_error);
|
struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) throw(std::bad_alloc,
|
||||||
|
std::runtime_error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search all indices, looking for file with specified SHA-256 (specifying hash of "" results "").
|
* Dump listing of regions to graphics system messages.
|
||||||
*
|
*
|
||||||
* parameter hash: The hash of file.
|
|
||||||
* returns: Absolute filename.
|
|
||||||
* throws std::bad_alloc: Not enough memory.
|
* throws std::bad_alloc: Not enough memory.
|
||||||
* throws std::runtime_error: Not found.
|
|
||||||
*/
|
*/
|
||||||
std::string lookup_file_by_sha256(const std::string& hash) throw(std::bad_alloc, std::runtime_error);
|
void dump_region_map() throw(std::bad_alloc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,6 +10,43 @@ std::pair<uint32_t, uint32_t> emucore_get_video_rate(bool interlace = false);
|
||||||
std::pair<uint32_t, uint32_t> emucore_get_audio_rate();
|
std::pair<uint32_t, uint32_t> emucore_get_audio_rate();
|
||||||
void emucore_basic_init();
|
void emucore_basic_init();
|
||||||
|
|
||||||
|
struct region_info_structure
|
||||||
|
{
|
||||||
|
virtual ~region_info_structure();
|
||||||
|
virtual std::string get_iname() = 0;
|
||||||
|
virtual std::string get_hname() = 0;
|
||||||
|
virtual bool compatible(const std::string& movie) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sysregion_info_structure
|
||||||
|
{
|
||||||
|
virtual ~sysregion_info_structure();
|
||||||
|
virtual std::string get_iname() = 0;
|
||||||
|
virtual void get_length_magic(uint64_t* magic) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rom_info_structure
|
||||||
|
{
|
||||||
|
virtual ~rom_info_structure();
|
||||||
|
virtual std::string get_iname() = 0;
|
||||||
|
virtual std::string get_hname() = 0;
|
||||||
|
virtual bool has_markup() = 0;
|
||||||
|
virtual unsigned mandatory_flags() = 0;
|
||||||
|
virtual size_t headersize(size_t imagesize) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct systype_info_structure
|
||||||
|
{
|
||||||
|
virtual ~systype_info_structure();
|
||||||
|
virtual std::string get_iname() = 0;
|
||||||
|
virtual std::string get_hname() = 0;
|
||||||
|
virtual size_t region_slots() = 0;
|
||||||
|
virtual struct region_info_structure* region_slot(size_t index) = 0;
|
||||||
|
virtual size_t rom_slots() = 0;
|
||||||
|
virtual struct rom_info_structure* rom_slot(size_t index) = 0;
|
||||||
|
virtual struct sysregion_info_structure* get_sysregion(const std::string& region) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct sram_slot_structure
|
struct sram_slot_structure
|
||||||
{
|
{
|
||||||
virtual ~sram_slot_structure();
|
virtual ~sram_slot_structure();
|
||||||
|
@ -45,6 +82,8 @@ protected:
|
||||||
endian rendian;
|
endian rendian;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
size_t emucore_systype_slots();
|
||||||
|
struct systype_info_structure* emucore_systype_slot(size_t index);
|
||||||
size_t emucore_sram_slots();
|
size_t emucore_sram_slots();
|
||||||
struct sram_slot_structure* emucore_sram_slot(size_t index);
|
struct sram_slot_structure* emucore_sram_slot(size_t index);
|
||||||
size_t emucore_vma_slots();
|
size_t emucore_vma_slots();
|
||||||
|
@ -52,5 +91,12 @@ struct vma_structure* emucore_vma_slot(size_t index);
|
||||||
void emucore_refresh_cart();
|
void emucore_refresh_cart();
|
||||||
std::vector<char> emucore_serialize();
|
std::vector<char> emucore_serialize();
|
||||||
void emucore_unserialize(const std::vector<char>& data);
|
void emucore_unserialize(const std::vector<char>& data);
|
||||||
|
void emucore_load_rom(systype_info_structure* rtype, region_info_structure* region,
|
||||||
|
const std::vector<std::vector<char>>& romslots, const std::vector<std::vector<char>>& markslots);
|
||||||
|
struct region_info_structure* emucore_current_region();
|
||||||
|
struct region_info_structure* emucore_region_for_sysregion(const std::string& sysregion);
|
||||||
|
struct systype_info_structure* emucore_systype_for_sysregion(const std::string& sysregion);
|
||||||
|
struct sysregion_info_structure* emucore_sysregion_for_sysregion(const std::string& sysregion);
|
||||||
|
void emucore_pre_load_settings();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -94,69 +94,6 @@ void set_random_seed() throw(std::bad_alloc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) throw(std::bad_alloc,
|
|
||||||
std::runtime_error)
|
|
||||||
{
|
|
||||||
struct rom_files f;
|
|
||||||
try {
|
|
||||||
f = rom_files(cmdline);
|
|
||||||
f.resolve_relative();
|
|
||||||
} catch(std::bad_alloc& e) {
|
|
||||||
OOM_panic();
|
|
||||||
} catch(std::exception& e) {
|
|
||||||
throw std::runtime_error(std::string("Can't resolve ROM files: ") + e.what());
|
|
||||||
}
|
|
||||||
messages << "ROM type: " << gtype::tostring(f.rtype, f.region) << std::endl;
|
|
||||||
if(f.rom != "") messages << name_subrom(f.rtype, 0) << " file: '" << f.rom << "'" << std::endl;
|
|
||||||
if(f.rom_xml != "") messages << name_subrom(f.rtype, 1) << " file: '" << f.rom_xml << "'"
|
|
||||||
<< std::endl;
|
|
||||||
if(f.slota != "") messages << name_subrom(f.rtype, 2) << " file: '" << f.slota << "'" << std::endl;
|
|
||||||
if(f.slota_xml != "") messages << name_subrom(f.rtype, 3) << " file: '" << f.slota_xml << "'"
|
|
||||||
<< 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;
|
|
||||||
try {
|
|
||||||
r = loaded_rom(f);
|
|
||||||
r.do_patch(cmdline);
|
|
||||||
} catch(std::bad_alloc& e) {
|
|
||||||
OOM_panic();
|
|
||||||
} catch(std::exception& e) {
|
|
||||||
throw std::runtime_error(std::string("Can't load ROM: ") + e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string not_present = "N/A";
|
|
||||||
if(r.rom.valid) messages << name_subrom(f.rtype, 0) << " hash: " << r.rom.sha256 << std::endl;
|
|
||||||
if(r.rom_xml.valid) messages << name_subrom(f.rtype, 1) << " hash: " << r.rom_xml.sha256 << std::endl;
|
|
||||||
if(r.slota.valid) messages << name_subrom(f.rtype, 2) << " hash: " << r.slota.sha256 << std::endl;
|
|
||||||
if(r.slota_xml.valid) messages << name_subrom(f.rtype, 3) << " hash: " << r.slota_xml.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_region_map() throw(std::bad_alloc)
|
|
||||||
{
|
|
||||||
std::vector<vma_structure*> regions = get_regions();
|
|
||||||
for(auto i : regions) {
|
|
||||||
char buf[256];
|
|
||||||
char echar;
|
|
||||||
if(i->get_endian() == vma_structure::E_LITTLE)
|
|
||||||
echar = 'L';
|
|
||||||
if(i->get_endian() == vma_structure::E_BIG)
|
|
||||||
echar = 'B';
|
|
||||||
if(i->get_endian() == vma_structure::E_HOST)
|
|
||||||
echar = 'N';
|
|
||||||
sprintf(buf, "Region: %016X-%016X %016X %s%c %s", i->get_base(), i->get_base() + i->get_size() - 1,
|
|
||||||
i->get_size(), i->is_readonly() ? "R-" : "RW", echar, i->get_name().c_str());
|
|
||||||
messages << buf << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fatal_error() throw()
|
void fatal_error() throw()
|
||||||
{
|
{
|
||||||
platform::fatal_error();
|
platform::fatal_error();
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include "core/bsnes.hpp"
|
|
||||||
|
|
||||||
#include "core/command.hpp"
|
#include "core/command.hpp"
|
||||||
#include "core/controller.hpp"
|
#include "core/controller.hpp"
|
||||||
#include "core/dispatch.hpp"
|
#include "core/dispatch.hpp"
|
||||||
|
@ -219,12 +217,12 @@ 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;
|
our_movie.main_checksums.resize(our_rom->main_slots.size());
|
||||||
our_movie.romxml_sha256 = our_rom->rom_xml.sha256;
|
our_movie.markup_checksums.resize(our_rom->markup_slots.size());
|
||||||
our_movie.slota_sha256 = our_rom->slota.sha256;
|
for(size_t i = 0; i < our_movie.main_checksums.size(); i++)
|
||||||
our_movie.slotaxml_sha256 = our_rom->slota_xml.sha256;
|
our_movie.main_checksums[i] = our_rom->main_slots[i].sha256;
|
||||||
our_movie.slotb_sha256 = our_rom->slotb.sha256;
|
for(size_t i = 0; i < our_movie.markup_checksums.size(); i++)
|
||||||
our_movie.slotbxml_sha256 = our_rom->slotb_xml.sha256;
|
our_movie.markup_checksums[i] = our_rom->markup_slots[i].sha256;
|
||||||
our_movie.savestate = emucore_serialize();
|
our_movie.savestate = emucore_serialize();
|
||||||
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,
|
||||||
|
@ -271,8 +269,7 @@ extern time_t random_seed_value;
|
||||||
|
|
||||||
void do_load_beginning() throw(std::bad_alloc, std::runtime_error)
|
void do_load_beginning() throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
SNES::config.random = false;
|
emucore_pre_load_settings();
|
||||||
SNES::config.expansion_port = SNES::System::ExpansionPortDevice::None;
|
|
||||||
|
|
||||||
//Negative return.
|
//Negative return.
|
||||||
rrdata::add_internal();
|
rrdata::add_internal();
|
||||||
|
@ -305,13 +302,15 @@ 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) {
|
systype_info_structure* systype = emucore_systype_for_sysregion(_movie.gametype);
|
||||||
|
region_info_structure* region = emucore_region_for_sysregion(_movie.gametype);
|
||||||
|
if(systype != our_rom->rtype) {
|
||||||
messages << "_movie.gametype = " << _movie.gametype << std::endl;
|
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->get_iname() << 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(gtype::toromregion(_movie.gametype) != our_rom->orig_region && our_rom->orig_region != REGION_AUTO)
|
|
||||||
|
if(!our_rom->orig_region->compatible(region->get_iname()))
|
||||||
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 != emucore_get_version()) {
|
if(_movie.coreversion != emucore_get_version()) {
|
||||||
|
@ -327,17 +326,24 @@ 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 < our_rom->rtype->rom_slots(); i++) {
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.romxml_sha256, our_rom->rom_xml, "XML #1", will_load_state);
|
if(_movie.main_checksums.size() > i)
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slota_sha256, our_rom->slota, "ROM #2", will_load_state);
|
rom_ok = rom_ok & warn_hash_mismatch(_movie.main_checksums[i], our_rom->main_slots[i],
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slotaxml_sha256, our_rom->slota_xml, "XML #2", will_load_state);
|
our_rom->rtype->rom_slot(i)->get_hname(), will_load_state);
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slotb_sha256, our_rom->slotb, "ROM #3", will_load_state);
|
else
|
||||||
rom_ok = rom_ok & warn_hash_mismatch(_movie.slotbxml_sha256, our_rom->slotb_xml, "XML #3", will_load_state);
|
rom_ok = rom_ok & warn_hash_mismatch("", our_rom->main_slots[i],
|
||||||
|
our_rom->rtype->rom_slot(i)->get_hname(), will_load_state);
|
||||||
|
if(_movie.markup_checksums.size() > i)
|
||||||
|
rom_ok = rom_ok & warn_hash_mismatch(_movie.markup_checksums[i], our_rom->markup_slots[i],
|
||||||
|
our_rom->rtype->rom_slot(i)->get_hname() + " markup", will_load_state);
|
||||||
|
else
|
||||||
|
rom_ok = rom_ok & warn_hash_mismatch("", our_rom->markup_slots[i],
|
||||||
|
our_rom->rtype->rom_slot(i)->get_hname() + " markup", will_load_state);
|
||||||
|
}
|
||||||
if(!rom_ok)
|
if(!rom_ok)
|
||||||
throw std::runtime_error("Incorrect ROM");
|
throw std::runtime_error("Incorrect ROM");
|
||||||
|
|
||||||
SNES::config.random = false;
|
emucore_pre_load_settings();
|
||||||
SNES::config.expansion_port = SNES::System::ExpansionPortDevice::None;
|
|
||||||
|
|
||||||
movie newmovie;
|
movie newmovie;
|
||||||
if(lmode == LOAD_STATE_PRESERVE)
|
if(lmode == LOAD_STATE_PRESERVE)
|
||||||
|
@ -354,7 +360,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 = region;
|
||||||
random_seed_value = _movie.rtc_second;
|
random_seed_value = _movie.rtc_second;
|
||||||
our_rom->load();
|
our_rom->load();
|
||||||
|
|
||||||
|
@ -407,39 +413,7 @@ 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) {
|
|
||||||
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;
|
messages << std::endl;
|
||||||
uint64_t mlength = _movie.get_movie_length();
|
uint64_t mlength = _movie.get_movie_length();
|
||||||
{
|
{
|
||||||
|
|
|
@ -296,7 +296,7 @@ porttype_t parse_controller_type(const std::string& type, bool port) throw(std::
|
||||||
moviefile::moviefile() throw(std::bad_alloc)
|
moviefile::moviefile() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
force_corrupt = false;
|
force_corrupt = false;
|
||||||
gametype = GT_INVALID;
|
gametype = "";
|
||||||
port1 = PT_INVALID;
|
port1 = PT_INVALID;
|
||||||
port2 = PT_INVALID;
|
port2 = PT_INVALID;
|
||||||
coreversion = "";
|
coreversion = "";
|
||||||
|
@ -305,6 +305,8 @@ moviefile::moviefile() throw(std::bad_alloc)
|
||||||
is_savestate = false;
|
is_savestate = false;
|
||||||
movie_rtc_second = rtc_second = DEFAULT_RTC_SECOND;
|
movie_rtc_second = rtc_second = DEFAULT_RTC_SECOND;
|
||||||
movie_rtc_subsecond = rtc_subsecond = DEFAULT_RTC_SUBSECOND;
|
movie_rtc_subsecond = rtc_subsecond = DEFAULT_RTC_SUBSECOND;
|
||||||
|
main_checksums.resize(27);
|
||||||
|
markup_checksums.resize(27);
|
||||||
}
|
}
|
||||||
|
|
||||||
moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtime_error)
|
moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtime_error)
|
||||||
|
@ -319,14 +321,7 @@ moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtim
|
||||||
read_linefile(r, "controlsversion", tmp);
|
read_linefile(r, "controlsversion", tmp);
|
||||||
if(tmp != "0")
|
if(tmp != "0")
|
||||||
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", gametype);
|
||||||
try {
|
|
||||||
gametype = gtype::togametype(tmp);
|
|
||||||
} catch(std::bad_alloc& e) {
|
|
||||||
throw;
|
|
||||||
} catch(std::exception& e) {
|
|
||||||
throw std::runtime_error("Illegal game type '" + tmp + "'");
|
|
||||||
}
|
|
||||||
tmp = "gamepad";
|
tmp = "gamepad";
|
||||||
read_linefile(r, "port1", tmp, true);
|
read_linefile(r, "port1", tmp, true);
|
||||||
port1 = porttype_info::lookup(tmp).value;
|
port1 = porttype_info::lookup(tmp).value;
|
||||||
|
@ -338,12 +333,16 @@ 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);
|
main_checksums.resize(27);
|
||||||
read_linefile(r, "romxml.sha256", romxml_sha256, true);
|
markup_checksums.resize(27);
|
||||||
read_linefile(r, "slota.sha256", slota_sha256, true);
|
read_linefile(r, "rom.sha256", main_checksums[0], true);
|
||||||
read_linefile(r, "slotaxml.sha256", slotaxml_sha256, true);
|
read_linefile(r, "romxml.sha256", markup_checksums[0], true);
|
||||||
read_linefile(r, "slotb.sha256", slotb_sha256, true);
|
for(size_t i = 0; i < 26; i++) {
|
||||||
read_linefile(r, "slotbxml.sha256", slotbxml_sha256, true);
|
read_linefile(r, (stringfmt() << "slot" << static_cast<char>('a' + i) << ".sha256").str(),
|
||||||
|
main_checksums[i + 1], true);
|
||||||
|
read_linefile(r, (stringfmt() << "slot" << static_cast<char>('a' + i) << "xml.sha256").str(),
|
||||||
|
markup_checksums[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;
|
||||||
|
@ -386,7 +385,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);
|
||||||
if(port1 != PT_GAMEPAD)
|
if(port1 != PT_GAMEPAD)
|
||||||
write_linefile(w, "port1", porttype_info::lookup(port1).name);
|
write_linefile(w, "port1", porttype_info::lookup(port1).name);
|
||||||
if(port2 != PT_NONE)
|
if(port2 != PT_NONE)
|
||||||
|
@ -398,12 +397,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", main_checksums[0], true);
|
||||||
write_linefile(w, "romxml.sha256", romxml_sha256, true);
|
write_linefile(w, "romxml.sha256", markup_checksums[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" << static_cast<char>('a' + i) << ".sha256").str(),
|
||||||
write_linefile(w, "slotb.sha256", slotb_sha256, true);
|
main_checksums[i + 1], true);
|
||||||
write_linefile(w, "slotbxml.sha256", slotbxml_sha256, true);
|
write_linefile(w, (stringfmt() << "slot" << static_cast<char>('a' + i) << "xml.sha256").str(),
|
||||||
|
markup_checksums[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);
|
||||||
|
@ -438,11 +439,6 @@ namespace
|
||||||
const int BLOCK_FRAMES = 1;
|
const int BLOCK_FRAMES = 1;
|
||||||
const int STEP_W = 2;
|
const int STEP_W = 2;
|
||||||
const int STEP_N = 3;
|
const int STEP_N = 3;
|
||||||
|
|
||||||
uint64_t magic[2][4] = {
|
|
||||||
{178683, 10738636, 16639264, 596096},
|
|
||||||
{6448, 322445, 19997208, 266440}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t moviefile::get_movie_length(uint64_t framebias) throw()
|
uint64_t moviefile::get_movie_length(uint64_t framebias) throw()
|
||||||
|
@ -452,62 +448,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];
|
||||||
|
emucore_sysregion_for_sysregion(gametype)->get_length_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;
|
||||||
|
@ -523,3 +471,12 @@ std::string sanitize_prefix(const std::string& in) throw(std::bad_alloc)
|
||||||
}
|
}
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_romdata_to_movie(struct moviefile& movie, const struct loaded_rom& r)
|
||||||
|
{
|
||||||
|
movie.gametype = r.rtype->get_sysregion(r.region->get_iname())->get_iname();
|
||||||
|
for(size_t i = 0; i < r.rtype->rom_slots() && i < 27; i++)
|
||||||
|
movie.main_checksums[i] = r.main_slots[i].sha256;
|
||||||
|
for(size_t i = 0; i < r.rtype->rom_slots() && i < 27; i++)
|
||||||
|
movie.markup_checksums[i] = r.markup_slots[i].sha256;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "lsnes.hpp"
|
#include "lsnes.hpp"
|
||||||
#include <snes/snes.hpp>
|
|
||||||
|
|
||||||
#include "core/misc.hpp"
|
#include "core/misc.hpp"
|
||||||
#include "core/png.hpp"
|
#include "core/png.hpp"
|
||||||
|
@ -7,6 +6,8 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
572
src/core/rom.cpp
572
src/core/rom.cpp
|
@ -1,5 +1,3 @@
|
||||||
#include "core/bsnes.hpp"
|
|
||||||
|
|
||||||
#include "core/command.hpp"
|
#include "core/command.hpp"
|
||||||
#include "core/dispatch.hpp"
|
#include "core/dispatch.hpp"
|
||||||
#include "core/framerate.hpp"
|
#include "core/framerate.hpp"
|
||||||
|
@ -27,167 +25,7 @@
|
||||||
#include <boost/iostreams/filtering_stream.hpp>
|
#include <boost/iostreams/filtering_stream.hpp>
|
||||||
#include <boost/iostreams/device/back_inserter.hpp>
|
#include <boost/iostreams/device/back_inserter.hpp>
|
||||||
|
|
||||||
//Some anti-typo defs.
|
|
||||||
#define SNES_TYPE "snes"
|
|
||||||
#define SNES_PAL "snes_pal"
|
|
||||||
#define SNES_NTSC "snes_ntsc"
|
|
||||||
#define BSX "bsx"
|
|
||||||
#define BSXSLOTTED "bsxslotted"
|
|
||||||
#define SUFAMITURBO "sufamiturbo"
|
|
||||||
#define SGB_TYPE "SGB"
|
|
||||||
#define SGB_PAL "sgb_pal"
|
|
||||||
#define SGB_NTSC "sgb_ntsc"
|
|
||||||
|
|
||||||
std::string gtype::tostring(rom_type rtype, rom_region region) throw(std::bad_alloc, std::runtime_error)
|
|
||||||
{
|
|
||||||
switch(rtype) {
|
|
||||||
case ROMTYPE_SNES:
|
|
||||||
switch(region) {
|
|
||||||
case REGION_AUTO: return "snes";
|
|
||||||
case REGION_NTSC: return "snes_ntsc";
|
|
||||||
case REGION_PAL: return "snes_pal";
|
|
||||||
};
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
switch(gametype) {
|
|
||||||
case GT_SNES_NTSC: return "snes_ntsc";
|
|
||||||
case GT_SNES_PAL: return "snes_pal";
|
|
||||||
case GT_SGB_NTSC: return "sgb_ntsc";
|
|
||||||
case GT_SGB_PAL: return "sgb_pal";
|
|
||||||
case GT_BSX: return "bsx";
|
|
||||||
case GT_BSX_SLOTTED: return "bsxslotted";
|
|
||||||
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
|
||||||
|
@ -200,14 +38,6 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* romtypes_to_recognize[] = {
|
|
||||||
"rom", "bsx", "bsxslotted", "dmg", "slot-a", "slot-b",
|
|
||||||
"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)
|
||||||
{
|
{
|
||||||
std::string value;
|
std::string value;
|
||||||
|
@ -232,10 +62,10 @@ loaded_slot::loaded_slot() throw(std::bad_alloc)
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded_slot::loaded_slot(const std::string& filename, const std::string& base, bool xml_flag)
|
loaded_slot::loaded_slot(const std::string& filename, const std::string& base, struct rom_info_structure& slot,
|
||||||
throw(std::bad_alloc, std::runtime_error)
|
bool xml_flag) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
bool headered = false;
|
size_t headered = 0;
|
||||||
xml = xml_flag;
|
xml = xml_flag;
|
||||||
if(filename == "") {
|
if(filename == "") {
|
||||||
valid = false;
|
valid = false;
|
||||||
|
@ -243,16 +73,15 @@ loaded_slot::loaded_slot(const std::string& filename, const std::string& base, b
|
||||||
}
|
}
|
||||||
valid = true;
|
valid = true;
|
||||||
data = read_file_relative(filename, base);
|
data = read_file_relative(filename, base);
|
||||||
if(!xml && data.size() % 1024 == 512)
|
if(!xml)
|
||||||
//Assume headered.
|
//Assume headered.
|
||||||
headered = true;
|
headered = slot.headersize(data.size());
|
||||||
if(headered && !xml) {
|
if(headered) {
|
||||||
if(data.size() >= 512) {
|
if(data.size() >= headered) {
|
||||||
memmove(&data[0], &data[512], data.size() - 512);
|
memmove(&data[0], &data[headered], data.size() - headered);
|
||||||
data.resize(data.size() - 512);
|
data.resize(data.size() - headered);
|
||||||
} else {
|
} else
|
||||||
data.resize(0);
|
data.resize(0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sha256 = sha256::hash(data);
|
sha256 = sha256::hash(data);
|
||||||
if(xml) {
|
if(xml) {
|
||||||
|
@ -287,169 +116,124 @@ 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 = rom_xml = slota = slota_xml = slotb = slotb_xml = "";
|
|
||||||
std::string arr[sizeof(romtypes_to_recognize) / sizeof(romtypes_to_recognize[0])];
|
|
||||||
unsigned long flags = 0;
|
|
||||||
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;
|
|
||||||
|
|
||||||
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(auto& i : main_slots)
|
||||||
rom_xml = resolve_file_relative(rom_xml, base_file);
|
i = resolve_file_relative(i, base_file);
|
||||||
slota = resolve_file_relative(slota, base_file);
|
for(auto& i : markup_slots)
|
||||||
slota_xml = resolve_file_relative(slota_xml, base_file);
|
i = resolve_file_relative(i, base_file);
|
||||||
slotb = resolve_file_relative(slotb, base_file);
|
base_file = "";
|
||||||
slotb_xml = resolve_file_relative(slotb_xml, base_file);
|
}
|
||||||
|
|
||||||
|
rom_files::rom_files(const std::vector<std::string>& cmdline) throw(std::bad_alloc, std::runtime_error)
|
||||||
|
{
|
||||||
|
std::string systype = findoption(cmdline, "system");
|
||||||
|
if(systype == "")
|
||||||
|
throw std::runtime_error("System type (--system=<sys>) must be given");
|
||||||
|
for(size_t i = 0; i < emucore_systype_slots(); i++) {
|
||||||
|
auto j = emucore_systype_slot(i);
|
||||||
|
if(j->get_iname() == systype) {
|
||||||
|
rtype = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!rtype)
|
||||||
|
throw std::runtime_error("Unrecognized system type '" + systype + "'");
|
||||||
|
|
||||||
|
std::string _region = findoption(cmdline, "region");
|
||||||
|
if(_region == "")
|
||||||
|
//Default.
|
||||||
|
region = rtype->region_slot(0);
|
||||||
|
else {
|
||||||
|
for(size_t i = 0; i < rtype->region_slots(); i++) {
|
||||||
|
auto j = rtype->region_slot(i);
|
||||||
|
if(j->get_iname() == _region) {
|
||||||
|
region = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!region)
|
||||||
|
throw std::runtime_error("Unrecognized region '" + _region + "'");
|
||||||
|
|
||||||
|
main_slots.resize(rtype->rom_slots());
|
||||||
|
markup_slots.resize(rtype->rom_slots());
|
||||||
|
|
||||||
|
unsigned complete = 0;
|
||||||
|
unsigned flags = 0;
|
||||||
|
for(size_t i = 0; i < rtype->rom_slots(); i++) {
|
||||||
|
auto j = rtype->rom_slot(i);
|
||||||
|
complete |= j->mandatory_flags();
|
||||||
|
std::string f = findoption(cmdline, j->get_iname());
|
||||||
|
if(f != "") {
|
||||||
|
flags |= j->mandatory_flags();
|
||||||
|
main_slots[i] = f;
|
||||||
|
}
|
||||||
|
f = findoption(cmdline, j->get_iname() + "-xml");
|
||||||
|
if(f != "") {
|
||||||
|
if(!j->has_markup())
|
||||||
|
throw std::runtime_error("ROM type '" + j->get_iname() + "' does not have markup");
|
||||||
|
markup_slots[i] = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(complete != flags)
|
||||||
|
(stringfmt() << "Required ROM image missing (flags=" << flags << ", expected=" << complete << ")").
|
||||||
|
throwex();
|
||||||
base_file = "";
|
base_file = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair<enum rom_type, enum rom_region> get_current_rom_info() throw()
|
|
||||||
{
|
|
||||||
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;
|
if(files.rtype == NULL) {
|
||||||
std::string _slota_xml = files.slota_xml;
|
rtype = NULL;
|
||||||
std::string _slotb = files.slotb;
|
region = orig_region = NULL;
|
||||||
std::string _slotb_xml = files.slotb_xml;
|
|
||||||
if(files.rtype == ROMTYPE_NONE) {
|
|
||||||
rtype = ROMTYPE_NONE;
|
|
||||||
region = orig_region = files.region;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if((_slota != "" || _slota_xml != "") && files.rtype == ROMTYPE_SNES) {
|
main_slots.resize(files.main_slots.size());
|
||||||
messages << "WARNING: SNES takes only 1 ROM image" << std::endl;
|
markup_slots.resize(files.markup_slots.size());
|
||||||
_slota = "";
|
|
||||||
_slota_xml = "";
|
|
||||||
}
|
|
||||||
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 < main_slots.size(); i++)
|
||||||
rom_xml = loaded_slot(files.rom_xml, files.base_file, true);
|
main_slots[i] = loaded_slot(files.main_slots[i], files.base_file, *rtype->rom_slot(i), false);
|
||||||
slota = loaded_slot(_slota, files.base_file, false);
|
for(size_t i = 0; i < markup_slots.size(); i++)
|
||||||
slota_xml = loaded_slot(_slota_xml, files.base_file, true);
|
if(rtype->rom_slot(i)->has_markup())
|
||||||
slotb = loaded_slot(_slotb, files.base_file, false);
|
markup_slots[i] = loaded_slot(files.markup_slots[i], files.base_file, *rtype->rom_slot(i),
|
||||||
slotb_xml = loaded_slot(_slotb_xml, files.base_file, true);
|
true);
|
||||||
orig_region = region = files.region;
|
orig_region = region = files.region;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if(!orig_region->compatible(region->get_iname()))
|
||||||
case REGION_AUTO:
|
throw std::runtime_error("Trying to force incompatible region");
|
||||||
SNES::config.region = SNES::System::Region::Autodetect;
|
|
||||||
break;
|
std::vector<std::vector<char>> romslots;
|
||||||
case REGION_NTSC:
|
std::vector<std::vector<char>> markslots;
|
||||||
SNES::config.region = SNES::System::Region::NTSC;
|
romslots.resize(main_slots.size());
|
||||||
break;
|
markslots.resize(markup_slots.size());
|
||||||
case REGION_PAL:
|
for(size_t i = 0; i < romslots.size(); i++)
|
||||||
SNES::config.region = SNES::System::Region::PAL;
|
romslots[i] = main_slots[i].data;
|
||||||
break;
|
for(size_t i = 0; i < markslots.size(); i++)
|
||||||
default:
|
markslots[i] = markup_slots[i].data;
|
||||||
throw std::runtime_error("Trying to force unknown region");
|
emucore_load_rom(rtype, region, romslots, markslots);
|
||||||
}
|
|
||||||
switch(rtype) {
|
region = emucore_current_region();
|
||||||
case ROMTYPE_SNES:
|
|
||||||
if(!snes_load_cartridge_normal(rom_xml, rom, rom))
|
|
||||||
throw std::runtime_error("Can't load cartridge ROM");
|
|
||||||
break;
|
|
||||||
case ROMTYPE_BSX:
|
|
||||||
if(region == REGION_PAL)
|
|
||||||
throw std::runtime_error("BSX can't be PAL");
|
|
||||||
if(!snes_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(!snes_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(!snes_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(!snes_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 = snes_get_region() ? REGION_PAL : REGION_NTSC;
|
|
||||||
snes_power();
|
|
||||||
auto framerate = emucore_get_video_rate();
|
auto framerate = emucore_get_video_rate();
|
||||||
auto soundrate = emucore_get_audio_rate();
|
auto soundrate = emucore_get_audio_rate();
|
||||||
set_nominal_framerate(1.0 * framerate.first / framerate.second);
|
set_nominal_framerate(1.0 * framerate.first / framerate.second);
|
||||||
information_dispatch::do_sound_rate(soundrate.first, soundrate.second);
|
information_dispatch::do_sound_rate(soundrate.first, soundrate.second);
|
||||||
current_rom_type = rtype;
|
|
||||||
current_region = region;
|
|
||||||
emucore_refresh_cart();
|
|
||||||
refresh_cart_mappings();
|
refresh_cart_mappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,16 +261,20 @@ 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])) {
|
bool found = false;
|
||||||
case 0: rom.patch(ips, offset); break;
|
for(size_t j = 0; j < rtype->rom_slots(); j++)
|
||||||
case 1: rom_xml.patch(ips, offset); break;
|
if(opt[1] == rtype->rom_slot(j)->get_iname()) {
|
||||||
case 2: slota.patch(ips, offset); break;
|
main_slots[j].patch(ips, offset);
|
||||||
case 3: slota_xml.patch(ips, offset); break;
|
found = true;
|
||||||
case 4: slotb.patch(ips, offset); break;
|
break;
|
||||||
case 5: slotb_xml.patch(ips, offset); break;
|
} else if(opt[1] == rtype->rom_slot(j)->get_iname() + "-xml" &&
|
||||||
default:
|
rtype->rom_slot(j)->has_markup()) {
|
||||||
|
markup_slots[j].patch(ips, offset);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
throw std::runtime_error("Invalid subROM '" + opt[1] + "' to patch");
|
throw std::runtime_error("Invalid subROM '" + opt[1] + "' to patch");
|
||||||
}
|
|
||||||
} catch(std::bad_alloc& e) {
|
} catch(std::bad_alloc& e) {
|
||||||
OOM_panic();
|
OOM_panic();
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
|
@ -568,84 +356,64 @@ std::map<std::string, std::vector<char>> load_sram_commandline(const std::vector
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name_subrom(enum rom_type major, unsigned romnumber) throw(std::bad_alloc)
|
struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) throw(std::bad_alloc,
|
||||||
|
std::runtime_error)
|
||||||
{
|
{
|
||||||
if(romnumber == 0)
|
struct rom_files f;
|
||||||
return "ROM";
|
try {
|
||||||
else if(romnumber == 1)
|
f = rom_files(cmdline);
|
||||||
return "ROM XML";
|
f.resolve_relative();
|
||||||
else if(major == ROMTYPE_BSX && romnumber == 2)
|
} catch(std::bad_alloc& e) {
|
||||||
return "BSX ROM";
|
OOM_panic();
|
||||||
else if(major == ROMTYPE_BSX && romnumber == 3)
|
} catch(std::exception& e) {
|
||||||
return "BSX XML";
|
throw std::runtime_error(std::string("Can't resolve ROM files: ") + e.what());
|
||||||
else if(major == ROMTYPE_BSXSLOTTED && romnumber == 2)
|
}
|
||||||
return "BSX ROM";
|
messages << "ROM type: " << f.rtype->get_iname() << "/" << f.region->get_iname() << std::endl;
|
||||||
else if(major == ROMTYPE_BSXSLOTTED && romnumber == 3)
|
for(size_t i = 0; i < f.rtype->rom_slots(); i++) {
|
||||||
return "BSX XML";
|
if(f.main_slots[i] != "")
|
||||||
else if(major == ROMTYPE_SGB && romnumber == 2)
|
messages << "'" << f.rtype->rom_slot(i)->get_hname() << "' file '" << f.main_slots[i]
|
||||||
return "DMG ROM";
|
<< std::endl;
|
||||||
else if(major == ROMTYPE_SGB && romnumber == 3)
|
if(f.markup_slots[i] != "" && f.rtype->rom_slot(i)->has_markup())
|
||||||
return "DMG XML";
|
messages << "'" << f.rtype->rom_slot(i)->get_hname() << "' markup file '"
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 2)
|
<< f.markup_slots[i] << std::endl;
|
||||||
return "SLOT A ROM";
|
}
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 3)
|
|
||||||
return "SLOT A XML";
|
struct loaded_rom r;
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 4)
|
try {
|
||||||
return "SLOT B ROM";
|
r = loaded_rom(f);
|
||||||
else if(major == ROMTYPE_SUFAMITURBO && romnumber == 5)
|
r.do_patch(cmdline);
|
||||||
return "SLOT B XML";
|
} catch(std::bad_alloc& e) {
|
||||||
else if(romnumber % 2)
|
OOM_panic();
|
||||||
return "UNKNOWN XML";
|
} catch(std::exception& e) {
|
||||||
else
|
throw std::runtime_error(std::string("Can't load ROM: ") + e.what());
|
||||||
return "UNKNOWN ROM";
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < r.rtype->rom_slots(); i++) {
|
||||||
|
if(r.main_slots[i].valid)
|
||||||
|
messages << "'" << f.rtype->rom_slot(i)->get_hname() << "' hash " << r.main_slots[i].sha256
|
||||||
|
<< std::endl;
|
||||||
|
if(r.markup_slots[i].valid && r.rtype->rom_slot(i)->has_markup())
|
||||||
|
messages << "'" << f.rtype->rom_slot(i)->get_hname() << "' markup hash '"
|
||||||
|
<< r.markup_slots[i].sha256 << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump_region_map() throw(std::bad_alloc)
|
||||||
int recognize_commandline_rom(enum rom_type major, const std::string& romname) throw(std::bad_alloc)
|
|
||||||
{
|
{
|
||||||
if(romname == romtypes_to_recognize[0])
|
std::vector<vma_structure*> regions = get_regions();
|
||||||
return 0;
|
for(auto i : regions) {
|
||||||
else if(romname == romtypes_to_recognize[6])
|
char buf[256];
|
||||||
return 1;
|
char echar;
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[1])
|
if(i->get_endian() == vma_structure::E_LITTLE)
|
||||||
return 2;
|
echar = 'L';
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[7])
|
if(i->get_endian() == vma_structure::E_BIG)
|
||||||
return 3;
|
echar = 'B';
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[2])
|
if(i->get_endian() == vma_structure::E_HOST)
|
||||||
return 2;
|
echar = 'N';
|
||||||
else if(major == ROMTYPE_BSX && romname == romtypes_to_recognize[8])
|
sprintf(buf, "Region: %016X-%016X %016X %s%c %s", i->get_base(), i->get_base() + i->get_size() - 1,
|
||||||
return 3;
|
i->get_size(), i->is_readonly() ? "R-" : "RW", echar, i->get_name().c_str());
|
||||||
else if(major == ROMTYPE_SGB && romname == romtypes_to_recognize[3])
|
messages << buf << std::endl;
|
||||||
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)
|
|
||||||
{
|
|
||||||
if((flags & 07700) >> 6 & ~(flags & 077))
|
|
||||||
throw std::runtime_error("SubROM XML specified without corresponding subROM");
|
|
||||||
if((flags & 1) == 0)
|
|
||||||
throw std::runtime_error("No SNES main cartridge ROM specified");
|
|
||||||
if((flags & 077) == 1)
|
|
||||||
return ROMTYPE_SNES;
|
|
||||||
if((flags & 077) == 3)
|
|
||||||
return ROMTYPE_BSX;
|
|
||||||
if((flags & 077) == 5)
|
|
||||||
return ROMTYPE_BSXSLOTTED;
|
|
||||||
if((flags & 077) == 9)
|
|
||||||
return ROMTYPE_SGB;
|
|
||||||
if((flags & 060) != 0 && (flags & 017) == 1)
|
|
||||||
return ROMTYPE_SUFAMITURBO;
|
|
||||||
throw std::runtime_error("Not valid combination of rom/bsx/bsxslotted/dmg/slot-a/slot-b");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
uint64_t ntsc_magic[4] = {178683, 10738636, 16639264, 596096};
|
||||||
|
uint64_t pal_magic[4] = {6448, 322445, 19997208, 266440};
|
||||||
|
|
||||||
class my_interfaced : public SNES::Interface
|
class my_interfaced : public SNES::Interface
|
||||||
{
|
{
|
||||||
string path(SNES::Cartridge::Slot slot, const string &hint)
|
string path(SNES::Cartridge::Slot slot, const string &hint)
|
||||||
|
@ -23,6 +26,179 @@ namespace
|
||||||
return "./";
|
return "./";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bsnes_region_info_structure : public region_info_structure
|
||||||
|
{
|
||||||
|
bsnes_region_info_structure(const std::string& _iname, const std::string& _hname, bool _autod)
|
||||||
|
{
|
||||||
|
hname = _hname;
|
||||||
|
iname = _iname;
|
||||||
|
autod = _autod;
|
||||||
|
}
|
||||||
|
~bsnes_region_info_structure() {}
|
||||||
|
std::string get_hname() { return hname; }
|
||||||
|
std::string get_iname() { return iname; }
|
||||||
|
bool compatible(const std::string& movie) { return autod || movie == iname; }
|
||||||
|
std::string hname;
|
||||||
|
std::string iname;
|
||||||
|
bool autod;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bsnes_sysregion_info_structure : public sysregion_info_structure
|
||||||
|
{
|
||||||
|
bsnes_sysregion_info_structure(const std::string& _iname, bool _pal)
|
||||||
|
{
|
||||||
|
iname = _iname;
|
||||||
|
pal = _pal;
|
||||||
|
}
|
||||||
|
~bsnes_sysregion_info_structure() {}
|
||||||
|
std::string get_iname() { return iname; }
|
||||||
|
void get_length_magic(uint64_t* magic)
|
||||||
|
{
|
||||||
|
if(pal)
|
||||||
|
memcpy(magic, pal_magic, sizeof(pal_magic));
|
||||||
|
else
|
||||||
|
memcpy(magic, ntsc_magic, sizeof(ntsc_magic));
|
||||||
|
}
|
||||||
|
std::string iname;
|
||||||
|
bool pal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bsnes_rom_info_structure : public rom_info_structure
|
||||||
|
{
|
||||||
|
bsnes_rom_info_structure(const std::string& _iname, const std::string& _hname, unsigned _mflags)
|
||||||
|
{
|
||||||
|
iname = _iname;
|
||||||
|
hname = _hname;
|
||||||
|
mflags = _mflags;
|
||||||
|
}
|
||||||
|
~bsnes_rom_info_structure() {}
|
||||||
|
std::string get_iname() { return iname; }
|
||||||
|
std::string get_hname() { return hname; }
|
||||||
|
bool has_markup() { return true; }
|
||||||
|
size_t headersize(size_t imagesize)
|
||||||
|
{
|
||||||
|
return (imagesize % 1024 == 512) ? 512 : 0;
|
||||||
|
}
|
||||||
|
virtual unsigned mandatory_flags() { return mflags; }
|
||||||
|
std::string iname;
|
||||||
|
std::string hname;
|
||||||
|
unsigned mflags;
|
||||||
|
};
|
||||||
|
|
||||||
|
bsnes_region_info_structure r_autodetect("autodetect", "Autodetect", true);
|
||||||
|
bsnes_region_info_structure r_ntsc("ntsc", "NTSC", false);
|
||||||
|
bsnes_region_info_structure r_pal("pal", "PAL", false);
|
||||||
|
bsnes_sysregion_info_structure t_snes_ntsc("snes_ntsc", false);
|
||||||
|
bsnes_sysregion_info_structure t_snes_pal("snes_pal", true);
|
||||||
|
bsnes_sysregion_info_structure t_bsx("bsx", false);
|
||||||
|
bsnes_sysregion_info_structure t_bsxslotted("bsxslotted", false);
|
||||||
|
bsnes_sysregion_info_structure t_sufamiturbo("sufamiturbo", false);
|
||||||
|
bsnes_sysregion_info_structure t_sgb_ntsc("sgb_ntsc", false);
|
||||||
|
bsnes_sysregion_info_structure t_sgb_pal("sgb_pal", true);
|
||||||
|
bsnes_rom_info_structure g_snes("rom", "Cartridge ROM", 1);
|
||||||
|
bsnes_rom_info_structure g_bsx_bios("bsxbios", "BS-X BIOS", 1);
|
||||||
|
bsnes_rom_info_structure g_bsx_flash("bsxflash", "BS-X FLASH", 2);
|
||||||
|
bsnes_rom_info_structure g_st_bios("stbios", "Sufami Turbo BIOS", 1);
|
||||||
|
bsnes_rom_info_structure g_st_slota("stslota", "Slot A ROM", 2);
|
||||||
|
bsnes_rom_info_structure g_st_slotb("stslotb", "Slot B ROM", 2);
|
||||||
|
bsnes_rom_info_structure g_sgb_bios("sgbbios", "SGB BIOS", 1);
|
||||||
|
bsnes_rom_info_structure g_dmg("dmg", "DMG ROM", 2);
|
||||||
|
|
||||||
|
struct bsnes_systype : public systype_info_structure
|
||||||
|
{
|
||||||
|
bsnes_systype(int index)
|
||||||
|
{
|
||||||
|
switch(index) {
|
||||||
|
case 0:
|
||||||
|
iname = "snes";
|
||||||
|
hname = "SNES";
|
||||||
|
regslots.push_back(&r_autodetect);
|
||||||
|
regslots.push_back(&r_ntsc);
|
||||||
|
regslots.push_back(&r_pal);
|
||||||
|
romslots.push_back(&g_snes);
|
||||||
|
sysregions["ntsc"] = &t_snes_ntsc;
|
||||||
|
sysregions["pal"] = &t_snes_pal;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
iname = "bsx";
|
||||||
|
hname = "BS-X (non-slotted)";
|
||||||
|
regslots.push_back(&r_ntsc);
|
||||||
|
romslots.push_back(&g_bsx_bios);
|
||||||
|
romslots.push_back(&g_bsx_flash);
|
||||||
|
sysregions["ntsc"] = &t_bsx;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
iname = "bsxslotted";
|
||||||
|
hname = "BS-X (slotted)";
|
||||||
|
regslots.push_back(&r_ntsc);
|
||||||
|
romslots.push_back(&g_bsx_bios);
|
||||||
|
romslots.push_back(&g_bsx_flash);
|
||||||
|
sysregions["ntsc"] = &t_bsxslotted;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
iname = "sufamiturbo";
|
||||||
|
hname = "Sufami Turbo";
|
||||||
|
regslots.push_back(&r_ntsc);
|
||||||
|
romslots.push_back(&g_st_bios);
|
||||||
|
romslots.push_back(&g_st_slota);
|
||||||
|
romslots.push_back(&g_st_slotb);
|
||||||
|
sysregions["ntsc"] = &t_sufamiturbo;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
iname = "sgb";
|
||||||
|
hname = "Super Game Boy";
|
||||||
|
regslots.push_back(&r_autodetect);
|
||||||
|
regslots.push_back(&r_ntsc);
|
||||||
|
regslots.push_back(&r_pal);
|
||||||
|
romslots.push_back(&g_sgb_bios);
|
||||||
|
romslots.push_back(&g_dmg);
|
||||||
|
sysregions["ntsc"] = &t_sgb_ntsc;
|
||||||
|
sysregions["pal"] = &t_sgb_pal;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
~bsnes_systype() {};
|
||||||
|
std::string get_iname() { return iname; }
|
||||||
|
std::string get_hname() { return hname; }
|
||||||
|
size_t region_slots() { return regslots.size(); };
|
||||||
|
struct region_info_structure* region_slot(size_t index)
|
||||||
|
{
|
||||||
|
return (index < regslots.size()) ? regslots[index] : NULL;
|
||||||
|
}
|
||||||
|
size_t rom_slots() { return romslots.size(); }
|
||||||
|
struct rom_info_structure* rom_slot(size_t index)
|
||||||
|
{
|
||||||
|
return (index < romslots.size()) ? romslots[index] : NULL;
|
||||||
|
}
|
||||||
|
struct sysregion_info_structure* get_sysregion(const std::string& region)
|
||||||
|
{
|
||||||
|
return sysregions.count(region) ? sysregions[region] : NULL;
|
||||||
|
}
|
||||||
|
std::string iname;
|
||||||
|
std::string hname;
|
||||||
|
std::vector<region_info_structure*> regslots;
|
||||||
|
std::vector<rom_info_structure*> romslots;
|
||||||
|
std::map<std::string, sysregion_info_structure*> sysregions;
|
||||||
|
};
|
||||||
|
|
||||||
|
bsnes_systype s_snes(0);
|
||||||
|
bsnes_systype s_bsx(1);
|
||||||
|
bsnes_systype s_bsxslotted(2);
|
||||||
|
bsnes_systype s_sufamiturbo(3);
|
||||||
|
bsnes_systype s_sgb(4);
|
||||||
|
|
||||||
|
void internal_load(const std::vector<std::vector<char>>& romslots,
|
||||||
|
const std::vector<std::vector<char>>&markslots, size_t i, const uint8_t*& rom, const char*& xml,
|
||||||
|
size_t& romsize)
|
||||||
|
{
|
||||||
|
if(i < romslots.size() && romslots[i].size()) {
|
||||||
|
rom = reinterpret_cast<const uint8_t*>(&romslots[i][0]);
|
||||||
|
romsize = romslots[i].size();
|
||||||
|
}
|
||||||
|
if(i < markslots.size() && markslots[i].size())
|
||||||
|
xml = &markslots[i][0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string emucore_get_version()
|
std::string emucore_get_version()
|
||||||
|
@ -296,3 +472,76 @@ void emucore_unserialize(const std::vector<char>& buf)
|
||||||
if(!SNES::system.unserialize(s))
|
if(!SNES::system.unserialize(s))
|
||||||
throw std::runtime_error("SNES core rejected savestate");
|
throw std::runtime_error("SNES core rejected savestate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t emucore_systype_slots()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct systype_info_structure* emucore_systype_slot(size_t index)
|
||||||
|
{
|
||||||
|
switch(index) {
|
||||||
|
case 0: return &s_snes;
|
||||||
|
case 1: return &s_bsx;
|
||||||
|
case 2: return &s_bsxslotted;
|
||||||
|
case 3: return &s_sufamiturbo;
|
||||||
|
case 4: return &s_sgb;
|
||||||
|
default: return NULL;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void emucore_load_rom(systype_info_structure* rtype, region_info_structure* region,
|
||||||
|
const std::vector<std::vector<char>>& romslots, const std::vector<std::vector<char>>& markslots)
|
||||||
|
{
|
||||||
|
if(region == &r_autodetect)
|
||||||
|
SNES::config.region = SNES::System::Region::Autodetect;
|
||||||
|
else if(region == &r_ntsc)
|
||||||
|
SNES::config.region = SNES::System::Region::NTSC;
|
||||||
|
else if(region == &r_pal)
|
||||||
|
SNES::config.region = SNES::System::Region::PAL;
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Trying to force unknown region");
|
||||||
|
const uint8_t* rom0 = NULL;
|
||||||
|
const char* xml0 = NULL;
|
||||||
|
size_t rom0size = 0;
|
||||||
|
const uint8_t* rom1 = NULL;
|
||||||
|
const char* xml1 = NULL;
|
||||||
|
size_t rom1size = 0;
|
||||||
|
const uint8_t* rom2 = NULL;
|
||||||
|
const char* xml2 = NULL;
|
||||||
|
size_t rom2size = 0;
|
||||||
|
internal_load(romslots, markslots, 0, rom0, xml0, rom0size);
|
||||||
|
internal_load(romslots, markslots, 1, rom1, xml1, rom1size);
|
||||||
|
internal_load(romslots, markslots, 2, rom2, xml2, rom2size);
|
||||||
|
|
||||||
|
if(rtype == &s_snes) {
|
||||||
|
if(!snes_load_cartridge_normal(xml0, rom0, rom0size))
|
||||||
|
throw std::runtime_error("Can't load cartridge ROM");
|
||||||
|
} else if(rtype == &s_bsx) {
|
||||||
|
if(!snes_load_cartridge_bsx(xml0, rom0, rom0size, xml1, rom1, rom1size))
|
||||||
|
throw std::runtime_error("Can't load cartridge ROM");
|
||||||
|
} else if(rtype == &s_bsxslotted) {
|
||||||
|
if(!snes_load_cartridge_bsx_slotted(xml0, rom0, rom0size, xml1, rom1, rom1size))
|
||||||
|
throw std::runtime_error("Can't load cartridge ROM");
|
||||||
|
} else if(rtype == &s_sgb) {
|
||||||
|
if(!snes_load_cartridge_super_game_boy(xml0, rom0, rom0size, xml1, rom1, rom1size))
|
||||||
|
throw std::runtime_error("Can't load cartridge ROM");
|
||||||
|
} else if(rtype == &s_sufamiturbo) {
|
||||||
|
if(!snes_load_cartridge_sufami_turbo(xml0, rom0, rom0size, xml1, rom1, rom1size, xml2, rom2, rom2size))
|
||||||
|
throw std::runtime_error("Can't load cartridge ROM");
|
||||||
|
} else
|
||||||
|
throw std::runtime_error("Unknown cartridge type");
|
||||||
|
snes_power();
|
||||||
|
emucore_refresh_cart();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct region_info_structure* emucore_current_region()
|
||||||
|
{
|
||||||
|
return snes_get_region() ? &r_pal : &r_ntsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emucore_pre_load_settings()
|
||||||
|
{
|
||||||
|
SNES::config.random = false;
|
||||||
|
SNES::config.expansion_port = SNES::System::ExpansionPortDevice::None;
|
||||||
|
}
|
|
@ -16,3 +16,64 @@ vma_structure::vma_structure(const std::string& _name, uint64_t _base, uint64_t
|
||||||
vma_structure::~vma_structure()
|
vma_structure::~vma_structure()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
region_info_structure::~region_info_structure()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
sysregion_info_structure::~sysregion_info_structure()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
rom_info_structure::~rom_info_structure()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
systype_info_structure::~systype_info_structure()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct region_info_structure* emucore_region_for_sysregion(const std::string& sysregion)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < emucore_systype_slots(); i++) {
|
||||||
|
auto j = emucore_systype_slot(i);
|
||||||
|
for(size_t k = 0; k < j->region_slots(); k++) {
|
||||||
|
auto l = j->region_slot(k);
|
||||||
|
auto n = l->get_iname();
|
||||||
|
auto x = j->get_sysregion(n);
|
||||||
|
if(x && x->get_iname() == sysregion)
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct systype_info_structure* emucore_systype_for_sysregion(const std::string& sysregion)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < emucore_systype_slots(); i++) {
|
||||||
|
auto j = emucore_systype_slot(i);
|
||||||
|
for(size_t k = 0; k < j->region_slots(); k++) {
|
||||||
|
auto l = j->region_slot(k);
|
||||||
|
auto n = l->get_iname();
|
||||||
|
auto x = j->get_sysregion(n);
|
||||||
|
if(x && x->get_iname() == sysregion)
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sysregion_info_structure* emucore_sysregion_for_sysregion(const std::string& sysregion)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < emucore_systype_slots(); i++) {
|
||||||
|
auto j = emucore_systype_slot(i);
|
||||||
|
for(size_t k = 0; k < j->region_slots(); k++) {
|
||||||
|
auto l = j->region_slot(k);
|
||||||
|
auto n = l->get_iname();
|
||||||
|
auto x = j->get_sysregion(n);
|
||||||
|
if(x && x->get_iname() == sysregion)
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -28,13 +28,7 @@ struct moviefile generate_movie_template(std::vector<std::string> cmdline, loade
|
||||||
movie.port2 = PT_NONE;
|
movie.port2 = PT_NONE;
|
||||||
movie.coreversion = emucore_get_version();
|
movie.coreversion = emucore_get_version();
|
||||||
movie.projectid = get_random_hexstring(40);
|
movie.projectid = get_random_hexstring(40);
|
||||||
movie.gametype = gtype::togametype(r.rtype, r.region);
|
copy_romdata_to_movie(movie, r);
|
||||||
movie.rom_sha256 = r.rom.sha256;
|
|
||||||
movie.romxml_sha256 = r.rom_xml.sha256;
|
|
||||||
movie.slota_sha256 = r.slota.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;
|
||||||
|
@ -179,11 +173,9 @@ 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->get_sysregion(r.region->get_iname())->get_iname() << std::endl;
|
||||||
if(r.region == REGION_PAL)
|
auto vrate = emucore_get_video_rate();
|
||||||
set_nominal_framerate(322445.0/6448.0);
|
set_nominal_framerate(1.0 * vrate.first / vrate.second);
|
||||||
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();
|
||||||
|
|
|
@ -26,28 +26,12 @@
|
||||||
#define CNAME_SUPERSCOPE "Superscope"
|
#define CNAME_SUPERSCOPE "Superscope"
|
||||||
#define CNAME_JUSTIFIER "Justifier"
|
#define CNAME_JUSTIFIER "Justifier"
|
||||||
#define CNAME_JUSTIFIERS "2 Justifiers"
|
#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
|
||||||
{
|
{
|
||||||
|
@ -72,137 +56,110 @@ 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)
|
||||||
case 0: return rom.rom;
|
return rom.markup_slots[index / 2];
|
||||||
case 1: return rom.rom_xml;
|
else
|
||||||
case 2: return rom.slota;
|
return rom.main_slots[index / 2];
|
||||||
case 3: return rom.slota_xml;
|
}
|
||||||
case 4: return rom.slotb;
|
|
||||||
case 5: return rom.slotb_xml;
|
struct region_info_structure* region_from_string(struct systype_info_structure* s, const std::string& str)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < s->region_slots(); i++) {
|
||||||
|
auto r = s->region_slot(i);
|
||||||
|
if(r->get_hname() == str)
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
return rom.rom;
|
return s->region_slot(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum rom_region region_from_string(const std::string& str)
|
unsigned populate_region_choices(struct systype_info_structure* s, wxString* array)
|
||||||
{
|
{
|
||||||
if(str == RNAME_NTSC)
|
if(!s) {
|
||||||
return REGION_NTSC;
|
array[0] = towxstring("NULL");
|
||||||
if(str == RNAME_PAL)
|
return 1;
|
||||||
return REGION_PAL;
|
}
|
||||||
return REGION_AUTO;
|
size_t x = s->region_slots();
|
||||||
}
|
for(size_t i = 0; i < x; i++)
|
||||||
|
array[i] = towxstring(s->region_slot(i)->get_hname());
|
||||||
unsigned populate_region_choices(wxString* array)
|
return x;
|
||||||
{
|
|
||||||
array[0] = wxT(RNAME_AUTO);
|
|
||||||
array[1] = wxT(RNAME_NTSC);
|
|
||||||
array[2] = wxT(RNAME_PAL);
|
|
||||||
return 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned populate_system_choices(wxString* array)
|
unsigned populate_system_choices(wxString* array)
|
||||||
{
|
{
|
||||||
array[0] = wxT(TNAME_SNES);
|
size_t x = emucore_systype_slots();
|
||||||
array[1] = wxT(TNAME_BSX_NS);
|
for(size_t i = 0; i < x; i++)
|
||||||
array[2] = wxT(TNAME_BSX_S);
|
array[i] = towxstring(emucore_systype_slot(i)->get_hname());
|
||||||
array[3] = wxT(TNAME_SUFAMITURBO);
|
return x;
|
||||||
array[4] = wxT(TNAME_SGB);
|
|
||||||
return 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_present_roms(enum rom_type rtype, unsigned flags)
|
bool check_present_roms(struct systype_info_structure* s, unsigned flags)
|
||||||
{
|
{
|
||||||
switch(rtype)
|
if(!s)
|
||||||
{
|
|
||||||
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;
|
return false;
|
||||||
};
|
size_t x = s->rom_slots();
|
||||||
}
|
unsigned p = 0;
|
||||||
|
unsigned a = 0;
|
||||||
std::string romname(enum rom_type rtype, unsigned index)
|
for(size_t i = 0; i < x; i++) {
|
||||||
{
|
unsigned lflags = s->rom_slot(i)->mandatory_flags();
|
||||||
switch(rtype) {
|
a |= lflags;
|
||||||
case ROMTYPE_SNES:
|
if((flags >> i) & 1)
|
||||||
switch(index) {
|
p |= lflags;
|
||||||
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 "";
|
return (p == a);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned romname_to_index(enum rom_type rtype, const wxString& _name)
|
std::string romname(struct systype_info_structure* s, unsigned index)
|
||||||
|
{
|
||||||
|
if(index >= s->rom_slots())
|
||||||
|
return "";
|
||||||
|
return s->rom_slot(index)->get_hname();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned romname_to_index(struct systype_info_structure* s, 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 < s->rom_slots(); i++) {
|
||||||
if(romname(rtype, i) == name)
|
auto base = s->rom_slot(i)->get_hname();
|
||||||
|
if(base == name)
|
||||||
return 2 * i;
|
return 2 * i;
|
||||||
if(romname(rtype, i) + MARKUP_POSTFIX == name)
|
if(base + MARKUP_POSTFIX == name)
|
||||||
return 2 * i + 1;
|
return 2 * i + 1;
|
||||||
}
|
}
|
||||||
return 2 * ROMSELECT_ROM_COUNT;
|
return 2 * s->rom_slots();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned fill_rom_names(enum rom_type rtype, std::string* array)
|
unsigned fill_rom_names(struct systype_info_structure* s, std::string* array)
|
||||||
{
|
{
|
||||||
unsigned r = 0;
|
unsigned r = 0;
|
||||||
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++) {
|
for(unsigned i = 0; i < s->rom_slots(); i++) {
|
||||||
std::string s = romname(rtype, i);
|
std::string t = romname(s, i);
|
||||||
if(s.length())
|
if(t.length())
|
||||||
array[r++] = s;
|
array[r++] = t;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum rom_type romtype_from_string(const std::string& str)
|
struct systype_info_structure* romtype_from_string(const std::string& str)
|
||||||
{
|
{
|
||||||
if(str == TNAME_SNES)
|
for(size_t i = 0; i < emucore_systype_slots(); i++) {
|
||||||
return ROMTYPE_SNES;
|
auto j = emucore_systype_slot(i);
|
||||||
if(str == TNAME_BSX_NS)
|
if(j->get_hname() == str)
|
||||||
return ROMTYPE_BSX;
|
return j;
|
||||||
if(str == TNAME_BSX_S)
|
}
|
||||||
return ROMTYPE_BSXSLOTTED;
|
return NULL;
|
||||||
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(struct systype_info_structure* s)
|
||||||
{
|
{
|
||||||
enum rom_type rtype = romtype_from_string(str);
|
return (s->region_slots() <= 1);
|
||||||
return (rtype != ROMTYPE_SNES && rtype != ROMTYPE_SGB);
|
}
|
||||||
|
|
||||||
|
std::string game_id(struct loaded_rom& r)
|
||||||
|
{
|
||||||
|
for(size_t i = 1; i < r.main_slots.size(); i++)
|
||||||
|
if(r.main_slots[i].valid)
|
||||||
|
return r.main_slots[i].sha256;
|
||||||
|
return r.main_slots[0].sha256;
|
||||||
}
|
}
|
||||||
|
|
||||||
class textboxloadfilename : public wxFileDropTarget
|
class textboxloadfilename : public wxFileDropTarget
|
||||||
|
@ -458,10 +415,10 @@ 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];
|
wxString rtchoices[128];
|
||||||
wxString rrchoices[32];
|
wxString rrchoices[128];
|
||||||
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(NULL, rrchoices);
|
||||||
|
|
||||||
Centre();
|
Centre();
|
||||||
|
|
||||||
|
@ -529,17 +486,32 @@ 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)) {
|
auto _rtype = romtype_from_string(rtype);
|
||||||
|
if(has_forced_region(_rtype)) {
|
||||||
region_combo->Disable();
|
region_combo->Disable();
|
||||||
remembered_region = tostdstring(region_combo->GetValue());
|
remembered_region = tostdstring(region_combo->GetValue());
|
||||||
|
region_combo->Clear();
|
||||||
|
region_combo->Append(towxstring(_rtype->region_slot(0)->get_hname()));
|
||||||
|
region_combo->SetSelection(0);
|
||||||
} else {
|
} else {
|
||||||
if(remembered_region != "")
|
if(remembered_region == "")
|
||||||
|
remembered_region = tostdstring(region_combo->GetValue());
|
||||||
|
region_combo->Clear();
|
||||||
|
bool old_ok = false;
|
||||||
|
for(size_t i = 0; i < _rtype->region_slots(); i++) {
|
||||||
|
std::string x = _rtype->region_slot(i)->get_hname();
|
||||||
|
region_combo->Append(towxstring(x));
|
||||||
|
if(x == remembered_region)
|
||||||
|
old_ok = true;
|
||||||
|
}
|
||||||
|
region_combo->SetSelection(0);
|
||||||
|
if(old_ok)
|
||||||
region_combo->SetValue(towxstring(remembered_region));
|
region_combo->SetValue(towxstring(remembered_region));
|
||||||
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(_rtype, tmp);
|
||||||
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++)
|
for(unsigned i = 0; i < ROMSELECT_ROM_COUNT; i++)
|
||||||
slots[i]->hide(romgrid);
|
slots[i]->hide(romgrid);
|
||||||
for(unsigned i = 0; i < c; i++) {
|
for(unsigned i = 0; i < c; i++) {
|
||||||
|
@ -554,7 +526,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()));
|
auto 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);
|
||||||
|
@ -589,21 +561,16 @@ 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 = region_from_string(rfiles.rtype, tostdstring(region_combo->GetValue()));
|
||||||
rfiles.rom = slots[0]->get_filename();
|
rfiles.main_slots.resize(rfiles.rtype->rom_slots());
|
||||||
rfiles.rom_xml = slots[0]->get_markup();
|
rfiles.markup_slots.resize(rfiles.rtype->rom_slots());
|
||||||
rfiles.slota = slots[1]->get_filename();
|
for(size_t i = 0; i < rfiles.rtype->rom_slots() && i < ROMSELECT_ROM_COUNT; i++) {
|
||||||
rfiles.slota_xml = slots[1]->get_markup();
|
rfiles.main_slots[i] = slots[i]->get_filename();
|
||||||
rfiles.slotb = slots[2]->get_filename();
|
rfiles.markup_slots[i] = slots[i]->get_markup();
|
||||||
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 = game_id(*our_rom);
|
||||||
our_rom_name = our_rom->slota.sha256;
|
|
||||||
else if(our_rom->slotb.valid)
|
|
||||||
our_rom_name = our_rom->slotb.sha256;
|
|
||||||
else
|
|
||||||
our_rom_name = our_rom->rom.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;
|
||||||
|
@ -767,22 +734,16 @@ void patching_done(struct loaded_rom& rom, wxWindow* modwin)
|
||||||
struct loaded_rom* our_rom = &rom;
|
struct loaded_rom* our_rom = &rom;
|
||||||
try {
|
try {
|
||||||
emucore_basic_init();
|
emucore_basic_init();
|
||||||
if(our_rom->slota.valid)
|
our_rom_name = game_id(*our_rom);
|
||||||
our_rom_name = our_rom->slota.sha256;
|
|
||||||
else if(our_rom->slotb.valid)
|
|
||||||
our_rom_name = our_rom->slotb.sha256;
|
|
||||||
else
|
|
||||||
our_rom_name = our_rom->rom.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->get_sysregion(our_rom->region->get_iname())->get_iname()
|
||||||
if(our_rom->region == REGION_PAL)
|
<< std::endl;
|
||||||
set_nominal_framerate(322445.0/6448.0);
|
auto vrate = emucore_get_video_rate();
|
||||||
else if(our_rom->region == REGION_NTSC)
|
set_nominal_framerate(1.0 * vrate.first / vrate.second);
|
||||||
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 +989,6 @@ 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.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 = emucore_get_version();
|
f.coreversion = emucore_get_version();
|
||||||
|
@ -1036,12 +996,7 @@ 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;
|
copy_romdata_to_movie(f, *our_rom);
|
||||||
f.romxml_sha256 = our_rom->rom_xml.sha256;
|
|
||||||
f.slota_sha256 = our_rom->slota.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,9 @@ 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->get_sysregion(r.region->get_iname())->get_iname() << std::endl;
|
||||||
if(r.region == REGION_PAL)
|
auto vrate = emucore_get_video_rate();
|
||||||
set_nominal_framerate(322445.0/6448.0);
|
set_nominal_framerate(1.0 * vrate.first / vrate.second);
|
||||||
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 +288,9 @@ 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 = emucore_region_for_sysregion(movie.gametype);
|
||||||
|
if(!our_rom->region)
|
||||||
|
throw std::runtime_error("Core does not support game type '" + movie.gametype + "'");
|
||||||
our_rom->load();
|
our_rom->load();
|
||||||
dumper_startup(dumper, mode, prefix, length);
|
dumper_startup(dumper, mode, prefix, length);
|
||||||
startup_lua_scripts(cmdline);
|
startup_lua_scripts(cmdline);
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
#include "core/moviefile.hpp"
|
#include "core/moviefile.hpp"
|
||||||
#include "core/rrdata.hpp"
|
#include "core/rrdata.hpp"
|
||||||
|
#include "library/string.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
std::string name_romtype(rom_type r)
|
std::string name_romtype(systype_info_structure* r)
|
||||||
{
|
{
|
||||||
if(r == ROMTYPE_SNES) return "SNES";
|
if(r)
|
||||||
if(r == ROMTYPE_BSX) return "BS-X (non-slotted)";
|
return r->get_hname();
|
||||||
if(r == ROMTYPE_BSXSLOTTED) return "BS-X (slotted)";
|
else
|
||||||
if(r == ROMTYPE_SUFAMITURBO) return "Sufami turbo";
|
return "Unknown";
|
||||||
if(r == ROMTYPE_SGB) return "SGB";
|
|
||||||
return "Unknown";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name_region(rom_region r)
|
std::string name_region(region_info_structure* r)
|
||||||
{
|
{
|
||||||
if(r == REGION_PAL) return "PAL";
|
if(r)
|
||||||
if(r == REGION_NTSC) return "NTSC";
|
return r->get_hname();
|
||||||
return "Unknown";
|
else
|
||||||
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name_porttype(porttype_t r)
|
std::string name_porttype(porttype_t r)
|
||||||
|
@ -60,8 +60,9 @@ 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);
|
|
||||||
rom_region reg = gtype::toromregion(m.gametype);
|
auto rtype = emucore_systype_for_sysregion(m.gametype);
|
||||||
|
auto reg = emucore_region_for_sysregion(m.gametype);
|
||||||
std::cout << "Console: " << name_romtype(rtype) << std::endl;
|
std::cout << "Console: " << name_romtype(rtype) << std::endl;
|
||||||
std::cout << "Region: " << name_region(reg) << std::endl;
|
std::cout << "Region: " << name_region(reg) << std::endl;
|
||||||
std::cout << "Port #1: " << name_porttype(m.port1) << std::endl;
|
std::cout << "Port #1: " << name_porttype(m.port1) << std::endl;
|
||||||
|
@ -72,32 +73,21 @@ 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 < m.main_checksums.size(); i++) {
|
||||||
std::cout << "ROM checksum: " << escape_string(m.rom_sha256) << std::endl;
|
std::string name = (stringfmt() << "Unknown ROM #" << i).str();
|
||||||
if(m.romxml_sha256 != "")
|
if(rtype && rtype->rom_slot(i))
|
||||||
std::cout << "ROM XML checksum: " << escape_string(m.romxml_sha256) << std::endl;
|
name = rtype->rom_slot(i)->get_hname();
|
||||||
else
|
if(m.main_checksums[i] != "")
|
||||||
std::cout << "Using default settings for ROM" << std::endl;
|
std::cout << name << " checksum: "<< escape_string(m.main_checksums[i]) << std::endl;
|
||||||
} else
|
}
|
||||||
std::cout << "No main ROM present" << std::endl;
|
for(size_t i = 0; i < m.markup_checksums.size(); i++) {
|
||||||
if(m.slota_sha256 != "") {
|
std::string name = (stringfmt() << "Unknown ROM #" << i).str();
|
||||||
std::cout << "BS/ST-A/DMG checksum: " << escape_string(m.slota_sha256) << std::endl;
|
if(rtype && rtype->rom_slot(i))
|
||||||
if(m.slotaxml_sha256 != "")
|
name = rtype->rom_slot(i)->get_hname();
|
||||||
std::cout << "BS/ST-A/DMG XML checksum: " << escape_string(m.slotaxml_sha256)
|
if(m.markup_checksums[i] != "")
|
||||||
|
std::cout << name << " markup checksum: "<< escape_string(m.markup_checksums[i])
|
||||||
<< std::endl;
|
<< 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)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "lsnes.hpp"
|
#include "lsnes.hpp"
|
||||||
//#include <snes/snes.hpp>
|
|
||||||
#include "core/advdumper.hpp"
|
#include "core/advdumper.hpp"
|
||||||
#include "core/dispatch.hpp"
|
#include "core/dispatch.hpp"
|
||||||
#include "interface/core.hpp"
|
#include "interface/core.hpp"
|
||||||
|
|
Loading…
Add table
Reference in a new issue