-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathkeyboard.js
More file actions
130 lines (115 loc) · 3.75 KB
/
keyboard.js
File metadata and controls
130 lines (115 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//
// apple2e keyboard emulation
//
// Copyright 2018-2026, John Clark
//
// Released under the GNU General Public License
// https://www.gnu.org/licenses/gpl.html
//
// ref: https://en.wikipedia.org/wiki/Apple_II_character_set
//
export class Keyboard
{
constructor() {
this._key = 0x7f;
this._key_pressed = false;
this._caps_lock_ever_pressed = false; // Track if user has toggled Caps Lock
this.key_map = {
0x25: 0x08, // (left arrow)
0x26: 0x0b, // (up arrow)
0x27: 0x15, // (right arrow)
0x28: 0x0a, // (down arrow)
0xbc: 0x2c, // , (comma)
0xbe: 0x2e, // . (period)
0xbf: 0x2f, // / (slash)
0xc0: 0x60, // ` (grave)
0xde: 0x27, // ' (single quote)
};
this.key_map_ctrl = {
0x43: 0x03, // c (break)
0x47: 0x07, // g (bell)
0x4a: 0x0a, // j (new line)
0x4d: 0x0d, // m (carriage return)
};
this.key_map_shift = {
0x30: 0x29, // ) (right paren)
0x31: 0x21, // ! (exclamation)
0x32: 0x40, // @ (at)
0x33: 0x23, // # (pound)
0x34: 0x24, // $ (currency)
0x35: 0x25, // % (percent)
0x36: 0x5e, // ^ (caret)
0x37: 0x26, // & (ampersand)
0x38: 0x2a, // * (star)
0x39: 0x28, // ( (left paren)
0x3b: 0x3a, // : (colon)
0x3d: 0x2b, // + (plus)
0xad: 0x5f, // _ (underbar)
0xbc: 0x3c, // < (less than)
0xbe: 0x3e, // > (greater than)
0xc0: 0x7e, // ~ (tilde)
0xbf: 0x3f, // ? (question mark)
0xdb: 0x7b, // { (left curly bracket)
0xdc: 0x7c, // | (pipe)
0xdd: 0x7d, // } (right curly bracket)
0xde: 0x22, // " (double quote)
};
}
get key() { return this._key; };
set key(val) { this._key = val; }
get key_pressed() { return this._key_pressed; };
set key_pressed(val) { this._key_pressed = (val != 0); }
strobe() {
this._key = 0x7f;
}
key_down(code, shift, ctrl, meta, caps_lock) {
// detect caps lock press
if(code === 0x14) {
this._caps_lock_ever_pressed = true;
return;
}
this._key_pressed = true;
// control
if(ctrl) {
if(code in this.key_map_ctrl) {
code = this.key_map_ctrl[code];
} else if(code >= 0x41 && code <= 0x5a) {
code = code - 0x40; // Ctrl+A=0x01 .. Ctrl+Z=0x1a
} else {
return; // unknown control key
}
}
// shift
else if(shift) {
if(code in this.key_map_shift) {
code = this.key_map_shift[code];
}
// else allow letter keys (A-Z) to pass through as uppercase
else if(code < 0x41 || code > 0x5a) {
return; // unknown shift key
}
}
// caps lock
else if(caps_lock && !this._caps_lock_ever_pressed) {
// by default letters are always uppercase
this._caps_lock_ever_pressed = true;
}
else if(!caps_lock && this._caps_lock_ever_pressed && code >= 0x41 && code <= 0x5a) {
code += 0x20;
}
// regular keys
else {
if(code in this.key_map) {
code = this.key_map[code];
}
// convert unshifted letter keys to lowercase
// else if(code >= 0x41 && code <= 0x5a) {
// code = code + 0x20; // convert to lowercase
// }
}
this._key = code | 0x80;
}
key_up() {
this._key_pressed = false;
}
}