1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include "gustate.h"
30#include "gusemu.h"
31
32#define GUSregb(position) (* (gusptr+(position)))
33#define GUSregw(position) (*(GUSword *) (gusptr+(position)))
34#define GUSregd(position) (*(GUSdword *)(gusptr+(position)))
35
36
37unsigned int gus_read(GUSEmuState * state, int port, int size)
38{
39 int value_read = 0;
40
41 GUSbyte *gusptr;
42 gusptr = state->gusdatapos;
43 GUSregd(portaccesses)++;
44
45 switch (port & 0xff0f)
46 {
47
48
49 case 0x206:
50
51
52
53
54 return GUSregb(IRQStatReg2x6);
55
56 case 0x208:
57 if (GUSregb(GUS45TimerCtrl) & 1)
58 return GUSregb(TimerStatus2x8);
59 return GUSregb(AdLibStatus2x8);
60 case 0x309:
61 case 0x209:
62 return GUSregb(AdLibData2x9);
63 case 0x20A:
64 return GUSregb(AdLibCommand2xA);
65
66#if 0
67 case 0x20B:
68 switch (GUSregb(RegCtrl_2xF) & 0x07)
69 {
70 case 0:
71 if (GUSregb(MixerCtrlReg2x0) & 0x40)
72 return GUSregb(IRQ_2xB);
73 else
74 return GUSregb(DMA_2xB);
75
76
77 case 6:
78 return GUSregb(Jumper_2xB);
79 default:;
80 }
81 break;
82#endif
83
84 case 0x20C:
85 value_read = GUSregb(SB2xCd);
86 if (GUSregb(StatRead_2xF) & 0x20)
87 GUSregb(SB2xCd) ^= 0x80;
88 return value_read;
89
90 case 0x20E:
91 if (GUSregb(RegCtrl_2xF) & 0x80)
92 {
93 GUSregb(StatRead_2xF) |= 0x80;
94 GUS_irqrequest(state, state->gusirq, 1);
95 }
96 return GUSregb(SB2xE);
97 case 0x20F:
98
99
100 value_read = (GUSregb(StatRead_2xF) & 0xf9);
101 if (GUSregb(MixerCtrlReg2x0) & 0x08)
102 value_read |= 2;
103 return value_read;
104
105
106 case 0x302:
107 return GUSregb(VoiceSelReg3x2);
108 case 0x303:
109 return GUSregb(FunkSelReg3x3);
110 case 0x304:
111 case 0x305:
112 switch (GUSregb(FunkSelReg3x3))
113 {
114
115 case 0x41:
116 value_read = GUSregb(GUS41DMACtrl);
117 GUSregb(GUS41DMACtrl) &= 0xbb;
118 if (state->gusdma >= 4)
119 value_read |= 0x04;
120 if (GUSregb(IRQStatReg2x6) & 0x80)
121 {
122 value_read |= 0x40;
123 GUSregb(IRQStatReg2x6) &= 0x7f;
124 if (!GUSregb(IRQStatReg2x6))
125 GUS_irqclear(state, state->gusirq);
126 }
127 return (GUSbyte) value_read;
128
129
130
131 case 0x45:
132 return GUSregb(GUS45TimerCtrl);
133
134
135 case 0x49:
136 return GUSregb(GUS49SampCtrl) & 0xbf;
137
138
139
140 case 0x80:
141 case 0x81:
142 case 0x82:
143 case 0x83:
144 case 0x84:
145 case 0x85:
146 case 0x86:
147 case 0x87:
148 case 0x88:
149 case 0x89:
150 case 0x8a:
151 case 0x8b:
152 case 0x8c:
153 case 0x8d:
154 {
155 int offset = 2 * (GUSregb(FunkSelReg3x3) & 0x0f);
156 offset += ((int) GUSregb(VoiceSelReg3x2) & 0x1f) << 5;
157 value_read = GUSregw(offset);
158 }
159 break;
160
161 case 0x8e:
162 return GUSregb(NumVoices);
163 case 0x8f:
164
165 return GUSregb(SynVoiceIRQ8f);
166 default:
167 return 0xffff;
168 }
169 if (size == 1)
170 {
171 if ((port & 0xff0f) == 0x305)
172 value_read = value_read >> 8;
173 value_read &= 0xff;
174 }
175 return (GUSword) value_read;
176
177
178 case 0x307:
179 {
180 GUSbyte *adr;
181 adr = state->himemaddr + (GUSregd(GUSDRAMPOS24bit) & 0xfffff);
182 return *adr;
183 }
184 default:;
185 }
186 return 0xffff;
187}
188
189void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
190{
191 GUSbyte *gusptr;
192 gusptr = state->gusdatapos;
193 GUSregd(portaccesses)++;
194
195 switch (port & 0xff0f)
196 {
197 case 0x200:
198 GUSregb(MixerCtrlReg2x0) = (GUSbyte) data;
199 break;
200 case 0x206:
201 if (GUSregb(GUS45TimerCtrl) & 0x20)
202 {
203 GUSregb(TimerStatus2x8) |= 0x08;
204 GUSregb(IRQStatReg2x6) = 0x10;
205 GUS_irqrequest(state, state->gusirq, 1);
206 }
207 break;
208 case 0x308:
209 case 0x208:
210 GUSregb(AdLibCommand2xA) = (GUSbyte) data;
211 break;
212 case 0x309:
213 case 0x209:
214 if ((GUSregb(AdLibCommand2xA) == 0x04) && (!(GUSregb(GUS45TimerCtrl) & 1)))
215 {
216 if (data & 0x80)
217 GUSregb(TimerStatus2x8) &= 0x1f;
218 else
219 GUSregb(TimerDataReg2x9) = (GUSbyte) data;
220 }
221 else
222 {
223 GUSregb(AdLibData2x9) = (GUSbyte) data;
224 if (GUSregb(GUS45TimerCtrl) & 0x02)
225 {
226 GUSregb(TimerStatus2x8) |= 0x01;
227 GUSregb(IRQStatReg2x6) = 0x10;
228 GUS_irqrequest(state, state->gusirq, 1);
229 }
230 }
231 break;
232 case 0x20A:
233 GUSregb(AdLibStatus2x8) = (GUSbyte) data;
234 break;
235 case 0x20B:
236 switch (GUSregb(RegCtrl_2xF) & 0x7)
237 {
238 case 0:
239 if (GUSregb(MixerCtrlReg2x0) & 0x40)
240 GUSregb(IRQ_2xB) = (GUSbyte) data;
241 else
242 GUSregb(DMA_2xB) = (GUSbyte) data;
243 break;
244
245 case 5:
246 GUSregb(StatRead_2xF) = 0;
247 if (!GUSregb(IRQStatReg2x6))
248 GUS_irqclear(state, state->gusirq);
249 break;
250 case 6:
251 GUSregb(Jumper_2xB) = (GUSbyte) data;
252 break;
253 default:;
254 }
255 break;
256 case 0x20C:
257 if (GUSregb(GUS45TimerCtrl) & 0x20)
258 {
259 GUSregb(TimerStatus2x8) |= 0x10;
260 GUSregb(IRQStatReg2x6) = 0x10;
261 GUS_irqrequest(state, state->gusirq, 1);
262 }
263 case 0x20D:
264 GUSregb(SB2xCd) = (GUSbyte) data;
265 break;
266 case 0x20E:
267 GUSregb(SB2xE) = (GUSbyte) data;
268 break;
269 case 0x20F:
270 GUSregb(RegCtrl_2xF) = (GUSbyte) data;
271 break;
272 case 0x302:
273 GUSregb(VoiceSelReg3x2) = (GUSbyte) data;
274 break;
275 case 0x303:
276 GUSregb(FunkSelReg3x3) = (GUSbyte) data;
277 if ((GUSbyte) data == 0x8f)
278 {
279 int voice;
280 if (GUSregd(voicewavetableirq))
281 {
282 for (voice = 0; voice < 31; voice++)
283 {
284 if (GUSregd(voicewavetableirq) & (1 << voice))
285 {
286 GUSregd(voicewavetableirq) ^= (1 << voice);
287 GUSregb(voice << 5) &= 0x7f;
288 if (!GUSregd(voicewavetableirq))
289 GUSregb(IRQStatReg2x6) &= 0xdf;
290 if (!GUSregb(IRQStatReg2x6))
291 GUS_irqclear(state, state->gusirq);
292 GUSregb(SynVoiceIRQ8f) = voice | 0x60;
293 return;
294 }
295 }
296 }
297 else if (GUSregd(voicevolrampirq))
298 {
299 for (voice = 0; voice < 31; voice++)
300 {
301 if (GUSregd(voicevolrampirq) & (1 << voice))
302 {
303 GUSregd(voicevolrampirq) ^= (1 << voice);
304 GUSregb((voice << 5) + VSRVolRampControl) &= 0x7f;
305 if (!GUSregd(voicevolrampirq))
306 GUSregb(IRQStatReg2x6) &= 0xbf;
307 if (!GUSregb(IRQStatReg2x6))
308 GUS_irqclear(state, state->gusirq);
309 GUSregb(SynVoiceIRQ8f) = voice | 0x80;
310 return;
311 }
312 }
313 }
314 GUSregb(SynVoiceIRQ8f) = 0xe8;
315 }
316 break;
317 case 0x304:
318 case 0x305:
319 {
320 GUSword writedata = (GUSword) data;
321 GUSword readmask = 0x0000;
322 if (size == 1)
323 {
324 readmask = 0xff00;
325 writedata &= 0xff;
326 if ((port & 0xff0f) == 0x305)
327 {
328 writedata = (GUSword) (writedata << 8);
329 readmask = 0x00ff;
330 }
331 }
332 switch (GUSregb(FunkSelReg3x3))
333 {
334
335 case 0x00:
336 case 0x01:
337 case 0x02:
338 case 0x03:
339 case 0x04:
340 case 0x05:
341 case 0x06:
342 case 0x07:
343 case 0x08:
344 case 0x09:
345 case 0x0a:
346 case 0x0b:
347 case 0x0c:
348 case 0x0d:
349 {
350 int offset;
351 if (!(GUSregb(GUS4cReset) & 0x01))
352 break;
353 offset = 2 * (GUSregb(FunkSelReg3x3) & 0x0f);
354 offset += (GUSregb(VoiceSelReg3x2) & 0x1f) << 5;
355 GUSregw(offset) = (GUSword) ((GUSregw(offset) & readmask) | writedata);
356 }
357 break;
358
359 case 0x0e:
360 GUSregb(NumVoices) = (GUSbyte) data;
361 break;
362
363
364 case 0x41:
365 GUSregb(GUS41DMACtrl) = (GUSbyte) data;
366 if (data & 0x01)
367 GUS_dmarequest(state);
368 break;
369 case 0x42:
370 GUSregw(GUS42DMAStart) = (GUSregw(GUS42DMAStart) & readmask) | writedata;
371 GUSregb(GUS50DMAHigh) &= 0xf;
372 break;
373 case 0x43:
374 GUSregd(GUSDRAMPOS24bit) =
375 (GUSregd(GUSDRAMPOS24bit) & (readmask | 0xff0000)) | writedata;
376 break;
377 case 0x44:
378 GUSregd(GUSDRAMPOS24bit) =
379 (GUSregd(GUSDRAMPOS24bit) & 0xffff) | ((data & 0x0f) << 16);
380 break;
381 case 0x45:
382 GUSregb(GUS45TimerCtrl) = (GUSbyte) data;
383 if (!(data & 0x20))
384 GUSregb(TimerStatus2x8) &= 0xe7;
385 if (!(data & 0x02))
386 GUSregb(TimerStatus2x8) &= 0xfe;
387 if (!(GUSregb(TimerStatus2x8) & 0x19))
388 GUSregb(IRQStatReg2x6) &= 0xef;
389
390 if ((GUSregw(TimerIRQs) > 1) && (GUSregb(TimerDataReg2x9) & 3))
391 {
392 if (GUSregb(TimerDataReg2x9) & 1)
393 {
394 if (!(GUSregb(TimerDataReg2x9) & 0x40))
395 GUSregb(TimerStatus2x8) |= 0xc0;
396 if (data & 4)
397 {
398 GUSregb(TimerStatus2x8) |= 4;
399 GUSregb(IRQStatReg2x6) |= 4;
400 }
401 }
402 if (GUSregb(TimerDataReg2x9) & 2)
403 {
404 if (!(GUSregb(TimerDataReg2x9) & 0x20))
405 GUSregb(TimerStatus2x8) |= 0xa0;
406 if (data & 8)
407 {
408 GUSregb(TimerStatus2x8) |= 2;
409 GUSregb(IRQStatReg2x6) |= 8;
410 }
411 }
412 GUSregw(TimerIRQs)--;
413 if (GUSregw(BusyTimerIRQs) > 1)
414 GUSregw(BusyTimerIRQs)--;
415 else
416 GUSregw(BusyTimerIRQs) =
417 GUS_irqrequest(state, state->gusirq, GUSregw(TimerIRQs));
418 }
419 else
420 GUSregw(TimerIRQs) = 0;
421
422 if (!(data & 0x04))
423 {
424 GUSregb(TimerStatus2x8) &= 0xfb;
425 GUSregb(IRQStatReg2x6) &= 0xfb;
426 }
427 if (!(data & 0x08))
428 {
429 GUSregb(TimerStatus2x8) &= 0xfd;
430 GUSregb(IRQStatReg2x6) &= 0xf7;
431 }
432 if (!GUSregb(IRQStatReg2x6))
433 GUS_irqclear(state, state->gusirq);
434 break;
435 case 0x46:
436 GUSregb(GUS46Counter1) = (GUSbyte) data;
437 break;
438 case 0x47:
439 GUSregb(GUS47Counter2) = (GUSbyte) data;
440 break;
441
442 case 0x49:
443 GUSregb(GUS49SampCtrl) = (GUSbyte) data;
444 break;
445
446 case 0x4c:
447 GUSregb(GUS4cReset) = (GUSbyte) data;
448 if (!(GUSregb(GUS4cReset) & 1))
449 {
450 GUSregd(voicewavetableirq) = 0;
451 GUSregd(voicevolrampirq) = 0;
452 GUSregw(TimerIRQs) = 0;
453 GUSregw(BusyTimerIRQs) = 0;
454 GUSregb(NumVoices) = 0xcd;
455 GUSregb(IRQStatReg2x6) = 0;
456 GUSregb(TimerStatus2x8) = 0;
457 GUSregb(AdLibData2x9) = 0;
458 GUSregb(TimerDataReg2x9) = 0;
459 GUSregb(GUS41DMACtrl) = 0;
460 GUSregb(GUS45TimerCtrl) = 0;
461 GUSregb(GUS49SampCtrl) = 0;
462 GUSregb(GUS4cReset) &= 0xf9;
463 GUS_irqclear(state, state->gusirq);
464 }
465
466
467 break;
468 }
469 }
470 break;
471 case 0x307:
472 {
473 GUSbyte *adr;
474 adr = state->himemaddr + (GUSregd(GUSDRAMPOS24bit) & 0xfffff);
475 *adr = (GUSbyte) data;
476 }
477 break;
478 }
479}
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500void gus_dma_transferdata(GUSEmuState * state, char *dma_addr, unsigned int count, int TC)
501{
502
503
504
505
506
507
508
509 char *srcaddr;
510 char *destaddr;
511 char msbmask = 0;
512 GUSbyte *gusptr;
513 gusptr = state->gusdatapos;
514
515 srcaddr = dma_addr;
516 {
517 int offset = (GUSregw(GUS42DMAStart) << 4) + (GUSregb(GUS50DMAHigh) & 0xf);
518 if (state->gusdma >= 4)
519 offset = (offset & 0xc0000) + (2 * (offset & 0x1fff0));
520 destaddr = (char *) state->himemaddr + offset;
521 }
522
523 GUSregw(GUS42DMAStart) += (GUSword) (count >> 4);
524 GUSregb(GUS50DMAHigh) = (GUSbyte) ((count + GUSregb(GUS50DMAHigh)) & 0xf);
525
526 if (GUSregb(GUS41DMACtrl) & 0x02)
527 {
528 char *tmpaddr = destaddr;
529 destaddr = srcaddr;
530 srcaddr = tmpaddr;
531 }
532
533 if ((GUSregb(GUS41DMACtrl) & 0x80) && (!(GUSregb(GUS41DMACtrl) & 0x02)))
534 msbmask = (const char) 0x80;
535 for (; count > 0; count--)
536 {
537 if (GUSregb(GUS41DMACtrl) & 0x40)
538 *(destaddr++) = *(srcaddr++);
539 else
540 *(destaddr++) = (msbmask ^ (*(srcaddr++)));
541 if (state->gusdma >= 4)
542 *(destaddr++) = (msbmask ^ (*(srcaddr++)));
543 }
544
545 if (TC)
546 {
547 (GUSregb(GUS41DMACtrl)) &= 0xfe;
548 if (GUSregb(GUS41DMACtrl) & 0x20)
549 {
550 GUSregb(IRQStatReg2x6) |= 0x80;
551 GUS_irqrequest(state, state->gusirq, 1);
552 }
553 }
554}
555