~sebsite/generic-tetromino-game

add option for input delay v4 APPLIED

Lorenz (xha): 1
 add option for input delay

 2 files changed, 58 insertions(+), 15 deletions(-)
Export patchset (mbox)
How do I use this?

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/42023/mbox | git am -3
Learn more about email & git

[PATCH v4] add option for input delay Export this patch

---
okok still learning hope this is correct now xd

 main.c                          | 64 +++++++++++++++++++++++++--------
 website/docs/options/index.html |  9 +++++
 2 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/main.c b/main.c
index 1c8dfe3..cfa2fd5 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;
@@ -8198,9 +8221,11 @@ onlineinput(uint8_t inputs)
}

static void
optionsinput(uint8_t inputs)
optionsinput(const uint8_t inputs[static 4][2])
{
	if (inputs & INPUT_MASK_DOWN) {
	uint8_t pressed = inputs[0][0] & ~inputs[1][0];

	if (pressed & INPUT_MASK_DOWN) {
		if ((state.options.page == 0 && state.options.pos == OPT_LAST)
				|| (state.options.page == state.options.userlen / 20 + 1
					&& state.options.pos >= state.options.userlen % 20 - 1)
@@ -8217,7 +8242,7 @@ optionsinput(uint8_t inputs)
			play_options_music();
		}
		play_sfx(SFX_LVLBLIP, 0);
	} else if (inputs & INPUT_MASK_UP) {
	} else if (pressed & INPUT_MASK_UP) {
		if (state.options.pos == 0) {
			uint8_t pos;
			if (state.options.page == 0) {
@@ -8241,16 +8266,16 @@ optionsinput(uint8_t inputs)
		}
		play_sfx(SFX_LVLBLIP, 0);
	}
	if (inputs & INPUT_MASK_LEFT) {
	if (pressed & INPUT_MASK_LEFT) {
		set_option(-1);
		play_sfx(SFX_MOVEBLIP, 0);
		play_options_music();
	} else if (inputs & INPUT_MASK_RIGHT) {
	} else if (pressed & INPUT_MASK_RIGHT) {
		set_option(1);
		play_sfx(SFX_MOVEBLIP, 0);
		play_options_music();
	}
	if (inputs & INPUT_MASK_FLIP_CW) {
	if (pressed & INPUT_MASK_FLIP_CW) {
		if (state.options.page == state.options.userlen / 20 + 1) {
			state.options.page = 0;
		} else if (state.options.userlen > 0) {
@@ -8259,7 +8284,7 @@ optionsinput(uint8_t inputs)
		draw_options_page();
		play_sfx(SFX_LVLBLIP, 0);
	}
	if (inputs & INPUT_MASK_FLIP_CCW) {
	if (pressed & INPUT_MASK_FLIP_CCW) {
		uint8_t pos = 0;
		if (state.options.page == 0) {
			if (state.options.userlen > 0) {
@@ -8275,7 +8300,15 @@ optionsinput(uint8_t inputs)
		optionsupdate();
		play_sfx(SFX_LVLBLIP, 0);
	}
	if (inputs & INPUT_MASK_START) {

	/* in the case that input delay is enabled and we ignore it when going
	 * out of the options (where input delay is not ignored) we will switch
	 * to the options screen again, since the main menu thinks we pressed
	 * start. to avoid this, let's not ignore the input delay here. */
	uint8_t delay = strcmp(options[OPT_INPUT_DELAY], "on") == 0 ? 2 : 0;
	uint8_t pressed_input_delay = inputs[delay][0] & ~inputs[delay + 1][0];

	if (pressed_input_delay & INPUT_MASK_START) {
		save_config();
		for (size_t i = 0; i < (size_t)OPT_LAST + 1; ++i)
			free(state.options.core[i].values);
@@ -8558,7 +8591,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 +8625,7 @@ handle_inputs(const uint8_t inputs[static 4][2])
		onlineinput(pressed);
		break;
	case OPTIONS:
		optionsinput(pressed);
		optionsinput(inputs);
		break;
	case INPUT:
		inputinput(pressed);
diff --git a/website/docs/options/index.html b/website/docs/options/index.html
index 0f6749b..82f1695 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 (except when exiting), 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
Thanks!

To gitsrht:~sebsite/generic-tetromino-game
   281df43..23610fb  main -> main