Improved, parallel controls with KEYSC driver

This change adds proper key control by querying the KEYSC directly
instead of using PRGM_GetKey(). This allows for the very distinctive
advantage of pressing multiples keys at once.

Controls are still quite hard to use, I'll think of an alternative
keymap.
This commit is contained in:
Lephenixnoir 2021-07-29 20:43:44 +02:00
parent cf6c10ed29
commit e14149c646
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
1 changed files with 160 additions and 56 deletions

View File

@ -196,65 +196,169 @@ static void R_SetViewSizeChange(int iDiff)
}
}
///////////////////////////////////////////////////////////////////////////////
// Keyboard input
//
// Instead of using libfxcg functions which only provide single-key analysis
// (GetKey, GetKeyWait, and PRGM_GetKey mainly), the following code uses a
// simple KEYSC driver. This is indirectly taken from gint code.
///////////////////////////////////////////////////////////////////////////////
/* Keyboard matrix codes */
#define KEYCODE_F1 0x91
#define KEYCODE_F2 0x92
#define KEYCODE_F3 0x93
#define KEYCODE_F4 0x94
#define KEYCODE_F5 0x95
#define KEYCODE_F6 0x96
#define KEYCODE_SHIFT 0x81
#define KEYCODE_OPTN 0x82
#define KEYCODE_VARS 0x83
#define KEYCODE_MENU 0x84
#define KEYCODE_LEFT 0x85
#define KEYCODE_UP 0x86
#define KEYCODE_ALPHA 0x71
#define KEYCODE_SQUARE 0x72
#define KEYCODE_POWER 0x73
#define KEYCODE_EXIT 0x74
#define KEYCODE_DOWN 0x75
#define KEYCODE_RIGHT 0x76
#define KEYCODE_XOT 0x61
#define KEYCODE_LOG 0x62
#define KEYCODE_LN 0x63
#define KEYCODE_SIN 0x64
#define KEYCODE_COS 0x65
#define KEYCODE_TAN 0x66
#define KEYCODE_FRAC 0x51
#define KEYCODE_FD 0x52
#define KEYCODE_LEFTP 0x53
#define KEYCODE_RIGHTP 0x54
#define KEYCODE_COMMA 0x55
#define KEYCODE_ARROW 0x56
#define KEYCODE_7 0x41
#define KEYCODE_8 0x42
#define KEYCODE_9 0x43
#define KEYCODE_DEL 0x44
#define KEYCODE_4 0x31
#define KEYCODE_5 0x32
#define KEYCODE_6 0x33
#define KEYCODE_MUL 0x34
#define KEYCODE_DIV 0x35
#define KEYCODE_1 0x21
#define KEYCODE_2 0x22
#define KEYCODE_3 0x23
#define KEYCODE_PLUS 0x24
#define KEYCODE_MINUS 0x25
#define KEYCODE_0 0x11
#define KEYCODE_DOT 0x12
#define KEYCODE_EXP 0x13
#define KEYCODE_NEG 0x14
#define KEYCODE_EXE 0x15
#define KEYCODE_ACON 0x07
/* Copy of the keyboard state, one byte per row */
typedef uint8_t KeyboardState[12] __attribute__((aligned(2)));
void ScanKeyboard(KeyboardState state)
{
volatile uint16_t *KEYSC = (void *)0xa44b0000;
uint16_t *array = (void *)state;
for(int i = 0; i < 6; i++) array[i] = KEYSC[i];
}
int KeycodeDown(KeyboardState state, int code)
{
int row = (code >> 4) ^ 1;
int col = 0x80 >> (code & 0x7);
return (state[row] & col) != 0;
}
int KeycodePressed(KeyboardState old_state, KeyboardState new_state, int code)
{
return !KeycodeDown(old_state, code) && KeycodeDown(new_state, code);
}
int KeycodeToDoomKey(int code)
{
switch(code)
{
case KEYCODE_LEFT: return KEY_LEFTARROW;
case KEYCODE_RIGHT: return KEY_RIGHTARROW;
case KEYCODE_UP: return KEY_UPARROW;
case KEYCODE_DOWN: return KEY_DOWNARROW;
case KEYCODE_EXE: return ' ';
case KEYCODE_ALPHA: return KEY_RCTRL;
case KEYCODE_F1: return '1';
case KEYCODE_F2: return '2';
case KEYCODE_F3: return '3';
case KEYCODE_F4: return '4';
case KEYCODE_F5: return '5';
case KEYCODE_F6: return '6';
case KEYCODE_SHIFT: return '7';
case KEYCODE_EXIT: return KEY_TAB;
case KEYCODE_OPTN: return KEY_PAUSE;
case KEYCODE_0: return KEY_SLEFTARROW;
case KEYCODE_DOT: return KEY_SRIGHTARROW;
default: return -1;
}
}
void I_StartTic (void)
{
static event_t event = {(evtype_t)0,0,0,0};
static int iOldKey = 0;
int iKey = PRGM_GetKey();
int iFilter = 1;
switch(iKey)
{
case KEY_PRGM_POWER:CGCheat();break;
case 32:R_SetViewSizeChange(-1);break;
case 42:R_SetViewSizeChange(1);break;
case 25:CGSwitchClip();break;
case 65:CGFreeMem();break;
case 58:CGRefreshSwitch();break;
break;
static KeyboardState st = { 0 };
default:iFilter = 0;
}
if(iFilter)
KeyboardState next_st;
ScanKeyboard(next_st);
/* Capture events for special keys */
if (KeycodePressed(st, next_st, KEYCODE_MENU))
I_Quit();
if (KeycodePressed(st, next_st, KEYCODE_POWER))
CGCheat();
if (KeycodePressed(st, next_st, KEYCODE_MINUS))
R_SetViewSizeChange(-1);
if (KeycodePressed(st, next_st, KEYCODE_PLUS))
R_SetViewSizeChange(1);
if (KeycodePressed(st, next_st, KEYCODE_ARROW))
CGSwitchClip();
if (KeycodePressed(st, next_st, KEYCODE_FD))
CGFreeMem();
if (KeycodePressed(st, next_st, KEYCODE_VARS))
CGRefreshSwitch();
/* Emit events for all changes between st and next_st */
for (int row = 0; row < 12; row++)
{
while(PRGM_GetKey());
return;
int changed = next_st[row] ^ st[row];
if (!changed)
continue;
for(int code = ((row ^ 1) << 4) | 0x7; code & 0x7; code--)
{
if(changed & 1)
{
int key = KeycodeToDoomKey(code);
if (key < 0)
continue;
event_t e;
e.type = KeycodeDown(next_st, code) ? ev_keydown : ev_keyup;
e.data1 = key;
D_PostEvent(&e);
}
changed >>= 1;
}
}
if(iKey == iOldKey)
{
return;
}
if(iOldKey)
{
event.type= ev_keyup;
D_PostEvent(&event);
}
iOldKey = iKey;
if(!iKey)
{
return;
}
event.type= ev_keydown;
switch(iKey)
{
case KEY_PRGM_LEFT:event.data1 = KEY_LEFTARROW;break;
case KEY_PRGM_RIGHT:event.data1 = KEY_RIGHTARROW;break;
case KEY_PRGM_UP:event.data1 = KEY_UPARROW;break;
case KEY_PRGM_DOWN:event.data1 = KEY_DOWNARROW;break;
case KEY_PRGM_RETURN:event.data1 = ' ';break;
case KEY_PRGM_ALPHA:event.data1 = KEY_RCTRL;break;
case KEY_PRGM_MENU:I_Quit();break;
case KEY_PRGM_F1:event.data1 = '1';break;
case KEY_PRGM_F2:event.data1 = '2';break;
case KEY_PRGM_F3:event.data1 = '3';break;
case KEY_PRGM_F4:event.data1 = '4';break;
case KEY_PRGM_F5:event.data1 = '5';break;
case KEY_PRGM_F6:event.data1 = '6';break;
case KEY_PRGM_SHIFT:event.data1 = '7';break;
case KEY_PRGM_EXIT:event.data1 = KEY_TAB;break;
case KEY_PRGM_OPTN:event.data1 = KEY_PAUSE;break;
case 61:event.data1 = KEY_SRIGHTARROW;break;
case 71:event.data1 = KEY_SLEFTARROW;break;
default:return;
}
D_PostEvent(&event);
memcpy(st, next_st, sizeof st);
}