input: increase allowed autofire rates from 5 to 30. add autofire_on_directions option to mister.ini (defaults to 0/off) (#1120)
This commit is contained in:
@@ -342,7 +342,10 @@ vrr_vesa_framerate=0
|
||||
; disable autofire if for some reason it's not required and accidentally triggered
|
||||
disable_autofire=0
|
||||
|
||||
; custom autofire rates (in hertz). up to five allowed.
|
||||
; allow autofire on directional inputs. typically not recommended. default is 0 (disabled).
|
||||
;autofire_on_directions=1
|
||||
|
||||
; custom autofire rates (in hertz). will round to nearest rate that divides evenly into 60hz.
|
||||
; can also use literal bit patterns for on/off cycles, i.e. 0b00111. each bit is one frame.
|
||||
;autofire_rates=10,0b00111,20,30
|
||||
|
||||
|
||||
28
autofire.cpp
28
autofire.cpp
@@ -24,8 +24,8 @@
|
||||
actual_refresh / 60 * autofire_rate_hz == real_autofire_rate_hz
|
||||
*/
|
||||
|
||||
#define MAX_AF_CODES 16
|
||||
#define MAX_AF_RATES 6
|
||||
#define MAX_AF_CODES 32
|
||||
#define MAX_AF_RATES 32
|
||||
#define AF_NAME_LEN 32
|
||||
|
||||
// global autofire cycle data.
|
||||
@@ -51,13 +51,11 @@ static struct AutofireData autofiredata_default[MAX_AF_RATES]; // hardcoded fall
|
||||
static int num_af_rates_default = 0;
|
||||
static int num_af_rates = 0;
|
||||
|
||||
|
||||
int get_autofire_rate_count()
|
||||
{
|
||||
return num_af_rates;
|
||||
}
|
||||
|
||||
|
||||
static void set_autofire_name(struct AutofireData *data, const char *base_name) {
|
||||
float hz = data->cycle_length > 0 ? (60.0f / data->cycle_length) : 0.0f;
|
||||
if (base_name && base_name[0]) {
|
||||
@@ -114,7 +112,6 @@ void set_autofire_code(int player, uint32_t code, uint32_t mask, int index, bool
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// step autofire rate; wrap to disabled at max.
|
||||
void inc_autofire_code(int player, uint32_t code, uint32_t mask) {
|
||||
if (get_autofire_locked(player, code)) return;
|
||||
@@ -125,16 +122,6 @@ void inc_autofire_code(int player, uint32_t code, uint32_t mask) {
|
||||
set_autofire_code(player, code, mask, index);
|
||||
}
|
||||
|
||||
// advance all autofire patterns (run once per frame)
|
||||
//void autofire_tick() {
|
||||
// for (int i = 1; i < num_af_rates; i++)
|
||||
// {
|
||||
//autofiredata[i].bit = (autofiredata[i].cycle_mask >> autofiredata[i].frame_count) & 1u;
|
||||
//if (++(autofiredata[i].frame_count) >= autofiredata[i].cycle_length)
|
||||
// autofiredata[i].frame_count = 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
// returns whether the buttons for this code should be held or released this frame.
|
||||
// (updated every time we call autofire_tick)
|
||||
bool get_autofire_bit(int player, uint32_t code, uint32_t frame_count) {
|
||||
@@ -179,8 +166,11 @@ bool is_autofire_enabled(int player, uint32_t code) {
|
||||
// some arcade shooters have pretty odd optimal autofire patterns to manage rank
|
||||
// let's hide them here for my shmup buddies
|
||||
static const struct AutofireData autofire_patterns[] = {
|
||||
{ "GUNFRONTIER", 0b111100000ULL, 9 },
|
||||
{ "GAREGGA", 0b1110000ULL, 7 },
|
||||
{ "GUNFRONTIER", 0b000001111ULL, 9 }, // gun frontier raises rank really fast in response to autofire. this is the fastest
|
||||
// you can fire without it triggering a rate increase
|
||||
{ "GAREGGA", 0b0000111ULL, 7 }, // i trusted google that battle garegga likes this rate but i'm terrified of the game
|
||||
// so please let me know if i'm wrong
|
||||
|
||||
};
|
||||
|
||||
// helper for formatting binary literal patterns.
|
||||
@@ -212,6 +202,10 @@ static void init_autofire_entry(struct AutofireData *data, uint64_t mask, int le
|
||||
if (data->cycle_length < 1) data->cycle_length = 1;
|
||||
}
|
||||
|
||||
// this will always result in an autofire rate that divides evenly into 60hz
|
||||
// could probably revisit and use a couple different algorithms to allow approximations
|
||||
// of non-divisible rates but the working theory was to keep this code easy to read
|
||||
// and if anybody needs something more complicated, fall back on a custom bitmask
|
||||
static inline struct AutofireData mask_from_hertz(double hz_target)
|
||||
{
|
||||
struct AutofireData p = {{0}, 0, 0};
|
||||
|
||||
3
cfg.cpp
3
cfg.cpp
@@ -133,8 +133,9 @@ static const ini_var_t ini_vars[] =
|
||||
{ "DEBUG", (void *)(&(cfg.debug)), UINT8, 0, 1 },
|
||||
{ "LOOKAHEAD", (void *)(&(cfg.lookahead)), UINT8, 0, 3 },
|
||||
{ "MAIN", (void*)(&(cfg.main)), STRING, 0, sizeof(cfg.main) - 1 },
|
||||
{"VFILTER_INTERLACE_DEFAULT", (void*)(&(cfg.vfilter_interlace_default)), STRING, 0, sizeof(cfg.vfilter_interlace_default) - 1 },
|
||||
{ "VFILTER_INTERLACE_DEFAULT", (void*)(&(cfg.vfilter_interlace_default)), STRING, 0, sizeof(cfg.vfilter_interlace_default) - 1 },
|
||||
{ "AUTOFIRE_RATES", (void *)(&(cfg.autofire_rates)), STRING, 0, sizeof(cfg.autofire_rates) - 1 },
|
||||
{ "AUTOFIRE_ON_DIRECTIONS", (void *)(&(cfg.autofire_on_directions)), UINT8, 0, 1 },
|
||||
|
||||
};
|
||||
|
||||
|
||||
3
cfg.h
3
cfg.h
@@ -102,7 +102,8 @@ typedef struct {
|
||||
uint8_t lookahead;
|
||||
char main[1024];
|
||||
char vfilter_interlace_default[1023];
|
||||
char autofire_rates[256];
|
||||
char autofire_rates[3072];
|
||||
uint8_t autofire_on_directions;
|
||||
|
||||
} cfg_t;
|
||||
|
||||
|
||||
10
input.cpp
10
input.cpp
@@ -1915,20 +1915,25 @@ static bool handle_autofire_toggle(int num, uint32_t mask, uint32_t code, char p
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const char *dir_bnames[] = { "Right", "Left", "Down", "Up" };
|
||||
|
||||
// we can only get here if the OSD or BTN_TGL keys were pressed
|
||||
// in that event we see if lastmask/lastcode tells us we're holding a button
|
||||
// and if we are, we toggle autofire for that button
|
||||
if (!user_io_osd_is_visible() && press && !cfg.disable_autofire)
|
||||
{
|
||||
if ((lastcode[num] && lastmask[num] && (lastmask[num] & 0xF) == 0)) // don't allow enabling autofire on directions
|
||||
if (lastcode[num] && lastmask[num] && (cfg.autofire_on_directions || (lastmask[num] & 0xF) == 0))
|
||||
{
|
||||
char *strat = str;
|
||||
inc_autofire_code(num, lastcode[num], lastmask[num]);
|
||||
|
||||
// display autofire status for each button in the mask
|
||||
FOR_EACH_SET_BIT(lastmask[num], btn) {
|
||||
strat += sprintf(strat, "%s\n", joy_bnames[btn-4]);
|
||||
if (btn < 4) {
|
||||
strat += sprintf(strat, "%s ", dir_bnames[btn]);
|
||||
} else {
|
||||
strat += sprintf(strat, "%s\n", joy_bnames[btn-4]);
|
||||
}
|
||||
}
|
||||
|
||||
const char *rate = get_autofire_rate_hz_button(num, lastcode[num]);
|
||||
@@ -5948,7 +5953,6 @@ int input_poll(int getchar)
|
||||
static uint32_t last_frame_count = 0;
|
||||
if (FRAME_TICK(last_frame_count)) {
|
||||
key_update_frames_held();
|
||||
//autofire_tick(); // advance all autofire patterns by 1
|
||||
}
|
||||
|
||||
int ret = input_test(getchar);
|
||||
|
||||
Reference in New Issue
Block a user