mirror of
https://github.com/libretro/beetle-wswan-libretro.git
synced 2024-11-23 07:59:40 +00:00
Implement persistent buffer API support
This commit is contained in:
parent
40077aee14
commit
6fd2acba28
@ -282,6 +282,7 @@ enum retro_language
|
||||
RETRO_LANGUAGE_PERSIAN = 20,
|
||||
RETRO_LANGUAGE_HEBREW = 21,
|
||||
RETRO_LANGUAGE_ASTURIAN = 22,
|
||||
RETRO_LANGUAGE_FINNISH = 23,
|
||||
RETRO_LANGUAGE_LAST,
|
||||
|
||||
/* Ensure sizeof(enum) == sizeof(int) */
|
||||
@ -712,6 +713,9 @@ enum retro_mod
|
||||
* state of rumble motors in controllers.
|
||||
* A strong and weak motor is supported, and they can be
|
||||
* controlled indepedently.
|
||||
* Should be called from either retro_init() or retro_load_game().
|
||||
* Should not be called from retro_set_environment().
|
||||
* Returns false if rumble functionality is unavailable.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24
|
||||
/* uint64_t * --
|
||||
@ -1374,6 +1378,121 @@ enum retro_mod
|
||||
* call will target the newly initialized driver.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64
|
||||
/* const struct retro_fastforwarding_override * --
|
||||
* Used by a libretro core to override the current
|
||||
* fastforwarding mode of the frontend.
|
||||
* If NULL is passed to this function, the frontend
|
||||
* will return true if fastforwarding override
|
||||
* functionality is supported (no change in
|
||||
* fastforwarding state will occur in this case).
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE 65
|
||||
/* const struct retro_system_content_info_override * --
|
||||
* Allows an implementation to override 'global' content
|
||||
* info parameters reported by retro_get_system_info().
|
||||
* Overrides also affect subsystem content info parameters
|
||||
* set via RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO.
|
||||
* This function must be called inside retro_set_environment().
|
||||
* If callback returns false, content info overrides
|
||||
* are unsupported by the frontend, and will be ignored.
|
||||
* If callback returns true, extended game info may be
|
||||
* retrieved by calling RETRO_ENVIRONMENT_GET_GAME_INFO_EXT
|
||||
* in retro_load_game() or retro_load_game_special().
|
||||
*
|
||||
* 'data' points to an array of retro_system_content_info_override
|
||||
* structs terminated by a { NULL, false, false } element.
|
||||
* If 'data' is NULL, no changes will be made to the frontend;
|
||||
* a core may therefore pass NULL in order to test whether
|
||||
* the RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE and
|
||||
* RETRO_ENVIRONMENT_GET_GAME_INFO_EXT callbacks are supported
|
||||
* by the frontend.
|
||||
*
|
||||
* For struct member descriptions, see the definition of
|
||||
* struct retro_system_content_info_override.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* - struct retro_system_info:
|
||||
* {
|
||||
* "My Core", // library_name
|
||||
* "v1.0", // library_version
|
||||
* "m3u|md|cue|iso|chd|sms|gg|sg", // valid_extensions
|
||||
* true, // need_fullpath
|
||||
* false // block_extract
|
||||
* }
|
||||
*
|
||||
* - Array of struct retro_system_content_info_override:
|
||||
* {
|
||||
* {
|
||||
* "md|sms|gg", // extensions
|
||||
* false, // need_fullpath
|
||||
* true // persistent_data
|
||||
* },
|
||||
* {
|
||||
* "sg", // extensions
|
||||
* false, // need_fullpath
|
||||
* false // persistent_data
|
||||
* },
|
||||
* { NULL, false, false }
|
||||
* }
|
||||
*
|
||||
* Result:
|
||||
* - Files of type m3u, cue, iso, chd will not be
|
||||
* loaded by the frontend. Frontend will pass a
|
||||
* valid path to the core, and core will handle
|
||||
* loading internally
|
||||
* - Files of type md, sms, gg will be loaded by
|
||||
* the frontend. A valid memory buffer will be
|
||||
* passed to the core. This memory buffer will
|
||||
* remain valid until retro_deinit() returns
|
||||
* - Files of type sg will be loaded by the frontend.
|
||||
* A valid memory buffer will be passed to the core.
|
||||
* This memory buffer will remain valid until
|
||||
* retro_load_game() (or retro_load_game_special())
|
||||
* returns
|
||||
*
|
||||
* NOTE: If an extension is listed multiple times in
|
||||
* an array of retro_system_content_info_override
|
||||
* structs, only the first instance will be registered
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_GAME_INFO_EXT 66
|
||||
/* const struct retro_game_info_ext ** --
|
||||
* Allows an implementation to fetch extended game
|
||||
* information, providing additional content path
|
||||
* and memory buffer status details.
|
||||
* This function may only be called inside
|
||||
* retro_load_game() or retro_load_game_special().
|
||||
* If callback returns false, extended game information
|
||||
* is unsupported by the frontend. In this case, only
|
||||
* regular retro_game_info will be available.
|
||||
* RETRO_ENVIRONMENT_GET_GAME_INFO_EXT is guaranteed
|
||||
* to return true if RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE
|
||||
* returns true.
|
||||
*
|
||||
* 'data' points to an array of retro_game_info_ext structs.
|
||||
*
|
||||
* For struct member descriptions, see the definition of
|
||||
* struct retro_game_info_ext.
|
||||
*
|
||||
* - If function is called inside retro_load_game(),
|
||||
* the retro_game_info_ext array is guaranteed to
|
||||
* have a size of 1 - i.e. the returned pointer may
|
||||
* be used to access directly the members of the
|
||||
* first retro_game_info_ext struct, for example:
|
||||
*
|
||||
* struct retro_game_info_ext *game_info_ext;
|
||||
* if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &game_info_ext))
|
||||
* printf("Content Directory: %s\n", game_info_ext->dir);
|
||||
*
|
||||
* - If the function is called inside retro_load_game_special(),
|
||||
* the retro_game_info_ext array is guaranteed to have a
|
||||
* size equal to the num_info argument passed to
|
||||
* retro_load_game_special()
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
@ -2777,6 +2896,213 @@ struct retro_system_info
|
||||
bool block_extract;
|
||||
};
|
||||
|
||||
/* Defines overrides which modify frontend handling of
|
||||
* specific content file types.
|
||||
* An array of retro_system_content_info_override is
|
||||
* passed to RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE
|
||||
* NOTE: In the following descriptions, references to
|
||||
* retro_load_game() may be replaced with
|
||||
* retro_load_game_special() */
|
||||
struct retro_system_content_info_override
|
||||
{
|
||||
/* A list of file extensions for which the override
|
||||
* should apply, delimited by a 'pipe' character
|
||||
* (e.g. "md|sms|gg")
|
||||
* Permitted file extensions are limited to those
|
||||
* included in retro_system_info::valid_extensions
|
||||
* and/or retro_subsystem_rom_info::valid_extensions */
|
||||
const char *extensions;
|
||||
|
||||
/* Overrides the need_fullpath value set in
|
||||
* retro_system_info and/or retro_subsystem_rom_info.
|
||||
* To reiterate:
|
||||
*
|
||||
* If need_fullpath is true and retro_load_game() is called:
|
||||
* - retro_game_info::path is guaranteed to contain a valid
|
||||
* path to an existent file
|
||||
* - retro_game_info::data and retro_game_info::size are invalid
|
||||
*
|
||||
* If need_fullpath is false and retro_load_game() is called:
|
||||
* - retro_game_info::path may be NULL
|
||||
* - retro_game_info::data and retro_game_info::size are guaranteed
|
||||
* to be valid
|
||||
*
|
||||
* In addition:
|
||||
*
|
||||
* If need_fullpath is true and retro_load_game() is called:
|
||||
* - retro_game_info_ext::full_path is guaranteed to contain a valid
|
||||
* path to an existent file
|
||||
* - retro_game_info_ext::archive_path may be NULL
|
||||
* - retro_game_info_ext::archive_file may be NULL
|
||||
* - retro_game_info_ext::dir is guaranteed to contain a valid path
|
||||
* to the directory in which the content file exists
|
||||
* - retro_game_info_ext::name is guaranteed to contain the
|
||||
* basename of the content file, without extension
|
||||
* - retro_game_info_ext::ext is guaranteed to contain the
|
||||
* extension of the content file in lower case format
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size
|
||||
* are invalid
|
||||
*
|
||||
* If need_fullpath is false and retro_load_game() is called:
|
||||
* - If retro_game_info_ext::file_in_archive is false:
|
||||
* - retro_game_info_ext::full_path is guaranteed to contain
|
||||
* a valid path to an existent file
|
||||
* - retro_game_info_ext::archive_path may be NULL
|
||||
* - retro_game_info_ext::archive_file may be NULL
|
||||
* - retro_game_info_ext::dir is guaranteed to contain a
|
||||
* valid path to the directory in which the content file exists
|
||||
* - retro_game_info_ext::name is guaranteed to contain the
|
||||
* basename of the content file, without extension
|
||||
* - retro_game_info_ext::ext is guaranteed to contain the
|
||||
* extension of the content file in lower case format
|
||||
* - If retro_game_info_ext::file_in_archive is true:
|
||||
* - retro_game_info_ext::full_path may be NULL
|
||||
* - retro_game_info_ext::archive_path is guaranteed to
|
||||
* contain a valid path to an existent compressed file
|
||||
* inside which the content file is located
|
||||
* - retro_game_info_ext::archive_file is guaranteed to
|
||||
* contain a valid path to an existent content file
|
||||
* inside the compressed file referred to by
|
||||
* retro_game_info_ext::archive_path
|
||||
* e.g. for a compressed file '/path/to/foo.zip'
|
||||
* containing 'bar.sfc'
|
||||
* > retro_game_info_ext::archive_path will be '/path/to/foo.zip'
|
||||
* > retro_game_info_ext::archive_file will be 'bar.sfc'
|
||||
* - retro_game_info_ext::dir is guaranteed to contain a
|
||||
* valid path to the directory in which the compressed file
|
||||
* (containing the content file) exists
|
||||
* - retro_game_info_ext::name is guaranteed to contain
|
||||
* EITHER
|
||||
* 1) the basename of the compressed file (containing
|
||||
* the content file), without extension
|
||||
* OR
|
||||
* 2) the basename of the content file inside the
|
||||
* compressed file, without extension
|
||||
* In either case, a core should consider 'name' to
|
||||
* be the canonical name/ID of the the content file
|
||||
* - retro_game_info_ext::ext is guaranteed to contain the
|
||||
* extension of the content file inside the compressed file,
|
||||
* in lower case format
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size are
|
||||
* guaranteed to be valid */
|
||||
bool need_fullpath;
|
||||
|
||||
/* If need_fullpath is false, specifies whether the content
|
||||
* data buffer available in retro_load_game() is 'persistent'
|
||||
*
|
||||
* If persistent_data is false and retro_load_game() is called:
|
||||
* - retro_game_info::data and retro_game_info::size
|
||||
* are valid only until retro_load_game() returns
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size
|
||||
* are valid only until retro_load_game() returns
|
||||
*
|
||||
* If persistent_data is true and retro_load_game() is called:
|
||||
* - retro_game_info::data and retro_game_info::size
|
||||
* are valid until retro_deinit() returns
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size
|
||||
* are valid until retro_deinit() returns */
|
||||
bool persistent_data;
|
||||
};
|
||||
|
||||
/* Similar to retro_game_info, but provides extended
|
||||
* information about the source content file and
|
||||
* game memory buffer status.
|
||||
* And array of retro_game_info_ext is returned by
|
||||
* RETRO_ENVIRONMENT_GET_GAME_INFO_EXT
|
||||
* NOTE: In the following descriptions, references to
|
||||
* retro_load_game() may be replaced with
|
||||
* retro_load_game_special() */
|
||||
struct retro_game_info_ext
|
||||
{
|
||||
/* - If file_in_archive is false, contains a valid
|
||||
* path to an existent content file (UTF-8 encoded)
|
||||
* - If file_in_archive is true, may be NULL */
|
||||
const char *full_path;
|
||||
|
||||
/* - If file_in_archive is false, may be NULL
|
||||
* - If file_in_archive is true, contains a valid path
|
||||
* to an existent compressed file inside which the
|
||||
* content file is located (UTF-8 encoded) */
|
||||
const char *archive_path;
|
||||
|
||||
/* - If file_in_archive is false, may be NULL
|
||||
* - If file_in_archive is true, contain a valid path
|
||||
* to an existent content file inside the compressed
|
||||
* file referred to by archive_path (UTF-8 encoded)
|
||||
* e.g. for a compressed file '/path/to/foo.zip'
|
||||
* containing 'bar.sfc'
|
||||
* > archive_path will be '/path/to/foo.zip'
|
||||
* > archive_file will be 'bar.sfc' */
|
||||
const char *archive_file;
|
||||
|
||||
/* - If file_in_archive is false, contains a valid path
|
||||
* to the directory in which the content file exists
|
||||
* (UTF-8 encoded)
|
||||
* - If file_in_archive is true, contains a valid path
|
||||
* to the directory in which the compressed file
|
||||
* (containing the content file) exists (UTF-8 encoded) */
|
||||
const char *dir;
|
||||
|
||||
/* Contains the canonical name/ID of the content file
|
||||
* (UTF-8 encoded). Intended for use when identifying
|
||||
* 'complementary' content named after the loaded file -
|
||||
* i.e. companion data of a different format (a CD image
|
||||
* required by a ROM), texture packs, internally handled
|
||||
* save files, etc.
|
||||
* - If file_in_archive is false, contains the basename
|
||||
* of the content file, without extension
|
||||
* - If file_in_archive is true, then string is
|
||||
* implementation specific. A frontend may choose to
|
||||
* set a name value of:
|
||||
* EITHER
|
||||
* 1) the basename of the compressed file (containing
|
||||
* the content file), without extension
|
||||
* OR
|
||||
* 2) the basename of the content file inside the
|
||||
* compressed file, without extension
|
||||
* RetroArch sets the 'name' value according to (1).
|
||||
* A frontend that supports routine loading of
|
||||
* content from archives containing multiple unrelated
|
||||
* content files may set the 'name' value according
|
||||
* to (2). */
|
||||
const char *name;
|
||||
|
||||
/* - If file_in_archive is false, contains the extension
|
||||
* of the content file in lower case format
|
||||
* - If file_in_archive is true, contains the extension
|
||||
* of the content file inside the compressed file,
|
||||
* in lower case format */
|
||||
const char *ext;
|
||||
|
||||
/* String of implementation specific meta-data. */
|
||||
const char *meta;
|
||||
|
||||
/* Memory buffer of loaded game content. Will be NULL:
|
||||
* IF
|
||||
* - retro_system_info::need_fullpath is true and
|
||||
* retro_system_content_info_override::need_fullpath
|
||||
* is unset
|
||||
* OR
|
||||
* - retro_system_content_info_override::need_fullpath
|
||||
* is true */
|
||||
const void *data;
|
||||
|
||||
/* Size of game content memory buffer, in bytes */
|
||||
size_t size;
|
||||
|
||||
/* True if loaded content file is inside a compressed
|
||||
* archive */
|
||||
bool file_in_archive;
|
||||
|
||||
/* - If data is NULL, value is unset/ignored
|
||||
* - If data is non-NULL:
|
||||
* - If persistent_data is false, data and size are
|
||||
* valid only until retro_load_game() returns
|
||||
* - If persistent_data is true, data and size are
|
||||
* are valid until retro_deinit() returns */
|
||||
bool persistent_data;
|
||||
};
|
||||
|
||||
struct retro_game_geometry
|
||||
{
|
||||
unsigned base_width; /* Nominal video width of game. */
|
||||
@ -2934,6 +3260,47 @@ struct retro_framebuffer
|
||||
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
|
||||
};
|
||||
|
||||
/* Used by a libretro core to override the current
|
||||
* fastforwarding mode of the frontend */
|
||||
struct retro_fastforwarding_override
|
||||
{
|
||||
/* Specifies the runtime speed multiplier that
|
||||
* will be applied when 'fastforward' is true.
|
||||
* For example, a value of 5.0 when running 60 FPS
|
||||
* content will cap the fast-forward rate at 300 FPS.
|
||||
* Note that the target multiplier may not be achieved
|
||||
* if the host hardware has insufficient processing
|
||||
* power.
|
||||
* Setting a value of 0.0 (or greater than 0.0 but
|
||||
* less than 1.0) will result in an uncapped
|
||||
* fast-forward rate (limited only by hardware
|
||||
* capacity).
|
||||
* If the value is negative, it will be ignored
|
||||
* (i.e. the frontend will use a runtime speed
|
||||
* multiplier of its own choosing) */
|
||||
float ratio;
|
||||
|
||||
/* If true, fastforwarding mode will be enabled.
|
||||
* If false, fastforwarding mode will be disabled. */
|
||||
bool fastforward;
|
||||
|
||||
/* If true, and if supported by the frontend, an
|
||||
* on-screen notification will be displayed while
|
||||
* 'fastforward' is true.
|
||||
* If false, and if supported by the frontend, any
|
||||
* on-screen fast-forward notifications will be
|
||||
* suppressed */
|
||||
bool notification;
|
||||
|
||||
/* If true, the core will have sole control over
|
||||
* when fastforwarding mode is enabled/disabled;
|
||||
* the frontend will not be able to change the
|
||||
* state set by 'fastforward' until either
|
||||
* 'inhibit_toggle' is set to false, or the core
|
||||
* is unloaded */
|
||||
bool inhibit_toggle;
|
||||
};
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
/* Environment callback. Gives implementations a way of performing
|
||||
|
245
libretro.c
245
libretro.c
@ -52,7 +52,8 @@ static retro_environment_t environ_cb;
|
||||
static retro_input_poll_t input_poll_cb;
|
||||
static retro_input_state_t input_state_cb;
|
||||
|
||||
static bool libretro_supports_bitmasks = false;
|
||||
static bool libretro_supports_persistent_buffer = false;
|
||||
static bool libretro_supports_bitmasks = false;
|
||||
|
||||
static bool overscan;
|
||||
static double last_sound_rate;
|
||||
@ -67,13 +68,13 @@ static unsigned rotate_joymap = 0;
|
||||
static MDFN_Surface *surf = NULL;
|
||||
static uint16_t *rotate_buf = NULL;
|
||||
|
||||
#define ROTATE_PIXEL_BUF(typename_t, src, width, height, dst) \
|
||||
{ \
|
||||
typename_t *in_ptr = (typename_t*)src; \
|
||||
typename_t *out_ptr = (typename_t*)dst; \
|
||||
size_t x, y; \
|
||||
for (x = 0; x < width; x++) \
|
||||
for (y = 0; y < height; y++) \
|
||||
#define ROTATE_PIXEL_BUF(typename_t, src, width, height, dst) \
|
||||
{ \
|
||||
typename_t *in_ptr = (typename_t*)src; \
|
||||
typename_t *out_ptr = (typename_t*)dst; \
|
||||
size_t x, y; \
|
||||
for (x = 0; x < width; x++) \
|
||||
for (y = 0; y < height; y++) \
|
||||
*(out_ptr + y + (((width - 1) - x) * height)) = *(in_ptr + x + (y * width)); \
|
||||
}
|
||||
|
||||
@ -240,7 +241,7 @@ static void init_frameskip(void)
|
||||
*/
|
||||
|
||||
int wsc = 1; /*color/mono*/
|
||||
uint32 rom_size;
|
||||
uint32 rom_size;
|
||||
|
||||
uint16 WSButtonStatus;
|
||||
|
||||
@ -248,21 +249,20 @@ static uint8 WSRCurrentSong;
|
||||
|
||||
MDFNGI EmulatedWSwan =
|
||||
{
|
||||
MDFN_MASTERCLOCK_FIXED(3072000),
|
||||
0,
|
||||
224, /* lcm_width */
|
||||
144, /* lcm_height */
|
||||
MDFN_MASTERCLOCK_FIXED(3072000),
|
||||
0,
|
||||
224, /* lcm_width */
|
||||
144, /* lcm_height */
|
||||
|
||||
224, /* Nominal width */
|
||||
144, /* Nominal height */
|
||||
224, /* Nominal width */
|
||||
144, /* Nominal height */
|
||||
|
||||
224, /* Framebuffer width */
|
||||
144, /* Framebuffer height */
|
||||
224, /* Framebuffer width */
|
||||
144, /* Framebuffer height */
|
||||
|
||||
2, /* Number of output sound channels */
|
||||
2, /* Number of output sound channels */
|
||||
};
|
||||
|
||||
|
||||
static void Reset(void)
|
||||
{
|
||||
int u0;
|
||||
@ -289,8 +289,6 @@ static uint8 *chee;
|
||||
|
||||
static void Emulate(EmulateSpecStruct *espec, int16_t *sndbuf)
|
||||
{
|
||||
uint16 butt_data;
|
||||
|
||||
espec->DisplayRect.x = 0;
|
||||
espec->DisplayRect.y = 0;
|
||||
espec->DisplayRect.w = 224;
|
||||
@ -303,9 +301,7 @@ static void Emulate(EmulateSpecStruct *espec, int16_t *sndbuf)
|
||||
if(espec->SoundFormatChanged)
|
||||
WSwan_SetSoundRate(RETRO_SAMPLE_RATE);
|
||||
|
||||
butt_data = chee[0] | (chee[1] << 8);
|
||||
|
||||
WSButtonStatus = butt_data;
|
||||
WSButtonStatus = chee[0] | (chee[1] << 8);
|
||||
|
||||
MDFNMP_ApplyPeriodicCheats();
|
||||
|
||||
@ -371,11 +367,12 @@ static const DLEntry Developers[] =
|
||||
|
||||
static uint32 SRAMSize;
|
||||
|
||||
static int Load(const uint8_t *data, size_t size)
|
||||
static int Load(bool persistent_data, const uint8_t *data, size_t size)
|
||||
{
|
||||
uint32 pow_size = 0;
|
||||
uint32 real_rom_size = 0;
|
||||
uint8 header[10];
|
||||
uint32 pow_size = 0;
|
||||
uint32 real_rom_size = 0;
|
||||
bool is_detective_conan = false;
|
||||
|
||||
if(size < 65536)
|
||||
return(0);
|
||||
@ -384,37 +381,70 @@ static int Load(const uint8_t *data, size_t size)
|
||||
pow_size = next_pow2(real_rom_size);
|
||||
rom_size = pow_size + (pow_size == 0);
|
||||
|
||||
wsCartROM = (uint8 *)calloc(1, rom_size);
|
||||
memcpy(header, data + rom_size - 10, 10);
|
||||
|
||||
/* This real_rom_size vs rom_size funny business
|
||||
* is intended primarily for handling
|
||||
* WSR files. */
|
||||
if(real_rom_size < rom_size)
|
||||
memset(wsCartROM, 0xFF, rom_size - real_rom_size);
|
||||
/* Detective Conan */
|
||||
is_detective_conan = ((header[8] | (header[9] << 8)) == 0x8de1 && (header[0]==0x01)&&(header[2]==0x27));
|
||||
|
||||
memcpy(wsCartROM + (rom_size - real_rom_size), data, size);
|
||||
/* Detective Conan needs to manipulate wsCartROM,
|
||||
* have to forcibly disable persistent buffer
|
||||
* support unfortunately because of this */
|
||||
if (is_detective_conan)
|
||||
{
|
||||
libretro_supports_persistent_buffer = false;
|
||||
persistent_data = false;
|
||||
}
|
||||
|
||||
memcpy(header, wsCartROM + rom_size - 10, 10);
|
||||
if (persistent_data)
|
||||
wsCartROM = (uint8 *)data;
|
||||
else
|
||||
{
|
||||
wsCartROM = (uint8 *)calloc(1, rom_size);
|
||||
|
||||
SRAMSize = 0;
|
||||
/* This real_rom_size vs rom_size funny business
|
||||
* is intended primarily for handling
|
||||
* WSR files. */
|
||||
if (real_rom_size < rom_size)
|
||||
memset(wsCartROM, 0xFF, rom_size - real_rom_size);
|
||||
|
||||
memcpy(wsCartROM + (rom_size - real_rom_size), data, size);
|
||||
}
|
||||
|
||||
SRAMSize = 0;
|
||||
eeprom_size = 0;
|
||||
|
||||
switch(header[5])
|
||||
{
|
||||
case 0x01: SRAMSize = 8 * 1024; break;
|
||||
case 0x02: SRAMSize = 32 * 1024; break;
|
||||
case 0x03: SRAMSize = 128 * 1024; break;
|
||||
case 0x04: SRAMSize = 256 * 1024; break; /* Dicing Knight!, Judgement Silver */
|
||||
case 0x05: SRAMSize = 512 * 1024; break; /* Wonder Gate */
|
||||
|
||||
case 0x10: eeprom_size = 128; break;
|
||||
case 0x20: eeprom_size = 2 *1024; break;
|
||||
case 0x50: eeprom_size = 1024; break;
|
||||
case 0x01:
|
||||
SRAMSize = 8 * 1024;
|
||||
break;
|
||||
case 0x02:
|
||||
SRAMSize = 32 * 1024;
|
||||
break;
|
||||
case 0x03:
|
||||
SRAMSize = 128 * 1024;
|
||||
break;
|
||||
case 0x04:
|
||||
SRAMSize = 256 * 1024;
|
||||
break; /* Dicing Knight!, Judgement Silver */
|
||||
case 0x05:
|
||||
SRAMSize = 512 * 1024;
|
||||
break; /* Wonder Gate */
|
||||
case 0x10:
|
||||
eeprom_size = 128;
|
||||
break;
|
||||
case 0x20:
|
||||
eeprom_size = 2 *1024;
|
||||
break;
|
||||
case 0x50:
|
||||
eeprom_size = 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
if((header[8] | (header[9] << 8)) == 0x8de1 && (header[0]==0x01)&&(header[2]==0x27)) /* Detective Conan */
|
||||
if (is_detective_conan)
|
||||
{
|
||||
/* WS cpu is using cache/pipeline or there's protected ROM bank where pointing CS */
|
||||
/* WS cpu is using cache/pipeline or
|
||||
* there's protected ROM bank where pointing CS */
|
||||
wsCartROM[0xfffe8]=0xea;
|
||||
wsCartROM[0xfffe9]=0x00;
|
||||
wsCartROM[0xfffea]=0x00;
|
||||
@ -441,22 +471,10 @@ static int Load(const uint8_t *data, size_t size)
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void CloseGame(void)
|
||||
{
|
||||
WSwan_MemoryKill();
|
||||
|
||||
WSwan_SoundKill();
|
||||
|
||||
if(wsCartROM)
|
||||
{
|
||||
free(wsCartROM);
|
||||
wsCartROM = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetInput(int port, const char *type, void *ptr)
|
||||
{
|
||||
if(!port) chee = (uint8 *)ptr;
|
||||
if (!port)
|
||||
chee = (uint8 *)ptr;
|
||||
}
|
||||
|
||||
int StateAction(StateMem *sm, int load, int data_only)
|
||||
@ -539,28 +557,6 @@ static InputInfoStruct InputInfo =
|
||||
|
||||
static bool update_video, update_audio;
|
||||
|
||||
static bool MDFNI_LoadGame(
|
||||
const char *force_module, const uint8_t *data,
|
||||
size_t size)
|
||||
{
|
||||
if(Load(data, size) <= 0)
|
||||
return false;
|
||||
|
||||
MDFN_LoadGameCheats(NULL);
|
||||
MDFNMP_InstallReadPatches();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void MDFNI_CloseGame(void)
|
||||
{
|
||||
MDFN_FlushGameCheats(0);
|
||||
|
||||
CloseGame();
|
||||
|
||||
MDFNMP_Kill();
|
||||
}
|
||||
|
||||
static void check_system_specs(void)
|
||||
{
|
||||
/* TODO - should theoretically be level 4, but apparently
|
||||
@ -776,30 +772,23 @@ void retro_reset(void)
|
||||
DoSimpleCommand(MDFN_MSC_RESET);
|
||||
}
|
||||
|
||||
bool retro_load_game_special(unsigned a, const struct retro_game_info *b, size_t c)
|
||||
bool retro_load_game_special(unsigned a,
|
||||
const struct retro_game_info *b, size_t c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void set_volume (uint32_t *ptr, unsigned number)
|
||||
{
|
||||
switch(number)
|
||||
{
|
||||
default:
|
||||
*ptr = number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_PLAYERS 1
|
||||
#define MAX_BUTTONS 11
|
||||
static uint16_t input_buf;
|
||||
|
||||
bool retro_load_game(const struct retro_game_info *info)
|
||||
{
|
||||
const uint8_t *rom_data = NULL;
|
||||
size_t rom_size = 0;
|
||||
const unsigned rot_angle = 0;
|
||||
|
||||
struct retro_input_descriptor desc[] = {
|
||||
const struct retro_game_info_ext *info_ext = NULL;
|
||||
struct retro_input_descriptor desc[] = {
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "X Cursor Left" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "X Cursor Up" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "X Cursor Down" },
|
||||
@ -824,10 +813,25 @@ bool retro_load_game(const struct retro_game_info *info)
|
||||
overscan = false;
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_OVERSCAN, &overscan);
|
||||
|
||||
if (!MDFNI_LoadGame(MEDNAFEN_CORE_NAME_MODULE,
|
||||
(const uint8_t*)info->data, info->size))
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &info_ext) &&
|
||||
info_ext->persistent_data)
|
||||
{
|
||||
libretro_supports_persistent_buffer = true;
|
||||
rom_data = (const uint8_t*)info_ext->data;
|
||||
rom_size = info_ext->size;
|
||||
}
|
||||
else
|
||||
{
|
||||
libretro_supports_persistent_buffer = false;
|
||||
rom_data = (const uint8_t*)info->data;
|
||||
rom_size = info->size;
|
||||
}
|
||||
|
||||
if (Load(libretro_supports_persistent_buffer, rom_data, rom_size) <= 0)
|
||||
return false;
|
||||
|
||||
MDFN_LoadGameCheats(NULL);
|
||||
MDFNMP_InstallReadPatches();
|
||||
SetInput(0, "gamepad", &input_buf);
|
||||
|
||||
surf = (MDFN_Surface*)calloc(1, sizeof(*surf));
|
||||
@ -865,24 +869,34 @@ bool retro_load_game(const struct retro_game_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
rotate_tall = false;
|
||||
rotate_tall = false;
|
||||
select_pressed_last_frame = false;
|
||||
rotate_joymap = 0;
|
||||
rotate_joymap = 0;
|
||||
|
||||
check_variables(false);
|
||||
|
||||
WSwan_SetPixelFormat(RETRO_PIX_DEPTH,
|
||||
mono_pal_start, mono_pal_end);
|
||||
|
||||
update_video = false;
|
||||
update_audio = true;
|
||||
update_video = false;
|
||||
update_audio = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void retro_unload_game(void)
|
||||
{
|
||||
MDFNI_CloseGame();
|
||||
MDFN_FlushGameCheats(0);
|
||||
WSwan_MemoryKill();
|
||||
WSwan_SoundKill();
|
||||
|
||||
if(wsCartROM)
|
||||
{
|
||||
if (!libretro_supports_persistent_buffer)
|
||||
free(wsCartROM);
|
||||
wsCartROM = NULL;
|
||||
}
|
||||
MDFNMP_Kill();
|
||||
|
||||
if (surf)
|
||||
{
|
||||
@ -895,6 +909,8 @@ void retro_unload_game(void)
|
||||
if (rotate_buf)
|
||||
free(rotate_buf);
|
||||
rotate_buf = NULL;
|
||||
|
||||
libretro_supports_persistent_buffer = false;
|
||||
}
|
||||
|
||||
static void update_input(void)
|
||||
@ -969,7 +985,9 @@ static void update_input(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static uint64_t video_frames, audio_frames;
|
||||
#endif
|
||||
|
||||
void retro_run(void)
|
||||
{
|
||||
@ -1097,8 +1115,10 @@ void retro_run(void)
|
||||
video_cb(NULL, height, width, FB_HEIGHT * RETRO_PIX_BYTES);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
video_frames++;
|
||||
audio_frames += spec.SoundBufSize;
|
||||
#endif
|
||||
|
||||
for (total = 0; total < spec.SoundBufSize; )
|
||||
total += audio_batch_cb(sound_buf + total*2,
|
||||
@ -1164,6 +1184,7 @@ void retro_deinit(void)
|
||||
free(rotate_buf);
|
||||
rotate_buf = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (log_cb)
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO, "[%s]: Samples / Frame: %.5f\n",
|
||||
@ -1171,6 +1192,7 @@ void retro_deinit(void)
|
||||
log_cb(RETRO_LOG_INFO, "[%s]: Estimated FPS: %.5f\n",
|
||||
MEDNAFEN_CORE_NAME, (double)video_frames * 44100 / audio_frames);
|
||||
}
|
||||
#endif
|
||||
|
||||
libretro_supports_bitmasks = false;
|
||||
}
|
||||
@ -1189,14 +1211,23 @@ void retro_set_controller_port_device(unsigned in_port, unsigned device) { }
|
||||
|
||||
void retro_set_environment(retro_environment_t cb)
|
||||
{
|
||||
static const struct retro_system_content_info_override content_overrides[] = {
|
||||
{
|
||||
MEDNAFEN_CORE_EXTENSIONS, /* extensions */
|
||||
false, /* need_fullpath */
|
||||
true /* persistent_data */
|
||||
},
|
||||
{ NULL, false, false }
|
||||
};
|
||||
environ_cb = cb;
|
||||
|
||||
libretro_set_core_options(environ_cb);
|
||||
/* Request a persistent content data buffer */
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE,
|
||||
(void*)content_overrides);
|
||||
}
|
||||
|
||||
void retro_set_audio_sample(retro_audio_sample_t cb)
|
||||
{
|
||||
}
|
||||
void retro_set_audio_sample(retro_audio_sample_t cb) { }
|
||||
|
||||
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
|
||||
{
|
||||
@ -1252,7 +1283,7 @@ bool retro_serialize(void *data, size_t size)
|
||||
st.malloced = size;
|
||||
st.initial_malloc = 0;
|
||||
|
||||
ret = MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL);
|
||||
ret = MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL);
|
||||
|
||||
memcpy(data, st.data, size);
|
||||
free(st.data);
|
||||
|
Loading…
Reference in New Issue
Block a user