Add rumble support

This commit is contained in:
jdgleaver 2020-11-13 17:47:00 +00:00
parent 0f553228c1
commit e98bd085de
8 changed files with 220 additions and 14 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
*.o
*.so

View File

@ -194,6 +194,68 @@ static gamepad_layout_t gp_modern = { // Based on Original XBOX Doom 3 Collectio
16,
};
static struct retro_rumble_interface rumble = {0};
static bool rumble_enabled = false;
static uint16_t rumble_damage_strength = 0;
static int16_t rumble_damage_counter = -1;
static uint16_t rumble_touch_strength = 0;
static int16_t rumble_touch_counter = -1;
void retro_set_rumble_damage(int damage, float duration)
{
/* Rumble scales linearly from 0xFFF to 0xFFFF
* as damage increases from 1 to 80 */
int capped_damage = (damage < 80) ? damage : 80;
uint16_t strength = 0;
if (!rumble.set_rumble_state ||
(!rumble_enabled && (capped_damage > 0)))
return;
if ((capped_damage > 0) && (duration > 0.0f))
{
strength = 0xFFF + (capped_damage * 0x300);
rumble_damage_counter = (int16_t)((duration * (float)tic_vars.fps / 1000.0f) + 1.0f);
}
/* Return early if:
* - strength and last set value are both zero
* - strength is greater than zero but less than
* (or equal to) last set value */
if (((strength == 0) && (rumble_damage_strength == 0)) ||
((strength > 0) && (strength <= rumble_damage_strength)))
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, strength);
rumble_damage_strength = strength;
}
void retro_set_rumble_touch(unsigned intensity, float duration)
{
/* Rumble scales linearly from 0x1FE to 0xFFFF
* as intensity increases from 1 to 20 */
unsigned capped_intensity = (intensity < 20) ? intensity : 20;
uint16_t strength = 0;
if (!rumble.set_rumble_state ||
(!rumble_enabled && (capped_intensity > 0)))
return;
if ((capped_intensity > 0) && (duration > 0.0f))
{
strength = 0x1FE + (capped_intensity * 0xCB3);
rumble_touch_counter = (int16_t)((duration * (float)tic_vars.fps / 1000.0f) + 1.0f);
}
/* Return early if strength matches last
* set value */
if (strength == rumble_touch_strength)
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, strength);
rumble_touch_strength = strength;
}
char* FindFileInDir(const char* dir, const char* wfname, const char* ext);
static void check_system_specs(void)
@ -227,7 +289,18 @@ void retro_init(void)
void retro_deinit(void)
{
D_DoomDeinit();
libretro_supports_bitmasks = false;
retro_set_rumble_damage(0, 0.0f);
retro_set_rumble_touch(0, 0.0f);
memset(&rumble, 0, sizeof(struct retro_rumble_interface));
rumble_enabled = false;
rumble_damage_strength = 0;
rumble_damage_counter = -1;
rumble_touch_strength = 0;
rumble_touch_counter = -1;
}
unsigned retro_api_version(void)
@ -450,12 +523,23 @@ static void update_variables(bool startup)
find_recursive_on = false;
}
var.key = "prboom-rumble";
var.value = NULL;
rumble_enabled = false;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
if (!strcmp(var.value, "enabled"))
rumble_enabled = true;
if (!rumble_enabled)
{
retro_set_rumble_damage(0, 0.0f);
retro_set_rumble_touch(0, 0.0f);
}
var.key = "prboom-analog_deadzone";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
analog_deadzone = (int)(atoi(var.value) * 0.01f * ANALOG_RANGE);
}
analog_deadzone = (int)(atoi(var.value) * 0.01f * ANALOG_RANGE);
}
void I_SafeExit(int rc);
@ -473,6 +557,22 @@ void retro_run(void)
}
D_DoomLoop();
I_UpdateSound();
if (rumble_damage_counter > -1)
{
rumble_damage_counter--;
if (rumble_damage_counter == 0)
retro_set_rumble_damage(0, 0.0f);
}
if (rumble_touch_counter > -1)
{
rumble_touch_counter--;
if (rumble_touch_counter == 0)
retro_set_rumble_touch(0, 0.0f);
}
}
static void extract_basename(char *buf, const char *path, size_t size)
@ -550,6 +650,14 @@ bool retro_load_game(const struct retro_game_info *info)
int argc = 0;
static char *argv[32] = {NULL};
if (environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble))
{
if (log_cb)
log_cb(RETRO_LOG_INFO, "Rumble environment supported.\n");
}
else if (log_cb)
log_cb(RETRO_LOG_INFO, "Rumble environment not supported.\n");
update_variables(true);
argv[argc++] = strdup("prboom");

