PCem

view src/keyboard_amstrad.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 6425afff950f
children 9a88154e8608
line source
1 #include "ibm.h"
2 #include "io.h"
3 #include "mem.h"
4 #include "pic.h"
5 #include "pit.h"
6 #include "sound.h"
7 #include "sound_speaker.h"
8 #include "timer.h"
10 #include "keyboard.h"
11 #include "keyboard_amstrad.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;
26 uint8_t key_waiting;
27 uint8_t pa;
28 uint8_t pb;
29 } keyboard_amstrad;
31 static uint8_t key_queue[16];
32 static int key_queue_start = 0, key_queue_end = 0;
34 static uint8_t amstrad_systemstat_1, amstrad_systemstat_2;
36 void keyboard_amstrad_poll()
37 {
38 keybsenddelay += (1000 * TIMER_USEC);
39 if (keyboard_amstrad.wantirq)
40 {
41 keyboard_amstrad.wantirq = 0;
42 keyboard_amstrad.pa = keyboard_amstrad.key_waiting;
43 picint(2);
44 pclog("keyboard_amstrad : take IRQ\n");
45 }
46 if (key_queue_start != key_queue_end && !keyboard_amstrad.pa)
47 {
48 keyboard_amstrad.key_waiting = key_queue[key_queue_start];
49 pclog("Reading %02X from the key queue at %i\n", keyboard_amstrad.key_waiting, key_queue_start);
50 key_queue_start = (key_queue_start + 1) & 0xf;
51 keyboard_amstrad.wantirq = 1;
52 }
53 }
55 void keyboard_amstrad_adddata(uint8_t val)
56 {
57 key_queue[key_queue_end] = val;
58 pclog("keyboard_amstrad : %02X added to key queue at %i\n", val, key_queue_end);
59 key_queue_end = (key_queue_end + 1) & 0xf;
60 return;
61 }
63 void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv)
64 {
65 pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, keyboard_amstrad.pb);
67 switch (port)
68 {
69 case 0x61:
70 pclog("keyboard_amstrad : pb write %02X %02X %i %02X %i\n", val, keyboard_amstrad.pb, !(keyboard_amstrad.pb & 0x40), keyboard_amstrad.pb & 0x40, (val & 0x40));
71 if (!(keyboard_amstrad.pb & 0x40) && (val & 0x40)) /*Reset keyboard*/
72 {
73 pclog("keyboard_amstrad : reset keyboard\n");
74 keyboard_amstrad_adddata(0xaa);
75 }
76 keyboard_amstrad.pb = val;
77 ppi.pb = val;
79 speaker_gated = val & 1;
80 speaker_enable = val & 2;
81 if (speaker_enable)
82 was_speaker_enable = 1;
83 pit_set_gate(2, val & 1);
85 if (val & 0x80)
86 keyboard_amstrad.pa = 0;
87 break;
89 case 0x63:
90 break;
92 case 0x64:
93 amstrad_systemstat_1 = val;
94 break;
96 case 0x65:
97 amstrad_systemstat_2 = val;
98 break;
100 default:
101 pclog("\nBad XT keyboard write %04X %02X\n", port, val);
102 // dumpregs();
103 // exit(-1);
104 }
105 }
107 uint8_t keyboard_amstrad_read(uint16_t port, void *priv)
108 {
109 uint8_t temp;
110 // pclog("keyboard_amstrad : read %04X ", port);
111 switch (port)
112 {
113 case 0x60:
114 if (keyboard_amstrad.pb & 0x80)
115 {
116 temp = (amstrad_systemstat_1 | 0xd) & 0x7f;
117 }
118 else
119 {
120 temp = keyboard_amstrad.pa;
121 if (key_queue_start == key_queue_end)
122 {
123 keyboard_amstrad.wantirq = 0;
124 }
125 else
126 {
127 keyboard_amstrad.key_waiting = key_queue[key_queue_start];
128 key_queue_start = (key_queue_start + 1) & 0xf;
129 keyboard_amstrad.wantirq = 1;
130 }
131 }
132 break;
134 case 0x61:
135 temp = keyboard_amstrad.pb;
136 break;
138 case 0x62:
139 if (keyboard_amstrad.pb & 0x04)
140 temp = amstrad_systemstat_2 & 0xf;
141 else
142 temp = amstrad_systemstat_2 >> 4;
143 temp |= (ppispeakon ? 0x20 : 0);
144 break;
146 default:
147 pclog("\nBad XT keyboard read %04X\n", port);
148 // dumpregs();
149 // exit(-1);
150 }
151 // pclog("%02X %04X:%04X\n", temp, CS, pc);
152 return temp;
153 }
155 void keyboard_amstrad_reset()
156 {
157 keyboard_amstrad.wantirq = 0;
159 keyboard_scan = 1;
160 }
162 void keyboard_amstrad_init()
163 {
164 //return;
165 pclog("keyboard_amstrad_init\n");
166 io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL, NULL);
167 keyboard_amstrad_reset();
168 keyboard_send = keyboard_amstrad_adddata;
169 keyboard_poll = keyboard_amstrad_poll;
171 timer_add(keyboard_amstrad_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
172 }