1 /*
2 * Copyright (C) 2002-2015 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19
20 #include <iomanip>
21 #include <sstream>
22 #include <string.h>
23 #include <math.h>
24 #include "dosbox.h"
25 #include "inout.h"
26 #include "mixer.h"
27 #include "dma.h"
28 #include "pic.h"
29 #include "hardware.h"
30 #include "setup.h"
31 #include "support.h"
32 #include "shell.h"
33 using namespace std;
34
35 void MIDI_RawOutByte(Bit8u data);
36 bool MIDI_Available(void);
37
38 #define SB_PIC_EVENTS 0
39
40 #define DSP_MAJOR 3
41 #define DSP_MINOR 1
42
43 #define MIXER_INDEX 0x04
44 #define MIXER_DATA 0x05
45
46 #define DSP_RESET 0x06
47 #define DSP_READ_DATA 0x0A
48 #define DSP_WRITE_DATA 0x0C
49 #define DSP_WRITE_STATUS 0x0C
50 #define DSP_READ_STATUS 0x0E
51 #define DSP_ACK_16BIT 0x0f
52
53 #define DSP_NO_COMMAND 0
54
55 #define DMA_BUFSIZE 1024
56 #define DSP_BUFSIZE 64
57 #define DSP_DACSIZE 512
58
59 //Should be enough for sound generated in millisecond blocks
60 #define SB_BUF_SIZE 8096
61 #define SB_SH 14
62 #define SB_SH_MASK ((1 << SB_SH)-1)
63
64 enum {DSP_S_RESET,DSP_S_RESET_WAIT,DSP_S_NORMAL,DSP_S_HIGHSPEED};
65 enum SB_TYPES {SBT_NONE=0,SBT_1=1,SBT_PRO1=2,SBT_2=3,SBT_PRO2=4,SBT_16=6,SBT_GB=7};
66 enum SB_IRQS {SB_IRQ_8,SB_IRQ_16,SB_IRQ_MPU};
67
68 enum DSP_MODES {
69 MODE_NONE,
70 MODE_DAC,
71 MODE_DMA,
72 MODE_DMA_PAUSE,
73 MODE_DMA_MASKED
74
75 };
76
77 enum DMA_MODES {
78 DSP_DMA_NONE,
79 DSP_DMA_2,DSP_DMA_3,DSP_DMA_4,DSP_DMA_8,
80 DSP_DMA_16,DSP_DMA_16_ALIASED
81 };
82
83 enum {
84 PLAY_MONO,PLAY_STEREO
85 };
86
87 struct SB_INFO {
88 Bitu freq;
89 struct {
90 bool stereo,sign,autoinit;
91 DMA_MODES mode;
92 Bitu rate,mul;
93 Bitu total,left,min;
94 Bit64u start;
95 union {
96 Bit8u b8[DMA_BUFSIZE];
97 Bit16s b16[DMA_BUFSIZE];
98 } buf;
99 Bitu bits;
100 DmaChannel * chan;
101 Bitu remain_size;
102 } dma;
103 bool speaker;
104 bool midi;
105 Bit8u time_constant;
106 DSP_MODES mode;
107 SB_TYPES type;
108 struct {
109 bool pending_8bit;
110 bool pending_16bit;
111 } irq;
112 struct {
113 Bit8u state;
114 Bit8u cmd;
115 Bit8u cmd_len;
116 Bit8u cmd_in_pos;
117 Bit8u cmd_in[DSP_BUFSIZE];
118 struct {
119 Bit8u lastval;
120 Bit8u data[DSP_BUFSIZE];
121 Bitu pos,used;
122 } in,out;
123 Bit8u test_register;
124 Bitu write_busy;
125 } dsp;
126 struct {
127 Bit16s data[DSP_DACSIZE+1];
128 Bitu used;
129 Bit16s last;
130 } dac;
131 struct {
132 Bit8u index;
133 Bit8u dac[2],fm[2],cda[2],master[2],lin[2];
134 Bit8u mic;
135 bool stereo;
136 bool enabled;
137 bool filtered;
138 Bit8u unhandled[0x48];
139 } mixer;
140 struct {
141 Bit8u reference;
142 Bits stepsize;
143 bool haveref;
144 } adpcm;
145 struct {
146 Bitu base;
147 Bitu irq;
148 Bit8u dma8,dma16;
149 } hw;
150 struct {
151 Bits value;
152 Bitu count;
153 } e2;
154 MixerChannel * chan;
155 };
156
157
158
159 static SB_INFO sb;
160
161 static char const * const copyright_string="COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
162
163 // number of bytes in input for commands (sb/sbpro)
164 static Bit8u DSP_cmd_len_sb[256] = {
165 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00
166 // 1,0,0,0, 2,0,2,2, 0,0,0,0, 0,0,0,0, // 0x10
167 1,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x10 Wari hack
168 0,0,0,0, 2,0,0,0, 0,0,0,0, 0,0,0,0, // 0x20
169 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, // 0x30
170
171 1,2,2,0, 0,0,0,0, 2,0,0,0, 0,0,0,0, // 0x40
172 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50
173 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60
174 0,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x70
175
176 2,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x80
177 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x90
178 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xa0
179 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xb0
180
181 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xc0
182 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xd0
183 1,0,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, // 0xe0
184 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // 0xf0
185 };
186
187 // number of bytes in input for commands (sb16)
188 static Bit8u DSP_cmd_len_sb16[256] = {
189 0,0,0,0, 1,2,0,0, 1,0,0,0, 0,0,2,1, // 0x00
190 // 1,0,0,0, 2,0,2,2, 0,0,0,0, 0,0,0,0, // 0x10
191 1,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x10 Wari hack
192 0,0,0,0, 2,0,0,0, 0,0,0,0, 0,0,0,0, // 0x20
193 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, // 0x30
194
195 1,2,2,0, 0,0,0,0, 2,0,0,0, 0,0,0,0, // 0x40
196 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50
197 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60
198 0,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x70
199
200 2,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x80
201 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x90
202 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xa0
203 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xb0
204
205 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xc0
206 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xd0
207 1,0,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, // 0xe0
208 0,0,0,0, 0,0,0,0, 0,1,0,0, 0,0,0,0 // 0xf0
209 };
210
211 static Bit8u ASP_regs[256];
212 static bool ASP_init_in_progress = false;
213
214 static int E2_incr_table[4][9] = {
215 { 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 },
216 { -0x01, 0x02, -0x04, 0x08, 0x10, -0x20, 0x40, -0x80, 165 },
217 { -0x01, 0x02, 0x04, -0x08, 0x10, -0x20, -0x40, 0x80, -151 },
218 { 0x01, -0x02, 0x04, -0x08, -0x10, 0x20, -0x40, 0x80, 90 }
219 };
220
221 #ifndef max
222 #define max(a,b) ((a)>(b)?(a):(b))
223 #endif
224 #ifndef min
225 #define min(a,b) ((a)<(b)?(a):(b))
226 #endif
227
228 static void DSP_ChangeMode(DSP_MODES mode);
229 static void CheckDMAEnd();
230 static void END_DMA_Event(Bitu);
231 static void DMA_Silent_Event(Bitu val);
232 static void GenerateDMASound(Bitu size);
233
DSP_SetSpeaker(bool how)234 static void DSP_SetSpeaker(bool how) {
235 if (sb.speaker==how) return;
236 sb.speaker=how;
237 if (sb.type==SBT_16) return;
238 sb.chan->Enable(how);
239 if (sb.speaker) {
240 PIC_RemoveEvents(DMA_Silent_Event);
241 CheckDMAEnd();
242 } else {
243
244 }
245 }
246
SB_RaiseIRQ(SB_IRQS type)247 static INLINE void SB_RaiseIRQ(SB_IRQS type) {
248 LOG(LOG_SB,LOG_NORMAL)("Raising IRQ");
249 switch (type) {
250 case SB_IRQ_8:
251 if (sb.irq.pending_8bit) {
252 // LOG_MSG("SB: 8bit irq pending");
253 return;
254 }
255 sb.irq.pending_8bit=true;
256 PIC_ActivateIRQ(sb.hw.irq);
257 break;
258 case SB_IRQ_16:
259 if (sb.irq.pending_16bit) {
260 // LOG_MSG("SB: 16bit irq pending");
261 return;
262 }
263 sb.irq.pending_16bit=true;
264 PIC_ActivateIRQ(sb.hw.irq);
265 break;
266 default:
267 break;
268 }
269 }
270
DSP_FlushData(void)271 static INLINE void DSP_FlushData(void) {
272 sb.dsp.out.used=0;
273 sb.dsp.out.pos=0;
274 }
275
DSP_DMA_CallBack(DmaChannel * chan,DMAEvent event)276 static void DSP_DMA_CallBack(DmaChannel * chan, DMAEvent event) {
277 if (chan!=sb.dma.chan || event==DMA_REACHED_TC) return;
278 else if (event==DMA_MASKED) {
279 if (sb.mode==MODE_DMA) {
280 GenerateDMASound(sb.dma.min);
281 sb.mode=MODE_DMA_MASKED;
282 // DSP_ChangeMode(MODE_DMA_MASKED);
283 LOG(LOG_SB,LOG_NORMAL)("DMA masked,stopping output, left %d",chan->currcnt);
284 }
285 } else if (event==DMA_UNMASKED) {
286 if (sb.mode==MODE_DMA_MASKED && sb.dma.mode!=DSP_DMA_NONE) {
287 DSP_ChangeMode(MODE_DMA);
288 // sb.mode=MODE_DMA;
289 CheckDMAEnd();
290 LOG(LOG_SB,LOG_NORMAL)("DMA unmasked,starting output, auto %d block %d",chan->autoinit,chan->basecnt);
291 }
292 }
293 }
294
295 #define MIN_ADAPTIVE_STEP_SIZE 0
296 #define MAX_ADAPTIVE_STEP_SIZE 32767
297 #define DC_OFFSET_FADE 254
298
decode_ADPCM_4_sample(Bit8u sample,Bit8u & reference,Bits & scale)299 static INLINE Bit8u decode_ADPCM_4_sample(Bit8u sample,Bit8u & reference,Bits& scale) {
300 static const Bit8s scaleMap[64] = {
301 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7,
302 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15,
303 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30,
304 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60
305 };
306 static const Bit8u adjustMap[64] = {
307 0, 0, 0, 0, 0, 16, 16, 16,
308 0, 0, 0, 0, 0, 16, 16, 16,
309 240, 0, 0, 0, 0, 16, 16, 16,
310 240, 0, 0, 0, 0, 16, 16, 16,
311 240, 0, 0, 0, 0, 16, 16, 16,
312 240, 0, 0, 0, 0, 16, 16, 16,
313 240, 0, 0, 0, 0, 0, 0, 0,
314 240, 0, 0, 0, 0, 0, 0, 0
315 };
316
317 Bits samp = sample + scale;
318
319 if ((samp < 0) || (samp > 63)) {
320 LOG(LOG_SB,LOG_ERROR)("Bad ADPCM-4 sample");
321 if(samp < 0 ) samp = 0;
322 if(samp > 63) samp = 63;
323 }
324
325 Bits ref = reference + scaleMap[samp];
326 if (ref > 0xff) reference = 0xff;
327 else if (ref < 0x00) reference = 0x00;
328 else reference = (Bit8u)(ref&0xff);
329 scale = (scale + adjustMap[samp]) & 0xff;
330
331 return reference;
332 }
333
decode_ADPCM_2_sample(Bit8u sample,Bit8u & reference,Bits & scale)334 static INLINE Bit8u decode_ADPCM_2_sample(Bit8u sample,Bit8u & reference,Bits& scale) {
335 static const Bit8s scaleMap[24] = {
336 0, 1, 0, -1, 1, 3, -1, -3,
337 2, 6, -2, -6, 4, 12, -4, -12,
338 8, 24, -8, -24, 6, 48, -16, -48
339 };
340 static const Bit8u adjustMap[24] = {
341 0, 4, 0, 4,
342 252, 4, 252, 4, 252, 4, 252, 4,
343 252, 4, 252, 4, 252, 4, 252, 4,
344 252, 0, 252, 0
345 };
346
347 Bits samp = sample + scale;
348 if ((samp < 0) || (samp > 23)) {
349 LOG(LOG_SB,LOG_ERROR)("Bad ADPCM-2 sample");
350 if(samp < 0 ) samp = 0;
351 if(samp > 23) samp = 23;
352 }
353
354 Bits ref = reference + scaleMap[samp];
355 if (ref > 0xff) reference = 0xff;
356 else if (ref < 0x00) reference = 0x00;
357 else reference = (Bit8u)(ref&0xff);
358 scale = (scale + adjustMap[samp]) & 0xff;
359
360 return reference;
361 }
362
decode_ADPCM_3_sample(Bit8u sample,Bit8u & reference,Bits & scale)363 INLINE Bit8u decode_ADPCM_3_sample(Bit8u sample,Bit8u & reference,Bits& scale) {
364 static const Bit8s scaleMap[40] = {
365 0, 1, 2, 3, 0, -1, -2, -3,
366 1, 3, 5, 7, -1, -3, -5, -7,
367 2, 6, 10, 14, -2, -6, -10, -14,
368 4, 12, 20, 28, -4, -12, -20, -28,
369 5, 15, 25, 35, -5, -15, -25, -35
370 };
371 static const Bit8u adjustMap[40] = {
372 0, 0, 0, 8, 0, 0, 0, 8,
373 248, 0, 0, 8, 248, 0, 0, 8,
374 248, 0, 0, 8, 248, 0, 0, 8,
375 248, 0, 0, 8, 248, 0, 0, 8,
376 248, 0, 0, 0, 248, 0, 0, 0
377 };
378
379 Bits samp = sample + scale;
380 if ((samp < 0) || (samp > 39)) {
381 LOG(LOG_SB,LOG_ERROR)("Bad ADPCM-3 sample");
382 if(samp < 0 ) samp = 0;
383 if(samp > 39) samp = 39;
384 }
385
386 Bits ref = reference + scaleMap[samp];
387 if (ref > 0xff) reference = 0xff;
388 else if (ref < 0x00) reference = 0x00;
389 else reference = (Bit8u)(ref&0xff);
390 scale = (scale + adjustMap[samp]) & 0xff;
391
392 return reference;
393 }
394
GenerateDMASound(Bitu size)395 static void GenerateDMASound(Bitu size) {
396 Bitu read=0;Bitu done=0;Bitu i=0;
397
398 if(sb.dma.autoinit) {
399 if (sb.dma.left <= size) size = sb.dma.left;
400 } else if (sb.dma.left <= sb.dma.min) size = sb.dma.left;
401
402 switch (sb.dma.mode) {
403 case DSP_DMA_2:
404 read=sb.dma.chan->Read(size,sb.dma.buf.b8);
405 if (read && sb.adpcm.haveref) {
406 sb.adpcm.haveref=false;
407 sb.adpcm.reference=sb.dma.buf.b8[0];
408 sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE;
409 i++;
410 }
411 for (;i<read;i++) {
412 MixTemp[done++]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >> 6) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize);
413 MixTemp[done++]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >> 4) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize);
414 MixTemp[done++]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >> 2) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize);
415 MixTemp[done++]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >> 0) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize);
416 }
417 sb.chan->AddSamples_m8(done,MixTemp);
418 break;
419 case DSP_DMA_3:
420 read=sb.dma.chan->Read(size,sb.dma.buf.b8);
421 if (read && sb.adpcm.haveref) {
422 sb.adpcm.haveref=false;
423 sb.adpcm.reference=sb.dma.buf.b8[0];
424 sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE;
425 i++;
426 }
427 for (;i<read;i++) {
428 MixTemp[done++]=decode_ADPCM_3_sample((sb.dma.buf.b8[i] >> 5) & 0x7,sb.adpcm.reference,sb.adpcm.stepsize);
429 MixTemp[done++]=decode_ADPCM_3_sample((sb.dma.buf.b8[i] >> 2) & 0x7,sb.adpcm.reference,sb.adpcm.stepsize);
430 MixTemp[done++]=decode_ADPCM_3_sample((sb.dma.buf.b8[i] & 0x3) << 1,sb.adpcm.reference,sb.adpcm.stepsize);
431 }
432 sb.chan->AddSamples_m8(done,MixTemp);
433 break;
434 case DSP_DMA_4:
435 read=sb.dma.chan->Read(size,sb.dma.buf.b8);
436 if (read && sb.adpcm.haveref) {
437 sb.adpcm.haveref=false;
438 sb.adpcm.reference=sb.dma.buf.b8[0];
439 sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE;
440 i++;
441 }
442 for (;i<read;i++) {
443 MixTemp[done++]=decode_ADPCM_4_sample(sb.dma.buf.b8[i] >> 4,sb.adpcm.reference,sb.adpcm.stepsize);
444 MixTemp[done++]=decode_ADPCM_4_sample(sb.dma.buf.b8[i]& 0xf,sb.adpcm.reference,sb.adpcm.stepsize);
445 }
446 sb.chan->AddSamples_m8(done,MixTemp);
447 break;
448 case DSP_DMA_8:
449 if (sb.dma.stereo) {
450 read=sb.dma.chan->Read(size,&sb.dma.buf.b8[sb.dma.remain_size]);
451 Bitu total=read+sb.dma.remain_size;
452 if (!sb.dma.sign) sb.chan->AddSamples_s8(total>>1,sb.dma.buf.b8);
453 else sb.chan->AddSamples_s8s(total>>1,(Bit8s*)sb.dma.buf.b8);
454 if (total&1) {
455 sb.dma.remain_size=1;
456 sb.dma.buf.b8[0]=sb.dma.buf.b8[total-1];
457 } else sb.dma.remain_size=0;
458 } else {
459 read=sb.dma.chan->Read(size,sb.dma.buf.b8);
460 if (!sb.dma.sign) sb.chan->AddSamples_m8(read,sb.dma.buf.b8);
461 else sb.chan->AddSamples_m8s(read,(Bit8s *)sb.dma.buf.b8);
462 }
463 break;
464 case DSP_DMA_16:
465 case DSP_DMA_16_ALIASED:
466 if (sb.dma.stereo) {
467 /* In DSP_DMA_16_ALIASED mode temporarily divide by 2 to get number of 16-bit
468 samples, because 8-bit DMA Read returns byte size, while in DSP_DMA_16 mode
469 16-bit DMA Read returns word size */
470 read=sb.dma.chan->Read(size,(Bit8u *)&sb.dma.buf.b16[sb.dma.remain_size])
471 >> (sb.dma.mode==DSP_DMA_16_ALIASED ? 1:0);
472 Bitu total=read+sb.dma.remain_size;
473 #if defined(WORDS_BIGENDIAN)
474 if (sb.dma.sign) sb.chan->AddSamples_s16_nonnative(total>>1,sb.dma.buf.b16);
475 else sb.chan->AddSamples_s16u_nonnative(total>>1,(Bit16u *)sb.dma.buf.b16);
476 #else
477 if (sb.dma.sign) sb.chan->AddSamples_s16(total>>1,sb.dma.buf.b16);
478 else sb.chan->AddSamples_s16u(total>>1,(Bit16u *)sb.dma.buf.b16);
479 #endif
480 if (total&1) {
481 sb.dma.remain_size=1;
482 sb.dma.buf.b16[0]=sb.dma.buf.b16[total-1];
483 } else sb.dma.remain_size=0;
484 } else {
485 read=sb.dma.chan->Read(size,(Bit8u *)sb.dma.buf.b16)
486 >> (sb.dma.mode==DSP_DMA_16_ALIASED ? 1:0);
487 #if defined(WORDS_BIGENDIAN)
488 if (sb.dma.sign) sb.chan->AddSamples_m16_nonnative(read,sb.dma.buf.b16);
489 else sb.chan->AddSamples_m16u_nonnative(read,(Bit16u *)sb.dma.buf.b16);
490 #else
491 if (sb.dma.sign) sb.chan->AddSamples_m16(read,sb.dma.buf.b16);
492 else sb.chan->AddSamples_m16u(read,(Bit16u *)sb.dma.buf.b16);
493 #endif
494 }
495 //restore buffer length value to byte size in aliased mode
496 if (sb.dma.mode==DSP_DMA_16_ALIASED) read=read<<1;
497 break;
498 default:
499 LOG_MSG("Unhandled dma mode %d",sb.dma.mode);
500 sb.mode=MODE_NONE;
501 return;
502 }
503 sb.dma.left-=read;
504 if (!sb.dma.left) {
505 PIC_RemoveEvents(END_DMA_Event);
506 if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16);
507 else SB_RaiseIRQ(SB_IRQ_8);
508 if (!sb.dma.autoinit) {
509 LOG(LOG_SB,LOG_NORMAL)("Single cycle transfer ended");
510 sb.mode=MODE_NONE;
511 sb.dma.mode=DSP_DMA_NONE;
512 } else {
513 sb.dma.left=sb.dma.total;
514 if (!sb.dma.left) {
515 LOG(LOG_SB,LOG_NORMAL)("Auto-init transfer with 0 size");
516 sb.mode=MODE_NONE;
517 }
518 }
519 }
520 }
521
522 /* old version...
523 static void GenerateDACSound(Bitu len) {
524 if (!sb.dac.used) {
525 sb.mode=MODE_NONE;
526 return;
527 }
528 Bitu dac_add=(sb.dac.used<<16)/len;
529 Bitu dac_pos=0;
530 Bit16s * out=(Bit16s *)MixTemp;
531 for (Bitu i=len;i;i--) {
532 *out++=sb.dac.data[0+(dac_pos>>16)];
533 dac_pos+=dac_add;
534 }
535 sb.dac.used=0;
536 sb.chan->AddSamples_m16(len,(Bit16s *)MixTemp);
537 }
538 */
539
DMA_Silent_Event(Bitu val)540 static void DMA_Silent_Event(Bitu val) {
541 if (sb.dma.left<val) val=sb.dma.left;
542 Bitu read=sb.dma.chan->Read(val,sb.dma.buf.b8);
543 sb.dma.left-=read;
544 if (!sb.dma.left) {
545 if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16);
546 else SB_RaiseIRQ(SB_IRQ_8);
547 if (sb.dma.autoinit) sb.dma.left=sb.dma.total;
548 else {
549 sb.mode=MODE_NONE;
550 sb.dma.mode=DSP_DMA_NONE;
551 }
552 }
553 if (sb.dma.left) {
554 Bitu bigger=(sb.dma.left > sb.dma.min) ? sb.dma.min : sb.dma.left;
555 float delay=(bigger*1000.0f)/sb.dma.rate;
556 PIC_AddEvent(DMA_Silent_Event,delay,bigger);
557 }
558
559 }
560
END_DMA_Event(Bitu val)561 static void END_DMA_Event(Bitu val) {
562 GenerateDMASound(val);
563 }
564
CheckDMAEnd(void)565 static void CheckDMAEnd(void) {
566 if (!sb.dma.left) return;
567 if (!sb.speaker && sb.type!=SBT_16) {
568 Bitu bigger=(sb.dma.left > sb.dma.min) ? sb.dma.min : sb.dma.left;
569 float delay=(bigger*1000.0f)/sb.dma.rate;
570 PIC_AddEvent(DMA_Silent_Event,delay,bigger);
571 LOG(LOG_SB,LOG_NORMAL)("Silent DMA Transfer scheduling IRQ in %.3f milliseconds",delay);
572 } else if (sb.dma.left<sb.dma.min) {
573 float delay=(sb.dma.left*1000.0f)/sb.dma.rate;
574 LOG(LOG_SB,LOG_NORMAL)("Short transfer scheduling IRQ in %.3f milliseconds",delay);
575 PIC_AddEvent(END_DMA_Event,delay,sb.dma.left);
576 }
577 }
578
DSP_ChangeMode(DSP_MODES mode)579 static void DSP_ChangeMode(DSP_MODES mode) {
580 if (sb.mode==mode) return;
581 else sb.chan->FillUp();
582 sb.mode=mode;
583 }
584
DSP_RaiseIRQEvent(Bitu)585 static void DSP_RaiseIRQEvent(Bitu /*val*/) {
586 SB_RaiseIRQ(SB_IRQ_8);
587 }
588
DSP_DoDMATransfer(DMA_MODES mode,Bitu freq,bool stereo)589 static void DSP_DoDMATransfer(DMA_MODES mode,Bitu freq,bool stereo) {
590 char const * type;
591 sb.mode=MODE_DMA_MASKED;
592 sb.chan->FillUp();
593 sb.dma.left=sb.dma.total;
594 sb.dma.mode=mode;
595 sb.dma.stereo=stereo;
596 sb.irq.pending_8bit=false;
597 sb.irq.pending_16bit=false;
598 switch (mode) {
599 case DSP_DMA_2:
600 type="2-bits ADPCM";
601 sb.dma.mul=(1 << SB_SH)/4;
602 break;
603 case DSP_DMA_3:
604 type="3-bits ADPCM";
605 sb.dma.mul=(1 << SB_SH)/3;
606 break;
607 case DSP_DMA_4:
608 type="4-bits ADPCM";
609 sb.dma.mul=(1 << SB_SH)/2;
610 break;
611 case DSP_DMA_8:
612 type="8-bits PCM";
613 sb.dma.mul=(1 << SB_SH);
614 break;
615 case DSP_DMA_16_ALIASED:
616 type="16-bits(aliased) PCM";
617 sb.dma.mul=(1 << SB_SH)*2;
618 break;
619 case DSP_DMA_16:
620 type="16-bits PCM";
621 sb.dma.mul=(1 << SB_SH);
622 break;
623 default:
624 LOG(LOG_SB,LOG_ERROR)("DSP:Illegal transfer mode %d",mode);
625 return;
626 }
627 if (sb.dma.stereo) sb.dma.mul*=2;
628 sb.dma.rate=(sb.freq*sb.dma.mul) >> SB_SH;
629 sb.dma.min=(sb.dma.rate*3)/1000;
630 sb.chan->SetFreq(freq);
631 sb.dma.mode=mode;
632 PIC_RemoveEvents(END_DMA_Event);
633 sb.dma.chan->Register_Callback(DSP_DMA_CallBack);
634 #if (C_DEBUG)
635 LOG(LOG_SB,LOG_NORMAL)("DMA Transfer:%s %s %s freq %d rate %d size %d",
636 type,
637 sb.dma.stereo ? "Stereo" : "Mono",
638 sb.dma.autoinit ? "Auto-Init" : "Single-Cycle",
639 freq,sb.dma.rate,sb.dma.total
640 );
641 #endif
642 }
643
DSP_PrepareDMA_Old(DMA_MODES mode,bool autoinit,bool sign)644 static void DSP_PrepareDMA_Old(DMA_MODES mode,bool autoinit,bool sign) {
645 sb.dma.autoinit=autoinit;
646 sb.dma.sign=sign;
647 if (!autoinit) sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
648 sb.dma.chan=GetDMAChannel(sb.hw.dma8);
649 DSP_DoDMATransfer(mode,sb.freq / (sb.mixer.stereo ? 2 : 1),sb.mixer.stereo);
650 }
651
DSP_PrepareDMA_New(DMA_MODES mode,Bitu length,bool autoinit,bool stereo)652 static void DSP_PrepareDMA_New(DMA_MODES mode,Bitu length,bool autoinit,bool stereo) {
653 Bitu freq=sb.freq;
654 //equal length if data format and dma channel are both 16-bit or 8-bit
655 sb.dma.total=length;
656 sb.dma.autoinit=autoinit;
657 if (mode==DSP_DMA_16) {
658 if (sb.hw.dma16!=0xff) {
659 sb.dma.chan=GetDMAChannel(sb.hw.dma16);
660 if (sb.dma.chan==NULL) {
661 sb.dma.chan=GetDMAChannel(sb.hw.dma8);
662 mode=DSP_DMA_16_ALIASED;
663 sb.dma.total<<=1;
664 }
665 } else {
666 sb.dma.chan=GetDMAChannel(sb.hw.dma8);
667 mode=DSP_DMA_16_ALIASED;
668 //UNDOCUMENTED:
669 //In aliased mode sample length is written to DSP as number of
670 //16-bit samples so we need double 8-bit DMA buffer length
671 sb.dma.total<<=1;
672 }
673 } else sb.dma.chan=GetDMAChannel(sb.hw.dma8);
674 DSP_DoDMATransfer(mode,freq,stereo);
675 }
676
677
DSP_AddData(Bit8u val)678 static void DSP_AddData(Bit8u val) {
679 if (sb.dsp.out.used<DSP_BUFSIZE) {
680 Bitu start=sb.dsp.out.used+sb.dsp.out.pos;
681 if (start>=DSP_BUFSIZE) start-=DSP_BUFSIZE;
682 sb.dsp.out.data[start]=val;
683 sb.dsp.out.used++;
684 } else {
685 LOG(LOG_SB,LOG_ERROR)("DSP:Data Output buffer full");
686 }
687 }
688
689
DSP_FinishReset(Bitu)690 static void DSP_FinishReset(Bitu /*val*/) {
691 DSP_FlushData();
692 DSP_AddData(0xaa);
693 sb.dsp.state=DSP_S_NORMAL;
694 }
695
DSP_Reset(void)696 static void DSP_Reset(void) {
697 LOG(LOG_SB,LOG_ERROR)("DSP:Reset");
698 PIC_DeActivateIRQ(sb.hw.irq);
699
700 DSP_ChangeMode(MODE_NONE);
701 DSP_FlushData();
702 sb.dsp.cmd=DSP_NO_COMMAND;
703 sb.dsp.cmd_len=0;
704 sb.dsp.in.pos=0;
705 sb.dsp.write_busy=0;
706 PIC_RemoveEvents(DSP_FinishReset);
707
708 sb.dma.left=0;
709 sb.dma.total=0;
710 sb.dma.stereo=false;
711 sb.dma.sign=false;
712 sb.dma.autoinit=false;
713 sb.dma.mode=DSP_DMA_NONE;
714 sb.dma.remain_size=0;
715 if (sb.dma.chan) sb.dma.chan->Clear_Request();
716
717 sb.freq=22050;
718 sb.time_constant=45;
719 sb.dac.used=0;
720 sb.dac.last=0;
721 sb.e2.value=0xaa;
722 sb.e2.count=0;
723 sb.irq.pending_8bit=false;
724 sb.irq.pending_16bit=false;
725 sb.chan->SetFreq(22050);
726 // DSP_SetSpeaker(false);
727 PIC_RemoveEvents(END_DMA_Event);
728 }
729
DSP_DoReset(Bit8u val)730 static void DSP_DoReset(Bit8u val) {
731 if (((val&1)!=0) && (sb.dsp.state!=DSP_S_RESET)) {
732 //TODO Get out of highspeed mode
733 DSP_Reset();
734 sb.dsp.state=DSP_S_RESET;
735 } else if (((val&1)==0) && (sb.dsp.state==DSP_S_RESET)) { // reset off
736 sb.dsp.state=DSP_S_RESET_WAIT;
737 PIC_RemoveEvents(DSP_FinishReset);
738 PIC_AddEvent(DSP_FinishReset,20.0f/1000.0f,0); // 20 microseconds
739 }
740 }
741
DSP_E2_DMA_CallBack(DmaChannel *,DMAEvent event)742 static void DSP_E2_DMA_CallBack(DmaChannel * /*chan*/, DMAEvent event) {
743 if (event==DMA_UNMASKED) {
744 Bit8u val=(Bit8u)(sb.e2.value&0xff);
745 DmaChannel * chan=GetDMAChannel(sb.hw.dma8);
746 chan->Register_Callback(0);
747 chan->Write(1,&val);
748 }
749 }
750
DSP_ADC_CallBack(DmaChannel *,DMAEvent event)751 static void DSP_ADC_CallBack(DmaChannel * /*chan*/, DMAEvent event) {
752 if (event!=DMA_UNMASKED) return;
753 Bit8u val=128;
754 DmaChannel * ch=GetDMAChannel(sb.hw.dma8);
755 while (sb.dma.left--) {
756 ch->Write(1,&val);
757 }
758 SB_RaiseIRQ(SB_IRQ_8);
759 ch->Register_Callback(0);
760 }
761
DSP_ChangeRate(Bitu freq)762 static void DSP_ChangeRate(Bitu freq) {
763 if (sb.freq!=freq && sb.dma.mode!=DSP_DMA_NONE) {
764 sb.chan->FillUp();
765 sb.chan->SetFreq(freq / (sb.mixer.stereo ? 2 : 1));
766 sb.dma.rate=(freq*sb.dma.mul) >> SB_SH;
767 sb.dma.min=(sb.dma.rate*3)/1000;
768 }
769 sb.freq=freq;
770 }
771
772 Bitu DEBUG_EnableDebugger(void);
773
774 #define DSP_SB16_ONLY if (sb.type != SBT_16) { LOG(LOG_SB,LOG_ERROR)("DSP:Command %2X requires SB16",sb.dsp.cmd); break; }
775 #define DSP_SB2_ABOVE if (sb.type <= SBT_1) { LOG(LOG_SB,LOG_ERROR)("DSP:Command %2X requires SB2 or above",sb.dsp.cmd); break; }
776
DSP_DoCommand(void)777 static void DSP_DoCommand(void) {
778 // LOG_MSG("DSP Command %X",sb.dsp.cmd);
779 switch (sb.dsp.cmd) {
780 case 0x04:
781 if (sb.type == SBT_16) {
782 /* SB16 ASP set mode register */
783 if ((sb.dsp.in.data[0]&0xf1)==0xf1) ASP_init_in_progress=true;
784 else ASP_init_in_progress=false;
785 LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (set mode register to %X)",sb.dsp.cmd,sb.dsp.in.data[0]);
786 } else {
787 /* DSP Status SB 2.0/pro version. NOT SB16. */
788 DSP_FlushData();
789 if (sb.type == SBT_2) DSP_AddData(0x88);
790 else if ((sb.type == SBT_PRO1) || (sb.type == SBT_PRO2)) DSP_AddData(0x7b);
791 else DSP_AddData(0xff); //Everything enabled
792 }
793 break;
794 case 0x05: /* SB16 ASP set codec parameter */
795 LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (set codec parameter)",sb.dsp.cmd);
796 break;
797 case 0x08: /* SB16 ASP get version */
798 LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X sub %X",sb.dsp.cmd,sb.dsp.in.data[0]);
799 if (sb.type == SBT_16) {
800 switch (sb.dsp.in.data[0]) {
801 case 0x03:
802 DSP_AddData(0x18); // version ID (??)
803 break;
804 default:
805 LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X sub %X",sb.dsp.cmd,sb.dsp.in.data[0]);
806 break;
807 }
808 } else {
809 LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X sub %X",sb.dsp.cmd,sb.dsp.in.data[0]);
810 }
811 break;
812 case 0x0e: /* SB16 ASP set register */
813 if (sb.type == SBT_16) {
814 // LOG(LOG_SB,LOG_NORMAL)("SB16 ASP set register %X := %X",sb.dsp.in.data[0],sb.dsp.in.data[1]);
815 ASP_regs[sb.dsp.in.data[0]] = sb.dsp.in.data[1];
816 } else {
817 LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (set register)",sb.dsp.cmd);
818 }
819 break;
820 case 0x0f: /* SB16 ASP get register */
821 if (sb.type == SBT_16) {
822 if ((ASP_init_in_progress) && (sb.dsp.in.data[0]==0x83)) {
823 ASP_regs[0x83] = ~ASP_regs[0x83];
824 }
825 // LOG(LOG_SB,LOG_NORMAL)("SB16 ASP get register %X == %X",sb.dsp.in.data[0],ASP_regs[sb.dsp.in.data[0]]);
826 DSP_AddData(ASP_regs[sb.dsp.in.data[0]]);
827 } else {
828 LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (get register)",sb.dsp.cmd);
829 }
830 break;
831 case 0x10: /* Direct DAC */
832 DSP_ChangeMode(MODE_DAC);
833 if (sb.dac.used<DSP_DACSIZE) {
834 sb.dac.data[sb.dac.used++]=(Bit8s(sb.dsp.in.data[0] ^ 0x80)) << 8;
835 sb.dac.data[sb.dac.used++]=(Bit8s(sb.dsp.in.data[0] ^ 0x80)) << 8;
836 }
837 break;
838 case 0x24: /* Singe Cycle 8-Bit DMA ADC */
839 sb.dma.left=sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
840 sb.dma.sign=false;
841 LOG(LOG_SB,LOG_ERROR)("DSP:Faked ADC for %d bytes",sb.dma.total);
842 GetDMAChannel(sb.hw.dma8)->Register_Callback(DSP_ADC_CallBack);
843 break;
844 case 0x14: /* Singe Cycle 8-Bit DMA DAC */
845 case 0x15: /* Wari hack. Waru uses this one instead of 0x14, but some weird stuff going on there anyway */
846 case 0x91: /* Singe Cycle 8-Bit DMA High speed DAC */
847 /* Note: 0x91 is documented only for DSP ver.2.x and 3.x, not 4.x */
848 DSP_PrepareDMA_Old(DSP_DMA_8,false,false);
849 break;
850 case 0x90: /* Auto Init 8-bit DMA High Speed */
851 case 0x1c: /* Auto Init 8-bit DMA */
852 DSP_SB2_ABOVE; /* Note: 0x90 is documented only for DSP ver.2.x and 3.x, not 4.x */
853 DSP_PrepareDMA_Old(DSP_DMA_8,true,false);
854 break;
855 case 0x38: /* Write to SB MIDI Output */
856 if (sb.midi == true) MIDI_RawOutByte(sb.dsp.in.data[0]);
857 break;
858 case 0x40: /* Set Timeconstant */
859 DSP_ChangeRate(1000000 / (256 - sb.dsp.in.data[0]));
860 break;
861 case 0x41: /* Set Output Samplerate */
862 case 0x42: /* Set Input Samplerate */
863 /* Note: 0x42 is handled like 0x41, needed by Fasttracker II */
864 DSP_SB16_ONLY;
865 DSP_ChangeRate((sb.dsp.in.data[0] << 8) | sb.dsp.in.data[1]);
866 break;
867 case 0x48: /* Set DMA Block Size */
868 DSP_SB2_ABOVE;
869 //TODO Maybe check limit for new irq?
870 sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
871 break;
872 case 0x75: /* 075h : Single Cycle 4-bit ADPCM Reference */
873 sb.adpcm.haveref=true;
874 case 0x74: /* 074h : Single Cycle 4-bit ADPCM */
875 DSP_PrepareDMA_Old(DSP_DMA_4,false,false);
876 break;
877 case 0x77: /* 077h : Single Cycle 3-bit(2.6bit) ADPCM Reference*/
878 sb.adpcm.haveref=true;
879 case 0x76: /* 074h : Single Cycle 3-bit(2.6bit) ADPCM */
880 DSP_PrepareDMA_Old(DSP_DMA_3,false,false);
881 break;
882 case 0x7d: /* Auto Init 4-bit ADPCM Reference */
883 DSP_SB2_ABOVE;
884 sb.adpcm.haveref=true;
885 DSP_PrepareDMA_Old(DSP_DMA_4,true,false);
886 break;
887 case 0x17: /* 017h : Single Cycle 2-bit ADPCM Reference*/
888 sb.adpcm.haveref=true;
889 case 0x16: /* 074h : Single Cycle 2-bit ADPCM */
890 DSP_PrepareDMA_Old(DSP_DMA_2,false,false);
891 break;
892 case 0x80: /* Silence DAC */
893 PIC_AddEvent(&DSP_RaiseIRQEvent,
894 (1000.0f*(1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8))/sb.freq));
895 break;
896 case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
897 case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
898 case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
899 case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
900 DSP_SB16_ONLY;
901 /* Generic 8/16 bit DMA */
902 // DSP_SetSpeaker(true); //SB16 always has speaker enabled
903 sb.dma.sign=(sb.dsp.in.data[0] & 0x10) > 0;
904 DSP_PrepareDMA_New((sb.dsp.cmd & 0x10) ? DSP_DMA_16 : DSP_DMA_8,
905 1+sb.dsp.in.data[1]+(sb.dsp.in.data[2] << 8),
906 (sb.dsp.cmd & 0x4)>0,
907 (sb.dsp.in.data[0] & 0x20) > 0
908 );
909 break;
910 case 0xd5: /* Halt 16-bit DMA */
911 DSP_SB16_ONLY;
912 case 0xd0: /* Halt 8-bit DMA */
913 // DSP_ChangeMode(MODE_NONE);
914 // Games sometimes already program a new dma before stopping, gives noise
915 if (sb.mode==MODE_NONE) {
916 // possibly different code here that does not switch to MODE_DMA_PAUSE
917 }
918 sb.mode=MODE_DMA_PAUSE;
919 PIC_RemoveEvents(END_DMA_Event);
920 break;
921 case 0xd1: /* Enable Speaker */
922 DSP_SetSpeaker(true);
923 break;
924 case 0xd3: /* Disable Speaker */
925 DSP_SetSpeaker(false);
926 break;
927 case 0xd8: /* Speaker status */
928 DSP_SB2_ABOVE;
929 DSP_FlushData();
930 if (sb.speaker) DSP_AddData(0xff);
931 else DSP_AddData(0x00);
932 break;
933 case 0xd6: /* Continue DMA 16-bit */
934 DSP_SB16_ONLY;
935 case 0xd4: /* Continue DMA 8-bit*/
936 if (sb.mode==MODE_DMA_PAUSE) {
937 sb.mode=MODE_DMA_MASKED;
938 if (sb.dma.chan!=NULL) sb.dma.chan->Register_Callback(DSP_DMA_CallBack);
939 }
940 break;
941 case 0xd9: /* Exit Autoinitialize 16-bit */
942 DSP_SB16_ONLY;
943 case 0xda: /* Exit Autoinitialize 8-bit */
944 DSP_SB2_ABOVE;
945 /* Set mode to single transfer so it ends with current block */
946 sb.dma.autoinit=false; //Should stop itself
947 break;
948 case 0xe0: /* DSP Identification - SB2.0+ */
949 DSP_FlushData();
950 DSP_AddData(~sb.dsp.in.data[0]);
951 break;
952 case 0xe1: /* Get DSP Version */
953 DSP_FlushData();
954 switch (sb.type) {
955 case SBT_1:
956 DSP_AddData(0x1);DSP_AddData(0x05);break;
957 case SBT_2:
958 DSP_AddData(0x2);DSP_AddData(0x1);break;
959 case SBT_PRO1:
960 DSP_AddData(0x3);DSP_AddData(0x0);break;
961 case SBT_PRO2:
962 DSP_AddData(0x3);DSP_AddData(0x2);break;
963 case SBT_16:
964 DSP_AddData(0x4);DSP_AddData(0x5);break;
965 default:
966 break;
967 }
968 break;
969 case 0xe2: /* Weird DMA identification write routine */
970 {
971 LOG(LOG_SB,LOG_NORMAL)("DSP Function 0xe2");
972 for (Bitu i = 0; i < 8; i++)
973 if ((sb.dsp.in.data[0] >> i) & 0x01) sb.e2.value += E2_incr_table[sb.e2.count % 4][i];
974 sb.e2.value += E2_incr_table[sb.e2.count % 4][8];
975 sb.e2.count++;
976 GetDMAChannel(sb.hw.dma8)->Register_Callback(DSP_E2_DMA_CallBack);
977 }
978 break;
979 case 0xe3: /* DSP Copyright */
980 {
981 DSP_FlushData();
982 for (size_t i=0;i<=strlen(copyright_string);i++) {
983 DSP_AddData(copyright_string[i]);
984 }
985 }
986 break;
987 case 0xe4: /* Write Test Register */
988 sb.dsp.test_register=sb.dsp.in.data[0];
989 break;
990 case 0xe8: /* Read Test Register */
991 DSP_FlushData();
992 DSP_AddData(sb.dsp.test_register);;
993 break;
994 case 0xf2: /* Trigger 8bit IRQ */
995 //Small delay in order to emulate the slowness of the DSP, fixes Llamatron 2012 and Lemmings 3D
996 PIC_AddEvent(&DSP_RaiseIRQEvent,0.01f);
997 break;
998 case 0xf3: /* Trigger 16bit IRQ */
999 DSP_SB16_ONLY;
1000 SB_RaiseIRQ(SB_IRQ_16);
1001 break;
1002 case 0xf8: /* Undocumented, pre-SB16 only */
1003 DSP_FlushData();
1004 DSP_AddData(0);
1005 break;
1006 case 0x30: case 0x31:
1007 LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented MIDI I/O command %2X",sb.dsp.cmd);
1008 break;
1009 case 0x34: case 0x35: case 0x36: case 0x37:
1010 DSP_SB2_ABOVE;
1011 LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented MIDI UART command %2X",sb.dsp.cmd);
1012 break;
1013 case 0x7f: case 0x1f:
1014 DSP_SB2_ABOVE;
1015 LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented auto-init DMA ADPCM command %2X",sb.dsp.cmd);
1016 break;
1017 case 0x20:
1018 DSP_AddData(0x7f); // fake silent input for Creative parrot
1019 break;
1020 case 0x2c:
1021 case 0x98: case 0x99: /* Documented only for DSP 2.x and 3.x */
1022 case 0xa0: case 0xa8: /* Documented only for DSP 3.x */
1023 LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented input command %2X",sb.dsp.cmd);
1024 break;
1025 case 0xf9: /* SB16 ASP ??? */
1026 if (sb.type == SBT_16) {
1027 LOG(LOG_SB,LOG_NORMAL)("SB16 ASP unknown function %x",sb.dsp.in.data[0]);
1028 // just feed it what it expects
1029 switch (sb.dsp.in.data[0]) {
1030 case 0x0b:
1031 DSP_AddData(0x00);
1032 break;
1033 case 0x0e:
1034 DSP_AddData(0xff);
1035 break;
1036 case 0x0f:
1037 DSP_AddData(0x07);
1038 break;
1039 case 0x23:
1040 DSP_AddData(0x00);
1041 break;
1042 case 0x24:
1043 DSP_AddData(0x00);
1044 break;
1045 case 0x2b:
1046 DSP_AddData(0x00);
1047 break;
1048 case 0x2c:
1049 DSP_AddData(0x00);
1050 break;
1051 case 0x2d:
1052 DSP_AddData(0x00);
1053 break;
1054 case 0x37:
1055 DSP_AddData(0x38);
1056 break;
1057 default:
1058 DSP_AddData(0x00);
1059 break;
1060 }
1061 } else {
1062 LOG(LOG_SB,LOG_NORMAL)("SB16 ASP unknown function %X",sb.dsp.cmd);
1063 }
1064 break;
1065 default:
1066 LOG(LOG_SB,LOG_ERROR)("DSP:Unhandled (undocumented) command %2X",sb.dsp.cmd);
1067 break;
1068 }
1069 sb.dsp.cmd=DSP_NO_COMMAND;
1070 sb.dsp.cmd_len=0;
1071 sb.dsp.in.pos=0;
1072 }
1073
DSP_DoWrite(Bit8u val)1074 static void DSP_DoWrite(Bit8u val) {
1075 switch (sb.dsp.cmd) {
1076 case DSP_NO_COMMAND:
1077 sb.dsp.cmd=val;
1078 if (sb.type == SBT_16) sb.dsp.cmd_len=DSP_cmd_len_sb16[val];
1079 else sb.dsp.cmd_len=DSP_cmd_len_sb[val];
1080 sb.dsp.in.pos=0;
1081 if (!sb.dsp.cmd_len) DSP_DoCommand();
1082 break;
1083 default:
1084 sb.dsp.in.data[sb.dsp.in.pos]=val;
1085 sb.dsp.in.pos++;
1086 if (sb.dsp.in.pos>=sb.dsp.cmd_len) DSP_DoCommand();
1087 }
1088 }
1089
DSP_ReadData(void)1090 static Bit8u DSP_ReadData(void) {
1091 /* Static so it repeats the last value on succesive reads (JANGLE DEMO) */
1092 if (sb.dsp.out.used) {
1093 sb.dsp.out.lastval=sb.dsp.out.data[sb.dsp.out.pos];
1094 sb.dsp.out.pos++;
1095 if (sb.dsp.out.pos>=DSP_BUFSIZE) sb.dsp.out.pos-=DSP_BUFSIZE;
1096 sb.dsp.out.used--;
1097 }
1098 return sb.dsp.out.lastval;
1099 }
1100
1101 //The soundblaster manual says 2.0 Db steps but we'll go for a bit less
1102 #define CALCVOL(_VAL) (float)pow(10.0f,((float)(31-_VAL)*-1.3f)/20)
CTMIXER_UpdateVolumes(void)1103 static void CTMIXER_UpdateVolumes(void) {
1104 if (!sb.mixer.enabled) return;
1105 MixerChannel * chan;
1106 //adjust to get linear master volume slider in trackers
1107 chan=MIXER_FindChannel("SB");
1108 if (chan) chan->SetVolume(float(sb.mixer.master[0])/31.0f*CALCVOL(sb.mixer.dac[0]),
1109 float(sb.mixer.master[1])/31.0f*CALCVOL(sb.mixer.dac[1]));
1110 chan=MIXER_FindChannel("FM");
1111 if (chan) chan->SetVolume(float(sb.mixer.master[0])/31.0f*CALCVOL(sb.mixer.fm[0]),
1112 float(sb.mixer.master[1])/31.0f*CALCVOL(sb.mixer.fm[1]));
1113 chan=MIXER_FindChannel("CDAUDIO");
1114 if (chan) chan->SetVolume(float(sb.mixer.master[0])/31.0f*CALCVOL(sb.mixer.cda[0]),
1115 float(sb.mixer.master[1])/31.0f*CALCVOL(sb.mixer.cda[1]));
1116 }
1117
CTMIXER_Reset(void)1118 static void CTMIXER_Reset(void) {
1119 sb.mixer.fm[0]=
1120 sb.mixer.fm[1]=
1121 sb.mixer.cda[0]=
1122 sb.mixer.cda[1]=
1123 sb.mixer.dac[0]=
1124 sb.mixer.dac[1]=31;
1125 sb.mixer.master[0]=
1126 sb.mixer.master[1]=31;
1127 CTMIXER_UpdateVolumes();
1128 }
1129
1130 #define SETPROVOL(_WHICH_,_VAL_) \
1131 _WHICH_[0]= ((((_VAL_) & 0xf0) >> 3)|(sb.type==SBT_16 ? 1:3)); \
1132 _WHICH_[1]= ((((_VAL_) & 0x0f) << 1)|(sb.type==SBT_16 ? 1:3)); \
1133
1134 #define MAKEPROVOL(_WHICH_) \
1135 ((((_WHICH_[0] & 0x1e) << 3) | ((_WHICH_[1] & 0x1e) >> 1)) | \
1136 ((sb.type==SBT_PRO1 || sb.type==SBT_PRO2) ? 0x11:0))
1137
DSP_ChangeStereo(bool stereo)1138 static void DSP_ChangeStereo(bool stereo) {
1139 if (!sb.dma.stereo && stereo) {
1140 sb.chan->SetFreq(sb.freq/2);
1141 sb.dma.mul*=2;
1142 sb.dma.rate=(sb.freq*sb.dma.mul) >> SB_SH;
1143 sb.dma.min=(sb.dma.rate*3)/1000;
1144 } else if (sb.dma.stereo && !stereo) {
1145 sb.chan->SetFreq(sb.freq);
1146 sb.dma.mul/=2;
1147 sb.dma.rate=(sb.freq*sb.dma.mul) >> SB_SH;
1148 sb.dma.min=(sb.dma.rate*3)/1000;
1149 }
1150 sb.dma.stereo=stereo;
1151 }
1152
CTMIXER_Write(Bit8u val)1153 static void CTMIXER_Write(Bit8u val) {
1154 switch (sb.mixer.index) {
1155 case 0x00: /* Reset */
1156 CTMIXER_Reset();
1157 LOG(LOG_SB,LOG_WARN)("Mixer reset value %x",val);
1158 break;
1159 case 0x02: /* Master Volume (SB2 Only) */
1160 SETPROVOL(sb.mixer.master,(val&0xf)|(val<<4));
1161 CTMIXER_UpdateVolumes();
1162 break;
1163 case 0x04: /* DAC Volume (SBPRO) */
1164 SETPROVOL(sb.mixer.dac,val);
1165 CTMIXER_UpdateVolumes();
1166 break;
1167 case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro + FM volume (SB2 Only) */
1168 //volume controls both channels
1169 SETPROVOL(sb.mixer.fm,(val&0xf)|(val<<4));
1170 CTMIXER_UpdateVolumes();
1171 if(val&0x60) LOG(LOG_SB,LOG_WARN)("Turned FM one channel off. not implemented %X",val);
1172 //TODO Change FM Mode if only 1 fm channel is selected
1173 break;
1174 case 0x08: /* CDA Volume (SB2 Only) */
1175 SETPROVOL(sb.mixer.cda,(val&0xf)|(val<<4));
1176 CTMIXER_UpdateVolumes();
1177 break;
1178 case 0x0a: /* Mic Level (SBPRO) or DAC Volume (SB2): 2-bit, 3-bit on SB16 */
1179 if (sb.type==SBT_2) {
1180 sb.mixer.dac[0]=sb.mixer.dac[1]=((val & 0x6) << 2)|3;
1181 CTMIXER_UpdateVolumes();
1182 } else {
1183 sb.mixer.mic=((val & 0x7) << 2)|(sb.type==SBT_16?1:3);
1184 }
1185 break;
1186 case 0x0e: /* Output/Stereo Select */
1187 sb.mixer.stereo=(val & 0x2) > 0;
1188 sb.mixer.filtered=(val & 0x20) > 0;
1189 DSP_ChangeStereo(sb.mixer.stereo);
1190 LOG(LOG_SB,LOG_WARN)("Mixer set to %s",sb.dma.stereo ? "STEREO" : "MONO");
1191 break;
1192 case 0x22: /* Master Volume (SBPRO) */
1193 SETPROVOL(sb.mixer.master,val);
1194 CTMIXER_UpdateVolumes();
1195 break;
1196 case 0x26: /* FM Volume (SBPRO) */
1197 SETPROVOL(sb.mixer.fm,val);
1198 CTMIXER_UpdateVolumes();
1199 break;
1200 case 0x28: /* CD Audio Volume (SBPRO) */
1201 SETPROVOL(sb.mixer.cda,val);
1202 CTMIXER_UpdateVolumes();
1203 break;
1204 case 0x2e: /* Line-in Volume (SBPRO) */
1205 SETPROVOL(sb.mixer.lin,val);
1206 break;
1207 //case 0x20: /* Master Volume Left (SBPRO) ? */
1208 case 0x30: /* Master Volume Left (SB16) */
1209 if (sb.type==SBT_16) {
1210 sb.mixer.master[0]=val>>3;
1211 CTMIXER_UpdateVolumes();
1212 }
1213 break;
1214 //case 0x21: /* Master Volume Right (SBPRO) ? */
1215 case 0x31: /* Master Volume Right (SB16) */
1216 if (sb.type==SBT_16) {
1217 sb.mixer.master[1]=val>>3;
1218 CTMIXER_UpdateVolumes();
1219 }
1220 break;
1221 case 0x32: /* DAC Volume Left (SB16) */
1222 if (sb.type==SBT_16) {
1223 sb.mixer.dac[0]=val>>3;
1224 CTMIXER_UpdateVolumes();
1225 }
1226 break;
1227 case 0x33: /* DAC Volume Right (SB16) */
1228 if (sb.type==SBT_16) {
1229 sb.mixer.dac[1]=val>>3;
1230 CTMIXER_UpdateVolumes();
1231 }
1232 break;
1233 case 0x34: /* FM Volume Left (SB16) */
1234 if (sb.type==SBT_16) {
1235 sb.mixer.fm[0]=val>>3;
1236 CTMIXER_UpdateVolumes();
1237 }
1238 break;
1239 case 0x35: /* FM Volume Right (SB16) */
1240 if (sb.type==SBT_16) {
1241 sb.mixer.fm[1]=val>>3;
1242 CTMIXER_UpdateVolumes();
1243 }
1244 break;
1245 case 0x36: /* CD Volume Left (SB16) */
1246 if (sb.type==SBT_16) {
1247 sb.mixer.cda[0]=val>>3;
1248 CTMIXER_UpdateVolumes();
1249 }
1250 break;
1251 case 0x37: /* CD Volume Right (SB16) */
1252 if (sb.type==SBT_16) {
1253 sb.mixer.cda[1]=val>>3;
1254 CTMIXER_UpdateVolumes();
1255 }
1256 break;
1257 case 0x38: /* Line-in Volume Left (SB16) */
1258 if (sb.type==SBT_16) sb.mixer.lin[0]=val>>3;
1259 break;
1260 case 0x39: /* Line-in Volume Right (SB16) */
1261 if (sb.type==SBT_16) sb.mixer.lin[1]=val>>3;
1262 break;
1263 case 0x3a:
1264 if (sb.type==SBT_16) sb.mixer.mic=val>>3;
1265 break;
1266 case 0x80: /* IRQ Select */
1267 sb.hw.irq=0xff;
1268 if (val & 0x1) sb.hw.irq=2;
1269 else if (val & 0x2) sb.hw.irq=5;
1270 else if (val & 0x4) sb.hw.irq=7;
1271 else if (val & 0x8) sb.hw.irq=10;
1272 break;
1273 case 0x81: /* DMA Select */
1274 sb.hw.dma8=0xff;
1275 sb.hw.dma16=0xff;
1276 if (val & 0x1) sb.hw.dma8=0;
1277 else if (val & 0x2) sb.hw.dma8=1;
1278 else if (val & 0x8) sb.hw.dma8=3;
1279 if (val & 0x20) sb.hw.dma16=5;
1280 else if (val & 0x40) sb.hw.dma16=6;
1281 else if (val & 0x80) sb.hw.dma16=7;
1282 LOG(LOG_SB,LOG_NORMAL)("Mixer select dma8:%x dma16:%x",sb.hw.dma8,sb.hw.dma16);
1283 break;
1284 default:
1285
1286 if( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */
1287 (sb.type == SBT_16 && sb.mixer.index >= 0x3b && sb.mixer.index <= 0x47)) /* New SB16 registers */
1288 sb.mixer.unhandled[sb.mixer.index] = val;
1289 LOG(LOG_SB,LOG_WARN)("MIXER:Write %X to unhandled index %X",val,sb.mixer.index);
1290 }
1291 }
1292
CTMIXER_Read(void)1293 static Bit8u CTMIXER_Read(void) {
1294 Bit8u ret;
1295 // if ( sb.mixer.index< 0x80) LOG_MSG("Read mixer %x",sb.mixer.index);
1296 switch (sb.mixer.index) {
1297 case 0x00: /* RESET */
1298 return 0x00;
1299 case 0x02: /* Master Volume (SB2 Only) */
1300 return ((sb.mixer.master[1]>>1) & 0xe);
1301 case 0x22: /* Master Volume (SBPRO) */
1302 return MAKEPROVOL(sb.mixer.master);
1303 case 0x04: /* DAC Volume (SBPRO) */
1304 return MAKEPROVOL(sb.mixer.dac);
1305 case 0x06: /* FM Volume (SB2 Only) + FM output selection */
1306 return ((sb.mixer.fm[1]>>1) & 0xe);
1307 case 0x08: /* CD Volume (SB2 Only) */
1308 return ((sb.mixer.cda[1]>>1) & 0xe);
1309 case 0x0a: /* Mic Level (SBPRO) or Voice (SB2 Only) */
1310 if (sb.type==SBT_2) return (sb.mixer.dac[0]>>2);
1311 else return ((sb.mixer.mic >> 2) & (sb.type==SBT_16 ? 7:6));
1312 case 0x0e: /* Output/Stereo Select */
1313 return 0x11|(sb.mixer.stereo ? 0x02 : 0x00)|(sb.mixer.filtered ? 0x20 : 0x00);
1314 case 0x26: /* FM Volume (SBPRO) */
1315 return MAKEPROVOL(sb.mixer.fm);
1316 case 0x28: /* CD Audio Volume (SBPRO) */
1317 return MAKEPROVOL(sb.mixer.cda);
1318 case 0x2e: /* Line-IN Volume (SBPRO) */
1319 return MAKEPROVOL(sb.mixer.lin);
1320 case 0x30: /* Master Volume Left (SB16) */
1321 if (sb.type==SBT_16) return sb.mixer.master[0]<<3;
1322 ret=0xa;
1323 break;
1324 case 0x31: /* Master Volume Right (S16) */
1325 if (sb.type==SBT_16) return sb.mixer.master[1]<<3;
1326 ret=0xa;
1327 break;
1328 case 0x32: /* DAC Volume Left (SB16) */
1329 if (sb.type==SBT_16) return sb.mixer.dac[0]<<3;
1330 ret=0xa;
1331 break;
1332 case 0x33: /* DAC Volume Right (SB16) */
1333 if (sb.type==SBT_16) return sb.mixer.dac[1]<<3;
1334 ret=0xa;
1335 break;
1336 case 0x34: /* FM Volume Left (SB16) */
1337 if (sb.type==SBT_16) return sb.mixer.fm[0]<<3;
1338 ret=0xa;
1339 break;
1340 case 0x35: /* FM Volume Right (SB16) */
1341 if (sb.type==SBT_16) return sb.mixer.fm[1]<<3;
1342 ret=0xa;
1343 break;
1344 case 0x36: /* CD Volume Left (SB16) */
1345 if (sb.type==SBT_16) return sb.mixer.cda[0]<<3;
1346 ret=0xa;
1347 break;
1348 case 0x37: /* CD Volume Right (SB16) */
1349 if (sb.type==SBT_16) return sb.mixer.cda[1]<<3;
1350 ret=0xa;
1351 break;
1352 case 0x38: /* Line-in Volume Left (SB16) */
1353 if (sb.type==SBT_16) return sb.mixer.lin[0]<<3;
1354 ret=0xa;
1355 break;
1356 case 0x39: /* Line-in Volume Right (SB16) */
1357 if (sb.type==SBT_16) return sb.mixer.lin[1]<<3;
1358 ret=0xa;
1359 break;
1360 case 0x3a: /* Mic Volume (SB16) */
1361 if (sb.type==SBT_16) return sb.mixer.mic<<3;
1362 ret=0xa;
1363 break;
1364 case 0x80: /* IRQ Select */
1365 switch (sb.hw.irq) {
1366 case 2: return 0x1;
1367 case 5: return 0x2;
1368 case 7: return 0x4;
1369 case 10: return 0x8;
1370 }
1371 case 0x81: /* DMA Select */
1372 ret=0;
1373 switch (sb.hw.dma8) {
1374 case 0:ret|=0x1;break;
1375 case 1:ret|=0x2;break;
1376 case 3:ret|=0x8;break;
1377 }
1378 switch (sb.hw.dma16) {
1379 case 5:ret|=0x20;break;
1380 case 6:ret|=0x40;break;
1381 case 7:ret|=0x80;break;
1382 }
1383 return ret;
1384 case 0x82: /* IRQ Status */
1385 return (sb.irq.pending_8bit ? 0x1 : 0) |
1386 (sb.irq.pending_16bit ? 0x2 : 0) |
1387 ((sb.type == SBT_16) ? 0x20 : 0);
1388 default:
1389 if ( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */
1390 (sb.type == SBT_16 && sb.mixer.index >= 0x3b && sb.mixer.index <= 0x47)) /* New SB16 registers */
1391 ret = sb.mixer.unhandled[sb.mixer.index];
1392 else
1393 ret=0xa;
1394 LOG(LOG_SB,LOG_WARN)("MIXER:Read from unhandled index %X",sb.mixer.index);
1395 }
1396 return ret;
1397 }
1398
1399
read_sb(Bitu port,Bitu)1400 static Bitu read_sb(Bitu port,Bitu /*iolen*/) {
1401 switch (port-sb.hw.base) {
1402 case MIXER_INDEX:
1403 return sb.mixer.index;
1404 case MIXER_DATA:
1405 return CTMIXER_Read();
1406 case DSP_READ_DATA:
1407 return DSP_ReadData();
1408 case DSP_READ_STATUS:
1409 //TODO See for high speed dma :)
1410 if (sb.irq.pending_8bit) {
1411 sb.irq.pending_8bit=false;
1412 PIC_DeActivateIRQ(sb.hw.irq);
1413 }
1414 if (sb.dsp.out.used) return 0xff;
1415 else return 0x7f;
1416 case DSP_ACK_16BIT:
1417 sb.irq.pending_16bit=false;
1418 break;
1419 case DSP_WRITE_STATUS:
1420 switch (sb.dsp.state) {
1421 case DSP_S_NORMAL:
1422 sb.dsp.write_busy++;
1423 if (sb.dsp.write_busy & 8) return 0xff;
1424 return 0x7f;
1425 case DSP_S_RESET:
1426 case DSP_S_RESET_WAIT:
1427 return 0xff;
1428 }
1429 return 0xff;
1430 case DSP_RESET:
1431 return 0xff;
1432 default:
1433 LOG(LOG_SB,LOG_NORMAL)("Unhandled read from SB Port %4X",port);
1434 break;
1435 }
1436 return 0xff;
1437 }
1438
write_sb(Bitu port,Bitu val,Bitu)1439 static void write_sb(Bitu port,Bitu val,Bitu /*iolen*/) {
1440 Bit8u val8=(Bit8u)(val&0xff);
1441 switch (port-sb.hw.base) {
1442 case DSP_RESET:
1443 DSP_DoReset(val8);
1444 break;
1445 case DSP_WRITE_DATA:
1446 DSP_DoWrite(val8);
1447 break;
1448 case MIXER_INDEX:
1449 sb.mixer.index=val8;
1450 break;
1451 case MIXER_DATA:
1452 CTMIXER_Write(val8);
1453 break;
1454 default:
1455 LOG(LOG_SB,LOG_NORMAL)("Unhandled write to SB Port %4X",port);
1456 break;
1457 }
1458 }
1459
adlib_gusforward(Bitu,Bitu val,Bitu)1460 static void adlib_gusforward(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
1461 adlib_commandreg=(Bit8u)(val&0xff);
1462 }
1463
SB_Get_Address(Bitu & sbaddr,Bitu & sbirq,Bitu & sbdma)1464 bool SB_Get_Address(Bitu& sbaddr, Bitu& sbirq, Bitu& sbdma) {
1465 sbaddr=0;
1466 sbirq =0;
1467 sbdma =0;
1468 if (sb.type == SBT_NONE) return false;
1469 else {
1470 sbaddr=sb.hw.base;
1471 sbirq =sb.hw.irq;
1472 sbdma = sb.hw.dma8;
1473 return true;
1474 }
1475 }
1476
SBLASTER_CallBack(Bitu len)1477 static void SBLASTER_CallBack(Bitu len) {
1478 switch (sb.mode) {
1479 case MODE_NONE:
1480 case MODE_DMA_PAUSE:
1481 case MODE_DMA_MASKED:
1482 sb.chan->AddSilence();
1483 break;
1484 case MODE_DAC:
1485 // GenerateDACSound(len);
1486 // break;
1487 if (!sb.dac.used) {
1488 sb.mode=MODE_NONE;
1489 return;
1490 }
1491 sb.chan->AddStretched(sb.dac.used,sb.dac.data);
1492 sb.dac.used=0;
1493 break;
1494 case MODE_DMA:
1495 len*=sb.dma.mul;
1496 if (len&SB_SH_MASK) len+=1 << SB_SH;
1497 len>>=SB_SH;
1498 if (len>sb.dma.left) len=sb.dma.left;
1499 GenerateDMASound(len);
1500 break;
1501 }
1502 }
1503
1504 class SBLASTER: public Module_base {
1505 private:
1506 /* Data */
1507 IO_ReadHandleObject ReadHandler[0x10];
1508 IO_WriteHandleObject WriteHandler[0x10];
1509 AutoexecObject autoexecline;
1510 MixerObject MixerChan;
1511 OPL_Mode oplmode;
1512
1513 /* Support Functions */
Find_Type_And_Opl(Section_prop * config,SB_TYPES & type,OPL_Mode & opl_mode)1514 void Find_Type_And_Opl(Section_prop* config,SB_TYPES& type, OPL_Mode& opl_mode){
1515 const char * sbtype=config->Get_string("sbtype");
1516 if (!strcasecmp(sbtype,"sb1")) type=SBT_1;
1517 else if (!strcasecmp(sbtype,"sb2")) type=SBT_2;
1518 else if (!strcasecmp(sbtype,"sbpro1")) type=SBT_PRO1;
1519 else if (!strcasecmp(sbtype,"sbpro2")) type=SBT_PRO2;
1520 else if (!strcasecmp(sbtype,"sb16")) type=SBT_16;
1521 else if (!strcasecmp(sbtype,"gb")) type=SBT_GB;
1522 else if (!strcasecmp(sbtype,"none")) type=SBT_NONE;
1523 else type=SBT_16;
1524
1525 if (type==SBT_16) {
1526 if ((!IS_EGAVGA_ARCH) || !SecondDMAControllerAvailable()) type=SBT_PRO2;
1527 }
1528
1529 /* OPL/CMS Init */
1530 const char * omode=config->Get_string("oplmode");
1531 if (!strcasecmp(omode,"none")) opl_mode=OPL_none;
1532 else if (!strcasecmp(omode,"cms")) opl_mode=OPL_cms;
1533 else if (!strcasecmp(omode,"opl2")) opl_mode=OPL_opl2;
1534 else if (!strcasecmp(omode,"dualopl2")) opl_mode=OPL_dualopl2;
1535 else if (!strcasecmp(omode,"opl3")) opl_mode=OPL_opl3;
1536 else if (!strcasecmp(omode,"opl3gold")) opl_mode=OPL_opl3gold;
1537 /* Else assume auto */
1538 else {
1539 switch (type) {
1540 case SBT_NONE:
1541 opl_mode=OPL_none;
1542 break;
1543 case SBT_GB:
1544 opl_mode=OPL_cms;
1545 break;
1546 case SBT_1:
1547 case SBT_2:
1548 opl_mode=OPL_opl2;
1549 break;
1550 case SBT_PRO1:
1551 opl_mode=OPL_dualopl2;
1552 break;
1553 case SBT_PRO2:
1554 case SBT_16:
1555 opl_mode=OPL_opl3;
1556 break;
1557 }
1558 }
1559 }
1560 public:
SBLASTER(Section * configuration)1561 SBLASTER(Section* configuration):Module_base(configuration) {
1562 Bitu i;
1563 Section_prop * section=static_cast<Section_prop *>(configuration);
1564
1565 sb.hw.base=section->Get_hex("sbbase");
1566 sb.hw.irq=section->Get_int("irq");
1567 Bitu dma8bit=section->Get_int("dma");
1568 if (dma8bit>0xff) dma8bit=0xff;
1569 sb.hw.dma8=(Bit8u)(dma8bit&0xff);
1570 Bitu dma16bit=section->Get_int("hdma");
1571 if (dma16bit>0xff) dma16bit=0xff;
1572 sb.hw.dma16=(Bit8u)(dma16bit&0xff);
1573
1574 sb.mixer.enabled=section->Get_bool("sbmixer");
1575 sb.mixer.stereo=false;
1576
1577 Find_Type_And_Opl(section,sb.type,oplmode);
1578
1579 switch (oplmode) {
1580 case OPL_none:
1581 WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB);
1582 break;
1583 case OPL_cms:
1584 WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB);
1585 CMS_Init(section);
1586 break;
1587 case OPL_opl2:
1588 CMS_Init(section);
1589 // fall-through
1590 case OPL_dualopl2:
1591 case OPL_opl3:
1592 case OPL_opl3gold:
1593 OPL_Init(section,oplmode);
1594 break;
1595 }
1596 if (sb.type==SBT_NONE || sb.type==SBT_GB) return;
1597
1598 sb.chan=MixerChan.Install(&SBLASTER_CallBack,22050,"SB");
1599 sb.dsp.state=DSP_S_NORMAL;
1600 sb.dsp.out.lastval=0xaa;
1601 sb.dma.chan=NULL;
1602
1603 for (i=4;i<=0xf;i++) {
1604 if (i==8 || i==9) continue;
1605 //Disable mixer ports for lower soundblaster
1606 if ((sb.type==SBT_1 || sb.type==SBT_2) && (i==4 || i==5)) continue;
1607 ReadHandler[i].Install(sb.hw.base+i,read_sb,IO_MB);
1608 WriteHandler[i].Install(sb.hw.base+i,write_sb,IO_MB);
1609 }
1610 for (i=0;i<256;i++) ASP_regs[i] = 0;
1611 ASP_regs[5] = 0x01;
1612 ASP_regs[9] = 0xf8;
1613
1614 DSP_Reset();
1615 CTMIXER_Reset();
1616
1617 // The documentation does not specify if SB gets initialized with the speaker enabled
1618 // or disabled. Real SBPro2 has it disabled.
1619 sb.speaker=false;
1620 // On SB16 the speaker flag does not affect actual speaker state.
1621 if (sb.type == SBT_16) sb.chan->Enable(true);
1622 else sb.chan->Enable(false);
1623
1624 // Create set blaster line
1625 ostringstream temp;
1626 temp << "SET BLASTER=A" << setw(3)<< hex << sb.hw.base
1627 << " I" << dec << (Bitu)sb.hw.irq << " D" << (Bitu)sb.hw.dma8;
1628 if (sb.type==SBT_16) temp << " H" << (Bitu)sb.hw.dma16;
1629 temp << " T" << static_cast<unsigned int>(sb.type) << ends;
1630
1631 autoexecline.Install(temp.str());
1632
1633 /* Soundblaster midi interface */
1634 if (!MIDI_Available()) sb.midi = false;
1635 else sb.midi = true;
1636 }
1637
~SBLASTER()1638 ~SBLASTER() {
1639 switch (oplmode) {
1640 case OPL_none:
1641 break;
1642 case OPL_cms:
1643 CMS_ShutDown(m_configuration);
1644 break;
1645 case OPL_opl2:
1646 CMS_ShutDown(m_configuration);
1647 // fall-through
1648 case OPL_dualopl2:
1649 case OPL_opl3:
1650 case OPL_opl3gold:
1651 OPL_ShutDown(m_configuration);
1652 break;
1653 }
1654 if (sb.type==SBT_NONE || sb.type==SBT_GB) return;
1655 DSP_Reset(); // Stop everything
1656 }
1657 }; //End of SBLASTER class
1658
1659
1660 static SBLASTER* test;
SBLASTER_ShutDown(Section *)1661 void SBLASTER_ShutDown(Section* /*sec*/) {
1662 delete test;
1663 }
1664
SBLASTER_Init(Section * sec)1665 void SBLASTER_Init(Section* sec) {
1666 test = new SBLASTER(sec);
1667 sec->AddDestroyFunction(&SBLASTER_ShutDown,true);
1668 }
1669