Lorenz (xha): 1 add option for input delay 2 files changed, 43 insertions(+), 7 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~sebsite/generic-tetromino-game/patches/41960/mbox | git am -3Learn more about email & git
--- :) main.c | 41 +++++++++++++++++++++++++++------ website/docs/options/index.html | 9 ++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index 1c8dfe3..b00ddae 100644 --- a/main.c +++ b/main.c @@ -115,6 +115,7 @@ enum option { OPT_COLORS, OPT_GARBAGE_PILING, OPT_HARD_DROP, + OPT_INPUT_DELAY, OPT_INPUT_HANDLER, OPT_LINES_PER_LEVEL, OPT_MUSIC, @@ -2249,6 +2250,11 @@ option_string_values(enum option opt, const char *const **restrict values, valbuf[2] = "with lock"; *nvalues = 3; break; + case OPT_INPUT_DELAY: + valbuf[0] = "off"; + valbuf[1] = "on"; + *nvalues = 2; + break; case OPT_INPUT_HANDLER: valbuf[0] = "vanilla"; *nvalues = 1; @@ -2830,6 +2836,8 @@ set_option_string(const char *key, const char *val, const char **restrict err) *err = parse_config_string(key, val, OPT_GARBAGE_PILING); } else if (strcmp(key, "hard_drop") == 0) { *err = parse_config_string(key, val, OPT_HARD_DROP); + } else if (strcmp(key, "input_delay") == 0) { + *err = parse_config_string(key, val, OPT_INPUT_DELAY); } else if (strcmp(key, "input_handler") == 0) { *err = parse_config_string(key, val, OPT_INPUT_HANDLER); } else if (strcmp(key, "lines_per_level") == 0) { @@ -2859,6 +2867,7 @@ parse_config(void) options[OPT_COLORS] = xstrdup("classic"); options[OPT_GARBAGE_PILING] = xstrdup("on"); options[OPT_HARD_DROP] = xstrdup("off"); + options[OPT_INPUT_DELAY] = xstrdup("off"); options[OPT_INPUT_HANDLER] = xstrdup("vanilla"); options[OPT_LINES_PER_LEVEL] = xstrdup("vanilla"); options[OPT_MUSIC] = xstrdup("random"); @@ -3041,6 +3050,8 @@ save_config(void) goto close_and_unlink; if (write_config_string(f, "hard_drop", options[OPT_HARD_DROP]) == -1) goto close_and_unlink; + if (write_config_string(f, "input_delay", options[OPT_INPUT_DELAY]) == -1) + goto close_and_unlink; if (write_config_string(f, "input_handler", options[OPT_INPUT_HANDLER]) == -1) goto close_and_unlink; if (write_config_string(f, "lines_per_level", options[OPT_LINES_PER_LEVEL]) == -1) @@ -3166,6 +3177,7 @@ draw_core_option(void) case OPT_COLORS: case OPT_GARBAGE_PILING: case OPT_HARD_DROP: + case OPT_INPUT_DELAY: case OPT_PAUSE: case OPT_SAVE_HIGHSCORES: case OPT_SFX: @@ -3288,6 +3300,7 @@ draw_options_page(void) writefg("COLORS", 2, y++, WHITE); writefg("GARBAGE PILING", 2, y++, WHITE); writefg("HARD DROP", 2, y++, WHITE); + writefg("INPUT DELAY", 2, y++, WHITE); writefg("INPUT HANDLER", 2, y++, WHITE); writefg("LINES PER LEVEL", 2, y++, WHITE); writefg("MUSIC", 2, y++, WHITE); @@ -4070,6 +4083,7 @@ read_replay_metadata(FILE *f) { /* TODO: most likely a memory leak here */ options[OPT_HARD_DROP] = xstrdup("off"); + options[OPT_INPUT_DELAY] = xstrdup("off"); options[OPT_LINES_PER_LEVEL] = xstrdup("vanilla"); options[OPT_RNG] = xstrdup("classic"); @@ -4094,6 +4108,8 @@ read_replay_metadata(FILE *f) if (strcmp(line, "hard_drop") == 0) { err = parse_config_string(line, val, OPT_HARD_DROP); + } else if (strcmp(line, "input_delay") == 0) { + err = parse_config_string(line, val, OPT_INPUT_DELAY); } else if (strcmp(line, "lines_per_level") == 0) { err = parse_config_string(line, val, OPT_LINES_PER_LEVEL); } else if (strcmp(line, "rng") == 0) { @@ -7789,9 +7805,12 @@ static int gameinput(const uint8_t inputs[static 4][2], uint8_t i) { struct game_state *g = &state.game.players[i]; - uint8_t pressed = inputs[0][i] & ~inputs[1][i]; - uint8_t held = inputs[0][i] & inputs[1][i]; - uint8_t released = ~inputs[0][i] & inputs[1][i]; + + uint8_t delay = strcmp(options[OPT_INPUT_DELAY], "on") == 0 ? 2 : 0; + uint8_t pressed = inputs[delay][i] & ~inputs[delay + 1][i]; + uint8_t held = inputs[delay][i] & inputs[delay + 1][i]; + uint8_t released = ~inputs[delay][i] & inputs[delay + 1][i]; + if (g->over) { if (pressed == INPUT_MASK_START) { /* only start pressed; no other buttons */ @@ -7821,11 +7840,11 @@ gameinput(const uint8_t inputs[static 4][2], uint8_t i) /* only if not pushing down (and not pressed up) */ if (pressed & (INPUT_MASK_RIGHT | INPUT_MASK_LEFT)) { g->das = 0; - shift(g, inputs[0][i]); + shift(g, inputs[delay][i]); } else if (held & (INPUT_MASK_RIGHT | INPUT_MASK_LEFT)) { ++g->das; if (g->das >= 16) - shift(g, inputs[0][i]); + shift(g, inputs[delay][i]); } } if (released & INPUT_MASK_UP) { @@ -7887,6 +7906,10 @@ save_replay(void) if (write_config_string(f, "hard_drop", options[OPT_HARD_DROP]) == -1) goto write_err; } + if (strcmp(options[OPT_INPUT_DELAY], "off") != 0) { + if (write_config_string(f, "input_delay", options[OPT_INPUT_DELAY]) == -1) + goto write_err; + } if (strcmp(options[OPT_LINES_PER_LEVEL], "vanilla") != 0) { if (write_config_string(f, "lines_per_level", options[OPT_LINES_PER_LEVEL]) == -1) goto write_err; @@ -8558,7 +8581,8 @@ read_inputs(void))[2] static void handle_inputs(const uint8_t inputs[static 4][2]) { - uint8_t pressed = inputs[0][0] & ~inputs[1][0]; + uint8_t delay = strcmp(options[OPT_INPUT_DELAY], "on") == 0 ? 2 : 0; + uint8_t pressed = inputs[delay][0] & ~inputs[delay + 1][0]; switch (state.scr) { case TITLE: titleinput(pressed); @@ -8591,7 +8615,10 @@ handle_inputs(const uint8_t inputs[static 4][2]) onlineinput(pressed); break; case OPTIONS: - optionsinput(pressed); + /* input delay might get enabled in the options: to avoid + * disabling it again with the same key press, disable input + * delay for the options */ + optionsinput(inputs[0][0] & ~inputs[1][0]); break; case INPUT: inputinput(pressed); diff --git a/website/docs/options/index.html b/website/docs/options/index.html index 0f6749b..aca0012 100644 --- a/website/docs/options/index.html +++ b/website/docs/options/index.html @@ -61,6 +61,15 @@ <dd>Pressing the up button will snap the tetromino to the bottom of the board and immediately lock it.</dd> </dl> </section> + <section> + <h3 class="option">Input Delay</h3> + <dl> + <dt class="optval">On</dt> + <dd><span class="i">(default)</span>The input delay of NES Tetris (2 frames) will be emulated. Note that the options screen doesn't have input delay, regardless of this setting.</dd> + <dt class="optval">Off</dt> + <dd>The inputs will be processed as soon as they are available.</dd> + </dl> + </section> <!-- TODO: finish me --> <section> <h3 class="option">Lines per level</h3> -- 2.41.0
Mostly looks good, the one issue I found is that you can't exit the options screen when input delay is enabled, since the start button press is read twice.