View File

@ -32,10 +32,10 @@ struct retro_core_option_definition option_defs_us[] = {
"Internal resolution (restart)",
"Configure the resolution. Requires a restart.",
{
{ "320x200", NULL },
{ "640x400", NULL },
{ "960x600", NULL },
{ "1280x800", NULL },
{ "320x200", NULL },
{ "640x400", NULL },
{ "960x600", NULL },
{ "1280x800", NULL },
{ "1600x1000", NULL },
{ "1920x1200", NULL },
{ "2240x1400", NULL },
@ -49,8 +49,8 @@ struct retro_core_option_definition option_defs_us[] = {
"Mouse active when using Gamepad",
"Allows you to use mouse inputs even when User 1's device type isn't set to 'RetroKeyboard/Mouse'.",
{
{ "disabled", "Disabled"},
{ "enabled", "Enabled"},
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled"
@ -60,21 +60,32 @@ struct retro_core_option_definition option_defs_us[] = {
"Look on parent folders for IWADs",
"Scans parent folders for IWADs. NOTE: You need to disable this if you want to run SIGIL.",
{
{ "disabled", "Disabled" },
{ "enabled", "Enabled" },
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"enabled"
},
{
"prboom-rumble",
"Rumble Effects",
"Enables haptic feedback when using a rumble-equipped gamepad.",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled"
},
{
"prboom-analog_deadzone",
"Analog Deadzone (percent)",
"Sets the deadzone of the Gamepad analog sticks when the input device type is set to 'Gamepad Modern'.",
"Sets the deadzone of the gamepad analog sticks when the input device type is set to 'Gamepad Modern'.",
{
{ "0", NULL },
{ "5", NULL },
{ "10", NULL },
{ "15", NULL },
{ "10", NULL },
{ "15", NULL },
{ "20", NULL },
{ "25", NULL },
{ "30", NULL },

View File

@ -68,6 +68,8 @@ typedef enum
static void P_NewChaseDir(mobj_t *actor);
void P_ZBumpCheck(mobj_t *); // phares
extern void retro_set_rumble_damage(int damage, float duration);
//
// ENEMY THINKING
// Enemies are allways spawned
@ -2108,6 +2110,7 @@ void A_Fall(mobj_t *actor)
void A_Explode(mobj_t *thingy)
{
P_RadiusAttack( thingy, thingy->target, 128 );
retro_set_rumble_damage(60, 500.f);
}
//
@ -2546,6 +2549,7 @@ void A_Die(mobj_t *actor)
void A_Detonate(mobj_t *mo)
{
P_RadiusAttack(mo, mo->target, mo->info->damage);
retro_set_rumble_damage(60, 500.f);
}
//

View File

@ -288,6 +288,8 @@ boolean P_GivePower(player_t *player, int power)
// P_TouchSpecialThing
//
extern void retro_set_rumble_touch(unsigned intensity, float duration);
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
{
player_t *player;
@ -314,12 +316,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!P_GiveArmor (player, green_armor_class))
return;
player->message = s_GOTARMOR; // Ty 03/22/98 - externalized
retro_set_rumble_touch(12, 160.0f);
break;
case SPR_ARM2:
if (!P_GiveArmor (player, blue_armor_class))
return;
player->message = s_GOTMEGA; // Ty 03/22/98 - externalized
retro_set_rumble_touch(14, 160.0f);
break;
// bonus items
@ -329,6 +333,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
player->health = (maxhealth * 2);
player->mo->health = player->health;
player->message = s_GOTHTHBONUS; // Ty 03/22/98 - externalized
retro_set_rumble_touch(5, 160.0f);
break;
case SPR_BON2:
@ -338,6 +343,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!player->armortype)
player->armortype = green_armor_class;
player->message = s_GOTARMBONUS; // Ty 03/22/98 - externalized
retro_set_rumble_touch(5, 160.0f);
break;
case SPR_SOUL:
@ -347,6 +353,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
player->mo->health = player->health;
player->message = s_GOTSUPER; // Ty 03/22/98 - externalized
sound = sfx_getpow;
retro_set_rumble_touch(14, 160.0f);
break;
case SPR_MEGA:
@ -357,6 +364,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
P_GiveArmor (player,blue_armor_class);
player->message = s_GOTMSPHERE; // Ty 03/22/98 - externalized
sound = sfx_getpow;
retro_set_rumble_touch(16, 160.0f);
break;
// cards
@ -365,6 +373,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!player->cards[it_bluecard])
player->message = s_GOTBLUECARD; // Ty 03/22/98 - externalized
P_GiveCard (player, it_bluecard);
retro_set_rumble_touch(7, 150.0f);
if (!netgame)
break;
return;
@ -373,6 +382,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!player->cards[it_yellowcard])
player->message = s_GOTYELWCARD; // Ty 03/22/98 - externalized
P_GiveCard (player, it_yellowcard);
retro_set_rumble_touch(7, 150.0f);
if (!netgame)
break;
return;
@ -381,6 +391,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!player->cards[it_redcard])
player->message = s_GOTREDCARD; // Ty 03/22/98 - externalized
P_GiveCard (player, it_redcard);
retro_set_rumble_touch(7, 150.0f);
if (!netgame)
break;
return;
@ -389,6 +400,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!player->cards[it_blueskull])
player->message = s_GOTBLUESKUL; // Ty 03/22/98 - externalized
P_GiveCard (player, it_blueskull);
retro_set_rumble_touch(8, 150.0f);
if (!netgame)
break;
return;
@ -397,6 +409,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!player->cards[it_yellowskull])
player->message = s_GOTYELWSKUL; // Ty 03/22/98 - externalized
P_GiveCard (player, it_yellowskull);
retro_set_rumble_touch(8, 150.0f);
if (!netgame)
break;
return;
@ -405,6 +418,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!player->cards[it_redskull])
player->message = s_GOTREDSKULL; // Ty 03/22/98 - externalized
P_GiveCard (player, it_redskull);
retro_set_rumble_touch(8, 150.0f);
if (!netgame)
break;
return;
@ -414,6 +428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (!P_GiveBody (player, 10))
return;
player->message = s_GOTSTIM; // Ty 03/22/98 - externalized
retro_set_rumble_touch(6, 160.0f);
break;
case SPR_MEDI:
@ -424,6 +439,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
player->message = s_GOTMEDINEED; // Ty 03/22/98 - externalized
else
player->message = s_GOTMEDIKIT; // Ty 03/22/98 - externalized
retro_set_rumble_touch(8, 160.0f);
break;
@ -433,6 +450,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTINVUL; // Ty 03/22/98 - externalized
sound = sfx_getpow;
retro_set_rumble_touch(18, 160.0f);
break;
case SPR_PSTR:
@ -442,6 +460,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
if (player->readyweapon != WP_FIST)
player->pendingweapon = WP_FIST;
sound = sfx_getpow;
retro_set_rumble_touch(20, 180.0f);
break;
case SPR_PINS:
@ -449,6 +468,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTINVIS; // Ty 03/22/98 - externalized
sound = sfx_getpow;
retro_set_rumble_touch(18, 160.0f);
break;
case SPR_SUIT:
@ -456,6 +476,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTSUIT; // Ty 03/22/98 - externalized
sound = sfx_getpow;
retro_set_rumble_touch(18, 160.0f);
break;
case SPR_PMAP:
@ -463,6 +484,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTMAP; // Ty 03/22/98 - externalized
sound = sfx_getpow;
retro_set_rumble_touch(18, 160.0f);
break;
case SPR_PVIS:
@ -470,6 +492,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTVISOR; // Ty 03/22/98 - externalized
sound = sfx_getpow;
retro_set_rumble_touch(18, 160.0f);
break;
// ammo
@ -485,48 +508,57 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
}
player->message = s_GOTCLIP; // Ty 03/22/98 - externalized
retro_set_rumble_touch(6, 140.0f);
break;
case SPR_AMMO:
if (!P_GiveAmmo (player, AM_CLIP,5))
return;
player->message = s_GOTCLIPBOX; // Ty 03/22/98 - externalized
retro_set_rumble_touch(8, 140.0f);
break;
case SPR_ROCK:
if (!P_GiveAmmo (player, AM_MISL,1))
return;
player->message = s_GOTROCKET; // Ty 03/22/98 - externalized
retro_set_rumble_touch(6, 140.0f);
break;
case SPR_BROK:
if (!P_GiveAmmo (player, AM_MISL,5))
return;
player->message = s_GOTROCKBOX; // Ty 03/22/98 - externalized
retro_set_rumble_touch(8, 140.0f);
break;
case SPR_CELL:
if (!P_GiveAmmo (player, AM_CELL,1))
return;
player->message = s_GOTCELL; // Ty 03/22/98 - externalized
retro_set_rumble_touch(6, 140.0f);
break;
case SPR_CELP:
if (!P_GiveAmmo (player, AM_CELL,5))
return;
player->message = s_GOTCELLBOX; // Ty 03/22/98 - externalized
retro_set_rumble_touch(8, 140.0f);
break;
case SPR_SHEL:
if (!P_GiveAmmo (player, AM_SHELL,1))
return;
player->message = s_GOTSHELLS; // Ty 03/22/98 - externalized
retro_set_rumble_touch(6, 140.0f);
break;
case SPR_SBOX:
if (!P_GiveAmmo (player, AM_SHELL,5))
return;
player->message = s_GOTSHELLBOX; // Ty 03/22/98 - externalized
retro_set_rumble_touch(8, 140.0f);
break;
case SPR_BPAK:
@ -539,6 +571,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
for (i=0 ; i<NUMAMMO ; i++)
P_GiveAmmo (player, i, 1);
player->message = s_GOTBACKPACK; // Ty 03/22/98 - externalized
retro_set_rumble_touch(12, 160.0f);
break;
// weapons
@ -547,6 +580,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTBFG9000; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
retro_set_rumble_touch(20, 180.0f);
break;
case SPR_MGUN:
@ -554,6 +588,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTCHAINGUN; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
retro_set_rumble_touch(15, 180.0f);
break;
case SPR_CSAW:
@ -561,6 +596,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTCHAINSAW; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
retro_set_rumble_touch(15, 180.0f);
break;
case SPR_LAUN:
@ -568,6 +604,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTLAUNCHER; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
retro_set_rumble_touch(18, 180.0f);
break;
case SPR_PLAS:
@ -575,6 +612,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTPLASMA; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
retro_set_rumble_touch(17, 180.0f);
break;
case SPR_SHOT:
@ -582,6 +620,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTSHOTGUN; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
retro_set_rumble_touch(14, 180.0f);
break;
case SPR_SGN2:
@ -589,6 +628,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
return;
player->message = s_GOTSHOTGUN2; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
retro_set_rumble_touch(16, 180.0f);
break;
default:

