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