Merge pull request #162 from jdgleaver/rumble

Add rumble support
This commit is contained in:
Autechre 2020-11-18 17:01:55 +01:00 committed by GitHub
commit 93e27debd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 145 additions and 17 deletions

View File

@ -513,6 +513,75 @@ static void check_frame_blend_variable(void)
/* Interframe blending END */
/***************************/
/************************/
/* Rumble support START */
/************************/
static struct retro_rumble_interface rumble = {0};
static uint16_t rumble_strength_last = 0;
static uint16_t rumble_strength_up = 0;
static uint16_t rumble_strength_down = 0;
static uint16_t rumble_level = 0;
static bool rumble_active = false;
void cartridge_set_rumble(unsigned active)
{
if (!rumble.set_rumble_state ||
!rumble_level)
return;
if (active)
rumble_strength_up++;
else
rumble_strength_down++;
rumble_active = true;
}
static void apply_rumble(void)
{
uint16_t strength;
if (!rumble.set_rumble_state ||
!rumble_level)
return;
strength = (rumble_strength_up > 0) ?
(rumble_strength_up * rumble_level) /
(rumble_strength_up + rumble_strength_down) : 0;
rumble_strength_up = 0;
rumble_strength_down = 0;
if (strength == rumble_strength_last)
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, strength);
rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, strength);
rumble_strength_last = strength;
}
static void deactivate_rumble(void)
{
rumble_strength_up = 0;
rumble_strength_down = 0;
rumble_active = false;
if (!rumble.set_rumble_state ||
(rumble_strength_last == 0))
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, 0);
rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, 0);
rumble_strength_last = 0;
}
/**********************/
/* Rumble support END */
/**********************/
bool file_present_in_system(std::string fname)
{
const char *systemdirtmp = NULL;
@ -769,6 +838,10 @@ void retro_deinit(void)
video_buf = NULL;
deinit_frame_blending();
libretro_supports_bitmasks = false;
deactivate_rumble();
memset(&rumble, 0, sizeof(struct retro_rumble_interface));
rumble_level = 0;
}
void retro_set_environment(retro_environment_t cb)
@ -1045,10 +1118,10 @@ static void check_variables(void)
darkFilterLevel = static_cast<unsigned>(atoi(var.value));
}
gb.setDarkFilterLevel(darkFilterLevel);
var.key = "gambatte_up_down_allowed";
var.value = NULL;
up_down_allowed = false;
var.key = "gambatte_up_down_allowed";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "enabled"))
@ -1056,8 +1129,18 @@ static void check_variables(void)
else
up_down_allowed = false;
}
else
up_down_allowed = false;
rumble_level = 0;
var.key = "gambatte_rumble_level";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
rumble_level = atoi(var.value);
rumble_level = (rumble_level > 10) ? 10 : rumble_level;
rumble_level = (rumble_level > 0) ? ((0x1999 * rumble_level) + 0x5) : 0;
}
if (rumble_level == 0)
deactivate_rumble();
/* Interframe blending option has its own handler */
check_frame_blend_variable();
@ -1352,6 +1435,11 @@ bool retro_load_game(const struct retro_game_info *info)
return false;
}
if (environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble))
log_cb(RETRO_LOG_INFO, "Rumble environment supported.\n");
else
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" },
@ -1600,6 +1688,10 @@ void retro_run()
audio_batch_cb(sound_buf.i16, read_avail);
#endif
/* Apply any 'pending' rumble effects */
if (rumble_active)
apply_rumble();
frames_count++;
bool updated = false;

View File

