mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2024-11-23 07:49:48 +00:00
Add dedicated RetroPad fast-forward button
This commit is contained in:
parent
d7adc32658
commit
1faa9f2bcb
@ -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 * --
|
||||
@ -1321,6 +1325,69 @@ enum retro_mod
|
||||
* fallback, stderr).
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61
|
||||
/* unsigned * --
|
||||
* Unsigned value is the number of active input devices
|
||||
* provided by the frontend. This may change between
|
||||
* frames, but will remain constant for the duration
|
||||
* of each frame.
|
||||
* If callback returns true, a core need not poll any
|
||||
* input device with an index greater than or equal to
|
||||
* the number of active devices.
|
||||
* If callback returns false, the number of active input
|
||||
* devices is unknown. In this case, all input devices
|
||||
* should be considered active.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62
|
||||
/* const struct retro_audio_buffer_status_callback * --
|
||||
* Lets the core know the occupancy level of the frontend
|
||||
* audio buffer. Can be used by a core to attempt frame
|
||||
* skipping in order to avoid buffer under-runs.
|
||||
* A core may pass NULL to disable buffer status reporting
|
||||
* in the frontend.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63
|
||||
/* const unsigned * --
|
||||
* Sets minimum frontend audio latency in milliseconds.
|
||||
* Resultant audio latency may be larger than set value,
|
||||
* or smaller if a hardware limit is encountered. A frontend
|
||||
* is expected to honour requests up to 512 ms.
|
||||
*
|
||||
* - If value is less than current frontend
|
||||
* audio latency, callback has no effect
|
||||
* - If value is zero, default frontend audio
|
||||
* latency is set
|
||||
*
|
||||
* May be used by a core to increase audio latency and
|
||||
* therefore decrease the probability of buffer under-runs
|
||||
* (crackling) when performing 'intensive' operations.
|
||||
* A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK
|
||||
* to implement audio-buffer-based frame skipping may achieve
|
||||
* optimal results by setting the audio latency to a 'high'
|
||||
* (typically 6x or 8x) integer multiple of the expected
|
||||
* frame time.
|
||||
*
|
||||
* WARNING: This can only be called from within retro_run().
|
||||
* Calling this can require a full reinitialization of audio
|
||||
* drivers in the frontend, so it is important to call it very
|
||||
* sparingly, and usually only with the users explicit consent.
|
||||
* An eventual driver reinitialize will happen so that audio
|
||||
* callbacks happening after this call within the same retro_run()
|
||||
* 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).
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
@ -2210,6 +2277,30 @@ struct retro_frame_time_callback
|
||||
retro_usec_t reference;
|
||||
};
|
||||
|
||||
/* Notifies a libretro core of the current occupancy
|
||||
* level of the frontend audio buffer.
|
||||
*
|
||||
* - active: 'true' if audio buffer is currently
|
||||
* in use. Will be 'false' if audio is
|
||||
* disabled in the frontend
|
||||
*
|
||||
* - occupancy: Given as a value in the range [0,100],
|
||||
* corresponding to the occupancy percentage
|
||||
* of the audio buffer
|
||||
*
|
||||
* - underrun_likely: 'true' if the frontend expects an
|
||||
* audio buffer underrun during the
|
||||
* next frame (indicates that a core
|
||||
* should attempt frame skipping)
|
||||
*
|
||||
* It will be called right before retro_run() every frame. */
|
||||
typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)(
|
||||
bool active, unsigned occupancy, bool underrun_likely);
|
||||
struct retro_audio_buffer_status_callback
|
||||
{
|
||||
retro_audio_buffer_status_callback_t callback;
|
||||
};
|
||||
|
||||
/* Pass this to retro_video_refresh_t if rendering to hardware.
|
||||
* Passing NULL to retro_video_refresh_t is still a frame dupe as normal.
|
||||
* */
|
||||
@ -2658,7 +2749,7 @@ struct retro_input_descriptor
|
||||
struct retro_system_info
|
||||
{
|
||||
/* All pointers are owned by libretro implementation, and pointers must
|
||||
* remain valid until retro_deinit() is called. */
|
||||
* remain valid until it is unloaded. */
|
||||
|
||||
const char *library_name; /* Descriptive name of library. Should not
|
||||
* contain any version numbers, etc. */
|
||||
@ -2857,6 +2948,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
|
||||
|
@ -41,7 +41,10 @@ static retro_environment_t environ_cb;
|
||||
static gambatte::video_pixel_t* video_buf;
|
||||
static gambatte::GB gb;
|
||||
|
||||
static bool libretro_supports_bitmasks = false;
|
||||
static bool libretro_supports_bitmasks = false;
|
||||
static bool libretro_supports_ff_override = false;
|
||||
static bool libretro_ff_enabled = false;
|
||||
static bool libretro_ff_enabled_prev = false;
|
||||
|
||||
static bool show_gb_link_settings = true;
|
||||
|
||||
@ -617,6 +620,31 @@ static void deactivate_rumble(void)
|
||||
/* Rumble support END */
|
||||
/**********************/
|
||||
|
||||
/* Fast forward override */
|
||||
void set_fastforward_override(bool fastforward)
|
||||
{
|
||||
struct retro_fastforwarding_override ff_override;
|
||||
|
||||
if (!libretro_supports_ff_override)
|
||||
return;
|
||||
|
||||
ff_override.ratio = -1.0f;
|
||||
ff_override.notification = true;
|
||||
|
||||
if (fastforward)
|
||||
{
|
||||
ff_override.fastforward = true;
|
||||
ff_override.inhibit_toggle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ff_override.fastforward = false;
|
||||
ff_override.inhibit_toggle = false;
|
||||
}
|
||||
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE, &ff_override);
|
||||
}
|
||||
|
||||
bool file_present_in_system(std::string fname)
|
||||
{
|
||||
const char *systemdirtmp = NULL;
|
||||
@ -716,11 +744,17 @@ class SNESInput : public gambatte::InputGetter
|
||||
int16_t ret = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
|
||||
for (i = 0; i < sizeof(input::btn_map) / sizeof(input::map); i++)
|
||||
res |= (ret & (1 << input::btn_map[i].snes)) ? input::btn_map[i].gb : 0;
|
||||
|
||||
libretro_ff_enabled = libretro_supports_ff_override &&
|
||||
(ret & (1 << RETRO_DEVICE_ID_JOYPAD_R2));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < sizeof(input::btn_map) / sizeof(input::map); i++)
|
||||
res |= input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, input::btn_map[i].snes) ? input::btn_map[i].gb : 0;
|
||||
|
||||
libretro_ff_enabled = libretro_supports_ff_override &&
|
||||
input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2);
|
||||
}
|
||||
|
||||
if (!up_down_allowed)
|
||||
@ -734,6 +768,13 @@ class SNESInput : public gambatte::InputGetter
|
||||
res &= ~(gambatte::InputGetter::LEFT | gambatte::InputGetter::RIGHT);
|
||||
}
|
||||
|
||||
/* Handle fast forward button */
|
||||
if (libretro_ff_enabled != libretro_ff_enabled_prev)
|
||||
{
|
||||
set_fastforward_override(libretro_ff_enabled);
|
||||
libretro_ff_enabled_prev = libretro_ff_enabled;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
} static gb_input;
|
||||
@ -854,9 +895,13 @@ void retro_init(void)
|
||||
else
|
||||
use_official_bootloader = false;
|
||||
|
||||
libretro_supports_bitmasks = false;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
|
||||
libretro_supports_bitmasks = true;
|
||||
|
||||
libretro_supports_ff_override = false;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE, NULL))
|
||||
libretro_supports_ff_override = true;
|
||||
}
|
||||
|
||||
void retro_deinit(void)
|
||||
@ -872,7 +917,14 @@ void retro_deinit(void)
|
||||
#endif
|
||||
video_buf = NULL;
|
||||
deinit_frame_blending();
|
||||
libretro_supports_bitmasks = false;
|
||||
|
||||
if (libretro_ff_enabled)
|
||||
set_fastforward_override(false);
|
||||
|
||||
libretro_supports_bitmasks = false;
|
||||
libretro_supports_ff_override = false;
|
||||
libretro_ff_enabled = false;
|
||||
libretro_ff_enabled_prev = false;
|
||||
|
||||
deactivate_rumble();
|
||||
memset(&rumble, 0, sizeof(struct retro_rumble_interface));
|
||||
@ -1480,19 +1532,34 @@ bool retro_load_game(const struct retro_game_info *info)
|
||||
log_cb(RETRO_LOG_INFO, "Rumble environment not supported.\n");
|
||||
|
||||
struct retro_input_descriptor desc[] = {
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
|
||||
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
|
||||
struct retro_input_descriptor desc_ff[] = {
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "Fast Forward" },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
if (libretro_supports_ff_override)
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc_ff);
|
||||
else
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
|
||||
|
||||
#if defined(VIDEO_RGB565) || defined(VIDEO_ABGR1555)
|
||||
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
|
||||
|
Loading…
Reference in New Issue
Block a user