PCem
view src/keyboard_pcjr.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 | 923b243eba54 |
| children |
line source
1 #include "ibm.h"
2 #include "device.h"
3 #include "io.h"
4 #include "mem.h"
5 #include "pic.h"
6 #include "sound.h"
7 #include "sound_sn76489.h"
8 #include "sound_speaker.h"
9 #include "timer.h"
11 #include "keyboard.h"
12 #include "keyboard_pcjr.h"
14 #define STAT_PARITY 0x80
15 #define STAT_RTIMEOUT 0x40
16 #define STAT_TTIMEOUT 0x20
17 #define STAT_LOCK 0x10
18 #define STAT_CD 0x08
19 #define STAT_SYSFLAG 0x04
20 #define STAT_IFULL 0x02
21 #define STAT_OFULL 0x01
23 struct
24 {
25 int latched;
26 int data;
27 int nmi_enabled;
29 int serial_data[44];
30 int serial_pos;
32 uint8_t pa;
33 uint8_t pb;
34 } keyboard_pcjr;
36 static uint8_t key_queue[16];
37 static int key_queue_start = 0, key_queue_end = 0;
39 void keyboard_pcjr_poll()
40 {
41 keybsenddelay += (220 * TIMER_USEC);
44 if (key_queue_start != key_queue_end && !keyboard_pcjr.serial_pos && !keyboard_pcjr.latched)
45 {
46 int c;
47 int p = 0;
48 uint8_t key = key_queue[key_queue_start];
50 // pclog("Reading %02X from the key queue at %i\n", key, key_queue_start);
51 key_queue_start = (key_queue_start + 1) & 0xf;
53 keyboard_pcjr.latched = 1;
55 keyboard_pcjr.serial_data[0] = 1; /*Start bit*/
56 keyboard_pcjr.serial_data[1] = 0;
58 for (c = 0; c < 8; c++)
59 {
60 if (key & (1 << c))
61 {
62 keyboard_pcjr.serial_data[(c + 1) * 2] = 1;
63 keyboard_pcjr.serial_data[(c + 1) * 2 + 1] = 0;
64 p++;
65 }
66 else
67 {
68 keyboard_pcjr.serial_data[(c + 1) * 2] = 0;
69 keyboard_pcjr.serial_data[(c + 1) * 2 + 1] = 1;
70 }
71 }
73 if (p & 1) /*Parity*/
74 {
75 keyboard_pcjr.serial_data[9 * 2] = 1;
76 keyboard_pcjr.serial_data[9 * 2 + 1] = 0;
77 }
78 else
79 {
80 keyboard_pcjr.serial_data[9 * 2] = 0;
81 keyboard_pcjr.serial_data[9 * 2 + 1] = 1;
82 }
84 for (c = 0; c < 11; c++) /*11 stop bits*/
85 {
86 keyboard_pcjr.serial_data[(c + 10) * 2] = 0;
87 keyboard_pcjr.serial_data[(c + 10) * 2 + 1] = 0;
88 }
90 keyboard_pcjr.serial_pos++;
91 }
93 if (keyboard_pcjr.serial_pos)
94 {
95 keyboard_pcjr.data = keyboard_pcjr.serial_data[keyboard_pcjr.serial_pos - 1];
96 nmi = keyboard_pcjr.data;
97 keyboard_pcjr.serial_pos++;
98 if (keyboard_pcjr.serial_pos == 42+1)
99 keyboard_pcjr.serial_pos = 0;
100 // pclog("Keyboard poll %i %i\n", keyboard_pcjr.data, keyboard_pcjr.serial_pos);
101 }
102 }
104 void keyboard_pcjr_adddata(uint8_t val)
105 {
106 key_queue[key_queue_end] = val;
107 // pclog("keyboard_pcjr : %02X added to key queue at %i\n", val, key_queue_end);
108 key_queue_end = (key_queue_end + 1) & 0xf;
109 return;
110 }
112 void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv)
113 {
114 // pclog("keyboard_pcjr : write %04X %02X %02X\n", port, val, keyboard_pcjr.pb);
115 /* if (ram[8] == 0xc3)
116 {
117 output = 3;
118 }*/
119 switch (port)
120 {
121 case 0x60:
122 keyboard_pcjr.pa = val;
123 break;
125 case 0x61:
126 keyboard_pcjr.pb = val;
127 speaker_gated = val & 1;
128 speaker_enable = val & 2;
129 if (speaker_enable)
130 was_speaker_enable = 1;
131 pit_set_gate(2, val & 1);
132 sn76489_mute = speaker_mute = 1;
133 switch (val & 0x60)
134 {
135 case 0x00:
136 speaker_mute = 0;
137 break;
138 case 0x60:
139 sn76489_mute = 0;
140 break;
141 }
142 break;
144 case 0xa0:
145 keyboard_pcjr.nmi_enabled = val & 0x80;
146 pit_set_using_timer(1, !(val & 0x20));
147 break;
148 }
149 }
151 uint8_t keyboard_pcjr_read(uint16_t port, void *priv)
152 {
153 uint8_t temp;
154 // pclog("keyboard_pcjr : read %04X ", port);
155 switch (port)
156 {
157 case 0x60:
158 temp = keyboard_pcjr.pa;
159 break;
161 case 0x61:
162 temp = keyboard_pcjr.pb;
163 break;
165 case 0x62:
166 temp = (keyboard_pcjr.latched ? 1 : 0);
167 temp |= 0x02; /*Modem card not installed*/
168 temp |= (ppispeakon ? 0x10 : 0);
169 temp |= (ppispeakon ? 0x20 : 0);
170 temp |= (keyboard_pcjr.data ? 0x40: 0);
171 // temp |= 0x04;
172 if (keyboard_pcjr.data)
173 temp |= 0x40;
174 break;
176 case 0xa0:
177 keyboard_pcjr.latched = 0;
178 break;
180 default:
181 pclog("\nBad XT keyboard read %04X\n", port);
182 //dumpregs();
183 //exit(-1);
184 }
185 // pclog("%02X\n", temp);
186 return temp;
187 }
189 void keyboard_pcjr_reset()
190 {
191 }
193 void keyboard_pcjr_init()
194 {
195 //return;
196 io_sethandler(0x0060, 0x0004, keyboard_pcjr_read, NULL, NULL, keyboard_pcjr_write, NULL, NULL, NULL);
197 io_sethandler(0x00a0, 0x0008, keyboard_pcjr_read, NULL, NULL, keyboard_pcjr_write, NULL, NULL, NULL);
198 keyboard_pcjr_reset();
199 keyboard_send = keyboard_pcjr_adddata;
200 keyboard_poll = keyboard_pcjr_poll;
202 timer_add(keyboard_pcjr_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
203 }
