From 9ad7ad684d692572052b9c95788068e332411239 Mon Sep 17 00:00:00 2001 From: "Alejandro J. Cura" Date: Tue, 13 Oct 2026 18:56:32 -0300 Subject: [PATCH] Make arrows and numpad the player one keyboard controls in both emulators --- docs/guides/browser.md | 8 ++-- docs/guides/desktop.md | 8 ++-- docs/internals/input-protocol-v2.md | 8 ++-- docs/internals/web-emulator-architecture.md | 4 +- docs/legacy/sprites-api.md | 6 +-- docs/vs2/tutorial/first-game.md | 8 ++-- emulator/inputs_common.py | 4 +- emulator/pyglet1x/pygletdraw.py | 2 +- emulator/pyglet2x/keyboard_help.py | 2 +- tests/test_emulator_inputs_v2.py | 18 +++---- tests/test_pyglet_keyboard_help.py | 4 +- tests/test_web_input_v2.mjs | 12 ++--- web/README.md | 8 ++-- web/app-support.js | 40 ++++++++-------- web/index.html | 4 +- web/keyboard-layout.json | 52 ++++++++++----------- 16 files changed, 94 insertions(+), 94 deletions(-) diff --git a/docs/guides/browser.md b/docs/guides/browser.md index abdb4c1a..5ed7c19b 100644 --- a/docs/guides/browser.md +++ b/docs/guides/browser.md @@ -6,12 +6,12 @@ and touch controls. Pick a game from the launcher and press A to begin. | Control | Player 1 | Player 2 | |---|---|---| -| Up / Down / Left / Right | W / S / A / D | Arrow keys | -| A / B / C / D | Space / B / N / M | Numpad 0 / 1 / 2 / 3 | -| Select / Start | 1 / 2 | Numpad + / Enter | +| Up / Down / Left / Right | Arrow keys | W / S / A / D | +| A / B / C / D | Numpad 0 / 1 / 2 / 3 | Space / B / N / M | +| Select / Start | Numpad + / Enter | 1 / 2 | Press **F1** to see the keyboard layout. Select is `BACK` in the game API; -C and D are `X` and `Y`. Player 2 uses the numeric keypad, including its Enter +C and D are `X` and `Y`. Player 1 uses the numeric keypad, including its Enter key; the main Enter key is unassigned. The keypad works with Num Lock on or off. Either player can navigate the launcher with Up/Down and select with A. diff --git a/docs/guides/desktop.md b/docs/guides/desktop.md index 770a6b7f..f7e0828c 100644 --- a/docs/guides/desktop.md +++ b/docs/guides/desktop.md @@ -79,12 +79,12 @@ is in **Tech Demos**. ROM generation happens automatically when sources change. | Control | Player 1 | Player 2 | |---|---|---| -| Up / Down / Left / Right | W / S / A / D | Arrow keys | -| A / B / C / D | Space / B / N / M | Numpad 0 / 1 / 2 / 3 | -| Select / Start | 1 / 2 | Numpad + / Enter | +| Up / Down / Left / Right | Arrow keys | W / S / A / D | +| A / B / C / D | Numpad 0 / 1 / 2 / 3 | Space / B / N / M | +| Select / Start | Numpad + / Enter | 1 / 2 | Press **F1** to see the keyboard layout. Select is `BACK` in the game API; -C and D are `X` and `Y`. Player 2 uses the numeric keypad, including its Enter +C and D are `X` and `Y`. Player 1 uses the numeric keypad, including its Enter key; the main Enter key is unassigned. The keypad works with Num Lock on or off. Either player can navigate the launcher with Up/Down and select with A. diff --git a/docs/internals/input-protocol-v2.md b/docs/internals/input-protocol-v2.md index 5a3e214b..66205e70 100644 --- a/docs/internals/input-protocol-v2.md +++ b/docs/internals/input-protocol-v2.md @@ -112,12 +112,12 @@ be held together, just like controller controls. | Control | Player 1 | Player 2 | |---|---|---| -| Up / Down / Left / Right | W / S / A / D | Arrow keys | -| A / B / C / D | Space / B / N / M | Numpad 0 / 1 / 2 / 3 | -| Select / Start | 1 / 2 | Numpad + / Enter | +| Up / Down / Left / Right | Arrow keys | W / S / A / D | +| A / B / C / D | Numpad 0 / 1 / 2 / 3 | Space / B / N / M | +| Select / Start | Numpad + / Enter | 1 / 2 | Press **F1** to see the keyboard layout. Select is `BACK` in the game API; -C and D are `X` and `Y`. Player 2 uses the numeric keypad, including its Enter +C and D are `X` and `Y`. Player 1 uses the numeric keypad, including its Enter key; the main Enter key is unassigned. The keypad works with Num Lock on or off. Escape returns to the launcher, or closes an open overlay. The shared diagram diff --git a/docs/internals/web-emulator-architecture.md b/docs/internals/web-emulator-architecture.md index 9afadcbf..6ff0277f 100644 --- a/docs/internals/web-emulator-architecture.md +++ b/docs/internals/web-emulator-architecture.md @@ -120,8 +120,8 @@ and `extra`. The WASM worker stores those fields as primitive values exposed through `__vs_host`; `BrowserComms` reads them without allocating per-frame input objects. -Keyboard input uses the same allocation as the desktop emulator: WASD, -Space/B/N/M and 1/2 for Player 1; arrows, numpad 0/1/2/3 and numpad +/Enter +Keyboard input uses the same allocation as the desktop emulator: arrows, +numpad 0/1/2/3 and numpad +/Enter for Player 1; WASD, Space/B/N/M and 1/2 for Player 2. The full table lives in `input-protocol-v2.md`. F1 or the Keyboard button opens a modal diagram from `keyboard-layout.json`. Mapped keys light up in help without reaching the game; keys held while help diff --git a/docs/legacy/sprites-api.md b/docs/legacy/sprites-api.md index c94d6db6..61933c7a 100644 --- a/docs/legacy/sprites-api.md +++ b/docs/legacy/sprites-api.md @@ -45,9 +45,9 @@ the emulator starts. ### Running `./vs-emu.sh` (or `vs-emu.bat`) regenerates ROMs and starts the desktop -emulator. W/A/S/D move Joy1; Space/B/N/M are Joy1 A/B/X/Y; -1/2 are Back/Start. Arrows plus numpad 0/1/2/3 provide Joy2, -and numpad +/Enter are Joy2 Back/Start. F1 shows a keyboard diagram. +emulator. Arrows plus numpad 0/1/2/3 provide Joy1, +and numpad +/Enter are Joy1 Back/Start. W/A/S/D move Joy2; +Space/B/N/M are Joy2 A/B/X/Y; 1/2 are Joy2 Back/Start. F1 shows a keyboard diagram. A USB gamepad works too. To start one game straight away instead of walking the menu, name it: diff --git a/docs/vs2/tutorial/first-game.md b/docs/vs2/tutorial/first-game.md index 4fe0432b..6a1c3273 100644 --- a/docs/vs2/tutorial/first-game.md +++ b/docs/vs2/tutorial/first-game.md @@ -164,12 +164,12 @@ desktop emulator the keyboard stands in for them: | Control | Player 1 | Player 2 | |---|---|---| -| Up / Down / Left / Right | W / S / A / D | Arrow keys | -| A / B / C / D | Space / B / N / M | Numpad 0 / 1 / 2 / 3 | -| Select / Start | 1 / 2 | Numpad + / Enter | +| Up / Down / Left / Right | Arrow keys | W / S / A / D | +| A / B / C / D | Numpad 0 / 1 / 2 / 3 | Space / B / N / M | +| Select / Start | Numpad + / Enter | 1 / 2 | Press **F1** to see the keyboard layout. Select is `BACK` in the game API; -C and D are `X` and `Y`. Player 2 uses the numeric keypad, including its Enter +C and D are `X` and `Y`. Player 1 uses the numeric keypad, including its Enter key; the main Enter key is unassigned. The keypad works with Num Lock on or off. A USB gamepad works too. `joy2` is the second controller. Chapter 6 explains diff --git a/emulator/inputs_common.py b/emulator/inputs_common.py index 9a9b74c7..d8d49856 100644 --- a/emulator/inputs_common.py +++ b/emulator/inputs_common.py @@ -74,8 +74,8 @@ def pack_input(left, right, up, down, boton, accel, decel, reset): def keyboard_v2_state(keys): """Return (joy2, extra) for keyboard-only Input Protocol v2 controls. - Joy1 uses WASD and Space/B/N/M with 1/2 for Select/Start. Joy2 uses - arrows and numpad 0/1/2/3 with numpad +/Enter for Select/Start. + Joy1 uses arrows and numpad 0/1/2/3 with numpad +/Enter for + Select/Start. Joy2 uses WASD and Space/B/N/M with 1/2 for Select/Start. """ return _keyboard_channel(keys, "joy2"), _keyboard_channel(keys, "extra") diff --git a/emulator/pyglet1x/pygletdraw.py b/emulator/pyglet1x/pygletdraw.py index e205e8cb..897883b8 100644 --- a/emulator/pyglet1x/pygletdraw.py +++ b/emulator/pyglet1x/pygletdraw.py @@ -16,7 +16,7 @@ window.set_icon(logo) window.set_caption("Ventilastation Emulator") fps_display = pyglet.window.FPSDisplay(window) -help_label = pyglet.text.Label("P1 WASD Space/B/N/M 1/2 · P2 arrows numpad 0/1/2/3 +/Enter · Esc Q", font_name="Arial", font_size=12, y=5, x=window.width-5, color=(128, 128, 128, 255), anchor_x="right") +help_label = pyglet.text.Label("P1 arrows numpad 0/1/2/3 +/Enter · P2 WASD Space/B/N/M 1/2 · Esc Q", font_name="Arial", font_size=12, y=5, x=window.width-5, color=(128, 128, 128, 255), anchor_x="right") LED_SIZE = min(window.width, window.height) / 2 vertex_list = None diff --git a/emulator/pyglet2x/keyboard_help.py b/emulator/pyglet2x/keyboard_help.py index 1b7bfd88..7019c4e5 100644 --- a/emulator/pyglet2x/keyboard_help.py +++ b/emulator/pyglet2x/keyboard_help.py @@ -24,7 +24,7 @@ def __init__(self): self.titles = [pyglet.text.Label("Player %d · %s" % (player, description), font_name="Arial", weight="bold", anchor_y="top", batch=self.batch, group=text) - for player, description in [(1, "letter keys"), (2, "arrows + numpad")]] + for player, description in [(1, "arrows + numpad"), (2, "letter keys")]] self.footer = pyglet.text.Label( "Try keys here: they light up without controlling the game.\n" "F1 help · F4 settings · F2 CPU/GPU · F3 compare · F5 hall filter\n" diff --git a/tests/test_emulator_inputs_v2.py b/tests/test_emulator_inputs_v2.py index ee3bcd19..1ba0b1d8 100644 --- a/tests/test_emulator_inputs_v2.py +++ b/tests/test_emulator_inputs_v2.py @@ -108,14 +108,14 @@ def test_two_controllers_give_joy2_its_own_dpad_and_faces(): def test_keyboard_maps_all_protocol_v2_controls(): expected = { - "W": (4, 0, 0), "S": (8, 0, 0), "A": (1, 0, 0), "D": (2, 0, 0), - "SPACE": (16, 0, 0), "B": (32, 0, 0), "N": (64, 0, 0), "M": (0, 0, 1), - "_1": (0, 0, 8), "_2": (0, 0, 4), - "UP": (0, 4, 0), "DOWN": (0, 8, 0), "LEFT": (0, 1, 0), "RIGHT": (0, 2, 0), - "NUM_0": (0, 16, 0), "NUM_1": (0, 32, 0), "NUM_2": (0, 64, 0), "NUM_3": (0, 0, 2), - "NUM_ADD": (0, 0, 32), "NUM_ENTER": (0, 0, 16), - "NUM_INSERT": (0, 16, 0), "NUM_END": (0, 32, 0), - "NUM_DOWN": (0, 64, 0), "NUM_NEXT": (0, 0, 2), + "W": (0, 4, 0), "S": (0, 8, 0), "A": (0, 1, 0), "D": (0, 2, 0), + "SPACE": (0, 16, 0), "B": (0, 32, 0), "N": (0, 64, 0), "M": (0, 0, 2), + "_1": (0, 0, 32), "_2": (0, 0, 16), + "UP": (4, 0, 0), "DOWN": (8, 0, 0), "LEFT": (1, 0, 0), "RIGHT": (2, 0, 0), + "NUM_0": (16, 0, 0), "NUM_1": (32, 0, 0), "NUM_2": (64, 0, 0), "NUM_3": (0, 0, 1), + "NUM_ADD": (0, 0, 8), "NUM_ENTER": (0, 0, 4), + "NUM_INSERT": (16, 0, 0), "NUM_END": (32, 0, 0), + "NUM_DOWN": (64, 0, 0), "NUM_NEXT": (0, 0, 1), } class Keys: pressed = set() @@ -145,7 +145,7 @@ def __getitem__(self, symbol): gate.read(keys, False) keys.pressed = {"SPACE", "NUM_ADD"} keyboard, v2 = gate.read(keys, False) - assert pack_controllers(None, keyboard=keyboard, keyboard_v2=v2)[:3] == (16, 0, 32) + assert pack_controllers(None, keyboard=keyboard, keyboard_v2=v2)[:3] == (0, 16, 8) def test_ota_shortcut_requires_ctrl_or_command(): diff --git a/tests/test_pyglet_keyboard_help.py b/tests/test_pyglet_keyboard_help.py index 31d23e29..899004d3 100644 --- a/tests/test_pyglet_keyboard_help.py +++ b/tests/test_pyglet_keyboard_help.py @@ -67,8 +67,8 @@ def toggle(): inputs.keys[key.SPACE] = False inputs.encode_input_val() inputs.keys[key.SPACE] = True -assert inputs.encode_input_val() == (16, 0, 0, False) +assert inputs.encode_input_val() == (0, 16, 0, False) inputs.keys[key.ESCAPE] = True inputs.on_key_press(key.ESCAPE, 0) -assert inputs.encode_input_val() == (16, 0, 0, True) +assert inputs.encode_input_val() == (0, 16, 0, True) print('Native help previews keys, quarantines held input and consumes closing Escape/autorepeat') diff --git a/tests/test_web_input_v2.mjs b/tests/test_web_input_v2.mjs index 00384165..d72cd2c6 100644 --- a/tests/test_web_input_v2.mjs +++ b/tests/test_web_input_v2.mjs @@ -67,12 +67,12 @@ function testInvertedYAxis() { function testKeyboardMapsAllProtocolV2Controls() { const expected = { - KeyW: [4, 0, 0], KeyS: [8, 0, 0], KeyA: [1, 0, 0], KeyD: [2, 0, 0], - Space: [16, 0, 0], KeyB: [32, 0, 0], KeyN: [64, 0, 0], KeyM: [0, 0, 1], - Digit1: [0, 0, 8], Digit2: [0, 0, 4], - ArrowUp: [0, 4, 0], ArrowDown: [0, 8, 0], ArrowLeft: [0, 1, 0], ArrowRight: [0, 2, 0], - Numpad0: [0, 16, 0], Numpad1: [0, 32, 0], Numpad2: [0, 64, 0], Numpad3: [0, 0, 2], - NumpadAdd: [0, 0, 32], NumpadEnter: [0, 0, 16], + KeyW: [0, 4, 0], KeyS: [0, 8, 0], KeyA: [0, 1, 0], KeyD: [0, 2, 0], + Space: [0, 16, 0], KeyB: [0, 32, 0], KeyN: [0, 64, 0], KeyM: [0, 0, 2], + Digit1: [0, 0, 32], Digit2: [0, 0, 16], + ArrowUp: [4, 0, 0], ArrowDown: [8, 0, 0], ArrowLeft: [1, 0, 0], ArrowRight: [2, 0, 0], + Numpad0: [16, 0, 0], Numpad1: [32, 0, 0], Numpad2: [64, 0, 0], Numpad3: [0, 0, 1], + NumpadAdd: [0, 0, 8], NumpadEnter: [0, 0, 4], }; for (const [code, wanted] of Object.entries(expected)) { const input = keyboardInputForCodes([code]); diff --git a/web/README.md b/web/README.md index ab8d8e5c..e4ba7c50 100644 --- a/web/README.md +++ b/web/README.md @@ -25,12 +25,12 @@ remain available. | Control | Player 1 | Player 2 | |---|---|---| -| Up / Down / Left / Right | W / S / A / D | Arrow keys | -| A / B / C / D | Space / B / N / M | Numpad 0 / 1 / 2 / 3 | -| Select / Start | 1 / 2 | Numpad + / Enter | +| Up / Down / Left / Right | Arrow keys | W / S / A / D | +| A / B / C / D | Numpad 0 / 1 / 2 / 3 | Space / B / N / M | +| Select / Start | Numpad + / Enter | 1 / 2 | Press **F1** to see the keyboard layout. Select is `BACK` in the game API; -C and D are `X` and `Y`. Player 2 uses the numeric keypad, including its Enter +C and D are `X` and `Y`. Player 1 uses the numeric keypad, including its Enter key; the main Enter key is unassigned. The keypad works with Num Lock on or off. The Keyboard button or F1 opens a modal diagram with keys placed as on a diff --git a/web/app-support.js b/web/app-support.js index cf73de92..28fa39aa 100644 --- a/web/app-support.js +++ b/web/app-support.js @@ -26,26 +26,26 @@ const INPUT_EXTRA = Object.freeze({ // Keyboard controls deliberately match the desktop emulator. A key entry // can target either joystick byte or the protocol-v2 extra byte. const KEY_TO_INPUT = new Map([ - ["KeyA", { joy1: BUTTONS.JOY_LEFT }], - ["KeyD", { joy1: BUTTONS.JOY_RIGHT }], - ["KeyW", { joy1: BUTTONS.JOY_UP }], - ["KeyS", { joy1: BUTTONS.JOY_DOWN }], - ["Space", { joy1: BUTTONS.BUTTON_A }], - ["KeyB", { joy1: BUTTONS.BUTTON_B }], - ["KeyN", { joy1: BUTTONS.BUTTON_C }], - ["KeyM", { extra: INPUT_EXTRA.JOY1_Y }], - ["Digit1", { extra: INPUT_EXTRA.JOY1_BACK }], - ["Digit2", { extra: INPUT_EXTRA.JOY1_START }], - ["ArrowLeft", { joy2: BUTTONS.JOY_LEFT }], - ["ArrowRight", { joy2: BUTTONS.JOY_RIGHT }], - ["ArrowUp", { joy2: BUTTONS.JOY_UP }], - ["ArrowDown", { joy2: BUTTONS.JOY_DOWN }], - ["Numpad0", { joy2: BUTTONS.BUTTON_A }], - ["Numpad1", { joy2: BUTTONS.BUTTON_B }], - ["Numpad2", { joy2: BUTTONS.BUTTON_C }], - ["Numpad3", { extra: INPUT_EXTRA.JOY2_Y }], - ["NumpadAdd", { extra: INPUT_EXTRA.JOY2_BACK }], - ["NumpadEnter", { extra: INPUT_EXTRA.JOY2_START }], + ["KeyA", { joy2: BUTTONS.JOY_LEFT }], + ["KeyD", { joy2: BUTTONS.JOY_RIGHT }], + ["KeyW", { joy2: BUTTONS.JOY_UP }], + ["KeyS", { joy2: BUTTONS.JOY_DOWN }], + ["Space", { joy2: BUTTONS.BUTTON_A }], + ["KeyB", { joy2: BUTTONS.BUTTON_B }], + ["KeyN", { joy2: BUTTONS.BUTTON_C }], + ["KeyM", { extra: INPUT_EXTRA.JOY2_Y }], + ["Digit1", { extra: INPUT_EXTRA.JOY2_BACK }], + ["Digit2", { extra: INPUT_EXTRA.JOY2_START }], + ["ArrowLeft", { joy1: BUTTONS.JOY_LEFT }], + ["ArrowRight", { joy1: BUTTONS.JOY_RIGHT }], + ["ArrowUp", { joy1: BUTTONS.JOY_UP }], + ["ArrowDown", { joy1: BUTTONS.JOY_DOWN }], + ["Numpad0", { joy1: BUTTONS.BUTTON_A }], + ["Numpad1", { joy1: BUTTONS.BUTTON_B }], + ["Numpad2", { joy1: BUTTONS.BUTTON_C }], + ["Numpad3", { extra: INPUT_EXTRA.JOY1_Y }], + ["NumpadAdd", { extra: INPUT_EXTRA.JOY1_BACK }], + ["NumpadEnter", { extra: INPUT_EXTRA.JOY1_START }], ]); // Retained for consumers that only use the original Joy1 byte. diff --git a/web/index.html b/web/index.html index ae8ad688..54547e9f 100644 --- a/web/index.html +++ b/web/index.html @@ -245,8 +245,8 @@

Copy Diagnostics

Loading keyboard layout…

-

Player 1 Letter keys

-

Player 2 Arrows + numpad

+

Player 1 Arrows + numpad

+

Player 2 Letter keys