Fix tms9918a transparent color rendering
[qemu/z80.git] / hw / zx_keyboard.c
blob8b676bdb791ed8431b41ad74fee5af0c896cb6b1
1 /*
2 * ZX Spectrum Keyboard Emulation
4 * Copyright (c) 2007-2009 Stuart Brady <stuart.brady@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
24 #include "hw.h"
25 #include "qemu-timer.h"
26 #include "console.h"
27 #include "isa.h"
28 #include "sysemu.h"
29 #include "zx_keyboard.h"
30 #include "boards.h"
32 //#define DEBUG_ZX_KEYBOARD
34 #ifdef DEBUG_ZX_KEYBOARD
35 #define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
36 #else
37 #define DPRINTF(fmt, ...)
38 #endif
40 static int keystate[8];
42 uint32_t zx_keyboard_read(void *opaque, uint32_t addr)
44 int r = 0;
45 uint8_t colbits = 0xff;
47 uint32_t rowbits = ((addr >> 8) & 0xff);
49 for (r = 0; r < 8; r++) {
50 if (!(rowbits & (1 << r))) {
51 colbits &= keystate[r];
54 return colbits;
57 typedef struct {
58 int row;
59 int column;
60 } ZXKeypos;
62 #define DEF_ZX_KEY(name, row, column) ZX_KEY_ ## name,
63 enum zx_keys {
64 #include "zx_key_template.h"
65 ZX_MAX_KEYS
68 #define DEF_ZX_KEY(name, row, column) [ZX_KEY_ ## name] = {row, column},
69 static const ZXKeypos keypos[ZX_MAX_KEYS] = {
70 #include "zx_key_template.h"
73 static int zx_keypressed[ZX_MAX_KEYS];
74 static int qemu_keypressed[0x100];
76 static const int map[0x100][2] = {
77 [0 ... 0xff] = {-1, -1}, /* Unmapped by default */
79 [0x01] = {ZX_KEY_CAPSSHIFT, ZX_KEY_SPACE}, /* Escape */
81 [0x02] = {ZX_KEY_1, -1},
82 [0x03] = {ZX_KEY_2, -1},
83 [0x04] = {ZX_KEY_3, -1},
84 [0x05] = {ZX_KEY_4, -1},
85 [0x06] = {ZX_KEY_5, -1},
86 [0x07] = {ZX_KEY_6, -1},
87 [0x08] = {ZX_KEY_7, -1},
88 [0x09] = {ZX_KEY_8, -1},
89 [0x0a] = {ZX_KEY_9, -1},
90 [0x0b] = {ZX_KEY_0, -1},
92 [0x0c] = {ZX_KEY_SYMBSHIFT, ZX_KEY_J}, /* Minus */
94 [0x0e] = {ZX_KEY_CAPSSHIFT, ZX_KEY_0}, /* Backspace */
96 [0x10] = {ZX_KEY_Q, -1},
97 [0x11] = {ZX_KEY_W, -1},
98 [0x12] = {ZX_KEY_E, -1},
99 [0x13] = {ZX_KEY_R, -1},
100 [0x14] = {ZX_KEY_T, -1},
101 [0x15] = {ZX_KEY_Y, -1},
102 [0x16] = {ZX_KEY_U, -1},
103 [0x17] = {ZX_KEY_I, -1},
104 [0x18] = {ZX_KEY_O, -1},
105 [0x19] = {ZX_KEY_P, -1},
107 [0x0d] = {ZX_KEY_SYMBSHIFT, ZX_KEY_L}, /* Equals */
108 [0x0f] = {ZX_KEY_CAPSSHIFT, ZX_KEY_1}, /* Tab */
110 [0x1c] = {ZX_KEY_ENTER, -1},
112 [0x1d] = {ZX_KEY_SYMBSHIFT, -1}, /* Left Control */
114 [0x1e] = {ZX_KEY_A, -1},
115 [0x1f] = {ZX_KEY_S, -1},
116 [0x20] = {ZX_KEY_D, -1},
117 [0x21] = {ZX_KEY_F, -1},
118 [0x22] = {ZX_KEY_G, -1},
119 [0x23] = {ZX_KEY_H, -1},
120 [0x24] = {ZX_KEY_J, -1},
121 [0x25] = {ZX_KEY_K, -1},
122 [0x26] = {ZX_KEY_L, -1},
124 [0x27] = {ZX_KEY_SYMBSHIFT, ZX_KEY_O}, /* Semicolon */
125 [0x28] = {ZX_KEY_SYMBSHIFT, ZX_KEY_7}, /* Apostrophe */
127 [0x2a] = {ZX_KEY_CAPSSHIFT, -1}, /* Left Shift */
129 [0x2b] = {ZX_KEY_SYMBSHIFT, ZX_KEY_3}, /* Hash */
131 [0x2c] = {ZX_KEY_Z, -1},
132 [0x2d] = {ZX_KEY_X, -1},
133 [0x2e] = {ZX_KEY_C, -1},
134 [0x2f] = {ZX_KEY_V, -1},
135 [0x30] = {ZX_KEY_B, -1},
136 [0x31] = {ZX_KEY_N, -1},
137 [0x32] = {ZX_KEY_M, -1},
139 [0x33] = {ZX_KEY_SYMBSHIFT, ZX_KEY_N}, /* Comma */
140 [0x34] = {ZX_KEY_SYMBSHIFT, ZX_KEY_M}, /* Period */
141 [0x35] = {ZX_KEY_SYMBSHIFT, ZX_KEY_V}, /* Slash */
143 [0x36] = {ZX_KEY_CAPSSHIFT, -1}, /* Right Shift */
144 [0x37] = {ZX_KEY_SYMBSHIFT, ZX_KEY_B}, /* * (Numpad) */
145 [0x38] = {ZX_KEY_SYMBSHIFT, -1}, /* Left Alt */
146 [0x39] = {ZX_KEY_SPACE, -1}, /* Space Bar */
148 [0x47] = {ZX_KEY_7, -1}, /* 7 (Numpad) */
149 [0x48] = {ZX_KEY_8, -1}, /* 8 (Numpad) */
150 [0x49] = {ZX_KEY_9, -1}, /* 9 (Numpad) */
151 [0x4a] = {ZX_KEY_SYMBSHIFT, ZX_KEY_J}, /* Minus (Numpad) */
152 [0x4b] = {ZX_KEY_4, -1}, /* 4 (Numpad) */
153 [0x4c] = {ZX_KEY_5, -1}, /* 5 (Numpad) */
154 [0x4d] = {ZX_KEY_6, -1}, /* 6 (Numpad) */
155 [0x4e] = {ZX_KEY_SYMBSHIFT, ZX_KEY_K}, /* Plus (Numpad) */
156 [0x4f] = {ZX_KEY_1, -1}, /* 1 (Numpad) */
157 [0x50] = {ZX_KEY_2, -1}, /* 2 (Numpad) */
158 [0x51] = {ZX_KEY_3, -1}, /* 3 (Numpad) */
159 [0x52] = {ZX_KEY_0, -1}, /* 0 (Numpad) */
160 [0x53] = {ZX_KEY_SYMBSHIFT, ZX_KEY_M}, /* Period (Numpad) */
162 [0x9c] = {ZX_KEY_SYMBSHIFT, -1}, /* Enter (Numpad) */
163 [0x9d] = {ZX_KEY_SYMBSHIFT, -1}, /* Right Control */
164 [0xb5] = {ZX_KEY_SYMBSHIFT, ZX_KEY_V}, /* Slash (Numpad) */
165 [0xb8] = {ZX_KEY_SYMBSHIFT, -1}, /* Right Alt */
167 [0xc8] = {ZX_KEY_CAPSSHIFT, ZX_KEY_7}, /* Up Arrow */
168 [0xcb] = {ZX_KEY_CAPSSHIFT, ZX_KEY_5}, /* Left Arrow */
169 [0xcd] = {ZX_KEY_CAPSSHIFT, ZX_KEY_8}, /* Right Arrow */
170 [0xd0] = {ZX_KEY_CAPSSHIFT, ZX_KEY_6}, /* Down Arrow */
172 [0xdb] = {ZX_KEY_CAPSSHIFT, ZX_KEY_SYMBSHIFT}, /* Left Meta */
173 [0xdc] = {ZX_KEY_CAPSSHIFT, ZX_KEY_SYMBSHIFT}, /* Menu */
174 [0xdd] = {ZX_KEY_CAPSSHIFT, ZX_KEY_SYMBSHIFT}, /* Right Meta */
177 /* FIXME:
178 * Need to mappings from stepping on each other...
179 * or at least make them step on one another in a consistent manner?
180 * Could use separate state arrays for surpressing/adding keys
181 * and allow only one change to the modifier keys at a time...
183 * Also need to implement shifted mappings.
186 static void zx_put_keycode(void *opaque, int keycode)
188 int release = keycode & 0x80;
189 int key, row, col;
190 static int ext_keycode = 0;
191 int i;
192 int valid;
194 if (keycode == 0xe0) {
195 ext_keycode = 1;
196 } else {
197 if (ext_keycode) {
198 keycode |= 0x80;
199 } else {
200 keycode &= 0x7f;
202 ext_keycode = 0;
204 DPRINTF("Keycode 0x%02x (%s)\n", keycode, release ? "release" : "press");
206 if (release && qemu_keypressed[keycode]) {
207 valid = 1;
208 qemu_keypressed[keycode] = 0;
209 } else if (!release && !qemu_keypressed[keycode]) {
210 valid = 1;
211 qemu_keypressed[keycode] = 1;
212 } else {
213 valid = 0;
216 if (valid) {
217 for (i = 0; i < 2; i++) {
218 key = map[keycode][i];
219 if (key != -1) {
220 row = keypos[key].row;
221 col = keypos[key].column;
222 if (release) {
223 if (--zx_keypressed[key] <= 0) {
224 DPRINTF("Releasing 0x%02x\n", key);
225 zx_keypressed[key] = 0;
226 keystate[row] |= 1 << col;
228 } else {
229 DPRINTF("Pressing 0x%02x\n", key);
230 zx_keypressed[key]++;
231 keystate[row] &= ~(1 << col);
239 void zx_keyboard_init(void)
241 int i;
242 for (i=0; i<8; i++) {
243 keystate[i] = 0xff;
245 memset(zx_keypressed, 0, sizeof(zx_keypressed));
246 memset(qemu_keypressed, 0, sizeof(qemu_keypressed));
247 qemu_add_kbd_event_handler(zx_put_keycode, NULL);