Sound card support
[jpcrr.git] / org / jpc / modules / SoundCard.java
blob1927ca68f5dfd10a69ed90838a274f2251cf1bb4
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009-2010 H. Ilari Liusvaara
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as published by
10 the Free Software Foundation.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 Based on JPC x86 PC Hardware emulator,
22 A project from the Physics Dept, The University of Oxford
24 Details about original JPC can be found at:
26 www-jpc.physics.ox.ac.uk
30 package org.jpc.modules;
32 import org.jpc.emulator.*;
33 import org.jpc.modulesaux.*;
34 import org.jpc.emulator.motherboard.*;
35 import java.io.*;
37 public class SoundCard extends AbstractHardwareComponent implements IOPortCapable, TimerResponsive, DMATransferCapable, SoundOutputDevice
39 private int baseIOAddress;
40 private boolean irq2;
41 private boolean irq5;
42 private boolean irq7;
43 private boolean irq10;
44 private int dmaMask;
45 private int dmaRequested;
46 private boolean ioportRegistered;
47 private DMAController primaryDMAController;
48 private DMAController secondaryDMAController;
49 private Timer timer;
50 private Clock clock;
51 private InterruptController irqController;
52 private SoundDigitalOut pcmOutput;
54 private boolean irq8Bit;
55 private boolean irq16Bit;
57 private int mixerIndex;
58 private int mixerPrevIndex;
59 private int[] mixerRegisters;
61 private int dspCommandState;
62 private int[] dspOutput;
63 private int dspOutputUsed;
64 private long dspNextAttention;
66 //The following need to be programmed for DMA Engine.
67 private int dmaState; //DMA_*
68 private int samplesLeft; //Samples left in block.
69 private int origSamplesLeft; //Original samples in block.
70 private int soundFormat; //SNDFMT_*
71 private boolean stereo; //Stereo On?
72 private long interSampleTime; //Amount of time between samples.
73 private boolean istStereoAdjust; //InterSampleTime is affected by stereo.
75 private boolean dmaPaused; //DMA activity is paused.
76 private int dmaPauseLeft; //Amount of time left in DMA pause (-1 if indefinite)
77 private int dmaActiveMask; //Active DMA on these channels.
78 private boolean dmaRequest; //DMA request in progress.
79 private long dmaRequestTime; //DMA data request was made at this time.
80 private int partialSample; //Partial sample data.
81 private int partialSampleBytes; //Bytes of sample received.
82 private int wholeSampleBytes; //Bytes to obtain at once (max 4)
84 private int byteBuffer; //Byte buffer from last time (ADPCM only).
85 private int byteBufferSamples; //Number of samples in byte buffer.
87 private int adpcmReference; //ADPCM reference byte.
88 private byte adpcmScale; //ADPCM scale.
90 private long nextSampleTime; //DMA sample plays at this time.
92 private int dspArgumentRegister; //Temporary storage for DSP command argument.
93 private int dspNextDMA; //Next DMA parameters. -1 if none.
94 private int dspLastCommand; //Last DSP command.
96 private boolean e2Mode; //Do E2 write next time DMA is invoked.
97 private byte e2Value; //Value to write for E2.
98 private int e2Count; //E2 write counter.
100 //These are 0-65535 (or over...)
101 private int pcmAmplificationLeft;
102 private int pcmAmplificationRight;
103 private boolean speakerConnected;
105 //FM chups (1).
106 private FMChip fmChip;
107 private int fmIndex;
108 private long fmNextAttention;
109 private SoundDigitalOut fmOutput;
111 private static final int DMA_NONE = 0; //No DMA in progress.
112 private static final int DMA_SINGLE = 1; //Single-block DMA in progress.
113 private static final int DMA_CONTINUOUS = 2; //Auto-Init DMA in progress.
114 private static final int DMA_CONTINUOUS_EXIT = 3; //Auto-Init DMA last block in progress.
116 private static final int SNDFMT_2BIT_ADPCM = 0; //2-bit ADPCM.
117 private static final int SNDFMT_26BIT_ADPCM = 1; //2.6-bit (6-level) ADPCM.
118 private static final int SNDFMT_4BIT_ADPCM = 2; //4-bit ADPCM.
119 private static final int SNDFMT_2BIT_ADPCM_REF = 3; //2-bit ADPCM /w reference.
120 private static final int SNDFMT_26BIT_ADPCM_REF = 4; //2.6-bit (6-level) ADPCM /w reference.
121 private static final int SNDFMT_4BIT_ADPCM_REF = 5; //4-bit ADPCM /w reference.
122 private static final int SNDFMT_8BIT_PCM_SIGNED = 6; //8-bit PCM (SIGNED)
123 private static final int SNDFMT_8BIT_PCM_UNSIGNED = 7; //8-bit PCM (UNSIGNED)
124 private static final int SNDFMT_16BIT_PCM_LE_SIGNED = 8; //16-bit LE PCM (SIGNED)
125 private static final int SNDFMT_16BIT_PCM_LE_UNSIGNED = 9; //16-bit LE PCM (UNSIGNED)
126 private static final int SNDFMT_16BIT_PCM_BE_SIGNED = 10; //16-bit LE PCM (SIGNED)
127 private static final int SNDFMT_16BIT_PCM_BE_UNSIGNED = 11; //16-bit LE PCM (UNSIGNED)
129 private static final byte ADPCM_SCALE_INIT = 0;
131 private static final int typeFlag = 0x10;
132 private static final int QUEUE_SIZE = 256;
133 private static final int DSP_VERSION = 0x404; //4.04 (early SB16).
135 private static final int MIXER_REGISTERS = 25;
136 private static final int MIXREG_RESET = 0x00;
137 private static final int MIXREG_STATUS = 0x1;
138 private static final int MIXREG_DAC = 0x04;
139 private static final int MIXREG_MIC = 0x0A;
140 private static final int MIXREG_OUTPUT_CONTROL = 0x0E;
141 private static final int MIXREG_MASTER = 0x22;
142 private static final int MIXREG_FM = 0x26;
143 private static final int MIXREG_CD = 0x28;
144 private static final int MIXREG_LINEIN = 0x2E;
145 private static final int MIXREG_IRQSELECT = 0x80;
146 private static final int MIXREG_DMASELECT = 0x81;
147 private static final int MIXREG_IRQSTATUS = 0x82;
148 private static final int MIXREG_SB16_FIRST = 0x30;
149 private static final int MIXREG_LAST = 0x47;
151 private static final int MIXER_MASTER_LEFT = 0x00;
152 private static final int MIXER_MASTER_RIGHT = 0x01;
153 private static final int MIXER_DAC_LEFT = 0x02;
154 private static final int MIXER_DAC_RIGHT = 0x03;
155 private static final int MIXER_FM_LEFT = 0x04;
156 private static final int MIXER_FM_RIGHT = 0x05;
157 private static final int MIXER_OUTPUT_GAIN_CONTROL_LEFT = 0x11;
158 private static final int MIXER_OUTPUT_GAIN_CONTROL_RIGHT = 0x12;
159 private static final int MIXER_TREBLE_LEFT = 0x14;
160 private static final int MIXER_TREBLE_RIGHT = 0x15;
161 private static final int MIXER_BASS_LEFT = 0x16;
162 private static final int MIXER_BASS_RIGHT = 0x17;
163 private static final int MIXER_OUTPUT_CONTROL = 24;
165 //Following are here for completeness, but are not used.
166 private static final int MIXER_CD_LEFT = 0x06;
167 private static final int MIXER_CD_RIGHT = 0x07;
168 private static final int MIXER_LINEIN_LEFT = 0x08;
169 private static final int MIXER_LINEIN_RIGHT = 0x09;
170 private static final int MIXER_MIC = 0x0A;
171 private static final int MIXER_PCSPEAKER = 0x0B;
172 private static final int MIXER_INPUT_CONTROL_LEFT = 0x0D;
173 private static final int MIXER_INPUT_CONTROL_RIGHT = 0x0E;
174 private static final int MIXER_INPUT_GAIN_CONTROL_LEFT = 0x0F;
175 private static final int MIXER_INPUT_GAIN_CONTROL_RIGHT = 0x10;
176 private static final int MIXER_AUTOMATIC_GAIN_CONTROL = 0x13;
178 private static final int DSPSTATE_WAIT_COMMAND = 0;
179 private static final int DSPSTATE_DIRECT_DAC_SAMPLE = 1;
180 private static final int DSPSTATE_SILENCE_LOW = 2;
181 private static final int DSPSTATE_SILENCE_HIGH = 3;
182 private static final int DSPSTATE_TESTWRITE = 4;
183 private static final int DSPSTATE_IDWRITE = 5;
184 private static final int DSPSTATE_RATE_LOW = 6;
185 private static final int DSPSTATE_RATE_HIGH = 7;
186 private static final int DSPSTATE_BLOCKSIZE_LOW = 8;
187 private static final int DSPSTATE_BLOCKSIZE_HIGH = 9;
188 private static final int DSPSTATE_TC = 10;
189 private static final int DSPSTATE_OLDDMA_LOW = 11;
190 private static final int DSPSTATE_OLDDMA_HIGH = 12;
191 private static final int DSPSTATE_NEWDMA_LOW = 13;
192 private static final int DSPSTATE_NEWDMA_MID = 14;
193 private static final int DSPSTATE_NEWDMA_HIGH = 15;
194 private static final int DSPSTATE_DMA_IDENTIFY = 16;
196 private static final int ADPCM_4BIT_SCALE_MAX = 3;
197 private static final int ADPCM_26BIT_SCALE_MAX = 4;
198 private static final int ADPCM_2BIT_SCALE_MAX = 5;
199 private static final byte[] ADPCM_4BIT_LEVEL_SHIFT;
200 private static final byte[] ADPCM_26BIT_LEVEL_SHIFT;
201 private static final byte[] ADPCM_2BIT_LEVEL_SHIFT;
202 private static final int[] ADPCM_4BIT_LEVEL_MULT;
203 private static final int[] ADPCM_26BIT_LEVEL_MULT;
204 private static final int[] ADPCM_2BIT_LEVEL_MULT;
205 private static final int[] ADPCM_4BIT_SAMPLE_MULT;
206 private static final int[] ADPCM_26BIT_SAMPLE_MULT;
207 private static final int[] ADPCM_2BIT_SAMPLE_MULT;
209 private static final int DSPCMD_SC_DMA_8_1 = 0x14;
210 private static final int DSPCMD_SC_DMA_8_2 = 0x15;
211 private static final int DSPCMD_SC_DMA_8_3 = 0x91;
212 private static final int DSPCMD_AI_DMA_8_1 = 0x1C;
213 private static final int DSPCMD_AI_DMA_8_2 = 0x90;
214 private static final int DSPCMD_SC_ADPCM_2 = 0x16;
215 private static final int DSPCMD_SC_ADPCM_2_REF = 0x17;
216 private static final int DSPCMD_SC_ADPCM_26 = 0x76;
217 private static final int DSPCMD_SC_ADPCM_26_REF = 0x77;
218 private static final int DSPCMD_SC_ADPCM_4 = 0x74;
219 private static final int DSPCMD_SC_ADPCM_4_REF = 0x75;
220 private static final int DSPCMD_GENERIC_DMA_0 = 0xB0;
221 private static final int DSPCMD_GENERIC_DMA_1 = 0xB1;
222 private static final int DSPCMD_GENERIC_DMA_2 = 0xB2;
223 private static final int DSPCMD_GENERIC_DMA_3 = 0xB3;
224 private static final int DSPCMD_GENERIC_DMA_4 = 0xB4;
225 private static final int DSPCMD_GENERIC_DMA_5 = 0xB5;
226 private static final int DSPCMD_GENERIC_DMA_6 = 0xB6;
227 private static final int DSPCMD_GENERIC_DMA_7 = 0xB7;
228 private static final int DSPCMD_GENERIC_DMA_8 = 0xB8;
229 private static final int DSPCMD_GENERIC_DMA_9 = 0xB9;
230 private static final int DSPCMD_GENERIC_DMA_A = 0xBA;
231 private static final int DSPCMD_GENERIC_DMA_B = 0xBB;
232 private static final int DSPCMD_GENERIC_DMA_C = 0xBC;
233 private static final int DSPCMD_GENERIC_DMA_D = 0xBD;
234 private static final int DSPCMD_GENERIC_DMA_E = 0xBE;
235 private static final int DSPCMD_GENERIC_DMA_F = 0xBF;
236 private static final int DSPCMD_GENERIC_DMA_G = 0xC0;
237 private static final int DSPCMD_GENERIC_DMA_H = 0xC1;
238 private static final int DSPCMD_GENERIC_DMA_I = 0xC2;
239 private static final int DSPCMD_GENERIC_DMA_J = 0xC3;
240 private static final int DSPCMD_GENERIC_DMA_K = 0xC4;
241 private static final int DSPCMD_GENERIC_DMA_L = 0xC5;
242 private static final int DSPCMD_GENERIC_DMA_M = 0xC6;
243 private static final int DSPCMD_GENERIC_DMA_N = 0xC7;
244 private static final int DSPCMD_GENERIC_DMA_O = 0xC8;
245 private static final int DSPCMD_GENERIC_DMA_P = 0xC9;
246 private static final int DSPCMD_GENERIC_DMA_Q = 0xCA;
247 private static final int DSPCMD_GENERIC_DMA_R = 0xCB;
248 private static final int DSPCMD_GENERIC_DMA_S = 0xCC;
249 private static final int DSPCMD_GENERIC_DMA_T = 0xCD;
250 private static final int DSPCMD_GENERIC_DMA_U = 0xCE;
251 private static final int DSPCMD_GENERIC_DMA_V = 0xCF;
253 private static final int DSPCMD_DIRECT_DAC = 0x10;
254 private static final int DSPCMD_CONTINUE_DMA_AI = 0x45;
255 private static final int DSPCMD_CONTINUE_DMA_AI_16 = 0x47;
256 private static final int DSPCMD_SET_TC = 0x40;
257 private static final int DSPCMD_SET_OUTPUT_RATE = 0x41;
258 private static final int DSPCMD_SET_INPUT_RATE = 0x42;
259 private static final int DSPCMD_SET_BLOCKSIZE = 0x48;
260 private static final int DSPCMD_SILENCE = 0x80;
261 private static final int DSPCMD_PAUSE_DMA = 0xD0;
262 private static final int DSPCMD_SPEAKER_ON = 0xD1;
263 private static final int DSPCMD_SPEAKER_OFF = 0xD3;
264 private static final int DSPCMD_CONTINUE_DMA = 0xD4;
265 private static final int DSPCMD_PAUSE_DMA_16 = 0xD5;
266 private static final int DSPCMD_CONTINUE_DMA_16 = 0xD6;
267 private static final int DSPCMD_SPEAKER_STATUS = 0xD8;
268 private static final int DSPCMD_EXIT_DMA_16 = 0xD9;
269 private static final int DSPCMD_EXIT_DMA = 0xDA;
270 private static final int DSPCMD_DSP_IDENTIFY = 0xE0;
271 private static final int DSPCMD_DSP_VERSION = 0xE1;
272 private static final int DSPCMD_DMA_IDENTIFY = 0xE2;
273 private static final int DSPCMD_COPYRIGHT = 0xE3;
274 private static final int DSPCMD_WRITE_TEST = 0xE4;
275 private static final int DSPCMD_READ_TEST = 0xE8;
276 private static final int DSPCMD_RAISE_8BIT_IRQ = 0xF2;
277 private static final int DSPCMD_UNDOCUMENTED1 = 0xF8;
279 private static final byte[] E2_MAGIC = {-106, -91, 105, 90};
281 private static final int FM_CHIPS = 1;
282 private static final String copyright = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
283 public static final long TIME_NEVER = 0x7FFFFFFFFFFFFFFFL;
285 String lastMessage; //Not saved.
286 int portRepeats; //Not saved.
288 static
290 //These tables are as ones used in DosBox.
291 ADPCM_4BIT_LEVEL_SHIFT = new byte[] { -1, 0, 0, 0, 0, 1, 1, 1, -1, 0, 0, 0, 0, 1, 1, 1 };
292 ADPCM_26BIT_LEVEL_SHIFT = new byte[] { -1, 0, 0, 1, -1, 0, 0, 1 };
293 ADPCM_2BIT_LEVEL_SHIFT = new byte[] { -1, 1, -1, 1 };
294 ADPCM_4BIT_LEVEL_MULT = new int[] { 1, 1, 2, 4 };
295 ADPCM_26BIT_LEVEL_MULT = new int[] { 1, 1, 2, 4, 5};
296 ADPCM_2BIT_LEVEL_MULT = new int[] { 1, 1, 2, 4, 8, 16};
297 ADPCM_4BIT_SAMPLE_MULT = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 };
298 ADPCM_26BIT_SAMPLE_MULT = new int[] { 1, 3, 5, 7, -1, -3, -5, -7 };
299 ADPCM_2BIT_SAMPLE_MULT = new int[] { 1, 3, -1, -3 };
302 public void dumpSRPartial(SRDumper output) throws IOException
304 super.dumpSRPartial(output);
305 output.dumpInt(baseIOAddress);
306 output.dumpBoolean(irq2);
307 output.dumpBoolean(irq5);
308 output.dumpBoolean(irq7);
309 output.dumpBoolean(irq10);
310 output.dumpInt(dmaMask);
311 output.dumpInt(dmaRequested);
312 output.dumpBoolean(ioportRegistered);
313 output.dumpObject(clock);
314 output.dumpObject(primaryDMAController);
315 output.dumpObject(secondaryDMAController);
316 output.dumpObject(irqController);
317 output.dumpObject(timer);
318 output.dumpObject(pcmOutput);
320 output.dumpBoolean(irq8Bit);
321 output.dumpBoolean(irq16Bit);
323 output.dumpInt(mixerIndex);
324 output.dumpInt(mixerPrevIndex);
326 output.dumpInt(dspCommandState);
327 output.dumpArray(dspOutput);
328 output.dumpInt(dspOutputUsed);
329 output.dumpArray(mixerRegisters);
330 output.dumpLong(dspNextAttention);
332 output.dumpInt(pcmAmplificationLeft);
333 output.dumpInt(pcmAmplificationRight);
334 output.dumpBoolean(speakerConnected);
336 output.dumpObject(fmChip);
337 output.dumpObject(fmOutput);
338 output.dumpInt(fmIndex);
339 output.dumpLong(fmNextAttention);
341 output.dumpInt(dmaState);
342 output.dumpInt(samplesLeft);
343 output.dumpInt(origSamplesLeft);
344 output.dumpInt(soundFormat);
345 output.dumpBoolean(stereo);
346 output.dumpLong(interSampleTime);
347 output.dumpBoolean(istStereoAdjust);
348 output.dumpInt(dmaActiveMask);
349 output.dumpBoolean(dmaRequest);
350 output.dumpLong(dmaRequestTime);
351 output.dumpInt(partialSample);
352 output.dumpInt(partialSampleBytes);
353 output.dumpInt(wholeSampleBytes);
354 output.dumpInt(byteBuffer);
355 output.dumpInt(byteBufferSamples);
356 output.dumpInt(adpcmReference);
357 output.dumpByte(adpcmScale);
358 output.dumpLong(nextSampleTime);
359 output.dumpBoolean(dmaPaused);
360 output.dumpInt(dmaPauseLeft);
361 output.dumpInt(dspArgumentRegister);
362 output.dumpInt(dspNextDMA);
363 output.dumpInt(dspLastCommand);
365 output.dumpBoolean(e2Mode);
366 output.dumpByte(e2Value);
367 output.dumpInt(e2Count);
371 public SoundCard(SRLoader input) throws IOException
373 super(input);
374 baseIOAddress = input.loadInt();
375 irq2 = input.loadBoolean();
376 irq5 = input.loadBoolean();
377 irq7 = input.loadBoolean();
378 irq10 = input.loadBoolean();
379 dmaMask = input.loadInt();
380 dmaRequested = input.loadInt();
381 ioportRegistered = input.loadBoolean();
382 clock = (Clock)input.loadObject();
383 primaryDMAController = (DMAController)input.loadObject();
384 secondaryDMAController = (DMAController)input.loadObject();
385 irqController = (InterruptController)input.loadObject();
386 timer = (Timer)input.loadObject();
387 pcmOutput = (SoundDigitalOut)input.loadObject();
389 irq8Bit = input.loadBoolean();
390 irq16Bit = input.loadBoolean();
392 mixerIndex = input.loadInt();
393 mixerPrevIndex = input.loadInt();
395 dspCommandState = input.loadInt();
396 dspOutput = input.loadArrayInt();
397 dspOutputUsed = input.loadInt();
398 mixerRegisters = input.loadArrayInt();
399 dspNextAttention = input.loadLong();
401 pcmAmplificationLeft = input.loadInt();
402 pcmAmplificationRight = input.loadInt();
403 speakerConnected = input.loadBoolean();
405 fmChip = (FMChip)input.loadObject();
406 fmOutput = (SoundDigitalOut)input.loadObject();
407 fmIndex = input.loadInt();
408 fmNextAttention = input.loadLong();
410 dmaState = input.loadInt();
411 samplesLeft = input.loadInt();
412 origSamplesLeft = input.loadInt();
413 soundFormat = input.loadInt();
414 stereo = input.loadBoolean();
415 interSampleTime = input.loadLong();
416 istStereoAdjust = input.loadBoolean();
417 dmaActiveMask = input.loadInt();
418 dmaRequest = input.loadBoolean();
419 dmaRequestTime = input.loadLong();
420 partialSample = input.loadInt();
421 partialSampleBytes = input.loadInt();
422 wholeSampleBytes = input.loadInt();
423 byteBuffer = input.loadInt();
424 byteBufferSamples = input.loadInt();
425 adpcmReference = input.loadInt();
426 adpcmScale = input.loadByte();
427 nextSampleTime = input.loadLong();
428 dmaPaused = input.loadBoolean();
429 dmaPauseLeft = input.loadInt();
430 dspArgumentRegister = input.loadInt();
431 dspNextDMA = input.loadInt();
432 dspLastCommand = input.loadInt();
434 e2Mode = input.loadBoolean();
435 e2Value = input.loadByte();
436 e2Count = input.loadInt();
439 public SoundCard(String parameters) throws IOException
441 char mode = 0;
442 int tmp = 0;
443 int irq = 5;
444 baseIOAddress = 0x220;
445 int lowDMA = 1;
446 int highDMA = 5;
448 interSampleTime = 50000; //Something even reasonably sane.
449 dspNextDMA = -1 ; //No, don't program DMA on first DSP command.
451 fmChip = new FMChip();
452 fmOutput = null;
453 fmIndex = 0;
454 fmNextAttention = TIME_NEVER;
455 dspNextAttention = TIME_NEVER;
457 dspOutput = new int[QUEUE_SIZE];
458 mixerRegisters = new int[MIXER_REGISTERS];
459 mixerPrevIndex = 128;
460 mixerIndex = 128;
462 dspCommandState = DSPSTATE_WAIT_COMMAND;
464 for(int i = 0; i < parameters.length() + 1; i++) {
465 char ch = 0;
466 if(i < parameters.length())
467 ch = parameters.charAt(i);
469 if(ch >= '0' && ch <= '9' && mode != 0) {
470 tmp = tmp * 10 + (ch - '0');
471 continue;
472 } else if(ch >= '0' && ch <= '9' && mode == 0)
473 throw new IOException("Soundcard: Invalid spec '" + parameters + "'.");
474 if(mode == 'A')
475 if(tmp > 65516)
476 throw new IOException("Soundcard: Bad I/O port " + tmp + ".");
477 else
478 baseIOAddress = tmp;
479 else if(mode == 'I')
480 if(tmp != 2 && tmp != 5 && tmp != 7 && tmp != 10)
481 throw new IOException("Soundcard: Bad IRQ " + tmp + ".");
482 else
483 irq = tmp;
484 else if(mode == 'D')
485 if(tmp != 0 && tmp != 1 && tmp != 3)
486 throw new IOException("Soundcard: Bad low DMA " + tmp + ".");
487 else
488 lowDMA = tmp;
489 else if(mode == 'H')
490 if(tmp == 0)
491 highDMA = 0; //Disable high DMA.
492 else if(tmp != 5 && tmp != 6 || tmp != 7)
493 throw new IOException("Soundcard: Bad high DMA " + tmp + ".");
494 else
495 highDMA = tmp;
496 else if(mode > 0 || i > 0)
497 throw new IOException("Soundcard: Invalid setting type '" + mode + "'.");
498 if(ch == 0)
499 break;
500 mode = ch;
501 tmp = 0;
503 if(irq == 2)
504 irq2 = true;
505 if(irq == 5)
506 irq5 = true;
507 if(irq == 7)
508 irq7 = true;
509 if(irq == 10)
510 irq10 = true;
511 if(highDMA > 0)
512 dmaMask = (1 << lowDMA) | (1 << highDMA);
513 else
514 dmaMask = (1 << lowDMA);
515 dmaRequested = 0;
516 resetMixer();
519 private final void grabDMAChannels()
521 int toReq = dmaMask & ~dmaRequested;
522 if(primaryDMAController == null)
523 toReq &= 0xF0;
524 if(secondaryDMAController == null)
525 toReq &= 0x0F;
526 if((toReq & 1) != 0 && primaryDMAController != null)
527 primaryDMAController.registerChannel(0, this);
528 if((toReq & 2) != 0 && primaryDMAController != null)
529 primaryDMAController.registerChannel(1, this);
530 if((toReq & 8) != 0 && primaryDMAController != null)
531 primaryDMAController.registerChannel(3, this);
532 if((toReq & 32) != 0 && secondaryDMAController != null)
533 secondaryDMAController.registerChannel(1, this);
534 if((toReq & 64) != 0 && secondaryDMAController != null)
535 secondaryDMAController.registerChannel(2, this);
536 if((toReq & 128) != 0 && secondaryDMAController != null)
537 secondaryDMAController.registerChannel(3, this);
538 dmaRequested |= toReq;
539 dmaEngineUpdateDMADREQ();
542 public SoundCard() throws IOException
544 this("");
547 public void dumpStatusPartial(StatusDumper output)
549 super.dumpStatusPartial(output);
550 output.println("\tbaseIOAddress " + baseIOAddress);
551 output.println("\tirq8Bit " + irq8Bit);
552 output.println("\tirq16Bit " + irq16Bit);
553 output.println("\tirq2 " + irq2);
554 output.println("\tirq5 " + irq5);
555 output.println("\tirq7 " + irq7);
556 output.println("\tirq10 " + irq10);
557 output.println("\tdmaMask " + dmaMask);
558 output.println("\tdmaRequested " + dmaRequested);
559 output.println("\tioportRegistered " + ioportRegistered);
560 output.println("\tirqController <object #" + output.objectNumber(irqController) + ">"); if(irqController != null) irqController.dumpStatus(output);
561 output.println("\tprimaryDMAController <object #" + output.objectNumber(primaryDMAController) + ">"); if(primaryDMAController != null) primaryDMAController.dumpStatus(output);
562 output.println("\tsecondaryDMAController <object #" + output.objectNumber(secondaryDMAController) + ">"); if(secondaryDMAController != null) secondaryDMAController.dumpStatus(output);
563 output.println("\tclock <object #" + output.objectNumber(clock) + ">"); if(clock != null) clock.dumpStatus(output);
564 output.println("\ttimer <object #" + output.objectNumber(timer) + ">"); if(timer != null) timer.dumpStatus(output);
565 output.println("\tpcmOutput <object #" + output.objectNumber(pcmOutput) + ">"); if(pcmOutput != null) pcmOutput.dumpStatus(output);
567 output.println("\tmixerIndex " + mixerIndex);
568 output.println("\tmixerPrevIndex " + mixerPrevIndex);
569 output.printArray(mixerRegisters, "mixerRegisters");
571 output.println("\tpcmAmplificationLeft " + pcmAmplificationLeft);
572 output.println("\tpcmAmplificationRight " + pcmAmplificationRight);
573 output.println("\tspeakerConnected " + speakerConnected);
575 output.println("\tfmIndex " + fmIndex);
576 output.println("\tfmNextAttention " + fmNextAttention);
577 output.println("\tfmChip <object #" + output.objectNumber(fmChip) + ">"); if(fmChip != null) fmChip.dumpStatus(output);
578 output.println("\tfmOutput <object #" + output.objectNumber(fmOutput) + ">"); if(fmOutput != null) fmOutput.dumpStatus(output);
580 output.printArray(dspOutput, "dspOutput");
581 output.println("\tdspOutputUsed " + dspOutputUsed);
582 output.println("\tdspCommandState " + dspCommandState);
583 output.println("\tdspNextAttention " + dspNextAttention);
585 output.println("\tdmaState " + dmaState);
586 output.println("\tsamplesLeft " + samplesLeft);
587 output.println("\torigSamplesLeft " + origSamplesLeft);
588 output.println("\tsoundFormat " + soundFormat);
589 output.println("\tstereo " + stereo);
590 output.println("\tinterSampleTime " + interSampleTime);
591 output.println("\tistStereoAdjust " + istStereoAdjust);
592 output.println("\tdmaActiveMask " + dmaActiveMask);
593 output.println("\tdmaRequest " + dmaRequest);
594 output.println("\tdmaRequestTime " + dmaRequestTime);
595 output.println("\tpartialSample " + partialSample);
596 output.println("\tpartialSampleBytes " + partialSampleBytes);
597 output.println("\twholeSampleBytes " + wholeSampleBytes);
598 output.println("\tbyteBuffer " + byteBuffer);
599 output.println("\tbyteBufferSamples " + byteBufferSamples);
600 output.println("\tadpcmReference " + adpcmReference);
601 output.println("\tadpcmScale " + adpcmScale);
602 output.println("\tnextSampleTime " + nextSampleTime);
603 output.println("\tdmaPaused " + dmaPaused);
604 output.println("\tdmaPauseLeft " + dmaPauseLeft);
605 output.println("\tdspArgumentRegister " + dspArgumentRegister);
606 output.println("\tdspNextDMA " + dspNextDMA);
607 output.println("\tdspLastCommand " + dspLastCommand);
609 output.println("\te2Mode " + e2Mode);
610 output.println("\te2Value " + e2Value);
611 output.println("\te2Count " + e2Count);
614 public void dumpStatus(StatusDumper output)
616 if(output.dumped(this))
617 return;
619 output.println("#" + output.objectNumber(this) + ": SoundCard:");
620 dumpStatusPartial(output);
621 output.endObject();
624 public boolean initialised()
626 return ((irqController != null) && (clock != null) && (primaryDMAController != null) && (secondaryDMAController != null) && ioportRegistered);
629 public void acceptComponent(HardwareComponent component)
631 if((component instanceof InterruptController) && component.initialised()) {
632 irqController = (InterruptController)component;
634 if((component instanceof DMAController) && ((DMAController)component).isPrimary() && component.initialised()) {
635 primaryDMAController = (DMAController)component;
636 grabDMAChannels();
638 if((component instanceof DMAController) && !((DMAController)component).isPrimary() && component.initialised()) {
639 secondaryDMAController = (DMAController)component;
640 grabDMAChannels();
642 if((component instanceof Clock) && component.initialised()) {
643 clock = (Clock)component;
644 timer = clock.newTimer(this);
647 if((component instanceof IOPortHandler) && component.initialised() && !ioportRegistered) {
648 ((IOPortHandler)component).registerIOPortCapable(this);
649 ioportRegistered = true;
654 public int[] ioPortsRequested()
656 int[] ret;
657 ret = new int[20];
658 for(int i = 0; i < 16; i++)
659 ret[i] = baseIOAddress + i;
660 ret[ret.length - 4] = 0x388;
661 ret[ret.length - 3] = 0x389;
662 ret[ret.length - 2] = 0x38A;
663 ret[ret.length - 1] = 0x38B;
664 writeMessage("Requesting I/O ports.");
665 return ret;
668 public int getTimerType()
670 return 36;
673 public void ioPortWriteWord(int address, int data)
675 ioPortWriteByte(address, data & 0xFF);
676 ioPortWriteByte(address + 1, (data >>> 8) & 0xFF);
679 public void ioPortWriteLong(int address, int data)
681 ioPortWriteByte(address, data & 0xFF);
682 ioPortWriteByte(address + 1, (data >>> 8) & 0xFF);
683 ioPortWriteByte(address + 2, (data >>> 16) & 0xFF);
684 ioPortWriteByte(address + 3, (data >>> 24) & 0xFF);
687 public int ioPortReadWord(int address)
689 return (ioPortReadByte(address) | (ioPortReadByte(address + 1) << 8));
692 public int ioPortReadLong(int address)
694 return ioPortReadByte(address) | (ioPortReadByte(address + 1) << 8) |
695 (ioPortReadByte(address + 2) << 16) | (ioPortReadByte(address + 3) << 24);
698 public void ioPortWriteByte(int address, int data)
700 if(address >= baseIOAddress && address < baseIOAddress + 16)
701 if((address - baseIOAddress & ~1) != 8)
702 ioWrite(address - baseIOAddress, data);
703 else
704 ioWrite(address - baseIOAddress - 8, data);
705 else if(address >= 0x388 && address < 0x38C)
706 ioWrite(address - 0x388, data);
709 public int ioPortReadByte(int address)
711 int value = -1;
712 if(address >= baseIOAddress && address < baseIOAddress + 16)
713 if((address - baseIOAddress & ~1) != 8)
714 value = ioRead(address - baseIOAddress);
715 else
716 value = ioRead(address - baseIOAddress - 8);
717 else if(address >= 0x388 && address < 0x38C)
718 value = ioRead(address - 0x388);
720 return value;
723 public int handleTransfer(DMAController.DMAChannel channel, int position, int size)
725 byte[] buf = new byte[1];
726 int avail = size - position;
728 //Some weird command has DMA writing some mysterious values.
729 if(e2Mode) {
730 buf[0] = e2Value;
731 channel.writeMemory(buf, 0, position, 1);
732 e2Mode = false;
733 dmaEngineUpdateDMADREQ();
734 return position + 1;
737 // System.err.println("Informational: SB: Invoked DMA transfer handler.");
739 while(avail > 0 && partialSampleBytes < wholeSampleBytes) {
740 channel.readMemory(buf, 0, position, 1);
741 partialSample |= (((int)buf[0] & 0xFF) << (8 * partialSampleBytes));
742 position++;
743 partialSampleBytes++;
744 avail--;
746 dmaEngineUpdateDMADREQ();
747 if(partialSampleBytes == wholeSampleBytes)
748 dmaEngineSampleAvailable();
749 return position;
753 public int requestedSoundChannels()
755 return 1 + FM_CHIPS;
758 public void soundChannelCallback(SoundDigitalOut out)
760 if(pcmOutput == null)
761 pcmOutput = out;
762 else if(fmOutput == null) {
763 fmChip.setOutput(out);
764 fmOutput = out;
766 recomputeVolume(0); //These always happen at zero time.
769 //Set IRQ line status.
770 private final void setIRQ(int status)
772 if(irq2)
773 irqController.setIRQ(2, status);
774 if(irq5)
775 irqController.setIRQ(5, status);
776 if(irq7)
777 irqController.setIRQ(7, status);
778 if(irq10)
779 irqController.setIRQ(10, status);
782 //Read DMA Select register.
783 private final int readDMARegister()
785 return dmaMask;
788 //Write DMA Select register.
789 private final void writeDMARegister(int value)
791 value = value & 0xEB; //Mask invalid channels.
792 dmaMask = value;
793 grabDMAChannels();
796 //Read IRQ select register.
797 private final int readIRQRegister()
799 int value = 0xF0;
800 if(irq2)
801 value |= 1;
802 if(irq5)
803 value |= 2;
804 if(irq7)
805 value |= 4;
806 if(irq10)
807 value |= 8;
808 return value;
811 //Write IRQ select register.
812 private final void writeIRQRegister(int value)
814 irq2 = ((value & 1) != 0);
815 irq5 = ((value & 2) != 0);
816 irq7 = ((value & 4) != 0);
817 irq10 = ((value & 8) != 0);
820 //Reqd IRQ Status register value.
821 private final int readIRQStatus()
823 return typeFlag | (irq8Bit ? 1 : 0) | (irq16Bit ? 2 : 0);
826 //Set or clear 8 Bit requesting IRQ status.
827 private final void set8BitIRQ(boolean status)
829 boolean oldActive = irq8Bit || irq16Bit;
830 irq8Bit = status;
831 boolean newActive = irq8Bit || irq16Bit;
832 if(!oldActive && newActive)
833 writeMessage("Raising IRQ (8bit)");
834 if(oldActive && !newActive)
835 writeMessage("Lowering IRQ (8bit)");
836 if(oldActive != newActive)
837 setIRQ(newActive ? 1 : 0);
840 //Set or clear 16 Bit requesting IRQ status.
841 private final void set16BitIRQ(boolean status)
843 boolean oldActive = irq8Bit || irq16Bit;
844 irq16Bit = status;
845 boolean newActive = irq8Bit || irq16Bit;
846 if(!oldActive && newActive)
847 writeMessage("Raising IRQ (16bit)");
848 if(oldActive && !newActive)
849 writeMessage("Lowering IRQ (16bit)");
850 if(oldActive != newActive)
851 setIRQ(newActive ? 1 : 0);
854 private final void writeMessage(String message)
856 message = "Informational: " + message;
857 if(message.equals(lastMessage))
858 portRepeats++;
859 else {
860 if(portRepeats > 1)
861 System.err.println("<Last message repeted " + portRepeats + " times.>");
862 System.err.println(message);
863 lastMessage = message;
864 portRepeats = 1;
868 //Do I/O write. Possible offsets are 0-7 and 10-15.
869 public void ioWrite(int offset, int dataByte)
871 switch(offset) {
872 case 0:
873 fmIndex = dataByte;
874 return;
875 case 1:
876 //writeMessage("SB: FM write: " + fmIndex + " -> " + dataByte + ".");
877 writeFM(fmIndex, dataByte);
878 return;
879 case 2:
880 fmIndex = 256 + dataByte;
881 return;
882 case 3:
883 //writeMessage("SB: FM write: " + fmIndex + " -> " + dataByte + ".");
884 writeFM(fmIndex, dataByte);
885 return;
886 case 4:
887 mixerPrevIndex = mixerIndex;
888 if(!validMixerRegister(mixerPrevIndex, 0))
889 mixerPrevIndex |= 0x80;
890 mixerIndex = dataByte;
891 return;
892 case 5:
893 writeMixer(mixerIndex, dataByte);
894 return;
895 case 6:
896 writeMessage("SB: Resetting card.");
897 doReset(dataByte);
898 return;
899 case 12:
900 dspWrite(dataByte);
901 return;
902 case 7:
903 case 8:
904 case 9:
905 case 10:
906 case 11:
907 case 13:
908 case 14:
909 case 15:
910 default:
911 writeMessage("SB: Attempted write to port " + offset + ".");
912 //Not writable.
913 return;
917 //Do I/O read. Possible offsets are 0-7 and 10-15.
918 public int ioRead(int offset)
920 int tmp;
921 switch(offset) {
922 case 0:
923 case 2:
924 tmp = readFMStatus();
925 //writeMessage("SB: Read FM status " + (tmp & 0xE0) + ".");
926 return tmp;
927 case 1:
928 case 3:
929 writeMessage("SB: Tried to read FM data port.");
930 return 0; //Lets do like opl.cpp does...
931 case 4:
932 writeMessage("SB: Read mixer index (" + mixerIndex + ").");
933 return mixerIndex;
934 case 5:
935 tmp = readMixer(mixerIndex);
936 writeMessage("SB: Read mixer register " + mixerIndex + " -> " + tmp + ".");
937 return tmp;
938 case 10:
939 tmp = dspRead();
940 writeMessage("SB: Read value " + tmp + " from DSP.");
941 return tmp;
942 case 12:
943 return writeBufferStatus();
944 case 13:
945 //This is undocumented. What it does?
946 return 255;
947 case 14:
948 set8BitIRQ(false);
949 tmp = dspDataAvailableStatus();
950 if((tmp & 128) == 0)
951 writeMessage("SB: Read read buffer status / cleared 8-bit IRQ (no data in buffer).");
952 else
953 writeMessage("SB: Read read buffer status / cleared 8-bit IRQ (data in buffer).");
954 case 15:
955 set16BitIRQ(false);
956 return -1;
957 case 6:
958 case 7:
959 case 8:
960 case 9:
961 case 11:
962 default:
963 writeMessage("SB: Attempted read from port " + offset + ".");
964 return 255; //Not readable.
968 public void resetCard()
970 irq8Bit = false;
971 irq16Bit = false;
972 mixerIndex = 128;
973 mixerPrevIndex = 128;
974 dspOutputUsed = 0;
975 dspLastCommand = 0;
976 setIRQ(0);
977 speakerConnected = false;
978 dspCommandState = DSPSTATE_WAIT_COMMAND;
979 resetMixer();
980 dmaEngineKillTransfer();
981 e2Mode = false;
982 e2Value = (byte)0xAA;
983 e2Count = 0;
986 public void reset()
988 fmIndex = 0;
989 ioportRegistered = false;
990 if(clock != null)
991 fmChip.resetCard(clock.getTime());
992 else
993 fmChip.resetCard(0);
994 resetCard();
997 private final int writeBufferStatus()
999 return 127;
1002 private final int dspDataAvailableStatus()
1004 return 127 | ((dspOutputUsed > 0) ? 128 : 0);
1007 //Mode >=0 is read, <=0 is write.
1008 private final boolean validMixerRegister(int reg, int mode)
1010 if(reg == MIXREG_IRQSELECT || reg == MIXREG_DMASELECT || reg == MIXREG_DAC || reg == MIXREG_MIC || reg == MIXREG_OUTPUT_CONTROL)
1011 return true;
1012 if(reg == MIXREG_MASTER || reg == MIXREG_FM || reg == MIXREG_CD || reg == MIXREG_LINEIN)
1013 return true;
1014 if(reg == MIXREG_IRQSTATUS && mode >= 0)
1015 return true;
1016 if(reg < 0 || reg > MIXREG_LAST)
1017 return false;
1018 if(reg == MIXREG_RESET)
1019 return (mode <= 0);
1020 if(reg == MIXREG_STATUS)
1021 return (mode >= 0);
1022 if(reg >= MIXREG_SB16_FIRST)
1023 return true;
1024 return false;
1027 //Write Mixer data register.
1028 private final void writeMixer(int reg, int data)
1030 if(reg == MIXREG_IRQSELECT) {
1031 writeIRQRegister(data);
1032 return;
1034 if(reg == MIXREG_DMASELECT) {
1035 writeDMARegister(data);
1036 return;
1038 if(reg == MIXREG_RESET) {
1039 resetMixer();
1040 return;
1042 if(reg == MIXREG_DAC) {
1043 mixerRegisters[MIXER_DAC_LEFT] = (data & 0xF0) | 0x08;
1044 mixerRegisters[MIXER_DAC_RIGHT] = ((data & 0xF) << 4) | 0x08;
1045 recomputeVolume(clock.getTime());
1046 return;
1048 if(reg == MIXREG_MIC) {
1049 mixerRegisters[MIXER_MIC] = (data & 0x07) << 5;
1050 return;
1052 if(reg == MIXREG_OUTPUT_CONTROL) {
1053 mixerRegisters[MIXER_OUTPUT_CONTROL] = data;
1054 return;
1056 if(reg == MIXREG_MASTER) {
1057 mixerRegisters[MIXER_MASTER_LEFT] = (data & 0xF0) | 0x08;
1058 mixerRegisters[MIXER_MASTER_RIGHT] = ((data & 0xF) << 4) | 0x08;
1059 recomputeVolume(clock.getTime());
1060 return;
1062 if(reg == MIXREG_FM) {
1063 mixerRegisters[MIXER_FM_LEFT] = (data & 0xF0) | 0x08;
1064 mixerRegisters[MIXER_FM_RIGHT] = ((data & 0xF) << 4) | 0x08;
1065 recomputeVolume(clock.getTime());
1066 return;
1068 if(reg == MIXREG_CD) {
1069 mixerRegisters[MIXER_CD_LEFT] = (data & 0xF0) | 0x08;
1070 mixerRegisters[MIXER_CD_RIGHT] = ((data & 0xF) << 4) | 0x08;
1071 return;
1073 if(reg == MIXREG_LINEIN) {
1074 mixerRegisters[MIXER_LINEIN_LEFT] = (data & 0xF0) | 0x08;
1075 mixerRegisters[MIXER_LINEIN_RIGHT] = ((data & 0xF) << 4) | 0x08;
1076 return;
1078 if(!validMixerRegister(reg, -1))
1079 return; //Bad register.
1081 mixerRegisters[reg - MIXREG_SB16_FIRST] = data;
1082 recomputeVolume(clock.getTime());
1085 //Read Mixer data register.
1086 private final int readMixer(int reg)
1088 if(reg == MIXREG_IRQSELECT)
1089 return readIRQRegister();
1090 if(reg == MIXREG_DMASELECT)
1091 return readDMARegister();
1092 if(reg == MIXREG_IRQSTATUS)
1093 return readIRQStatus();
1094 if(reg == MIXREG_STATUS)
1095 return mixerPrevIndex;
1096 if(reg == MIXREG_DAC)
1097 return (mixerRegisters[MIXER_DAC_LEFT] & 0xF0) | ((mixerRegisters[MIXER_DAC_RIGHT] & 0xF0) >> 4);
1098 if(reg == MIXREG_MIC)
1099 return (mixerRegisters[MIXER_MIC] >> 5);
1100 if(reg == MIXREG_OUTPUT_CONTROL)
1101 return mixerRegisters[MIXER_OUTPUT_CONTROL];
1102 if(reg == MIXREG_MASTER)
1103 return (mixerRegisters[MIXER_MASTER_LEFT] & 0xF0) | ((mixerRegisters[MIXER_MASTER_RIGHT] & 0xF0) >> 4);
1104 if(reg == MIXREG_FM)
1105 return (mixerRegisters[MIXER_FM_LEFT] & 0xF0) | ((mixerRegisters[MIXER_FM_RIGHT] & 0xF0) >> 4);
1106 if(reg == MIXREG_CD)
1107 return (mixerRegisters[MIXER_CD_LEFT] & 0xF0) | ((mixerRegisters[MIXER_CD_RIGHT] & 0xF0) >> 4);
1108 if(reg == MIXREG_LINEIN)
1109 return (mixerRegisters[MIXER_LINEIN_LEFT] & 0xF0) | ((mixerRegisters[MIXER_LINEIN_RIGHT] & 0xF0) >> 4);
1110 if(!validMixerRegister(reg, 1))
1111 return -1; //Bad register.
1113 return mixerRegisters[reg - MIXREG_SB16_FIRST];
1116 private final void resetMixer()
1118 mixerRegisters[MIXER_MASTER_LEFT] = 0xC0;
1119 mixerRegisters[MIXER_MASTER_RIGHT] = 0xC0;
1120 mixerRegisters[MIXER_DAC_LEFT] = 0xC0;
1121 mixerRegisters[MIXER_DAC_RIGHT] = 0xC0;
1122 mixerRegisters[MIXER_FM_LEFT] = 0xC0;
1123 mixerRegisters[MIXER_FM_RIGHT] = 0xC0;
1124 mixerRegisters[MIXER_CD_LEFT] = 0x00;
1125 mixerRegisters[MIXER_CD_RIGHT] = 0x00;
1126 mixerRegisters[MIXER_LINEIN_LEFT] = 0x00;
1127 mixerRegisters[MIXER_LINEIN_RIGHT] = 0x00;
1128 mixerRegisters[MIXER_MIC] = 0x00;
1129 mixerRegisters[MIXER_PCSPEAKER] = 0x00;
1130 mixerRegisters[MIXER_OUTPUT_CONTROL] = 0x1F;
1131 mixerRegisters[MIXER_INPUT_CONTROL_LEFT] = 0x15;
1132 mixerRegisters[MIXER_INPUT_CONTROL_RIGHT] = 0x0B;
1133 mixerRegisters[MIXER_INPUT_GAIN_CONTROL_LEFT] = 0x00;
1134 mixerRegisters[MIXER_INPUT_GAIN_CONTROL_RIGHT] = 0x00;
1135 mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_LEFT] = 0x00;
1136 mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_RIGHT] = 0x00;
1137 mixerRegisters[MIXER_AUTOMATIC_GAIN_CONTROL] = 0x00;
1138 mixerRegisters[MIXER_TREBLE_LEFT] = 0x80;
1139 mixerRegisters[MIXER_TREBLE_RIGHT] = 0x80;
1140 mixerRegisters[MIXER_BASS_LEFT] = 0x80;
1141 mixerRegisters[MIXER_BASS_RIGHT] = 0x80;
1142 mixerRegisters[MIXER_OUTPUT_CONTROL] = 0;
1143 if(clock != null)
1144 recomputeVolume(clock.getTime());
1145 else
1146 recomputeVolume(0);
1149 private final void recomputeVolume(long timeStamp)
1151 double fractionalMasterLeft = (double)mixerRegisters[MIXER_MASTER_LEFT] / 255;
1152 double fractionalMasterRight = (double)mixerRegisters[MIXER_MASTER_RIGHT] / 255;
1153 double fractionalDACLeft = (double)mixerRegisters[MIXER_DAC_LEFT] / 255;
1154 double fractionalDACRight = (double)mixerRegisters[MIXER_DAC_RIGHT] / 255;
1155 double fractionalFMLeft = (double)mixerRegisters[MIXER_FM_LEFT] / 255;
1156 double fractionalFMRight = (double)mixerRegisters[MIXER_FM_RIGHT] / 255;
1157 int gainLeft = 1 << (mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_LEFT] >> 6);
1158 int gainRight = 1 << (mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_RIGHT] >> 6);
1160 pcmAmplificationLeft = (int)(65536 * fractionalMasterLeft * fractionalDACLeft * gainLeft);
1161 pcmAmplificationRight = (int)(65536 * fractionalMasterRight * fractionalDACRight * gainRight);
1162 // System.err.println("Informational: SBMixer: PCM amplification now " + pcmAmplificationLeft + "/" + pcmAmplificationRight + ".");
1164 double fmAmpLeft = fractionalMasterLeft * fractionalFMLeft * gainLeft;
1165 double fmAmpRight = fractionalMasterRight * fractionalFMRight * gainRight;
1166 if(fmOutput != null)
1167 fmOutput.addSample(timeStamp, (short)(2048 + 255 * fmAmpLeft), (short)(255 * fmAmpRight));
1169 //SB16 ignores this.
1171 if(!speakerConnected) {
1172 pcmAmplificationLeft = 0;
1173 pcmAmplificationRight = 0;
1178 //Send PCM sample, taking mixer into account.
1179 private final void sendPCMSample(long timestamp, short left, short right)
1181 sendSample(timestamp, left, right, pcmAmplificationLeft, pcmAmplificationRight, pcmOutput);
1184 private final void sendSample(long timestamp, short left, short right, int ampLeft, int ampRight,
1185 SoundDigitalOut out)
1187 //TODO: Support Bass/Treble.
1188 double _left = (double)left * ampLeft / 65536;
1189 double _right = (double)right * ampRight / 65536;
1191 if(_left > 32767) left = 32767;
1192 else if(_left < -32768) left = -32768;
1193 else left = (short)_left;
1195 if(_right > 32767) right = 32767;
1196 else if(_right < -32768) right = -32768;
1197 else right = (short)_right;
1199 out.addSample(timestamp, left, right);
1202 //Read FM synth #1 status register.
1203 private final int readFMStatus()
1205 return fmChip.status(clock.getTime());
1208 //Read from DSP.
1209 private final int dspRead()
1211 int value = dspOutput[0];
1212 if(dspOutputUsed > 1)
1213 System.arraycopy(dspOutput, 1, dspOutput, 0, dspOutputUsed - 1);
1214 dspOutputUsed--;
1215 return value;
1218 //Write FM synth #1 data register.
1219 private final void writeFM(int reg, int data)
1221 fmChip.write(clock.getTime(), reg, data);
1222 updateTimer();
1225 //Write to reset register.
1226 private final void doReset(int resetValue)
1228 resetCard();
1229 dspOutput[0] = 0xAA;
1230 dspOutputUsed = 1;
1233 //Recompute value for timer expiry.
1234 private final void updateTimer()
1236 long nextTime = TIME_NEVER;
1237 if(dspNextAttention < nextTime)
1238 nextTime = dspNextAttention;
1239 long tmp = fmChip.nextAttention(clock.getTime());
1240 if(tmp < nextTime)
1241 nextTime = tmp;
1242 if(nextTime != TIME_NEVER) {
1243 if(timer != null)
1244 timer.setExpiry(nextTime);
1245 } else
1246 if(timer != null)
1247 timer.disable();
1250 //Recompute value for timer expiry, setting DSP timer expiry.
1251 private final void updateTimer(long dspExpiry)
1253 dspNextAttention = dspExpiry;
1254 // if(dspNextAttention < TIME_NEVER)
1255 // System.err.println("Informational: SB: Setting next attention to " + dspNextAttention + ".");
1256 // else
1257 // System.err.println("Informational: SB: Clearing next attention.");
1258 updateTimer();
1261 public void callback()
1263 long timeNow = clock.getTime();
1264 boolean runAny = true;
1265 while(runAny) {
1266 runAny = false;
1267 if(dspNextAttention <= timeNow) {
1268 dspAttention(dspNextAttention);
1269 runAny = true;
1271 long tmp = fmChip.nextAttention(clock.getTime());
1272 if(tmp <= timeNow) {
1273 fmChip.attention(clock.getTime());
1274 runAny = true;
1276 if(runAny)
1277 updateTimer();
1281 //Put byte into DSP output queue.
1282 private final void dspOutputPut(int value)
1284 dspOutput[dspOutputUsed++] = value;
1287 private final String interpretMode(int mode)
1289 if(mode == 0)
1290 return "NONE";
1291 else if(mode == 1)
1292 return "SC";
1293 else if(mode == 2)
1294 return "AI";
1295 else if(mode == 3)
1296 return "AI_EXIT";
1297 else
1298 return "UNKNOWN(" + mode + ")";
1301 private final String interpretFormat(int format)
1303 switch(format) {
1304 case SNDFMT_2BIT_ADPCM:
1305 return "ADPCM_2_BIT";
1306 case SNDFMT_26BIT_ADPCM:
1307 return "ADPCM_2.6_BIT";
1308 case SNDFMT_4BIT_ADPCM:
1309 return "ADPCM_4_BIT";
1310 case SNDFMT_2BIT_ADPCM_REF:
1311 return "ADPCM_2_BIT_REF";
1312 case SNDFMT_26BIT_ADPCM_REF:
1313 return "ADPCM_2.6_BIT_REF";
1314 case SNDFMT_4BIT_ADPCM_REF:
1315 return "ADPCM_4_BIT_REF";
1316 case SNDFMT_8BIT_PCM_SIGNED:
1317 return "PCM_8BIT_SIGNED";
1318 case SNDFMT_8BIT_PCM_UNSIGNED:
1319 return "PCM_8BIT_PCM_UNSIGNED";
1320 case SNDFMT_16BIT_PCM_LE_SIGNED:
1321 return "PCM_16BIT_LE_SIGNED";
1322 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1323 return "PCM_16BIT_LE_UNSIGNED";
1324 case SNDFMT_16BIT_PCM_BE_SIGNED:
1325 return "PCM_16BIT_BE_SIGNED";
1326 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1327 return "PCM_16BIT_BE_UNSIGNED";
1328 default:
1329 return "UNKNOWN(" + format + ")";
1333 //Kick-start DMA transfer.
1334 private final void dmaEngineStartTransfer(int mode, int samples, int format, boolean stereoFlag)
1336 long timeNow = clock.getTime();
1337 dmaState = mode;
1338 samplesLeft = origSamplesLeft = samples;
1339 soundFormat = format;
1340 stereo = stereoFlag;
1341 partialSample = 0;
1342 partialSampleBytes = 0;
1343 wholeSampleBytes = 0;
1344 byteBuffer = 0;
1345 byteBufferSamples = 0;
1346 dmaPaused = false;
1347 nextSampleTime = timeNow;
1348 updateTimer(nextSampleTime);
1349 writeMessage("SBDSP: Starting DMA: mode=" + interpretMode(mode) + " samples=" + samples + " format=" +
1350 interpretFormat(format) + " stereoFlag=" + stereoFlag);
1353 //Kill DMA transfer.
1354 private final void dmaEngineKillTransfer()
1356 int activeChannels = dmaActiveMask;
1357 dmaState = DMA_NONE;
1358 dmaPaused = false;
1359 partialSampleBytes = wholeSampleBytes = partialSample = 0;
1360 dmaEngineUpdateDMADREQ();
1361 updateTimer(TIME_NEVER);
1362 if(activeChannels != 0)
1363 writeMessage("SBDSP: Killed DMA transfer.");
1366 //End DMA transfer.
1367 private final void dmaEngineEndTransfer()
1369 if(dmaState == DMA_CONTINUOUS) {
1370 writeMessage("SBDSP: Exiting DMA transfer.");
1371 dmaState = DMA_CONTINUOUS_EXIT;
1375 private final void dmaEnginePauseTransfer()
1377 dmaPaused = true;
1378 dmaPauseLeft = -1;
1379 updateTimer(TIME_NEVER);
1380 writeMessage("SBDSP: Pausing DMA transfer.");
1383 private final void dmaEnginePauseTransfer(int samples)
1385 dmaPaused = true;
1386 dmaPauseLeft = samples;
1387 writeMessage("SBDSP: Pausing DMA transfer for " + samples + " samples.");
1390 private final void dmaEngineContinueTransfer()
1392 dmaPaused = false;
1393 nextSampleTime = clock.getTime();
1394 updateTimer(nextSampleTime);
1395 writeMessage("SBDSP: Continuing DMA transfer.");
1398 private static final boolean is16Bit(int fmt)
1400 switch(fmt) {
1401 case SNDFMT_16BIT_PCM_LE_SIGNED:
1402 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1403 case SNDFMT_16BIT_PCM_BE_SIGNED:
1404 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1405 return true;
1406 default:
1407 return false;
1411 //Ok, one sample down. Handle us to be recalled if needed.
1412 private final void dmaEngineNextSample()
1414 //Clear remainants of preseent sample.
1415 partialSample = 0;
1416 partialSampleBytes = 0;
1417 wholeSampleBytes = 0;
1419 if(dmaPaused && dmaPauseLeft > 0) {
1420 --dmaPauseLeft;
1421 if(dmaPauseLeft == 0) {
1422 writeMessage("SBDSP: Continuing DMA transfer after timed pause.");
1423 set8BitIRQ(true);
1424 dmaPaused = false;
1428 if(dmaState == DMA_NONE || dmaPaused) {
1429 if(dmaPaused)
1430 System.err.println("Halting paused transfer.");
1431 updateTimer(TIME_NEVER);
1432 return;
1435 if(samplesLeft > 0)
1436 samplesLeft -= (stereo ? 2 : 1);
1438 if(samplesLeft <= 0) {
1439 //Block run out.
1440 if(is16Bit(soundFormat))
1441 set16BitIRQ(true);
1442 else
1443 set8BitIRQ(true);
1444 dspProgramNextDMA();
1445 if(dmaState == DMA_CONTINUOUS) {
1446 writeMessage("SBDSP: DMA transfer auto-reinitialized.");
1447 samplesLeft = origSamplesLeft;
1448 } else {
1449 //DMA mode exit.
1450 writeMessage("SBDSP: DMA transfer ended.");
1451 dmaState = DMA_NONE;
1452 updateTimer(TIME_NEVER);
1453 return;
1457 long timeNow = clock.getTime();
1458 long ist = interSampleTime;
1459 //Some modes output at half rate in stereo mode.
1460 if(stereo && istStereoAdjust)
1461 ist *= 2;
1462 if(dmaRequestTime == timeNow) {
1463 //Timely, schedule by supposed time.
1464 nextSampleTime = nextSampleTime + ist;
1465 } else {
1466 //Late. Schecdule by current time.
1467 nextSampleTime = timeNow + ist;
1469 updateTimer(nextSampleTime);
1472 //Update DMA engine DMA requests.
1473 private final void dmaEngineUpdateDMADREQ()
1475 if(!dmaRequest && partialSampleBytes < wholeSampleBytes) {
1476 dmaRequest = true;
1477 dmaRequestTime = clock.getTime();
1481 boolean highDMAAvailable = is16Bit(soundFormat) && ((dmaMask & 0xF0) != 0) && !e2Mode;
1482 int dmaProg = dmaMask & ~dmaActiveMask;
1483 boolean dmaActive = (partialSampleBytes < wholeSampleBytes) || e2Mode;
1485 if(highDMAAvailable) {
1486 for(int i = 0; i < 4; i++)
1487 if(secondaryDMAController != null && dmaActive && ((((dmaProg >> 4) >> i) & 1) != 0)) {
1488 // System.err.println("Informational: SB: Holding DMA DREQ for channel " + (4 + i) + ".");
1489 dmaActiveMask |= ((1 << 4) << i);
1490 secondaryDMAController.holdDmaRequest(i);
1493 for(int i = 0; i < 4; i++)
1494 if(primaryDMAController != null && dmaActive && (((dmaProg >> i) & 1) != 0)) {
1495 // System.err.println("Informational: SB: Holding DMA DREQ for channel " + i + ".");
1496 dmaActiveMask |= (1 << i);
1497 primaryDMAController.holdDmaRequest(i);
1500 if(partialSampleBytes == wholeSampleBytes && !e2Mode) {
1501 //Drop all transfer requests.
1502 dmaProg = dmaActiveMask;
1504 dmaRequest = false;
1505 for(int i = 0; i < 4; i++) {
1506 if(secondaryDMAController != null && (((dmaProg >> 4) >> i) & 1) != 0) {
1507 // System.err.println("Informational: SB: Releasing DMA DREQ for channel " + (4 + i) + ".");
1508 secondaryDMAController.releaseDmaRequest(i);
1509 dmaActiveMask &= ~((1 << 4) << i);
1511 if(primaryDMAController != null && ((dmaProg >> i) & 1) != 0) {
1512 // System.err.println("Informational: SB: Releasing DMA DREQ for channel " + i + ".");
1513 primaryDMAController.releaseDmaRequest(i);
1514 dmaActiveMask &= ~(1 << i);
1520 private final void dmaEngineAttention()
1522 if(clock.getTime() < nextSampleTime)
1523 return; //Not yet.
1524 // System.err.println("Informational: SB: DMA engine attention at " + clock.getTime() + ".");
1525 //DMA will set next attention.
1526 updateTimer(TIME_NEVER);
1528 //Update DREQ if not requested yet.
1529 if(!dmaRequest) {
1530 //Count the bytes.
1531 int bytes = 0;
1532 switch(soundFormat) {
1533 case SNDFMT_8BIT_PCM_SIGNED:
1534 case SNDFMT_8BIT_PCM_UNSIGNED:
1535 bytes += (stereo ? 2 : 1);
1536 break;
1537 case SNDFMT_16BIT_PCM_LE_SIGNED:
1538 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1539 case SNDFMT_16BIT_PCM_BE_SIGNED:
1540 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1541 bytes += (stereo ? 4 : 2);
1542 break;
1543 case SNDFMT_2BIT_ADPCM:
1544 case SNDFMT_26BIT_ADPCM:
1545 case SNDFMT_4BIT_ADPCM:
1546 //ADPCM is always mono.
1547 if(byteBufferSamples == 0)
1548 bytes += 1;
1549 break;
1550 case SNDFMT_2BIT_ADPCM_REF:
1551 case SNDFMT_26BIT_ADPCM_REF:
1552 case SNDFMT_4BIT_ADPCM_REF:
1553 //ADPCM is always mono.
1554 bytes += 1; //Reference
1555 if(byteBufferSamples == 0);
1556 bytes += 1;
1557 break;
1559 partialSampleBytes = 0;
1560 partialSample = 0;
1561 if(!dmaPaused) {
1562 wholeSampleBytes = bytes;
1563 dmaEngineUpdateDMADREQ();
1564 if(bytes == 0) {
1565 //The DMA engine can't handle requests for 0 bytes, so call sample available
1566 //immediately to keep the loop running.
1567 dmaEngineSampleAvailable();
1569 } else {
1570 wholeSampleBytes = 0;
1571 dmaEngineSampleAvailable();
1574 // System.err.println("Informational: SB: DMA engine attention handler exiting.");
1577 //Give attention to DSP.
1578 private final void dspAttention(long time)
1580 dmaEngineAttention();
1583 private final int extractBufferByte()
1585 int value = partialSample & 0xFF;
1586 partialSample = partialSample >>> 8;
1587 partialSampleBytes--;
1588 wholeSampleBytes--;
1589 return value;
1592 private final int nonRefFormatFor(int fmt)
1594 switch(fmt) {
1595 case SNDFMT_2BIT_ADPCM_REF:
1596 return SNDFMT_2BIT_ADPCM;
1597 case SNDFMT_26BIT_ADPCM_REF:
1598 return SNDFMT_26BIT_ADPCM;
1599 case SNDFMT_4BIT_ADPCM_REF:
1600 return SNDFMT_4BIT_ADPCM;
1601 default:
1602 return fmt;
1606 private final boolean hasReference(int fmt)
1608 switch(fmt) {
1609 case SNDFMT_2BIT_ADPCM_REF:
1610 case SNDFMT_26BIT_ADPCM_REF:
1611 case SNDFMT_4BIT_ADPCM_REF:
1612 return true;
1613 default:
1614 return false;
1618 private final int byteBufferSamplesADPCM(int fmt)
1620 switch(fmt) {
1621 case SNDFMT_2BIT_ADPCM:
1622 return 4;
1623 case SNDFMT_26BIT_ADPCM:
1624 return 3;
1625 case SNDFMT_4BIT_ADPCM:
1626 return 2;
1627 default:
1628 return 0;
1633 private final void dmaEngineSampleAvailable()
1635 int sampleL = 0, sampleR = 0;
1636 int levelShift = 0;
1637 long timeNow = clock.getTime();
1640 //There's no data in DMA paused mode. Just schedule next sample.
1641 if(dmaPaused) {
1642 dmaEngineNextSample();
1643 return;
1646 //System.err.println("Got requested DMA data for " + wholeSampleBytes + " bytes.");
1648 //Load Refrence byte if needed.
1649 if(hasReference(soundFormat)) {
1650 adpcmReference = extractBufferByte();
1651 adpcmScale = ADPCM_SCALE_INIT;
1652 soundFormat = nonRefFormatFor(soundFormat);
1653 //System.err.println("Got ADPCM reference: " + adpcmReference + ".");
1656 //Load byte buffer if needed in ADPCM modes.
1657 switch(soundFormat) {
1658 case SNDFMT_2BIT_ADPCM:
1659 case SNDFMT_26BIT_ADPCM:
1660 case SNDFMT_4BIT_ADPCM:
1661 if(byteBufferSamples == 0) {
1662 byteBuffer = extractBufferByte();
1663 // adpcmScale = ADPCM_SCALE_INIT; //Um, what?
1664 byteBufferSamples = byteBufferSamplesADPCM(soundFormat);
1665 //System.err.println("Reloading byte buffer with: " + byteBuffer + "(" + byteBufferSamples + ").");
1669 switch(soundFormat) {
1670 case SNDFMT_2BIT_ADPCM:
1671 dmaEngineADPCMDecode((byteBuffer >>> 6) & 3);
1672 byteBuffer = byteBuffer << 2;
1673 byteBufferSamples--;
1674 sampleL = sampleR = 256 * (adpcmReference - 128);
1675 break;
1676 case SNDFMT_26BIT_ADPCM:
1677 dmaEngineADPCMDecode((byteBuffer >>> 5) & 7);
1678 byteBuffer = byteBuffer << 3;
1679 byteBufferSamples--;
1680 sampleL = sampleR = 256 * (adpcmReference - 128);
1681 break;
1682 case SNDFMT_4BIT_ADPCM:
1683 dmaEngineADPCMDecode((byteBuffer >>> 4) & 0xF);
1684 byteBuffer = byteBuffer << 4;
1685 byteBufferSamples--;
1686 sampleL = sampleR = 256 * (adpcmReference - 128);
1687 break;
1688 case SNDFMT_8BIT_PCM_UNSIGNED:
1689 levelShift = 32768;
1690 case SNDFMT_8BIT_PCM_SIGNED:
1691 //Let's exploit integer overflows!
1692 sampleL = 256 * extractBufferByte();
1693 if(stereo)
1694 sampleR = 256 * extractBufferByte();
1695 else
1696 sampleR = sampleL;
1697 break;
1698 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1699 levelShift = 32768;
1700 case SNDFMT_16BIT_PCM_LE_SIGNED:
1701 //Let's exploit integer overflows!
1702 sampleL = extractBufferByte();
1703 sampleL |= (extractBufferByte() << 8);
1704 if(stereo) {
1705 sampleR = extractBufferByte();
1706 sampleR |= (extractBufferByte() << 8);
1707 } else
1708 sampleR = sampleL;
1709 break;
1710 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1711 levelShift = 32768;
1712 case SNDFMT_16BIT_PCM_BE_SIGNED:
1713 //Let's exploit integer overflows!
1714 sampleL = (extractBufferByte() << 8);
1715 sampleL |= extractBufferByte();
1716 if(stereo) {
1717 sampleR = (extractBufferByte() << 8);
1718 sampleR |= extractBufferByte();
1719 } else
1720 sampleR = sampleL;
1721 break;
1724 sendPCMSample(timeNow, (short)(sampleL - levelShift), (short)(sampleR - levelShift));
1725 dmaEngineNextSample();
1728 //Write byte to DSP.
1729 private final void dspWrite(int command)
1731 int blockSampleArg = origSamplesLeft - 1;
1732 if(dspCommandState != DSPSTATE_WAIT_COMMAND)
1733 writeMessage("SB: Command argument byte: " + command + " .");
1735 if(dspCommandState == DSPSTATE_WAIT_COMMAND) {
1736 switch(command) {
1738 case DSPCMD_SC_DMA_8_1:
1739 case DSPCMD_SC_DMA_8_2:
1740 case DSPCMD_SC_DMA_8_3:
1741 writeMessage("SBDSP: Received SC_DMA_8(" + command + ") command.");
1742 dspArgumentRegister = 0;
1743 dspCommandState = DSPSTATE_OLDDMA_LOW;
1744 break;
1745 case DSPCMD_AI_DMA_8_1:
1746 case DSPCMD_AI_DMA_8_2:
1747 writeMessage("SBDSP: Received AI_DMA_8(" + command + ") command.");
1748 dspArgumentRegister = 65536 | ((blockSampleArg & 0xFF) << 8) | ((blockSampleArg & 0xFF00) >> 8);
1749 dspNextDMA = dspArgumentRegister;
1750 break;
1751 case DSPCMD_SC_ADPCM_2:
1752 writeMessage("SBDSP: Received SC_ADPCM_2(" + command + ") command.");
1753 dspArgumentRegister = 2;
1754 dspCommandState = DSPSTATE_OLDDMA_LOW;
1755 break;
1756 case DSPCMD_SC_ADPCM_2_REF:
1757 writeMessage("SBDSP: Received SC_ADPCM_2_REF(" + command + ") command.");
1758 dspArgumentRegister = 3;
1759 dspCommandState = DSPSTATE_OLDDMA_LOW;
1760 break;
1761 case DSPCMD_SC_ADPCM_26:
1762 writeMessage("SBDSP: Received SC_ADPCM_26(" + command + ") command.");
1763 dspArgumentRegister = 4;
1764 dspCommandState = DSPSTATE_OLDDMA_LOW;
1765 break;
1766 case DSPCMD_SC_ADPCM_26_REF:
1767 writeMessage("SBDSP: Received SC_ADPCM_26_REF(" + command + ") command.");
1768 dspArgumentRegister = 5;
1769 dspCommandState = DSPSTATE_OLDDMA_LOW;
1770 break;
1771 case DSPCMD_SC_ADPCM_4:
1772 writeMessage("SBDSP: Received SC_ADPCM_4(" + command + ") command.");
1773 dspArgumentRegister = 6;
1774 dspCommandState = DSPSTATE_OLDDMA_LOW;
1775 break;
1776 case DSPCMD_SC_ADPCM_4_REF:
1777 writeMessage("SBDSP: Received SC_ADPCM_4_REF(" + command + ") command.");
1778 dspArgumentRegister = 7;
1779 dspCommandState = DSPSTATE_OLDDMA_LOW;
1780 break;
1781 case DSPCMD_GENERIC_DMA_0: case DSPCMD_GENERIC_DMA_1: case DSPCMD_GENERIC_DMA_2: case DSPCMD_GENERIC_DMA_3:
1782 case DSPCMD_GENERIC_DMA_4: case DSPCMD_GENERIC_DMA_5: case DSPCMD_GENERIC_DMA_6: case DSPCMD_GENERIC_DMA_7:
1783 case DSPCMD_GENERIC_DMA_8: case DSPCMD_GENERIC_DMA_9: case DSPCMD_GENERIC_DMA_A: case DSPCMD_GENERIC_DMA_B:
1784 case DSPCMD_GENERIC_DMA_C: case DSPCMD_GENERIC_DMA_D: case DSPCMD_GENERIC_DMA_E: case DSPCMD_GENERIC_DMA_F:
1785 case DSPCMD_GENERIC_DMA_G: case DSPCMD_GENERIC_DMA_H: case DSPCMD_GENERIC_DMA_I: case DSPCMD_GENERIC_DMA_J:
1786 case DSPCMD_GENERIC_DMA_K: case DSPCMD_GENERIC_DMA_L: case DSPCMD_GENERIC_DMA_M: case DSPCMD_GENERIC_DMA_N:
1787 case DSPCMD_GENERIC_DMA_O: case DSPCMD_GENERIC_DMA_P: case DSPCMD_GENERIC_DMA_Q: case DSPCMD_GENERIC_DMA_R:
1788 case DSPCMD_GENERIC_DMA_S: case DSPCMD_GENERIC_DMA_T: case DSPCMD_GENERIC_DMA_U: case DSPCMD_GENERIC_DMA_V:
1789 writeMessage("SBDSP: Received SC_GENERIC_DMA(" + command + ") command.");
1790 dspArgumentRegister = (command - 0xB0);
1791 dspCommandState = DSPSTATE_NEWDMA_LOW;
1792 break;
1793 case DSPCMD_DIRECT_DAC:
1794 writeMessage("SBDSP: Received DIRECT_DAC command.");
1795 dspCommandState = DSPSTATE_DIRECT_DAC_SAMPLE;
1796 break;
1797 case DSPCMD_SET_BLOCKSIZE:
1798 writeMessage("SBDSP: Received SET_BLOCKSIZE command.");
1799 dspCommandState = DSPSTATE_BLOCKSIZE_LOW;
1800 break;
1801 case DSPCMD_SET_TC:
1802 writeMessage("SBDSP: Received SET_TC command.");
1803 dspCommandState = DSPSTATE_TC;
1804 break;
1805 case DSPCMD_SET_INPUT_RATE:
1806 case DSPCMD_SET_OUTPUT_RATE:
1807 writeMessage("SBDSP: Received SET_RATE(" + command + ") command.");
1808 dspCommandState = DSPSTATE_RATE_LOW;
1809 break;
1810 case DSPCMD_SPEAKER_ON:
1811 writeMessage("SBDSP: Received SPEAKER_ON command.");
1812 speakerConnected = true;
1813 recomputeVolume(clock.getTime());
1814 break;
1815 case DSPCMD_SPEAKER_OFF:
1816 writeMessage("SBDSP: Received SPEAKER_OFF command.");
1817 speakerConnected = false;
1818 recomputeVolume(clock.getTime());
1819 break;
1820 case DSPCMD_SPEAKER_STATUS:
1821 writeMessage("SBDSP: Received SPEAKER_STATUS command.");
1822 if(speakerConnected)
1823 dspOutputPut(0xFF);
1824 else
1825 dspOutputPut(0x00);
1826 break;
1827 case DSPCMD_PAUSE_DMA:
1828 case DSPCMD_PAUSE_DMA_16:
1829 writeMessage("SBDSP: Received PAUSE_DMA(" + command + ") command.");
1830 dmaEnginePauseTransfer();
1831 break;
1832 case DSPCMD_CONTINUE_DMA:
1833 case DSPCMD_CONTINUE_DMA_16:
1834 case DSPCMD_CONTINUE_DMA_AI:
1835 case DSPCMD_CONTINUE_DMA_AI_16:
1836 writeMessage("SBDSP: Received CONTINUE_DMA(" + command + ") command.");
1837 dmaEngineContinueTransfer();
1838 break;
1839 case DSPCMD_SILENCE:
1840 writeMessage("SBDSP: Received SILENCE command.");
1841 dspCommandState = DSPSTATE_SILENCE_LOW;
1842 dspArgumentRegister = 0;
1843 break;
1844 case DSPCMD_EXIT_DMA:
1845 case DSPCMD_EXIT_DMA_16:
1846 writeMessage("SBDSP: Received EXIT_DMA command.");
1847 dmaEngineEndTransfer();
1848 break;
1849 case DSPCMD_DSP_IDENTIFY:
1850 writeMessage("SBDSP: Received DSP_IDENTIFY command.");
1851 dspCommandState = DSPSTATE_IDWRITE;
1852 break;
1853 case DSPCMD_DSP_VERSION:
1854 writeMessage("SBDSP: Received DSP_VERSION command.");
1855 dspOutputUsed = 0;
1856 dspOutputPut((DSP_VERSION >>> 8) & 0xFF);
1857 dspOutputPut(DSP_VERSION & 0xFF);
1858 break;
1859 case DSPCMD_DMA_IDENTIFY:
1860 writeMessage("SBDSP: Received DMA_IDENTIFY command.");
1861 dspCommandState = DSPSTATE_DMA_IDENTIFY;
1862 break;
1863 case DSPCMD_COPYRIGHT:
1864 writeMessage("SBDSP: Received COPYRIGHT command.");
1865 dspOutputUsed = 0;
1866 for(int k = 0; k < copyright.length(); k++)
1867 dspOutputPut((int)copyright.charAt(k));
1868 break;
1869 case DSPCMD_WRITE_TEST:
1870 writeMessage("SBDSP: Received WRITE_TEST command.");
1871 dspCommandState = DSPSTATE_TESTWRITE;
1872 break;
1873 case DSPCMD_READ_TEST:
1874 writeMessage("SBDSP: Received READ_TEST command.");
1875 dspOutputUsed = 0;
1876 dspOutputPut(dspLastCommand);
1877 break;
1878 case DSPCMD_RAISE_8BIT_IRQ:
1879 writeMessage("SBDSP: Received RAISE_IRQ command.");
1880 set8BitIRQ(true);
1881 break;
1882 case DSPCMD_UNDOCUMENTED1:
1883 //Weird undocumented command.
1884 writeMessage("SBDSP: Received UNDOCUMENTED command.");
1885 dspOutputUsed = 0;
1886 dspOutputPut(0);
1887 break;
1888 default:
1889 writeMessage("SBDSP: Received unknown command " + command + ".");
1891 } else if(dspCommandState == DSPSTATE_DIRECT_DAC_SAMPLE) {
1892 writeMessage("SBDSP: Setting direct output to " + command + ".");
1893 sendPCMSample(clock.getTime(), (short)(256 * command - 32768), (short)(256 * command - 32768));
1894 dspCommandState = DSPSTATE_WAIT_COMMAND;
1895 } else if(dspCommandState == DSPSTATE_SILENCE_LOW) {
1896 dspArgumentRegister = command;
1897 dspCommandState = DSPSTATE_SILENCE_HIGH;
1898 } else if(dspCommandState == DSPSTATE_SILENCE_HIGH) {
1899 dspArgumentRegister |= (command << 8);
1900 writeMessage("SBDSP: Starting silence of " + (dspArgumentRegister + 1) + " samples.");
1901 dmaEnginePauseTransfer(dspArgumentRegister + 1);
1902 dspCommandState = DSPSTATE_WAIT_COMMAND;
1903 } else if(dspCommandState == DSPSTATE_TESTWRITE) {
1904 writeMessage("SBDSP: Writing test register: data=" + command + ".");
1905 dspLastCommand = command;
1906 dspCommandState = DSPSTATE_WAIT_COMMAND;
1907 } else if(dspCommandState == DSPSTATE_IDWRITE) {
1908 dspOutputUsed = 0;
1909 writeMessage("SBDSP: Doing ID write: data=" + command + ".");
1910 dspOutputPut(~command);
1911 dspCommandState = DSPSTATE_WAIT_COMMAND;
1912 } else if(dspCommandState == DSPSTATE_BLOCKSIZE_LOW) {
1913 dspArgumentRegister = command;
1914 dspCommandState = DSPSTATE_BLOCKSIZE_HIGH;
1915 } else if(dspCommandState == DSPSTATE_BLOCKSIZE_HIGH) {
1916 dspArgumentRegister |= (command << 8);
1917 writeMessage("SBDSP: Setting block size to " + (dspArgumentRegister + 1) + " samples.");
1918 origSamplesLeft = dspArgumentRegister + 1;
1919 dspCommandState = DSPSTATE_WAIT_COMMAND;
1920 } else if(dspCommandState == DSPSTATE_RATE_LOW) {
1921 dspArgumentRegister = command << 8;
1922 dspCommandState = DSPSTATE_RATE_HIGH;
1923 } else if(dspCommandState == DSPSTATE_RATE_HIGH) {
1924 dspArgumentRegister |= command;
1925 writeMessage("SBDSP: Setting rate to " + (dspArgumentRegister) + "Hz.");
1926 interSampleTime = 1000000000 / dspArgumentRegister;
1927 istStereoAdjust = false;
1928 dspCommandState = DSPSTATE_WAIT_COMMAND;
1929 } else if(dspCommandState == DSPSTATE_TC) {
1930 writeMessage("SBDSP: Setting time constant to " + command + "(" + (1000000 / (256 - command)) + "Hz mono/" + (500000 / (256 - command)) + "Hz stereo).");
1931 interSampleTime = 1000 * (256 - command);
1932 istStereoAdjust = true;
1933 dspCommandState = DSPSTATE_WAIT_COMMAND;
1934 } else if(dspCommandState == DSPSTATE_OLDDMA_LOW) {
1935 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1936 dspCommandState = DSPSTATE_OLDDMA_HIGH;
1937 } else if(dspCommandState == DSPSTATE_NEWDMA_LOW) {
1938 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1939 dspCommandState = DSPSTATE_NEWDMA_MID;
1940 } else if(dspCommandState == DSPSTATE_NEWDMA_MID) {
1941 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1942 dspCommandState = DSPSTATE_NEWDMA_HIGH;
1943 } else if(dspCommandState == DSPSTATE_OLDDMA_HIGH) {
1944 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1945 dspCommandState = DSPSTATE_WAIT_COMMAND;
1946 writeMessage("SBDSP: Programming DMA register to " + dspArgumentRegister + ".");
1947 dspNextDMA = dspArgumentRegister;
1948 } else if(dspCommandState == DSPSTATE_NEWDMA_HIGH) {
1949 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1950 dspCommandState = DSPSTATE_WAIT_COMMAND;
1951 dspArgumentRegister |= 0x20000000;
1952 writeMessage("SBDSP: Programming DMA register to " + dspArgumentRegister + ".");
1953 dspNextDMA = dspArgumentRegister;
1954 } else if(dspCommandState == DSPSTATE_DMA_IDENTIFY) {
1955 //writeMessage("Old DMA identification is " + e2Value + ".");
1956 for(int i = 0; i < 8; i++)
1957 if(((command >>> i) & 1) != 0) {
1958 if(((E2_MAGIC[e2Count % 4] >>> i) & 1) != 0) {
1959 e2Value -= (byte)(1 << i);
1960 } else {
1961 e2Value += (byte)(1 << i);
1964 e2Value += E2_MAGIC[e2Count % 4];
1965 writeMessage("Sending DMA identification " + e2Value + ".");
1966 e2Count++;
1967 e2Mode = true;
1968 dmaEngineUpdateDMADREQ();
1969 dspCommandState = DSPSTATE_WAIT_COMMAND;
1972 //If no DMA, try to program it immediately. Some games rely on halting DMA to
1973 //be able to program it again immediately.
1974 if(dmaState == DMA_NONE || (dmaPaused && dmaPauseLeft < 0))
1975 dspProgramNextDMA();
1978 private final void dspProgramNextDMA()
1980 int samples;
1981 boolean oldStereoFlag = ((mixerRegisters[MIXER_OUTPUT_CONTROL] & 0x2) != 0);
1982 if(dspNextDMA == -1)
1983 return; //No Next DMA.
1985 //Set number of samples.
1986 samples = 1 + (((dspNextDMA & 0xFF) << 8) | ((dspNextDMA >> 8) & 0xFF));
1987 dspNextDMA = dspNextDMA >>> 16;
1988 if(dspNextDMA < 0x2000) {
1989 switch(dspNextDMA) {
1990 case 0: //8 Bits, Single cycle.
1991 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_8BIT_PCM_UNSIGNED, oldStereoFlag);
1992 break;
1993 case 1: //8 Bits, Auto-init.
1994 dmaEngineStartTransfer(DMA_CONTINUOUS, samples, SNDFMT_8BIT_PCM_UNSIGNED, oldStereoFlag);
1995 break;
1996 case 2: //2 Bit ADPCM, single cycle.
1997 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_2BIT_ADPCM, false);
1998 break;
1999 case 3: //2 Bit ADPCM, single cycle, reference.
2000 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_2BIT_ADPCM_REF, false);
2001 break;
2002 case 4: //2.6 Bit ADPCM, single cycle.
2003 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_26BIT_ADPCM, false);
2004 break;
2005 case 5: //2.6 Bit ADPCM, single cycle, reference.
2006 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_26BIT_ADPCM_REF, false);
2007 break;
2008 case 6: //4 Bit ADPCM, single cycle.
2009 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_4BIT_ADPCM, false);
2010 break;
2011 case 7: //4 Bit ADPCM, single cycle, reference.
2012 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_4BIT_ADPCM_REF, false);
2013 break;
2014 default:
2015 writeMessage("Trying to program unknown DMA mode " + dspNextDMA + ".");
2017 } else if((dspNextDMA & 0x2000) != 0) {
2018 boolean bits16 = ((dspNextDMA & 0x1000) == 0);
2019 boolean autoinit = ((dspNextDMA & 0x400) != 0);
2020 boolean signed = ((dspNextDMA & 0x10) != 0);
2021 boolean stereoFlag = ((dspNextDMA & 0x20) != 0);
2022 int mode = (autoinit ? DMA_CONTINUOUS : DMA_SINGLE);
2023 if(bits16)
2024 if(signed)
2025 dmaEngineStartTransfer(mode, samples, SNDFMT_16BIT_PCM_LE_SIGNED, stereoFlag);
2026 else
2027 dmaEngineStartTransfer(mode, samples, SNDFMT_16BIT_PCM_LE_UNSIGNED, stereoFlag);
2028 else
2029 if(signed)
2030 dmaEngineStartTransfer(mode, samples, SNDFMT_8BIT_PCM_SIGNED, stereoFlag);
2031 else
2032 dmaEngineStartTransfer(mode, samples, SNDFMT_8BIT_PCM_UNSIGNED, stereoFlag);
2033 } else
2034 writeMessage("Trying to program unknown DMA mode " + dspNextDMA + ".");
2036 //DMA command processed.
2037 dspNextDMA = -1;
2040 private final void dmaEngineADPCMDecode(int sample)
2042 int scaleMax = 0;
2043 byte[] levelShift = null;
2044 int[] levelMult = null;
2045 int[] sampleMult = null;
2047 if(soundFormat == SNDFMT_2BIT_ADPCM) {
2048 scaleMax = ADPCM_2BIT_SCALE_MAX;
2049 levelShift = ADPCM_2BIT_LEVEL_SHIFT;
2050 levelMult = ADPCM_2BIT_LEVEL_MULT;
2051 sampleMult = ADPCM_2BIT_SAMPLE_MULT;
2052 } else if(soundFormat == SNDFMT_26BIT_ADPCM) {
2053 scaleMax = ADPCM_26BIT_SCALE_MAX;
2054 levelShift = ADPCM_26BIT_LEVEL_SHIFT;
2055 levelMult = ADPCM_26BIT_LEVEL_MULT;
2056 sampleMult = ADPCM_26BIT_SAMPLE_MULT;
2057 } else if(soundFormat == SNDFMT_4BIT_ADPCM) {
2058 scaleMax = ADPCM_4BIT_SCALE_MAX;
2059 levelShift = ADPCM_4BIT_LEVEL_SHIFT;
2060 levelMult = ADPCM_4BIT_LEVEL_MULT;
2061 sampleMult = ADPCM_4BIT_SAMPLE_MULT;
2064 int index = adpcmScale;
2065 if(index > scaleMax) {
2066 System.err.println("Error: SB: ADPCM level out of range.");
2067 index = scaleMax;
2070 byte adjust = levelShift[sample];
2071 if((index == 0 && adjust < 0) || (index == scaleMax && adjust > 0))
2072 adjust = 0;
2073 adpcmScale += adjust;
2075 adpcmReference += (levelMult[index] * sampleMult[sample] / ((index == 0) ? 2 : 1));
2076 if(adpcmReference < 0)
2077 adpcmReference = 0;
2078 if(adpcmReference > 255)
2079 adpcmReference = 255;