View File

@ -54,6 +54,8 @@
extern void P_Thrust(player_t *, angle_t, fixed_t);
extern void retro_set_rumble_damage(int damage, float duration);
// The following array holds the recoil values // phares
static const int recoil_values[] = { // phares
@ -669,6 +671,8 @@ void A_Punch(player_t *player, pspdef_t *psp)
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y,
linetarget->x, linetarget->y);
R_SmoothPlaying_Reset(player); // e6y
retro_set_rumble_damage(30, 120.0f);
}
//
@ -718,6 +722,8 @@ void A_Saw(player_t *player, pspdef_t *psp)
player->mo->flags |= MF_JUSTATTACKED;
R_SmoothPlaying_Reset(player); // e6y
retro_set_rumble_damage(40, 120.0f);
}
//
@ -728,6 +734,7 @@ void A_FireMissile(player_t *player, pspdef_t *psp)
{
player->ammo[weaponinfo[player->readyweapon].ammo]--;
P_SpawnPlayerMissile(player->mo, MT_ROCKET);
retro_set_rumble_damage(50, 120.0f);
}
//
@ -738,6 +745,7 @@ void A_FireBFG(player_t *player, pspdef_t *psp)
{
player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS;
P_SpawnPlayerMissile(player->mo, MT_BFG);
retro_set_rumble_damage(50, 120.0f);
}
//
@ -802,6 +810,7 @@ void A_FireOldBFG(player_t *player, pspdef_t *psp)
P_CheckMissileSpawn(th);
}
while ((type != MT_PLASMA2) && (type = MT_PLASMA2)); //killough: obfuscated! // lgtm[cpp/assign-where-compare-meant]
retro_set_rumble_damage(50, 120.0f);
}
//
@ -814,6 +823,7 @@ void A_FirePlasma(player_t *player, pspdef_t *psp)
A_FireSomething(player,P_Random(pr_plasma)&1); // phares
P_SpawnPlayerMissile(player->mo, MT_PLASMA);
retro_set_rumble_damage(50, 120.0f);
}
//
@ -874,6 +884,8 @@ void A_FirePistol(player_t *player, pspdef_t *psp)
A_FireSomething(player,0); // phares
P_BulletSlope(player->mo);
P_GunShot(player->mo, !player->refire);
retro_set_rumble_damage(30, 120.0f);
}
//
@ -895,6 +907,8 @@ void A_FireShotgun(player_t *player, pspdef_t *psp)
for (i=0; i<7; i++)
P_GunShot(player->mo, false);
retro_set_rumble_damage(40, 120.0f);
}
//
@ -924,6 +938,8 @@ void A_FireShotgun2(player_t *player, pspdef_t *psp)
P_LineAttack(player->mo, angle, MISSILERANGE, bulletslope +
((t - P_Random(pr_shotgun))<<5), damage);
}
retro_set_rumble_damage(40, 120.0f);
}
//
@ -946,6 +962,8 @@ void A_FireCGun(player_t *player, pspdef_t *psp)
P_BulletSlope(player->mo);
P_GunShot(player->mo, !player->refire);
retro_set_rumble_damage(10, 120.0f);
}
#ifdef HEXEN

