Add keyboard opcodes (#295)

This commit is contained in:
Alexander Batalov 2023-06-01 19:01:03 +03:00 committed by GitHub
parent bf639a2c4a
commit 37e4822ed5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 320 additions and 4 deletions

View File

@ -271,6 +271,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/sfall_global_scripts.h" "src/sfall_global_scripts.h"
"src/sfall_ini.cc" "src/sfall_ini.cc"
"src/sfall_ini.h" "src/sfall_ini.h"
"src/sfall_kb_helpers.cc"
"src/sfall_kb_helpers.h"
"src/sfall_lists.cc" "src/sfall_lists.cc"
"src/sfall_lists.h" "src/sfall_lists.h"
"src/sfall_opcodes.cc" "src/sfall_opcodes.cc"

297
src/sfall_kb_helpers.cc Normal file
View File

@ -0,0 +1,297 @@
#include "sfall_kb_helpers.h"
#include <SDL.h>
/// Maps DirectInput DIK constants to SDL scancodes.
static constexpr SDL_Scancode kDiks[256] = {
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_ESCAPE, // DIK_ESCAPE
SDL_SCANCODE_1, // DIK_1
SDL_SCANCODE_2, // DIK_2
SDL_SCANCODE_3, // DIK_3
SDL_SCANCODE_4, // DIK_4
SDL_SCANCODE_5, // DIK_5
SDL_SCANCODE_6, // DIK_6
SDL_SCANCODE_7, // DIK_7
SDL_SCANCODE_8, // DIK_8
SDL_SCANCODE_9, // DIK_9
SDL_SCANCODE_0, // DIK_0
SDL_SCANCODE_MINUS, // DIK_MINUS
SDL_SCANCODE_EQUALS, // DIK_EQUALS
SDL_SCANCODE_BACKSPACE, // DIK_BACK
SDL_SCANCODE_TAB, // DIK_TAB
SDL_SCANCODE_Q, // DIK_Q
SDL_SCANCODE_W, // DIK_W
SDL_SCANCODE_E, // DIK_E
SDL_SCANCODE_R, // DIK_R
SDL_SCANCODE_T, // DIK_T
SDL_SCANCODE_Y, // DIK_Y
SDL_SCANCODE_U, // DIK_U
SDL_SCANCODE_I, // DIK_I
SDL_SCANCODE_O, // DIK_O
SDL_SCANCODE_P, // DIK_P
SDL_SCANCODE_LEFTBRACKET, // DIK_LBRACKET
SDL_SCANCODE_RIGHTBRACKET, // DIK_RBRACKET
SDL_SCANCODE_RETURN, // DIK_RETURN
SDL_SCANCODE_LCTRL, // DIK_LCONTROL
SDL_SCANCODE_A, // DIK_A
SDL_SCANCODE_S, // DIK_S
SDL_SCANCODE_D, // DIK_D
SDL_SCANCODE_F, // DIK_F
SDL_SCANCODE_G, // DIK_G
SDL_SCANCODE_H, // DIK_H
SDL_SCANCODE_J, // DIK_J
SDL_SCANCODE_K, // DIK_K
SDL_SCANCODE_L, // DIK_L
SDL_SCANCODE_SEMICOLON, // DIK_SEMICOLON
SDL_SCANCODE_APOSTROPHE, // DIK_APOSTROPHE
SDL_SCANCODE_GRAVE, // DIK_GRAVE
SDL_SCANCODE_LSHIFT, // DIK_LSHIFT
SDL_SCANCODE_BACKSLASH, // DIK_BACKSLASH
SDL_SCANCODE_Z, // DIK_Z
SDL_SCANCODE_X, // DIK_X
SDL_SCANCODE_C, // DIK_C
SDL_SCANCODE_V, // DIK_V
SDL_SCANCODE_B, // DIK_B
SDL_SCANCODE_N, // DIK_N
SDL_SCANCODE_M, // DIK_M
SDL_SCANCODE_COMMA, // DIK_COMMA
SDL_SCANCODE_PERIOD, // DIK_PERIOD
SDL_SCANCODE_SLASH, // DIK_SLASH
SDL_SCANCODE_RSHIFT, // DIK_RSHIFT
SDL_SCANCODE_KP_MULTIPLY, // DIK_MULTIPLY
SDL_SCANCODE_LALT, // DIK_LMENU
SDL_SCANCODE_SPACE, // DIK_SPACE
SDL_SCANCODE_CAPSLOCK, // DIK_CAPITAL
SDL_SCANCODE_F1, // DIK_F1
SDL_SCANCODE_F2, // DIK_F2
SDL_SCANCODE_F3, // DIK_F3
SDL_SCANCODE_F4, // DIK_F4
SDL_SCANCODE_F5, // DIK_F5
SDL_SCANCODE_F6, // DIK_F6
SDL_SCANCODE_F7, // DIK_F7
SDL_SCANCODE_F8, // DIK_F8
SDL_SCANCODE_F9, // DIK_F9
SDL_SCANCODE_F10, // DIK_F10
SDL_SCANCODE_NUMLOCKCLEAR, // DIK_NUMLOCK
SDL_SCANCODE_SCROLLLOCK, // DIK_SCROLL
SDL_SCANCODE_KP_7, // DIK_NUMPAD7
SDL_SCANCODE_KP_8, // DIK_NUMPAD8
SDL_SCANCODE_KP_9, // DIK_NUMPAD9
SDL_SCANCODE_KP_MINUS, // DIK_SUBTRACT
SDL_SCANCODE_KP_4, // DIK_NUMPAD4
SDL_SCANCODE_KP_5, // DIK_NUMPAD5
SDL_SCANCODE_KP_6, // DIK_NUMPAD6
SDL_SCANCODE_KP_PLUS, // DIK_ADD
SDL_SCANCODE_KP_1, // DIK_NUMPAD1
SDL_SCANCODE_KP_2, // DIK_NUMPAD2
SDL_SCANCODE_KP_3, // DIK_NUMPAD3
SDL_SCANCODE_KP_0, // DIK_NUMPAD0
SDL_SCANCODE_KP_PERIOD, // DIK_DECIMAL
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_F11, // DIK_F11
SDL_SCANCODE_F12, // DIK_F12
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_KP_EQUALS, // DIK_NUMPADEQUALS
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, // DIK_AT
SDL_SCANCODE_UNKNOWN, // DIK_COLON
SDL_SCANCODE_UNKNOWN, // DIK_UNDERLINE
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, // DIK_STOP
SDL_SCANCODE_UNKNOWN, // DIK_AX
SDL_SCANCODE_UNKNOWN, // DIK_UNLABELED
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_KP_ENTER, // DIK_NUMPADENTER
SDL_SCANCODE_RCTRL, // DIK_RCONTROL
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_KP_COMMA, // DIK_NUMPADCOMMA
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_SLASH, // DIK_DIVIDE
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_SYSREQ, // DIK_SYSRQ
SDL_SCANCODE_RALT, // DIK_RMENU
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_HOME, // DIK_HOME
SDL_SCANCODE_UP, // DIK_UP
SDL_SCANCODE_PAGEUP, // DIK_PRIOR
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_LEFT, // DIK_LEFT
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_RIGHT, // DIK_RIGHT
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_END, // DIK_END
SDL_SCANCODE_DOWN, // DIK_DOWN
SDL_SCANCODE_PAGEDOWN, // DIK_NEXT
SDL_SCANCODE_INSERT, // DIK_INSERT
SDL_SCANCODE_DELETE, // DIK_DELETE
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_LGUI, // DIK_LWIN
SDL_SCANCODE_RGUI, // DIK_RWIN
SDL_SCANCODE_APPLICATION, // DIK_APPS
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN,
};
/// Translates Sfall key code (DIK or VK constant) to SDL scancode.
static SDL_Scancode get_scancode_from_key(int key)
{
return kDiks[key & 0xFF];
}
bool sfall_kb_is_key_pressed(int key)
{
SDL_Scancode scancode = get_scancode_from_key(key);
if (scancode == SDL_SCANCODE_UNKNOWN) {
return false;
}
const Uint8* state = SDL_GetKeyboardState(nullptr);
return state[scancode] != 0;
}
void sfall_kb_press_key(int key)
{
SDL_Scancode scancode = get_scancode_from_key(key);
if (scancode == SDL_SCANCODE_UNKNOWN) {
return;
}
SDL_Event event;
event.key.keysym.scancode = scancode;
event.type = SDL_KEYDOWN;
SDL_PushEvent(&event);
event.type = SDL_KEYUP;
SDL_PushEvent(&event);
}

10
src/sfall_kb_helpers.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef FALLOUT_SFALL_KB_HELPERS_H_
#define FALLOUT_SFALL_KB_HELPERS_H_
/// Returns `true` if given key is pressed.
bool sfall_kb_is_key_pressed(int key);
/// Simulates pressing `key`.
void sfall_kb_press_key(int key);
#endif /* FALLOUT_SFALL_KB_HELPERS_H_ */

View File

@ -24,6 +24,7 @@
#include "sfall_global_scripts.h" #include "sfall_global_scripts.h"
#include "sfall_global_vars.h" #include "sfall_global_vars.h"
#include "sfall_ini.h" #include "sfall_ini.h"
#include "sfall_kb_helpers.h"
#include "sfall_lists.h" #include "sfall_lists.h"
#include "stat.h" #include "stat.h"
#include "svga.h" #include "svga.h"
@ -94,6 +95,13 @@ static void opGetPcBonusStat(Program* program)
programStackPushInteger(program, value); programStackPushInteger(program, value);
} }
// tap_key
static void op_tap_key(Program* program)
{
int key = programStackPopInteger(program);
sfall_kb_press_key(key);
}
// get_year // get_year
static void op_get_year(Program* program) static void op_get_year(Program* program)
{ {
@ -120,10 +128,8 @@ static void op_set_global_script_repeat(Program* program)
static void op_key_pressed(Program* program) static void op_key_pressed(Program* program)
{ {
int key = programStackPopInteger(program); int key = programStackPopInteger(program);
bool pressed = sfall_kb_is_key_pressed(key);
// TODO: Incomplete. programStackPushInteger(program, pressed ? 1 : 0);
programStackPushInteger(program, 0);
} }
// in_world_map // in_world_map
@ -882,6 +888,7 @@ void sfallOpcodesInit()
interpreterRegisterOpcode(0x815B, opSetPcBonusStat); interpreterRegisterOpcode(0x815B, opSetPcBonusStat);
interpreterRegisterOpcode(0x815C, op_get_pc_base_stat); interpreterRegisterOpcode(0x815C, op_get_pc_base_stat);
interpreterRegisterOpcode(0x815D, opGetPcBonusStat); interpreterRegisterOpcode(0x815D, opGetPcBonusStat);
interpreterRegisterOpcode(0x8162, op_tap_key);
interpreterRegisterOpcode(0x8163, op_get_year); interpreterRegisterOpcode(0x8163, op_get_year);
interpreterRegisterOpcode(0x8164, op_game_loaded); interpreterRegisterOpcode(0x8164, op_game_loaded);
interpreterRegisterOpcode(0x816A, op_set_global_script_repeat); interpreterRegisterOpcode(0x816A, op_set_global_script_repeat);