aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-03-04 23:08:57 +0100
committerBad Diode <bd@badd10de.dev>2022-03-04 23:08:57 +0100
commite835289d291bb8d0a9f0b56130412226c4cbec7c (patch)
tree77a4395deeec8b8de8b6589287547c613586f0a6
parenta46fb7bd7eb1cf4c3237c2f3c944dfc82bcc2ee5 (diff)
downloaduxnfb-e835289d291bb8d0a9f0b56130412226c4cbec7c.tar.gz
uxnfb-e835289d291bb8d0a9f0b56130412226c4cbec7c.zip
Add partial support for keyboard input
-rw-r--r--src/main.c231
1 files changed, 188 insertions, 43 deletions
diff --git a/src/main.c b/src/main.c
index de566ac..2bce9f7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,3 +1,4 @@
1#include <errno.h>
1#include <stdbool.h> 2#include <stdbool.h>
2#include <stdint.h> 3#include <stdint.h>
3#include <stdio.h> 4#include <stdio.h>
@@ -5,6 +6,8 @@
5#include <time.h> 6#include <time.h>
6#include <unistd.h> 7#include <unistd.h>
7 8
9#include <linux/input.h>
10
8#include "shorthand.h" 11#include "shorthand.h"
9#include "ppu.c" 12#include "ppu.c"
10#include "uxn-fast.c" 13#include "uxn-fast.c"
@@ -30,6 +33,142 @@ time_elapsed(Time since){
30 return (now.tv_sec - since.tv_sec) * 1e9 + (now.tv_nsec - since.tv_nsec); 33 return (now.tv_sec - since.tv_sec) * 1e9 + (now.tv_nsec - since.tv_nsec);
31} 34}
32 35
36typedef struct Keyboard {
37 int fd;
38 char map[KEY_MAX / 8 + 1];
39} Keyboard;
40
41static Keyboard keyboard;
42
43void
44init_input(void) {
45 const char *dev = "/dev/input/by-id/usb-Apple_Inc._Magic_Keyboard_with_Numeric_Keypad_F0T0167000DHTHKAD-if01-event-kbd";
46 keyboard.fd = open(dev, O_RDONLY);
47 if (keyboard.fd == -1) {
48 // TODO: should this be a warning and still work for applications that
49 // don't require a keyboard?
50 fprintf(stderr, "error: no couldn't open keyboard %s: %s.\n", dev, strerror(errno));
51 exit(EXIT_FAILURE);
52 }
53
54 memset(keyboard.map, 0, sizeof(keyboard.map));
55}
56
57void
58poll_keyboard(void) {
59 char map[KEY_MAX / 8 + 1];
60 memset(map, 0, sizeof(map));
61 ioctl(keyboard.fd, EVIOCGKEY(sizeof(map)), map);
62 for (size_t i = 0; i < sizeof(map); i++) {
63 keyboard.map[i] |= map[i];
64 }
65}
66
67void
68handle_keyboard(void) {
69 // Find mod keys.
70 bool shift_mod = false;
71 // bool ctrl_mod = false;
72 // bool alt_mod = false;
73 // bool meta_mod = false;
74 for (size_t i = 0; i < sizeof(keyboard.map); i++) {
75 for (size_t j = 0; j < 8; j++) {
76 char key = keyboard.map[i] & (1 << j);
77 if (key) {
78 char key_code = i * 8 + j;
79 switch (key_code) {
80 case KEY_LEFTSHIFT:
81 case KEY_RIGHTSHIFT: { shift_mod = true; } break;
82 // case KEY_LEFTCTRL:
83 // case KEY_RIGHTCTRL: { ctrl_mod = true; } break;
84 // case KEY_LEFTALT:
85 // case KEY_RIGHTALT: { alt_mod = true; } break;
86 // case KEY_LEFTMETA:
87 // case KEY_RIGHTMETA: { meta_mod = true; } break;
88 default: break;
89 }
90 }
91 }
92 }
93
94 // Handle normal keys.
95 for (size_t i = 0; i < sizeof(keyboard.map); i++) {
96 for (size_t j = 0; j < 8; j++) {
97 char key = keyboard.map[i] & (1 << j);
98 if (key) {
99 char key_code = i * 8 + j;
100 // Special keys.
101 // TODO: ...
102
103 // Normal keys.
104 char rune = '\0';
105 switch (key_code) {
106 case KEY_1: { rune = shift_mod ? '!' : '1'; } break;
107 case KEY_2: { rune = shift_mod ? '@' : '2'; } break;
108 case KEY_3: { rune = shift_mod ? '#' : '3'; } break;
109 case KEY_4: { rune = shift_mod ? '$' : '4'; } break;
110 case KEY_5: { rune = shift_mod ? '%' : '5'; } break;
111 case KEY_6: { rune = shift_mod ? '^' : '6'; } break;
112 case KEY_7: { rune = shift_mod ? '&' : '7'; } break;
113 case KEY_8: { rune = shift_mod ? '*' : '8'; } break;
114 case KEY_9: { rune = shift_mod ? '(' : '9'; } break;
115 case KEY_0: { rune = shift_mod ? ')' : '0'; } break;
116 case KEY_MINUS: { rune = shift_mod ? '_' : '-'; } break;
117 case KEY_EQUAL: { rune = shift_mod ? '+' : '+'; } break;
118 case KEY_Q: { rune = shift_mod ? 'Q' : 'q'; } break;
119 case KEY_W: { rune = shift_mod ? 'W' : 'w'; } break;
120 case KEY_E: { rune = shift_mod ? 'E' : 'e'; } break;
121 case KEY_R: { rune = shift_mod ? 'T' : 't'; } break;
122 case KEY_T: { rune = shift_mod ? 'T' : 't'; } break;
123 case KEY_Y: { rune = shift_mod ? 'Y' : 'y'; } break;
124 case KEY_U: { rune = shift_mod ? 'U' : 'u'; } break;
125 case KEY_I: { rune = shift_mod ? 'I' : 'i'; } break;
126 case KEY_O: { rune = shift_mod ? 'O' : 'o'; } break;
127 case KEY_P: { rune = shift_mod ? 'P' : 'p'; } break;
128 case KEY_LEFTBRACE: { rune = shift_mod ? '{' : '['; } break;
129 case KEY_RIGHTBRACE: { rune = shift_mod ? '}' : ']'; } break;
130 case KEY_A: { rune = shift_mod ? 'A' : 'a'; } break;
131 case KEY_S: { rune = shift_mod ? 'S' : 's'; } break;
132 case KEY_D: { rune = shift_mod ? 'D' : 'd'; } break;
133 case KEY_F: { rune = shift_mod ? 'F' : 'f'; } break;
134 case KEY_G: { rune = shift_mod ? 'G' : 'g'; } break;
135 case KEY_H: { rune = shift_mod ? 'H' : 'h'; } break;
136 case KEY_J: { rune = shift_mod ? 'J' : 'j'; } break;
137 case KEY_K: { rune = shift_mod ? 'K' : 'k'; } break;
138 case KEY_L: { rune = shift_mod ? 'L' : 'l'; } break;
139 case KEY_SEMICOLON: { rune = shift_mod ? ':' : ';'; } break;
140 case KEY_APOSTROPHE: { rune = shift_mod ? '"' : '\''; } break;
141 case KEY_GRAVE: { rune = shift_mod ? '~' : '`'; } break;
142 case KEY_BACKSLASH: { rune = shift_mod ? '|' : '\\'; } break;
143 case KEY_Z: { rune = shift_mod ? 'Z' : 'z'; } break;
144 case KEY_X: { rune = shift_mod ? 'X' : 'x'; } break;
145 case KEY_C: { rune = shift_mod ? 'C' : 'c'; } break;
146 case KEY_V: { rune = shift_mod ? 'V' : 'v'; } break;
147 case KEY_B: { rune = shift_mod ? 'B' : 'b'; } break;
148 case KEY_N: { rune = shift_mod ? 'N' : 'n'; } break;
149 case KEY_M: { rune = shift_mod ? 'M' : 'm'; } break;
150 case KEY_COMMA: { rune = shift_mod ? '<' : ','; } break;
151 case KEY_DOT: { rune = shift_mod ? '>' : '.'; } break;
152 case KEY_SLASH: { rune = shift_mod ? '?' : '/'; } break;
153 case KEY_SPACE: { rune = ' '; } break;
154 case KEY_TAB: { rune = '\t'; } break;
155 case KEY_BACKSPACE: { rune = 0x08; } break;
156 case KEY_ENTER:
157 case KEY_KPENTER: { rune = 0x0d; } break;
158 default: break;
159 }
160 if (rune) {
161 devctrl->dat[3] = rune;
162 uxn_eval(&u, mempeek16(devctrl->dat, 0));
163 devctrl->dat[3] = 0;
164 continue;
165 }
166 }
167 }
168 }
169 memset(keyboard.map, 0, sizeof(keyboard.map));
170}
171
33void 172void
34nil_talk(Device *d, u8 b0, u8 w) { 173nil_talk(Device *d, u8 b0, u8 w) {
35 (void)d; 174 (void)d;
@@ -103,51 +242,51 @@ screen_talk(Device *d, u8 b0, u8 w) {
103 if (w) { 242 if (w) {
104 switch (b0) { 243 switch (b0) {
105 case 0x1: { 244 case 0x1: {
106 d->vector = mempeek16(d->dat, 0x0); 245 d->vector = mempeek16(d->dat, 0x0);
107 } break; 246 } break;
108 case 0xe: { 247 case 0xe: {
109 u16 x = mempeek16(d->dat, 0x8); 248 u16 x = mempeek16(d->dat, 0x8);
110 u16 y = mempeek16(d->dat, 0xa); 249 u16 y = mempeek16(d->dat, 0xa);
111 u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; 250 u8 *addr = &d->mem[mempeek16(d->dat, 0xc)];
112 u8 *layer = d->dat[0xe] >> 4 & 0x1 ? pixels_fg : pixels_bg; 251 u8 *layer = d->dat[0xe] >> 4 & 0x1 ? pixels_fg : pixels_bg;
113 u8 mode = d->dat[0xe] >> 5; 252 u8 mode = d->dat[0xe] >> 5;
114 u8 color = d->dat[0xf] & 0xf; 253 u8 color = d->dat[0xf] & 0xf;
115 if(!mode) { 254 if(!mode) {
116 ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); 255 ppu_pixel(layer, x, y, d->dat[0xe] & 0x3);
117 } else if(mode-- & 0x1) { 256 } else if(mode-- & 0x1) {
118 u8 flipx = mode & 0x2; 257 u8 flipx = mode & 0x2;
119 u8 flipy = mode & 0x4; 258 u8 flipy = mode & 0x4;
120 ppu_1bpp(layer, x, y, addr, color, flipx, flipy); 259 ppu_1bpp(layer, x, y, addr, color, flipx, flipy);
121 } else { 260 } else {
122 u8 flipx = mode & 0x2; 261 u8 flipx = mode & 0x2;
123 u8 flipy = mode & 0x4; 262 u8 flipy = mode & 0x4;
124 ppu_2bpp(layer, x, y, addr, color, flipx, flipy); 263 ppu_2bpp(layer, x, y, addr, color, flipx, flipy);
125 } 264 }
126 if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 1); } 265 if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 1); }
127 if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 1); } 266 if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 1); }
128 } break; 267 } break;
129 case 0xf: { 268 case 0xf: {
130 u16 x = mempeek16(d->dat, 0x8); 269 u16 x = mempeek16(d->dat, 0x8);
131 u16 y = mempeek16(d->dat, 0xa); 270 u16 y = mempeek16(d->dat, 0xa);
132 u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; 271 u8 *addr = &d->mem[mempeek16(d->dat, 0xc)];
133 u8 *layer = d->dat[0xf] >> 6 & 0x1 ? pixels_fg : pixels_bg; 272 u8 *layer = d->dat[0xf] >> 6 & 0x1 ? pixels_fg : pixels_bg;
134 u8 color = d->dat[0xf] & 0xf; 273 u8 color = d->dat[0xf] & 0xf;
135 u8 flipx = (d->dat[0xf] >> 0x4) & 0x1; 274 u8 flipx = (d->dat[0xf] >> 0x4) & 0x1;
136 u8 flipy = (d->dat[0xf] >> 0x5) & 0x1; 275 u8 flipy = (d->dat[0xf] >> 0x5) & 0x1;
137 if(d->dat[0xf] >> 0x7 & 0x1) { 276 if(d->dat[0xf] >> 0x7 & 0x1) {
138 ppu_2bpp(layer, x, y, addr, color, flipx, flipy); 277 ppu_2bpp(layer, x, y, addr, color, flipx, flipy);
139 if(d->dat[0x6] & 0x04) { 278 if(d->dat[0x6] & 0x04) {
140 mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 16); 279 mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 16);
141 } 280 }
142 } else { 281 } else {
143 ppu_1bpp(layer, x, y, addr, color, flipx, flipy); 282 ppu_1bpp(layer, x, y, addr, color, flipx, flipy);
144 if(d->dat[0x6] & 0x04) { 283 if(d->dat[0x6] & 0x04) {
145 mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 8); 284 mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 8);
146 } 285 }
147 } 286 }
148 if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 8); } 287 if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 8); }
149 if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 8); } 288 if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 8); }
150 } break; 289 } break;
151 default: break; 290 default: break;
152 } 291 }
153 } 292 }
@@ -208,6 +347,9 @@ init_uxn(char *file_name) {
208 // Initialize framebuffer. 347 // Initialize framebuffer.
209 ppu_init(); 348 ppu_init();
210 349
350 // Initialize keybord.
351 init_input();
352
211 // Prepare devices. 353 // Prepare devices.
212 uxn_port(&u, 0x0, "system", system_talk); 354 uxn_port(&u, 0x0, "system", system_talk);
213 uxn_port(&u, 0x1, "console", console_talk); 355 uxn_port(&u, 0x1, "console", console_talk);
@@ -242,8 +384,11 @@ main(int argc, char *argv[]) {
242 uxn_eval(&u, 0x0100); 384 uxn_eval(&u, 0x0100);
243 Time frame_time = time_now(); 385 Time frame_time = time_now();
244 while (true) { 386 while (true) {
387 poll_keyboard();
245 size_t elapsed = time_elapsed(frame_time); 388 size_t elapsed = time_elapsed(frame_time);
246 if (elapsed >= 16666666) { 389 if (elapsed >= 16666666) {
390 handle_keyboard();
391
247 // Echo input to standard output. 392 // Echo input to standard output.
248 uxn_eval(&u, mempeek16(devscreen->dat, 0)); 393 uxn_eval(&u, mempeek16(devscreen->dat, 0));
249 394