View File

@ -220,6 +220,9 @@ static void P_StartButton
//
// No return
//
extern void retro_set_rumble_touch(unsigned intensity, float duration);
void P_ChangeSwitchTexture
( line_t* line,
int useAgain )
@ -280,6 +283,8 @@ void P_ChangeSwitchTexture
if (useAgain)
P_StartButton(line, position, switchlist[i], BUTTONTIME);
retro_set_rumble_touch(12, 200.0f);
}

View File

@ -360,6 +360,9 @@ static int st_fragscount;
// used to use appopriately pained face
static int st_oldhealth = -1;
// used to track armour reduction
static int st_oldarmour = -1;
// used for evil grin
static boolean oldweaponsowned[NUMWEAPONS];
@ -697,12 +700,28 @@ static void ST_updateWidgets(void)
}
extern void retro_set_rumble_damage(int damage, float duration);
void ST_Ticker(void)
{
st_clock++;
st_randomnumber = M_Random();
ST_updateWidgets();
/* If player has taken damage, trigger a
* rumble effect */
if (st_oldhealth > plyr->health)
{
int damage = st_oldhealth - plyr->health;
/* Add any armour damage */
if (st_oldarmour > plyr->armorpoints)
damage += st_oldarmour - plyr->armorpoints;
retro_set_rumble_damage(damage, 333.3333f);
}
st_oldhealth = plyr->health;
st_oldarmour = plyr->armorpoints;
}
int st_palette = 0;