@ -302,6 +302,26 @@ struct retro_core_option_definition option_defs_us[] = {
},
"disabled"
},
{
"gambatte_rumble_level",
"Gamepad Rumble Strength",
"Enables haptic feedback effects for supported games (Pokemon Pinball, Perfect Dark...).",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ "10", NULL },
{ NULL, NULL },
},
"10"
},
#ifdef HAVE_NETWORK
{
"gambatte_show_gb_link_settings",

View File

@ -24,6 +24,8 @@
#include <string.h>
#include <algorithm>
extern void cartridge_set_rumble(unsigned active);
namespace gambatte
{
@ -417,6 +419,7 @@ namespace gambatte
unsigned short rombank;
unsigned char rambank;
bool enableRam;
bool hasRumble;
static unsigned adjustedRombank(const unsigned bank) { return bank; }
void setRambank() const {
memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0,
@ -424,29 +427,41 @@ namespace gambatte
}
void setRombank() const { memptrs.setRombank(adjustedRombank(rombank) & (rombanks(memptrs) - 1));}
public:
explicit Mbc5(MemPtrs &memptrs)
explicit Mbc5(MemPtrs &memptrs, bool rumble)
: memptrs(memptrs),
rombank(1),
rambank(0),
enableRam(false)
enableRam(false),
hasRumble(rumble)
{
}
virtual void romWrite(const unsigned P, const unsigned data) {
switch (P >> 13 & 3) {
case 0:
switch (P >> 12 & 0x7) {
case 0x0:
case 0x1:
enableRam = (data & 0xF) == 0xA;
setRambank();
break;
case 1:
case 0x2:
case 0x3:
rombank = P < 0x3000 ? (rombank & 0x100) | data
: (data << 8 & 0x100) | (rombank & 0xFF);
setRombank();
break;
case 2:
rambank = data & 0xF;
case 0x4:
case 0x5:
if(hasRumble && ((P >> 12 & 0x7) == 4))
{
cartridge_set_rumble((data >> 3) & 1);
rambank = (data & ~8) & 0x0f;
}
else
{
rambank = data & 0x0f;
}
setRambank();
break;
case 3:
default:
break;
}
}
@ -527,6 +542,7 @@ namespace gambatte
unsigned rombanks = 2;
bool cgb = false;
enum Cartridgetype { PLAIN, MBC1, MBC2, MBC3, MBC5, HUC1, HUC3 } type = PLAIN;
bool rumble = false;
{
unsigned i;
@ -558,9 +574,9 @@ namespace gambatte
case 0x19: printf("MBC5 ROM loaded.\n"); type = MBC5; break;
case 0x1A: printf("MBC5 ROM+RAM loaded.\n"); type = MBC5; break;
case 0x1B: printf("MBC5 ROM+RAM+BATTERY loaded.\n"); type = MBC5; break;
case 0x1C: printf("MBC5+RUMBLE ROM not supported.\n"); type = MBC5; break;
case 0x1D: printf("MBC5+RUMBLE+RAM ROM not suported.\n"); type = MBC5; break;
case 0x1E: printf("MBC5+RUMBLE+RAM+BATTERY ROM not supported.\n"); type = MBC5; break;
case 0x1C: printf("MBC5+RUMBLE ROM loaded.\n"); type = MBC5; rumble = true; break;
case 0x1D: printf("MBC5+RUMBLE+RAM ROM loaded.\n"); type = MBC5; rumble = true; break;
case 0x1E: printf("MBC5+RUMBLE+RAM+BATTERY ROM loaded.\n"); type = MBC5; rumble = true; break;
case 0x20: printf("MBC6 ROM not supported.\n"); return -1;
case 0x22: printf("MBC7 ROM not supported.\n"); return -1;
case 0xFC: printf("Pocket Camera ROM not supported.\n"); return -1;
@ -630,7 +646,7 @@ namespace gambatte
break;
case MBC2: mbc.reset(new Mbc2(memptrs_)); break;
case MBC3: mbc.reset(new Mbc3(memptrs_, hasRtc(memptrs_.romdata()[0x147]) ? &rtc_ : 0)); break;
case MBC5: mbc.reset(new Mbc5(memptrs_)); break;
case MBC5: mbc.reset(new Mbc5(memptrs_, rumble)); break;
case HUC1: mbc.reset(new HuC1(memptrs_)); break;
case HUC3:
huc3_.set(true);