PCem

view src/keyboard_olim24.c @ 132:2b9cea0be424

Improvements to PC speaker - fixes sound on Beyond Castle Wolfenstein and probably other games as well.
author TomW
date Wed Jul 16 20:44:29 2014 +0100
parents 7f9686ece79d
children
line source
1 #include "ibm.h"
2 #include "io.h"
3 #include "mem.h"
4 #include "mouse.h"
5 #include "pic.h"
6 #include "sound.h"
7 #include "sound_speaker.h"
8 #include "timer.h"
10 #include "keyboard.h"
11 #include "keyboard_olim24.h"
13 #define STAT_PARITY 0x80
14 #define STAT_RTIMEOUT 0x40
15 #define STAT_TTIMEOUT 0x20
16 #define STAT_LOCK 0x10
17 #define STAT_CD 0x08
18 #define STAT_SYSFLAG 0x04
19 #define STAT_IFULL 0x02
20 #define STAT_OFULL 0x01
22 struct
23 {
24 int wantirq;
25 uint8_t command;
26 uint8_t status;
27 uint8_t out;
29 uint8_t output_port;
31 int param, param_total;
32 uint8_t params[16];
34 int mouse_mode;
35 } keyboard_olim24;
37 static uint8_t key_queue[16];
38 static int key_queue_start = 0, key_queue_end = 0;
40 static uint8_t mouse_scancodes[7];
42 void keyboard_olim24_poll()
43 {
44 keybsenddelay += (1000 * TIMER_USEC);
45 //pclog("poll %i\n", keyboard_olim24.wantirq);
46 if (keyboard_olim24.wantirq)
47 {
48 keyboard_olim24.wantirq = 0;
49 picint(2);
50 pclog("keyboard_olim24 : take IRQ\n");
51 }
52 if (!(keyboard_olim24.status & STAT_OFULL) && key_queue_start != key_queue_end)
53 {
54 pclog("Reading %02X from the key queue at %i\n", keyboard_olim24.out, key_queue_start);
55 keyboard_olim24.out = key_queue[key_queue_start];
56 key_queue_start = (key_queue_start + 1) & 0xf;
57 keyboard_olim24.status |= STAT_OFULL;
58 keyboard_olim24.status &= ~STAT_IFULL;
59 keyboard_olim24.wantirq = 1;
60 }
61 }
63 void keyboard_olim24_adddata(uint8_t val)
64 {
65 key_queue[key_queue_end] = val;
66 key_queue_end = (key_queue_end + 1) & 0xf;
67 pclog("keyboard_olim24 : %02X added to key queue %02X\n", val, keyboard_olim24.status);
68 return;
69 }
71 void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv)
72 {
73 pclog("keyboard_olim24 : write %04X %02X\n", port, val);
74 /* if (ram[8] == 0xc3)
75 {
76 output = 3;
77 }*/
78 switch (port)
79 {
80 case 0x60:
81 if (keyboard_olim24.param != keyboard_olim24.param_total)
82 {
83 keyboard_olim24.params[keyboard_olim24.param++] = val;
84 if (keyboard_olim24.param == keyboard_olim24.param_total)
85 {
86 switch (keyboard_olim24.command)
87 {
88 case 0x11:
89 keyboard_olim24.mouse_mode = 0;
90 mouse_scancodes[0] = keyboard_olim24.params[0];
91 mouse_scancodes[1] = keyboard_olim24.params[1];
92 mouse_scancodes[2] = keyboard_olim24.params[2];
93 mouse_scancodes[3] = keyboard_olim24.params[3];
94 mouse_scancodes[4] = keyboard_olim24.params[4];
95 mouse_scancodes[5] = keyboard_olim24.params[5];
96 mouse_scancodes[6] = keyboard_olim24.params[6];
97 break;
99 case 0x12:
100 keyboard_olim24.mouse_mode = 1;
101 mouse_scancodes[0] = keyboard_olim24.params[0];
102 mouse_scancodes[1] = keyboard_olim24.params[1];
103 mouse_scancodes[2] = keyboard_olim24.params[2];
104 break;
106 default:
107 pclog("Bad keyboard command complete %02X\n", keyboard_olim24.command);
108 // dumpregs();
109 // exit(-1);
110 }
111 }
112 }
113 else
114 {
115 keyboard_olim24.command = val;
116 switch (val)
117 {
118 case 0x01: /*Self-test*/
119 break;
121 case 0x05: /*Read ID*/
122 keyboard_olim24_adddata(0x00);
123 break;
125 case 0x11:
126 keyboard_olim24.param = 0;
127 keyboard_olim24.param_total = 9;
128 break;
130 case 0x12:
131 keyboard_olim24.param = 0;
132 keyboard_olim24.param_total = 4;
133 break;
135 default:
136 pclog("Bad keyboard command %02X\n", val);
137 // dumpregs();
138 // exit(-1);
139 }
140 }
142 break;
144 case 0x61:
145 ppi.pb = val;
147 speaker_gated = val & 1;
148 speaker_enable = val & 2;
149 if (speaker_enable)
150 was_speaker_enable = 1;
151 pit_set_gate(2, val & 1);
152 break;
153 }
154 }
156 uint8_t keyboard_olim24_read(uint16_t port, void *priv)
157 {
158 uint8_t temp;
159 // pclog("keyboard_olim24 : read %04X ", port);
160 switch (port)
161 {
162 case 0x60:
163 temp = keyboard_olim24.out;
164 if (key_queue_start == key_queue_end)
165 {
166 keyboard_olim24.status &= ~STAT_OFULL;
167 keyboard_olim24.wantirq = 0;
168 }
169 else
170 {
171 keyboard_olim24.out = key_queue[key_queue_start];
172 key_queue_start = (key_queue_start + 1) & 0xf;
173 keyboard_olim24.status |= STAT_OFULL;
174 keyboard_olim24.status &= ~STAT_IFULL;
175 keyboard_olim24.wantirq = 1;
176 }
177 break;
179 case 0x61:
180 return ppi.pb;
182 case 0x64:
183 temp = keyboard_olim24.status;
184 keyboard_olim24.status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT);
185 break;
187 default:
188 pclog("\nBad olim24 keyboard read %04X\n", port);
189 // dumpregs();
190 // exit(-1);
191 }
192 // pclog("%02X\n", temp);
193 return temp;
194 }
196 void keyboard_olim24_reset()
197 {
198 keyboard_olim24.status = STAT_LOCK | STAT_CD;
199 keyboard_olim24.wantirq = 0;
201 keyboard_scan = 1;
203 keyboard_olim24.param = keyboard_olim24.param_total = 0;
205 keyboard_olim24.mouse_mode = 0;
206 mouse_scancodes[0] = 0x1c;
207 mouse_scancodes[1] = 0x53;
208 mouse_scancodes[2] = 0x01;
209 mouse_scancodes[3] = 0x4b;
210 mouse_scancodes[4] = 0x4d;
211 mouse_scancodes[5] = 0x48;
212 mouse_scancodes[6] = 0x50;
213 }
215 static int mouse_x = 0, mouse_y = 0, mouse_b = 0;
216 void mouse_olim24_poll(int x, int y, int b)
217 {
218 mouse_x += x;
219 mouse_y += y;
221 pclog("mouse_poll - %i, %i %i, %i\n", x, y, mouse_x, mouse_y);
223 if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
224 if ((b & 1) && !(mouse_b & 1))
225 keyboard_olim24_adddata(mouse_scancodes[0]);
226 if (!(b & 1) && (mouse_b & 1))
227 keyboard_olim24_adddata(mouse_scancodes[0] | 0x80);
228 mouse_b = (mouse_b & ~1) | (b & 1);
230 if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
231 if ((b & 2) && !(mouse_b & 2))
232 keyboard_olim24_adddata(mouse_scancodes[2]);
233 if (!(b & 2) && (mouse_b & 2))
234 keyboard_olim24_adddata(mouse_scancodes[2] | 0x80);
235 mouse_b = (mouse_b & ~2) | (b & 2);
237 if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
238 if ((b & 4) && !(mouse_b & 4))
239 keyboard_olim24_adddata(mouse_scancodes[1]);
240 if (!(b & 4) && (mouse_b & 4))
241 keyboard_olim24_adddata(mouse_scancodes[1] | 0x80);
242 mouse_b = (mouse_b & ~4) | (b & 4);
244 if (keyboard_olim24.mouse_mode)
245 {
246 if (((key_queue_end - key_queue_start) & 0xf) > 12) return;
247 if (!mouse_x && !mouse_y) return;
249 mouse_y = -mouse_y;
251 if (mouse_x < -127) mouse_x = -127;
252 if (mouse_x > 127) mouse_x = 127;
253 if (mouse_x < -127) mouse_x = 0x80 | ((-mouse_x) & 0x7f);
255 if (mouse_y < -127) mouse_y = -127;
256 if (mouse_y > 127) mouse_y = 127;
257 if (mouse_y < -127) mouse_y = 0x80 | ((-mouse_y) & 0x7f);
259 keyboard_olim24_adddata(0xfe);
260 keyboard_olim24_adddata(mouse_x);
261 keyboard_olim24_adddata(mouse_y);
263 mouse_x = mouse_y = 0;
264 }
265 else
266 {
267 while (mouse_x < -4)
268 {
269 if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
270 mouse_x+=4;
271 keyboard_olim24_adddata(mouse_scancodes[3]);
272 }
273 while (mouse_x > 4)
274 {
275 if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
276 mouse_x-=4;
277 keyboard_olim24_adddata(mouse_scancodes[4]);
278 }
279 while (mouse_y < -4)
280 {
281 if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
282 mouse_y+=4;
283 keyboard_olim24_adddata(mouse_scancodes[5]);
284 }
285 while (mouse_y > 4)
286 {
287 if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
288 mouse_y-=4;
289 keyboard_olim24_adddata(mouse_scancodes[6]);
290 }
291 }
292 }
294 void keyboard_olim24_init()
295 {
296 //return;
297 io_sethandler(0x0060, 0x0002, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL, NULL);
298 io_sethandler(0x0064, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL, NULL);
299 keyboard_olim24_reset();
300 keyboard_send = keyboard_olim24_adddata;
301 keyboard_poll = keyboard_olim24_poll;
302 mouse_poll = mouse_olim24_poll;
304 timer_add(keyboard_olim24_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
305 }