NHMLFixup v10
[jpcrr.git] / org / jpc / modules / SoundCard.java
blobcc68fbcfe5d97d15fda0697ac48353992bea8d7c
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.output.*;
34 import org.jpc.modulesaux.*;
35 import org.jpc.emulator.motherboard.*;
36 import java.io.*;
38 public class SoundCard extends AbstractHardwareComponent implements IOPortCapable, TimerResponsive, DMATransferCapable, SoundOutputDevice
40 private int baseIOAddress;
41 private boolean irq2;
42 private boolean irq5;
43 private boolean irq7;
44 private boolean irq10;
45 private int dmaMask;
46 private int dmaRequested;
47 private boolean ioportRegistered;
48 private DMAController primaryDMAController;
49 private DMAController secondaryDMAController;
50 private Timer timer;
51 private Clock clock;
52 private InterruptController irqController;
53 private OutputChannelPCM pcmOutput;
55 private boolean irq8Bit;
56 private boolean irq16Bit;
58 private int mixerIndex;
59 private int mixerPrevIndex;
60 private int[] mixerRegisters;
62 private int dspCommandState;
63 private int[] dspOutput;
64 private int dspOutputUsed;
65 private long dspNextAttention;
67 //The following need to be programmed for DMA Engine.
68 private int dmaState; //DMA_*
69 private int samplesLeft; //Samples left in block.
70 private int origSamplesLeft; //Original samples in block.
71 private int soundFormat; //SNDFMT_*
72 private boolean stereo; //Stereo On?
73 private long interSampleTime; //Amount of time between samples.
74 private boolean istStereoAdjust; //InterSampleTime is affected by stereo.
76 private boolean dmaPaused; //DMA activity is paused.
77 private int dmaPauseLeft; //Amount of time left in DMA pause (-1 if indefinite)
78 private int dmaActiveMask; //Active DMA on these channels.
79 private boolean dmaRequest; //DMA request in progress.
80 private long dmaRequestTime; //DMA data request was made at this time.
81 private int partialSample; //Partial sample data.
82 private int partialSampleBytes; //Bytes of sample received.
83 private int wholeSampleBytes; //Bytes to obtain at once (max 4)
85 private int byteBuffer; //Byte buffer from last time (ADPCM only).
86 private int byteBufferSamples; //Number of samples in byte buffer.
88 private int adpcmReference; //ADPCM reference byte.
89 private byte adpcmScale; //ADPCM scale.
91 private long nextSampleTime; //DMA sample plays at this time.
93 private int dspArgumentRegister; //Temporary storage for DSP command argument.
94 private int dspNextDMA; //Next DMA parameters. -1 if none.
95 private int dspLastCommand; //Last DSP command.
97 private boolean e2Mode; //Do E2 write next time DMA is invoked.
98 private byte e2Value; //Value to write for E2.
99 private int e2Count; //E2 write counter.
101 private long lastPCMWrite; //Last time PCM write has been done.
102 private long lastFMWrite; //Last time FM write has been done.
104 private boolean speakerConnected;
106 public String STATUS_PCM_DAC;
107 public String STATUS_PCM_DMA;
108 public String STATUS_PCM_DMA_paused;
109 public String STATUS_FM_synth;
111 //FM chups (1).
112 private FMChip fmChip;
113 private int fmIndex;
114 private long fmNextAttention;
115 private OutputChannelFM fmOutput;
117 private static final int DMA_NONE = 0; //No DMA in progress.
118 private static final int DMA_SINGLE = 1; //Single-block DMA in progress.
119 private static final int DMA_CONTINUOUS = 2; //Auto-Init DMA in progress.
120 private static final int DMA_CONTINUOUS_EXIT = 3; //Auto-Init DMA last block in progress.
122 private static final int SNDFMT_2BIT_ADPCM = 0; //2-bit ADPCM.
123 private static final int SNDFMT_26BIT_ADPCM = 1; //2.6-bit (6-level) ADPCM.
124 private static final int SNDFMT_4BIT_ADPCM = 2; //4-bit ADPCM.
125 private static final int SNDFMT_2BIT_ADPCM_REF = 3; //2-bit ADPCM /w reference.
126 private static final int SNDFMT_26BIT_ADPCM_REF = 4; //2.6-bit (6-level) ADPCM /w reference.
127 private static final int SNDFMT_4BIT_ADPCM_REF = 5; //4-bit ADPCM /w reference.
128 private static final int SNDFMT_8BIT_PCM_SIGNED = 6; //8-bit PCM (SIGNED)
129 private static final int SNDFMT_8BIT_PCM_UNSIGNED = 7; //8-bit PCM (UNSIGNED)
130 private static final int SNDFMT_16BIT_PCM_LE_SIGNED = 8; //16-bit LE PCM (SIGNED)
131 private static final int SNDFMT_16BIT_PCM_LE_UNSIGNED = 9; //16-bit LE PCM (UNSIGNED)
132 private static final int SNDFMT_16BIT_PCM_BE_SIGNED = 10; //16-bit LE PCM (SIGNED)
133 private static final int SNDFMT_16BIT_PCM_BE_UNSIGNED = 11; //16-bit LE PCM (UNSIGNED)
135 private static final byte ADPCM_SCALE_INIT = 0;
137 private static final long ACTIVITY_TIMEOUT = 200000000;
139 private static final int typeFlag = 0x10;
140 private static final int QUEUE_SIZE = 256;
141 private static final int DSP_VERSION = 0x404; //4.04 (early SB16).
143 private static final int MIXER_REGISTERS = 25;
144 private static final int MIXREG_RESET = 0x00;
145 private static final int MIXREG_STATUS = 0x1;
146 private static final int MIXREG_DAC = 0x04;
147 private static final int MIXREG_MIC = 0x0A;
148 private static final int MIXREG_OUTPUT_CONTROL = 0x0E;
149 private static final int MIXREG_MASTER = 0x22;
150 private static final int MIXREG_FM = 0x26;
151 private static final int MIXREG_CD = 0x28;
152 private static final int MIXREG_LINEIN = 0x2E;
153 private static final int MIXREG_IRQSELECT = 0x80;
154 private static final int MIXREG_DMASELECT = 0x81;
155 private static final int MIXREG_IRQSTATUS = 0x82;
156 private static final int MIXREG_SB16_FIRST = 0x30;
157 private static final int MIXREG_LAST = 0x47;
159 private static final int MIXER_MASTER_LEFT = 0x00;
160 private static final int MIXER_MASTER_RIGHT = 0x01;
161 private static final int MIXER_DAC_LEFT = 0x02;
162 private static final int MIXER_DAC_RIGHT = 0x03;
163 private static final int MIXER_FM_LEFT = 0x04;
164 private static final int MIXER_FM_RIGHT = 0x05;
165 private static final int MIXER_OUTPUT_GAIN_CONTROL_LEFT = 0x11;
166 private static final int MIXER_OUTPUT_GAIN_CONTROL_RIGHT = 0x12;
167 private static final int MIXER_TREBLE_LEFT = 0x14;
168 private static final int MIXER_TREBLE_RIGHT = 0x15;
169 private static final int MIXER_BASS_LEFT = 0x16;
170 private static final int MIXER_BASS_RIGHT = 0x17;
171 private static final int MIXER_OUTPUT_CONTROL = 24;
173 //Following are here for completeness, but are not used.
174 private static final int MIXER_CD_LEFT = 0x06;
175 private static final int MIXER_CD_RIGHT = 0x07;
176 private static final int MIXER_LINEIN_LEFT = 0x08;
177 private static final int MIXER_LINEIN_RIGHT = 0x09;
178 private static final int MIXER_MIC = 0x0A;
179 private static final int MIXER_PCSPEAKER = 0x0B;
180 private static final int MIXER_INPUT_CONTROL_LEFT = 0x0D;
181 private static final int MIXER_INPUT_CONTROL_RIGHT = 0x0E;
182 private static final int MIXER_INPUT_GAIN_CONTROL_LEFT = 0x0F;
183 private static final int MIXER_INPUT_GAIN_CONTROL_RIGHT = 0x10;
184 private static final int MIXER_AUTOMATIC_GAIN_CONTROL = 0x13;
186 private static final int DSPSTATE_WAIT_COMMAND = 0;
187 private static final int DSPSTATE_DIRECT_DAC_SAMPLE = 1;
188 private static final int DSPSTATE_SILENCE_LOW = 2;
189 private static final int DSPSTATE_SILENCE_HIGH = 3;
190 private static final int DSPSTATE_TESTWRITE = 4;
191 private static final int DSPSTATE_IDWRITE = 5;
192 private static final int DSPSTATE_RATE_LOW = 6;
193 private static final int DSPSTATE_RATE_HIGH = 7;
194 private static final int DSPSTATE_BLOCKSIZE_LOW = 8;
195 private static final int DSPSTATE_BLOCKSIZE_HIGH = 9;
196 private static final int DSPSTATE_TC = 10;
197 private static final int DSPSTATE_OLDDMA_LOW = 11;
198 private static final int DSPSTATE_OLDDMA_HIGH = 12;
199 private static final int DSPSTATE_NEWDMA_LOW = 13;
200 private static final int DSPSTATE_NEWDMA_MID = 14;
201 private static final int DSPSTATE_NEWDMA_HIGH = 15;
202 private static final int DSPSTATE_DMA_IDENTIFY = 16;
204 private static final int ADPCM_4BIT_SCALE_MAX = 3;
205 private static final int ADPCM_26BIT_SCALE_MAX = 4;
206 private static final int ADPCM_2BIT_SCALE_MAX = 5;
207 private static final byte[] ADPCM_4BIT_LEVEL_SHIFT;
208 private static final byte[] ADPCM_26BIT_LEVEL_SHIFT;
209 private static final byte[] ADPCM_2BIT_LEVEL_SHIFT;
210 private static final int[] ADPCM_4BIT_LEVEL_MULT;
211 private static final int[] ADPCM_26BIT_LEVEL_MULT;
212 private static final int[] ADPCM_2BIT_LEVEL_MULT;
213 private static final int[] ADPCM_4BIT_SAMPLE_MULT;
214 private static final int[] ADPCM_26BIT_SAMPLE_MULT;
215 private static final int[] ADPCM_2BIT_SAMPLE_MULT;
217 private static final int DSPCMD_SC_DMA_8_1 = 0x14;
218 private static final int DSPCMD_SC_DMA_8_2 = 0x15;
219 private static final int DSPCMD_SC_DMA_8_3 = 0x91;
220 private static final int DSPCMD_AI_DMA_8_1 = 0x1C;
221 private static final int DSPCMD_AI_DMA_8_2 = 0x90;
222 private static final int DSPCMD_SC_ADPCM_2 = 0x16;
223 private static final int DSPCMD_SC_ADPCM_2_REF = 0x17;
224 private static final int DSPCMD_SC_ADPCM_26 = 0x76;
225 private static final int DSPCMD_SC_ADPCM_26_REF = 0x77;
226 private static final int DSPCMD_SC_ADPCM_4 = 0x74;
227 private static final int DSPCMD_SC_ADPCM_4_REF = 0x75;
228 private static final int DSPCMD_GENERIC_DMA_0 = 0xB0;
229 private static final int DSPCMD_GENERIC_DMA_1 = 0xB1;
230 private static final int DSPCMD_GENERIC_DMA_2 = 0xB2;
231 private static final int DSPCMD_GENERIC_DMA_3 = 0xB3;
232 private static final int DSPCMD_GENERIC_DMA_4 = 0xB4;
233 private static final int DSPCMD_GENERIC_DMA_5 = 0xB5;
234 private static final int DSPCMD_GENERIC_DMA_6 = 0xB6;
235 private static final int DSPCMD_GENERIC_DMA_7 = 0xB7;
236 private static final int DSPCMD_GENERIC_DMA_8 = 0xB8;
237 private static final int DSPCMD_GENERIC_DMA_9 = 0xB9;
238 private static final int DSPCMD_GENERIC_DMA_A = 0xBA;
239 private static final int DSPCMD_GENERIC_DMA_B = 0xBB;
240 private static final int DSPCMD_GENERIC_DMA_C = 0xBC;
241 private static final int DSPCMD_GENERIC_DMA_D = 0xBD;
242 private static final int DSPCMD_GENERIC_DMA_E = 0xBE;
243 private static final int DSPCMD_GENERIC_DMA_F = 0xBF;
244 private static final int DSPCMD_GENERIC_DMA_G = 0xC0;
245 private static final int DSPCMD_GENERIC_DMA_H = 0xC1;
246 private static final int DSPCMD_GENERIC_DMA_I = 0xC2;
247 private static final int DSPCMD_GENERIC_DMA_J = 0xC3;
248 private static final int DSPCMD_GENERIC_DMA_K = 0xC4;
249 private static final int DSPCMD_GENERIC_DMA_L = 0xC5;
250 private static final int DSPCMD_GENERIC_DMA_M = 0xC6;
251 private static final int DSPCMD_GENERIC_DMA_N = 0xC7;
252 private static final int DSPCMD_GENERIC_DMA_O = 0xC8;
253 private static final int DSPCMD_GENERIC_DMA_P = 0xC9;
254 private static final int DSPCMD_GENERIC_DMA_Q = 0xCA;
255 private static final int DSPCMD_GENERIC_DMA_R = 0xCB;
256 private static final int DSPCMD_GENERIC_DMA_S = 0xCC;
257 private static final int DSPCMD_GENERIC_DMA_T = 0xCD;
258 private static final int DSPCMD_GENERIC_DMA_U = 0xCE;
259 private static final int DSPCMD_GENERIC_DMA_V = 0xCF;
261 private static final int DSPCMD_DIRECT_DAC = 0x10;
262 private static final int DSPCMD_CONTINUE_DMA_AI = 0x45;
263 private static final int DSPCMD_CONTINUE_DMA_AI_16 = 0x47;
264 private static final int DSPCMD_SET_TC = 0x40;
265 private static final int DSPCMD_SET_OUTPUT_RATE = 0x41;
266 private static final int DSPCMD_SET_INPUT_RATE = 0x42;
267 private static final int DSPCMD_SET_BLOCKSIZE = 0x48;
268 private static final int DSPCMD_SILENCE = 0x80;
269 private static final int DSPCMD_PAUSE_DMA = 0xD0;
270 private static final int DSPCMD_SPEAKER_ON = 0xD1;
271 private static final int DSPCMD_SPEAKER_OFF = 0xD3;
272 private static final int DSPCMD_CONTINUE_DMA = 0xD4;
273 private static final int DSPCMD_PAUSE_DMA_16 = 0xD5;
274 private static final int DSPCMD_CONTINUE_DMA_16 = 0xD6;
275 private static final int DSPCMD_SPEAKER_STATUS = 0xD8;
276 private static final int DSPCMD_EXIT_DMA_16 = 0xD9;
277 private static final int DSPCMD_EXIT_DMA = 0xDA;
278 private static final int DSPCMD_DSP_IDENTIFY = 0xE0;
279 private static final int DSPCMD_DSP_VERSION = 0xE1;
280 private static final int DSPCMD_DMA_IDENTIFY = 0xE2;
281 private static final int DSPCMD_COPYRIGHT = 0xE3;
282 private static final int DSPCMD_WRITE_TEST = 0xE4;
283 private static final int DSPCMD_READ_TEST = 0xE8;
284 private static final int DSPCMD_RAISE_8BIT_IRQ = 0xF2;
285 private static final int DSPCMD_UNDOCUMENTED1 = 0xF8;
287 private static final byte[] E2_MAGIC = {-106, -91, 105, 90};
289 private static final int FM_CHIPS = 1;
290 private static final String copyright = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
291 public static final long TIME_NEVER = 0x7FFFFFFFFFFFFFFFL;
293 String lastMessage; //Not saved.
294 int portRepeats; //Not saved.
295 boolean soundDebuggingEnabled; //Not saved.
297 static
299 //These tables are as ones used in DosBox.
300 ADPCM_4BIT_LEVEL_SHIFT = new byte[] { -1, 0, 0, 0, 0, 1, 1, 1, -1, 0, 0, 0, 0, 1, 1, 1 };
301 ADPCM_26BIT_LEVEL_SHIFT = new byte[] { -1, 0, 0, 1, -1, 0, 0, 1 };
302 ADPCM_2BIT_LEVEL_SHIFT = new byte[] { -1, 1, -1, 1 };
303 ADPCM_4BIT_LEVEL_MULT = new int[] { 1, 1, 2, 4 };
304 ADPCM_26BIT_LEVEL_MULT = new int[] { 1, 1, 2, 4, 5};
305 ADPCM_2BIT_LEVEL_MULT = new int[] { 1, 1, 2, 4, 8, 16};
306 ADPCM_4BIT_SAMPLE_MULT = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 };
307 ADPCM_26BIT_SAMPLE_MULT = new int[] { 1, 3, 5, 7, -1, -3, -5, -7 };
308 ADPCM_2BIT_SAMPLE_MULT = new int[] { 1, 3, -1, -3 };
311 public void dumpSRPartial(SRDumper output) throws IOException
313 super.dumpSRPartial(output);
314 output.dumpInt(baseIOAddress);
315 output.dumpBoolean(irq2);
316 output.dumpBoolean(irq5);
317 output.dumpBoolean(irq7);
318 output.dumpBoolean(irq10);
319 output.dumpInt(dmaMask);
320 output.dumpInt(dmaRequested);
321 output.dumpBoolean(ioportRegistered);
322 output.dumpObject(clock);
323 output.dumpObject(primaryDMAController);
324 output.dumpObject(secondaryDMAController);
325 output.dumpObject(irqController);
326 output.dumpObject(timer);
327 output.dumpObject(pcmOutput);
329 output.dumpBoolean(irq8Bit);
330 output.dumpBoolean(irq16Bit);
332 output.dumpInt(mixerIndex);
333 output.dumpInt(mixerPrevIndex);
335 output.dumpInt(dspCommandState);
336 output.dumpArray(dspOutput);
337 output.dumpInt(dspOutputUsed);
338 output.dumpArray(mixerRegisters);
339 output.dumpLong(dspNextAttention);
341 output.dumpBoolean(speakerConnected);
343 output.dumpObject(fmChip);
344 output.dumpObject(fmOutput);
345 output.dumpInt(fmIndex);
346 output.dumpLong(fmNextAttention);
348 output.dumpInt(dmaState);
349 output.dumpInt(samplesLeft);
350 output.dumpInt(origSamplesLeft);
351 output.dumpInt(soundFormat);
352 output.dumpBoolean(stereo);
353 output.dumpLong(interSampleTime);
354 output.dumpBoolean(istStereoAdjust);
355 output.dumpInt(dmaActiveMask);
356 output.dumpBoolean(dmaRequest);
357 output.dumpLong(dmaRequestTime);
358 output.dumpInt(partialSample);
359 output.dumpInt(partialSampleBytes);
360 output.dumpInt(wholeSampleBytes);
361 output.dumpInt(byteBuffer);
362 output.dumpInt(byteBufferSamples);
363 output.dumpInt(adpcmReference);
364 output.dumpByte(adpcmScale);
365 output.dumpLong(nextSampleTime);
366 output.dumpBoolean(dmaPaused);
367 output.dumpInt(dmaPauseLeft);
368 output.dumpInt(dspArgumentRegister);
369 output.dumpInt(dspNextDMA);
370 output.dumpInt(dspLastCommand);
372 output.dumpBoolean(e2Mode);
373 output.dumpByte(e2Value);
374 output.dumpInt(e2Count);
375 output.dumpLong(lastPCMWrite);
376 output.dumpLong(lastFMWrite);
380 public SoundCard(SRLoader input) throws IOException
382 super(input);
383 baseIOAddress = input.loadInt();
384 irq2 = input.loadBoolean();
385 irq5 = input.loadBoolean();
386 irq7 = input.loadBoolean();
387 irq10 = input.loadBoolean();
388 dmaMask = input.loadInt();
389 dmaRequested = input.loadInt();
390 ioportRegistered = input.loadBoolean();
391 clock = (Clock)input.loadObject();
392 primaryDMAController = (DMAController)input.loadObject();
393 secondaryDMAController = (DMAController)input.loadObject();
394 irqController = (InterruptController)input.loadObject();
395 timer = (Timer)input.loadObject();
396 pcmOutput = (OutputChannelPCM)input.loadObject();
398 irq8Bit = input.loadBoolean();
399 irq16Bit = input.loadBoolean();
401 mixerIndex = input.loadInt();
402 mixerPrevIndex = input.loadInt();
404 dspCommandState = input.loadInt();
405 dspOutput = input.loadArrayInt();
406 dspOutputUsed = input.loadInt();
407 mixerRegisters = input.loadArrayInt();
408 dspNextAttention = input.loadLong();
410 speakerConnected = input.loadBoolean();
412 fmChip = (FMChip)input.loadObject();
413 fmOutput = (OutputChannelFM)input.loadObject();
414 fmIndex = input.loadInt();
415 fmNextAttention = input.loadLong();
417 dmaState = input.loadInt();
418 samplesLeft = input.loadInt();
419 origSamplesLeft = input.loadInt();
420 soundFormat = input.loadInt();
421 stereo = input.loadBoolean();
422 interSampleTime = input.loadLong();
423 istStereoAdjust = input.loadBoolean();
424 dmaActiveMask = input.loadInt();
425 dmaRequest = input.loadBoolean();
426 dmaRequestTime = input.loadLong();
427 partialSample = input.loadInt();
428 partialSampleBytes = input.loadInt();
429 wholeSampleBytes = input.loadInt();
430 byteBuffer = input.loadInt();
431 byteBufferSamples = input.loadInt();
432 adpcmReference = input.loadInt();
433 adpcmScale = input.loadByte();
434 nextSampleTime = input.loadLong();
435 dmaPaused = input.loadBoolean();
436 dmaPauseLeft = input.loadInt();
437 dspArgumentRegister = input.loadInt();
438 dspNextDMA = input.loadInt();
439 dspLastCommand = input.loadInt();
441 e2Mode = input.loadBoolean();
442 e2Value = input.loadByte();
443 e2Count = input.loadInt();
444 lastFMWrite = -2 * ACTIVITY_TIMEOUT;
445 lastPCMWrite = -2 * ACTIVITY_TIMEOUT;
446 updateStatus();
447 if(input.objectEndsHere())
448 return;
449 lastPCMWrite = input.loadLong();
450 lastFMWrite = input.loadLong();
451 updateStatus();
454 public SoundCard(String parameters) throws IOException
456 char mode = 0;
457 int tmp = 0;
458 int irq = 5;
459 baseIOAddress = 0x220;
460 int lowDMA = 1;
461 int highDMA = 5;
463 interSampleTime = 50000; //Something even reasonably sane.
464 dspNextDMA = -1 ; //No, don't program DMA on first DSP command.
466 fmChip = new FMChip();
467 fmOutput = null;
468 fmIndex = 0;
469 fmNextAttention = TIME_NEVER;
470 dspNextAttention = TIME_NEVER;
471 lastFMWrite = -2 * ACTIVITY_TIMEOUT;
472 lastPCMWrite = -2 * ACTIVITY_TIMEOUT;
474 dspOutput = new int[QUEUE_SIZE];
475 mixerRegisters = new int[MIXER_REGISTERS];
476 mixerPrevIndex = 128;
477 mixerIndex = 128;
479 dspCommandState = DSPSTATE_WAIT_COMMAND;
481 for(int i = 0; i < parameters.length() + 1; i++) {
482 char ch = 0;
483 if(i < parameters.length())
484 ch = parameters.charAt(i);
486 if(ch >= '0' && ch <= '9' && mode != 0) {
487 tmp = tmp * 10 + (ch - '0');
488 continue;
489 } else if(ch >= '0' && ch <= '9' && mode == 0)
490 throw new IOException("Soundcard: Invalid spec '" + parameters + "'.");
491 if(mode == 'A')
492 if(tmp > 65516)
493 throw new IOException("Soundcard: Bad I/O port " + tmp + ".");
494 else
495 baseIOAddress = tmp;
496 else if(mode == 'I')
497 if(tmp != 2 && tmp != 5 && tmp != 7 && tmp != 10)
498 throw new IOException("Soundcard: Bad IRQ " + tmp + ".");
499 else
500 irq = tmp;
501 else if(mode == 'D')
502 if(tmp != 0 && tmp != 1 && tmp != 3)
503 throw new IOException("Soundcard: Bad low DMA " + tmp + ".");
504 else
505 lowDMA = tmp;
506 else if(mode == 'H')
507 if(tmp == 0)
508 highDMA = 0; //Disable high DMA.
509 else if(tmp != 5 && tmp != 6 || tmp != 7)
510 throw new IOException("Soundcard: Bad high DMA " + tmp + ".");
511 else
512 highDMA = tmp;
513 else if(mode > 0 || i > 0)
514 throw new IOException("Soundcard: Invalid setting type '" + mode + "'.");
515 if(ch == 0)
516 break;
517 mode = ch;
518 tmp = 0;
520 if(irq == 2)
521 irq2 = true;
522 if(irq == 5)
523 irq5 = true;
524 if(irq == 7)
525 irq7 = true;
526 if(irq == 10)
527 irq10 = true;
528 if(highDMA > 0)
529 dmaMask = (1 << lowDMA) | (1 << highDMA);
530 else
531 dmaMask = (1 << lowDMA);
532 dmaRequested = 0;
533 resetMixer();
534 updateStatus();
537 private final void grabDMAChannels()
539 int toReq = dmaMask & ~dmaRequested;
540 if(primaryDMAController == null)
541 toReq &= 0xF0;
542 if(secondaryDMAController == null)
543 toReq &= 0x0F;
544 if((toReq & 1) != 0 && primaryDMAController != null)
545 primaryDMAController.registerChannel(0, this);
546 if((toReq & 2) != 0 && primaryDMAController != null)
547 primaryDMAController.registerChannel(1, this);
548 if((toReq & 8) != 0 && primaryDMAController != null)
549 primaryDMAController.registerChannel(3, this);
550 if((toReq & 32) != 0 && secondaryDMAController != null)
551 secondaryDMAController.registerChannel(1, this);
552 if((toReq & 64) != 0 && secondaryDMAController != null)
553 secondaryDMAController.registerChannel(2, this);
554 if((toReq & 128) != 0 && secondaryDMAController != null)
555 secondaryDMAController.registerChannel(3, this);
556 dmaRequested |= toReq;
557 dmaEngineUpdateDMADREQ();
560 public SoundCard() throws IOException
562 this("");
565 public void dumpStatusPartial(StatusDumper output)
567 super.dumpStatusPartial(output);
568 output.println("\tbaseIOAddress " + baseIOAddress);
569 output.println("\tirq8Bit " + irq8Bit);
570 output.println("\tirq16Bit " + irq16Bit);
571 output.println("\tirq2 " + irq2);
572 output.println("\tirq5 " + irq5);
573 output.println("\tirq7 " + irq7);
574 output.println("\tirq10 " + irq10);
575 output.println("\tdmaMask " + dmaMask);
576 output.println("\tdmaRequested " + dmaRequested);
577 output.println("\tioportRegistered " + ioportRegistered);
578 output.println("\tirqController <object #" + output.objectNumber(irqController) + ">"); if(irqController != null) irqController.dumpStatus(output);
579 output.println("\tprimaryDMAController <object #" + output.objectNumber(primaryDMAController) + ">"); if(primaryDMAController != null) primaryDMAController.dumpStatus(output);
580 output.println("\tsecondaryDMAController <object #" + output.objectNumber(secondaryDMAController) + ">"); if(secondaryDMAController != null) secondaryDMAController.dumpStatus(output);
581 output.println("\tclock <object #" + output.objectNumber(clock) + ">"); if(clock != null) clock.dumpStatus(output);
582 output.println("\ttimer <object #" + output.objectNumber(timer) + ">"); if(timer != null) timer.dumpStatus(output);
583 output.println("\tpcmOutput <object #" + output.objectNumber(pcmOutput) + ">"); if(pcmOutput != null) pcmOutput.dumpStatus(output);
585 output.println("\tmixerIndex " + mixerIndex);
586 output.println("\tmixerPrevIndex " + mixerPrevIndex);
587 output.printArray(mixerRegisters, "mixerRegisters");
589 output.println("\tspeakerConnected " + speakerConnected);
591 output.println("\tfmIndex " + fmIndex);
592 output.println("\tfmNextAttention " + fmNextAttention);
593 output.println("\tfmChip <object #" + output.objectNumber(fmChip) + ">"); if(fmChip != null) fmChip.dumpStatus(output);
594 output.println("\tfmOutput <object #" + output.objectNumber(fmOutput) + ">"); if(fmOutput != null) fmOutput.dumpStatus(output);
596 output.printArray(dspOutput, "dspOutput");
597 output.println("\tdspOutputUsed " + dspOutputUsed);
598 output.println("\tdspCommandState " + dspCommandState);
599 output.println("\tdspNextAttention " + dspNextAttention);
601 output.println("\tdmaState " + dmaState);
602 output.println("\tsamplesLeft " + samplesLeft);
603 output.println("\torigSamplesLeft " + origSamplesLeft);
604 output.println("\tsoundFormat " + soundFormat);
605 output.println("\tstereo " + stereo);
606 output.println("\tinterSampleTime " + interSampleTime);
607 output.println("\tistStereoAdjust " + istStereoAdjust);
608 output.println("\tdmaActiveMask " + dmaActiveMask);
609 output.println("\tdmaRequest " + dmaRequest);
610 output.println("\tdmaRequestTime " + dmaRequestTime);
611 output.println("\tpartialSample " + partialSample);
612 output.println("\tpartialSampleBytes " + partialSampleBytes);
613 output.println("\twholeSampleBytes " + wholeSampleBytes);
614 output.println("\tbyteBuffer " + byteBuffer);
615 output.println("\tbyteBufferSamples " + byteBufferSamples);
616 output.println("\tadpcmReference " + adpcmReference);
617 output.println("\tadpcmScale " + adpcmScale);
618 output.println("\tnextSampleTime " + nextSampleTime);
619 output.println("\tdmaPaused " + dmaPaused);
620 output.println("\tdmaPauseLeft " + dmaPauseLeft);
621 output.println("\tdspArgumentRegister " + dspArgumentRegister);
622 output.println("\tdspNextDMA " + dspNextDMA);
623 output.println("\tdspLastCommand " + dspLastCommand);
625 output.println("\te2Mode " + e2Mode);
626 output.println("\te2Value " + e2Value);
627 output.println("\te2Count " + e2Count);
630 public void dumpStatus(StatusDumper output)
632 if(output.dumped(this))
633 return;
635 output.println("#" + output.objectNumber(this) + ": SoundCard:");
636 dumpStatusPartial(output);
637 output.endObject();
640 public void DEBUGOPTION_soundcard_transfer_debugging(boolean _state)
642 soundDebuggingEnabled = _state;
647 public boolean initialised()
649 return ((irqController != null) && (clock != null) && (primaryDMAController != null) && (secondaryDMAController != null) && ioportRegistered);
652 public void acceptComponent(HardwareComponent component)
654 if((component instanceof InterruptController) && component.initialised()) {
655 irqController = (InterruptController)component;
657 if((component instanceof DMAController) && ((DMAController)component).isPrimary() && component.initialised()) {
658 primaryDMAController = (DMAController)component;
659 grabDMAChannels();
661 if((component instanceof DMAController) && !((DMAController)component).isPrimary() && component.initialised()) {
662 secondaryDMAController = (DMAController)component;
663 grabDMAChannels();
665 if((component instanceof Clock) && component.initialised()) {
666 clock = (Clock)component;
667 timer = clock.newTimer(this);
670 if((component instanceof IOPortHandler) && component.initialised() && !ioportRegistered) {
671 ((IOPortHandler)component).registerIOPortCapable(this);
672 ioportRegistered = true;
677 public int[] ioPortsRequested()
679 int[] ret;
680 ret = new int[20];
681 for(int i = 0; i < 16; i++)
682 ret[i] = baseIOAddress + i;
683 ret[ret.length - 4] = 0x388;
684 ret[ret.length - 3] = 0x389;
685 ret[ret.length - 2] = 0x38A;
686 ret[ret.length - 1] = 0x38B;
687 return ret;
690 public int getTimerType()
692 return 36;
695 public void ioPortWriteWord(int address, int data)
697 ioPortWriteByte(address, data & 0xFF);
698 ioPortWriteByte(address + 1, (data >>> 8) & 0xFF);
701 public void ioPortWriteLong(int address, int data)
703 ioPortWriteByte(address, data & 0xFF);
704 ioPortWriteByte(address + 1, (data >>> 8) & 0xFF);
705 ioPortWriteByte(address + 2, (data >>> 16) & 0xFF);
706 ioPortWriteByte(address + 3, (data >>> 24) & 0xFF);
709 public int ioPortReadWord(int address)
711 return (ioPortReadByte(address) | (ioPortReadByte(address + 1) << 8));
714 public int ioPortReadLong(int address)
716 return ioPortReadByte(address) | (ioPortReadByte(address + 1) << 8) |
717 (ioPortReadByte(address + 2) << 16) | (ioPortReadByte(address + 3) << 24);
720 public void ioPortWriteByte(int address, int data)
722 if(address >= baseIOAddress && address < baseIOAddress + 16)
723 if((address - baseIOAddress & ~1) != 8)
724 ioWrite(address - baseIOAddress, data);
725 else
726 ioWrite(address - baseIOAddress - 8, data);
727 else if(address >= 0x388 && address < 0x38C)
728 ioWrite(address - 0x388, data);
731 public int ioPortReadByte(int address)
733 int value = -1;
734 if(address >= baseIOAddress && address < baseIOAddress + 16)
735 if((address - baseIOAddress & ~1) != 8)
736 value = ioRead(address - baseIOAddress);
737 else
738 value = ioRead(address - baseIOAddress - 8);
739 else if(address >= 0x388 && address < 0x38C)
740 value = ioRead(address - 0x388);
742 return value;
745 public int handleTransfer(DMAController.DMAChannel channel, int position, int size)
747 byte[] buf = new byte[1];
748 int avail = size - position;
750 //Some weird command has DMA writing some mysterious values.
751 if(e2Mode) {
752 buf[0] = e2Value;
753 channel.writeMemory(buf, 0, position, 1);
754 e2Mode = false;
755 dmaEngineUpdateDMADREQ();
756 return position + 1;
759 while(avail > 0 && partialSampleBytes < wholeSampleBytes) {
760 channel.readMemory(buf, 0, position, 1);
761 partialSample |= (((int)buf[0] & 0xFF) << (8 * partialSampleBytes));
762 position++;
763 partialSampleBytes++;
764 avail--;
766 dmaEngineUpdateDMADREQ();
767 if(partialSampleBytes == wholeSampleBytes)
768 dmaEngineSampleAvailable();
769 return position;
773 public int requestedSoundChannels()
775 return 1 + FM_CHIPS;
778 public void soundChannelCallback(Output out, String name)
780 if(pcmOutput == null)
781 pcmOutput = new OutputChannelPCM(out, name);
782 else if(fmOutput == null) {
783 OutputChannelFM out2 = new OutputChannelFM(out, name);
784 fmChip.setOutput(out2);
785 fmOutput = out2;
787 recomputeVolume(0); //These always happen at zero time.
790 //Set IRQ line status.
791 private final void setIRQ(int status)
793 if(irq2)
794 irqController.setIRQ(2, status);
795 if(irq5)
796 irqController.setIRQ(5, status);
797 if(irq7)
798 irqController.setIRQ(7, status);
799 if(irq10)
800 irqController.setIRQ(10, status);
803 //Read DMA Select register.
804 private final int readDMARegister()
806 return dmaMask;
809 //Write DMA Select register.
810 private final void writeDMARegister(int value)
812 value = value & 0xEB; //Mask invalid channels.
813 dmaMask = value;
814 grabDMAChannels();
817 //Read IRQ select register.
818 private final int readIRQRegister()
820 int value = 0xF0;
821 if(irq2)
822 value |= 1;
823 if(irq5)
824 value |= 2;
825 if(irq7)
826 value |= 4;
827 if(irq10)
828 value |= 8;
829 return value;
832 //Write IRQ select register.
833 private final void writeIRQRegister(int value)
835 irq2 = ((value & 1) != 0);
836 irq5 = ((value & 2) != 0);
837 irq7 = ((value & 4) != 0);
838 irq10 = ((value & 8) != 0);
841 //Reqd IRQ Status register value.
842 private final int readIRQStatus()
844 return typeFlag | (irq8Bit ? 1 : 0) | (irq16Bit ? 2 : 0);
847 //Set or clear 8 Bit requesting IRQ status.
848 private final void set8BitIRQ(boolean status)
850 boolean oldActive = irq8Bit || irq16Bit;
851 irq8Bit = status;
852 boolean newActive = irq8Bit || irq16Bit;
853 if(oldActive != newActive)
854 setIRQ(newActive ? 1 : 0);
857 //Set or clear 16 Bit requesting IRQ status.
858 private final void set16BitIRQ(boolean status)
860 boolean oldActive = irq8Bit || irq16Bit;
861 irq16Bit = status;
862 boolean newActive = irq8Bit || irq16Bit;
863 if(oldActive != newActive)
864 setIRQ(newActive ? 1 : 0);
867 private final void writeMessage(String message)
869 writeMessage(message, false);
872 private final void writeMessage(String message, boolean priority)
874 if(!priority) {
875 if(!soundDebuggingEnabled)
876 return;
877 else
878 message = "Informational: " + message;
880 if(message.equals(lastMessage))
881 portRepeats++;
882 else {
883 if(portRepeats > 1)
884 System.err.println("<Last message repeted " + portRepeats + " times.>");
885 System.err.println(message);
886 lastMessage = message;
887 portRepeats = 1;
891 //Do I/O write. Possible offsets are 0-7 and 10-15.
892 public void ioWrite(int offset, int dataByte)
894 switch(offset) {
895 case 0:
896 fmIndex = dataByte;
897 return;
898 case 1:
899 writeFM(fmIndex, dataByte);
900 return;
901 case 2:
902 fmIndex = 256 + dataByte;
903 return;
904 case 3:
905 writeFM(fmIndex, dataByte);
906 return;
907 case 4:
908 mixerPrevIndex = mixerIndex;
909 if(!validMixerRegister(mixerPrevIndex, 0))
910 mixerPrevIndex |= 0x80;
911 mixerIndex = dataByte;
912 return;
913 case 5:
914 writeMixer(mixerIndex, dataByte);
915 return;
916 case 6:
917 writeMessage("SB: Resetting card.");
918 doReset(dataByte);
919 return;
920 case 12:
921 dspWrite(dataByte);
922 return;
923 case 7:
924 case 8:
925 case 9:
926 case 10:
927 case 11:
928 case 13:
929 case 14:
930 case 15:
931 default:
932 writeMessage("SB: Attempted write to port " + offset + ".");
933 //Not writable.
934 return;
938 //Do I/O read. Possible offsets are 0-7 and 10-15.
939 public int ioRead(int offset)
941 int tmp;
942 switch(offset) {
943 case 0:
944 case 2:
945 tmp = readFMStatus();
946 return tmp;
947 case 1:
948 case 3:
949 writeMessage("SB: Tried to read FM data port.");
950 return 0; //Lets do like opl.cpp does...
951 case 4:
952 return mixerIndex;
953 case 5:
954 tmp = readMixer(mixerIndex);
955 return tmp;
956 case 10:
957 tmp = dspRead();
958 return tmp;
959 case 12:
960 return writeBufferStatus();
961 case 13:
962 //This is undocumented. What it does?
963 return 255;
964 case 14:
965 set8BitIRQ(false);
966 tmp = dspDataAvailableStatus();
967 case 15:
968 set16BitIRQ(false);
969 return -1;
970 case 6:
971 case 7:
972 case 8:
973 case 9:
974 case 11:
975 default:
976 writeMessage("SB: Attempted read from port " + offset + ".");
977 return 255; //Not readable.
981 public void resetCard()
983 irq8Bit = false;
984 irq16Bit = false;
985 mixerIndex = 128;
986 mixerPrevIndex = 128;
987 dspOutputUsed = 0;
988 dspLastCommand = 0;
989 setIRQ(0);
990 speakerConnected = false;
991 dspCommandState = DSPSTATE_WAIT_COMMAND;
992 resetMixer();
993 dmaEngineKillTransfer();
994 e2Mode = false;
995 e2Value = (byte)0xAA;
996 e2Count = 0;
997 lastPCMWrite = -2 * ACTIVITY_TIMEOUT;
998 lastFMWrite = -2 * ACTIVITY_TIMEOUT;
999 updateStatus();
1002 public void reset()
1004 fmIndex = 0;
1005 ioportRegistered = false;
1006 if(clock != null)
1007 fmChip.resetCard(clock.getTime());
1008 else
1009 fmChip.resetCard(0);
1010 resetCard();
1013 private final int writeBufferStatus()
1015 return 127;
1018 private final int dspDataAvailableStatus()
1020 return 127 | ((dspOutputUsed > 0) ? 128 : 0);
1023 //Mode >=0 is read, <=0 is write.
1024 private final boolean validMixerRegister(int reg, int mode)
1026 if(reg == MIXREG_IRQSELECT || reg == MIXREG_DMASELECT || reg == MIXREG_DAC || reg == MIXREG_MIC || reg == MIXREG_OUTPUT_CONTROL)
1027 return true;
1028 if(reg == MIXREG_MASTER || reg == MIXREG_FM || reg == MIXREG_CD || reg == MIXREG_LINEIN)
1029 return true;
1030 if(reg == MIXREG_IRQSTATUS && mode >= 0)
1031 return true;
1032 if(reg < 0 || reg > MIXREG_LAST)
1033 return false;
1034 if(reg == MIXREG_RESET)
1035 return (mode <= 0);
1036 if(reg == MIXREG_STATUS)
1037 return (mode >= 0);
1038 if(reg >= MIXREG_SB16_FIRST)
1039 return true;
1040 return false;
1043 //Write Mixer data register.
1044 private final void writeMixer(int reg, int data)
1046 if(reg == MIXREG_IRQSELECT) {
1047 writeIRQRegister(data);
1048 return;
1050 if(reg == MIXREG_DMASELECT) {
1051 writeDMARegister(data);
1052 return;
1054 if(reg == MIXREG_RESET) {
1055 resetMixer();
1056 return;
1058 if(reg == MIXREG_DAC) {
1059 mixerRegisters[MIXER_DAC_LEFT] = (data & 0xF0) | 0x08;
1060 mixerRegisters[MIXER_DAC_RIGHT] = ((data & 0xF) << 4) | 0x08;
1061 recomputeVolume(clock.getTime());
1062 return;
1064 if(reg == MIXREG_MIC) {
1065 mixerRegisters[MIXER_MIC] = (data & 0x07) << 5;
1066 return;
1068 if(reg == MIXREG_OUTPUT_CONTROL) {
1069 mixerRegisters[MIXER_OUTPUT_CONTROL] = data;
1070 return;
1072 if(reg == MIXREG_MASTER) {
1073 mixerRegisters[MIXER_MASTER_LEFT] = (data & 0xF0) | 0x08;
1074 mixerRegisters[MIXER_MASTER_RIGHT] = ((data & 0xF) << 4) | 0x08;
1075 recomputeVolume(clock.getTime());
1076 return;
1078 if(reg == MIXREG_FM) {
1079 mixerRegisters[MIXER_FM_LEFT] = (data & 0xF0) | 0x08;
1080 mixerRegisters[MIXER_FM_RIGHT] = ((data & 0xF) << 4) | 0x08;
1081 recomputeVolume(clock.getTime());
1082 return;
1084 if(reg == MIXREG_CD) {
1085 mixerRegisters[MIXER_CD_LEFT] = (data & 0xF0) | 0x08;
1086 mixerRegisters[MIXER_CD_RIGHT] = ((data & 0xF) << 4) | 0x08;
1087 return;
1089 if(reg == MIXREG_LINEIN) {
1090 mixerRegisters[MIXER_LINEIN_LEFT] = (data & 0xF0) | 0x08;
1091 mixerRegisters[MIXER_LINEIN_RIGHT] = ((data & 0xF) << 4) | 0x08;
1092 return;
1094 if(!validMixerRegister(reg, -1))
1095 return; //Bad register.
1097 mixerRegisters[reg - MIXREG_SB16_FIRST] = data;
1098 recomputeVolume(clock.getTime());
1101 //Read Mixer data register.
1102 private final int readMixer(int reg)
1104 if(reg == MIXREG_IRQSELECT)
1105 return readIRQRegister();
1106 if(reg == MIXREG_DMASELECT)
1107 return readDMARegister();
1108 if(reg == MIXREG_IRQSTATUS)
1109 return readIRQStatus();
1110 if(reg == MIXREG_STATUS)
1111 return mixerPrevIndex;
1112 if(reg == MIXREG_DAC)
1113 return (mixerRegisters[MIXER_DAC_LEFT] & 0xF0) | ((mixerRegisters[MIXER_DAC_RIGHT] & 0xF0) >> 4);
1114 if(reg == MIXREG_MIC)
1115 return (mixerRegisters[MIXER_MIC] >> 5);
1116 if(reg == MIXREG_OUTPUT_CONTROL)
1117 return mixerRegisters[MIXER_OUTPUT_CONTROL];
1118 if(reg == MIXREG_MASTER)
1119 return (mixerRegisters[MIXER_MASTER_LEFT] & 0xF0) | ((mixerRegisters[MIXER_MASTER_RIGHT] & 0xF0) >> 4);
1120 if(reg == MIXREG_FM)
1121 return (mixerRegisters[MIXER_FM_LEFT] & 0xF0) | ((mixerRegisters[MIXER_FM_RIGHT] & 0xF0) >> 4);
1122 if(reg == MIXREG_CD)
1123 return (mixerRegisters[MIXER_CD_LEFT] & 0xF0) | ((mixerRegisters[MIXER_CD_RIGHT] & 0xF0) >> 4);
1124 if(reg == MIXREG_LINEIN)
1125 return (mixerRegisters[MIXER_LINEIN_LEFT] & 0xF0) | ((mixerRegisters[MIXER_LINEIN_RIGHT] & 0xF0) >> 4);
1126 if(!validMixerRegister(reg, 1))
1127 return -1; //Bad register.
1129 return mixerRegisters[reg - MIXREG_SB16_FIRST];
1132 private final void resetMixer()
1134 mixerRegisters[MIXER_MASTER_LEFT] = 0xC0;
1135 mixerRegisters[MIXER_MASTER_RIGHT] = 0xC0;
1136 mixerRegisters[MIXER_DAC_LEFT] = 0xC0;
1137 mixerRegisters[MIXER_DAC_RIGHT] = 0xC0;
1138 mixerRegisters[MIXER_FM_LEFT] = 0xC0;
1139 mixerRegisters[MIXER_FM_RIGHT] = 0xC0;
1140 mixerRegisters[MIXER_CD_LEFT] = 0x00;
1141 mixerRegisters[MIXER_CD_RIGHT] = 0x00;
1142 mixerRegisters[MIXER_LINEIN_LEFT] = 0x00;
1143 mixerRegisters[MIXER_LINEIN_RIGHT] = 0x00;
1144 mixerRegisters[MIXER_MIC] = 0x00;
1145 mixerRegisters[MIXER_PCSPEAKER] = 0x00;
1146 mixerRegisters[MIXER_OUTPUT_CONTROL] = 0x1F;
1147 mixerRegisters[MIXER_INPUT_CONTROL_LEFT] = 0x15;
1148 mixerRegisters[MIXER_INPUT_CONTROL_RIGHT] = 0x0B;
1149 mixerRegisters[MIXER_INPUT_GAIN_CONTROL_LEFT] = 0x00;
1150 mixerRegisters[MIXER_INPUT_GAIN_CONTROL_RIGHT] = 0x00;
1151 mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_LEFT] = 0x00;
1152 mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_RIGHT] = 0x00;
1153 mixerRegisters[MIXER_AUTOMATIC_GAIN_CONTROL] = 0x00;
1154 mixerRegisters[MIXER_TREBLE_LEFT] = 0x80;
1155 mixerRegisters[MIXER_TREBLE_RIGHT] = 0x80;
1156 mixerRegisters[MIXER_BASS_LEFT] = 0x80;
1157 mixerRegisters[MIXER_BASS_RIGHT] = 0x80;
1158 mixerRegisters[MIXER_OUTPUT_CONTROL] = 0;
1159 if(clock != null)
1160 recomputeVolume(clock.getTime());
1161 else
1162 recomputeVolume(0);
1165 private final void recomputeVolume(long timeStamp)
1167 int denominator = 255 * 255;
1168 int masterLeft = mixerRegisters[MIXER_MASTER_LEFT];
1169 int masterRight = mixerRegisters[MIXER_MASTER_RIGHT];
1170 int dacLeft = mixerRegisters[MIXER_DAC_LEFT];
1171 int dacRight = mixerRegisters[MIXER_DAC_RIGHT];
1172 int fmLeft = mixerRegisters[MIXER_FM_LEFT];
1173 int fmRight = mixerRegisters[MIXER_FM_RIGHT];
1174 int gainLeft = 1 << (mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_LEFT] >> 6);
1175 int gainRight = 1 << (mixerRegisters[MIXER_OUTPUT_GAIN_CONTROL_RIGHT] >> 6);
1177 int pcmAmpLeft = masterLeft * dacLeft * gainLeft;
1178 int pcmAmpRight = masterRight * dacRight * gainRight;
1179 int fmAmpLeft = masterLeft * fmLeft * gainLeft;
1180 int fmAmpRight = masterRight * fmRight * gainRight;
1181 if(pcmOutput != null)
1182 pcmOutput.addFrameVolumeChange(timeStamp, pcmAmpLeft, denominator, pcmAmpRight, denominator);
1183 if(fmOutput != null)
1184 fmOutput.addFrameVolumeChange(timeStamp, fmAmpLeft, denominator, fmAmpRight, denominator);
1187 //Send PCM sample, taking mixer into account.
1188 private final void sendPCMSample(long timestamp, short left, short right)
1190 pcmOutput.addFrameSampleStereo(timestamp, left, right);
1193 //Read FM synth #1 status register.
1194 private final int readFMStatus()
1196 return fmChip.status(clock.getTime());
1199 //Read from DSP.
1200 private final int dspRead()
1202 int value = dspOutput[0];
1203 if(dspOutputUsed > 1)
1204 System.arraycopy(dspOutput, 1, dspOutput, 0, dspOutputUsed - 1);
1205 dspOutputUsed--;
1206 return value;
1209 //Write FM synth #1 data register.
1210 private final void writeFM(int reg, int data)
1212 long ts = clock.getTime();
1213 lastFMWrite = ts;
1214 updateStatus();
1215 fmChip.write(ts, reg, data);
1216 updateTimer();
1219 //Write to reset register.
1220 private final void doReset(int resetValue)
1222 resetCard();
1223 dspOutput[0] = 0xAA;
1224 dspOutputUsed = 1;
1227 //Recompute value for timer expiry.
1228 private final void updateTimer()
1230 long ts = clock.getTime();
1231 long nActEnd = ((lastPCMWrite < lastFMWrite) ? lastPCMWrite : lastFMWrite) + ACTIVITY_TIMEOUT;
1232 long nextTime = TIME_NEVER;
1233 if(nActEnd > ts)
1234 nextTime = nActEnd;
1235 if(dspNextAttention < nextTime)
1236 nextTime = dspNextAttention;
1237 long tmp = fmChip.nextAttention(ts);
1238 if(tmp < nextTime)
1239 nextTime = tmp;
1240 if(nextTime != TIME_NEVER) {
1241 if(timer != null)
1242 timer.setExpiry(nextTime);
1243 } else
1244 if(timer != null)
1245 timer.disable();
1248 //Recompute value for timer expiry, setting DSP timer expiry.
1249 private final void updateTimer(long dspExpiry)
1251 dspNextAttention = dspExpiry;
1252 updateTimer();
1255 public void callback()
1257 long timeNow = clock.getTime();
1258 boolean runAny = true;
1259 while(runAny) {
1260 runAny = false;
1261 if((lastPCMWrite >= 0 && timeNow >= lastPCMWrite + ACTIVITY_TIMEOUT) ||
1262 (lastFMWrite >= 0 && timeNow >= lastFMWrite + ACTIVITY_TIMEOUT)) {
1263 updateStatus();
1264 runAny = true;
1266 if(dspNextAttention <= timeNow) {
1267 dspAttention(dspNextAttention);
1268 runAny = true;
1270 long tmp = fmChip.nextAttention(clock.getTime());
1271 if(tmp <= timeNow) {
1272 fmChip.attention(clock.getTime());
1273 runAny = true;
1275 if(runAny)
1276 updateTimer();
1280 //Put byte into DSP output queue.
1281 private final void dspOutputPut(int value)
1283 dspOutput[dspOutputUsed++] = value;
1286 private final String interpretMode(int mode)
1288 if(mode == 0)
1289 return "NONE";
1290 else if(mode == 1)
1291 return "SC";
1292 else if(mode == 2)
1293 return "AI";
1294 else if(mode == 3)
1295 return "AI_EXIT";
1296 else
1297 return "UNKNOWN(" + mode + ")";
1300 private final String interpretFormat(int format)
1302 switch(format) {
1303 case SNDFMT_2BIT_ADPCM:
1304 return "ADPCM_2_BIT";
1305 case SNDFMT_26BIT_ADPCM:
1306 return "ADPCM_2.6_BIT";
1307 case SNDFMT_4BIT_ADPCM:
1308 return "ADPCM_4_BIT";
1309 case SNDFMT_2BIT_ADPCM_REF:
1310 return "ADPCM_2_BIT_REF";
1311 case SNDFMT_26BIT_ADPCM_REF:
1312 return "ADPCM_2.6_BIT_REF";
1313 case SNDFMT_4BIT_ADPCM_REF:
1314 return "ADPCM_4_BIT_REF";
1315 case SNDFMT_8BIT_PCM_SIGNED:
1316 return "PCM_8BIT_SIGNED";
1317 case SNDFMT_8BIT_PCM_UNSIGNED:
1318 return "PCM_8BIT_PCM_UNSIGNED";
1319 case SNDFMT_16BIT_PCM_LE_SIGNED:
1320 return "PCM_16BIT_LE_SIGNED";
1321 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1322 return "PCM_16BIT_LE_UNSIGNED";
1323 case SNDFMT_16BIT_PCM_BE_SIGNED:
1324 return "PCM_16BIT_BE_SIGNED";
1325 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1326 return "PCM_16BIT_BE_UNSIGNED";
1327 default:
1328 return "UNKNOWN(" + format + ")";
1332 //Kick-start DMA transfer.
1333 private final void dmaEngineStartTransfer(int mode, int samples, int format, boolean stereoFlag)
1335 long timeNow = clock.getTime();
1336 dmaState = mode;
1337 samplesLeft = origSamplesLeft = samples;
1338 soundFormat = format;
1339 stereo = stereoFlag;
1340 partialSample = 0;
1341 partialSampleBytes = 0;
1342 wholeSampleBytes = 0;
1343 byteBuffer = 0;
1344 byteBufferSamples = 0;
1345 dmaPaused = false;
1346 nextSampleTime = timeNow;
1347 updateTimer(nextSampleTime);
1348 writeMessage("SBDSP: Starting DMA: mode=" + interpretMode(mode) + " samples=" + samples + " format=" +
1349 interpretFormat(format) + " stereoFlag=" + stereoFlag);
1350 updateStatus();
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.");
1364 updateStatus();
1367 //End DMA transfer.
1368 private final void dmaEngineEndTransfer()
1370 if(dmaState == DMA_CONTINUOUS) {
1371 writeMessage("SBDSP: Exiting DMA transfer.");
1372 dmaState = DMA_CONTINUOUS_EXIT;
1376 private final void dmaEnginePauseTransfer()
1378 dmaPaused = true;
1379 dmaPauseLeft = -1;
1380 updateTimer(TIME_NEVER);
1381 writeMessage("SBDSP: Pausing DMA transfer.");
1382 updateStatus();
1385 private final void dmaEnginePauseTransfer(int samples)
1387 dmaPaused = true;
1388 dmaPauseLeft = samples;
1389 writeMessage("SBDSP: Pausing DMA transfer for " + samples + " samples.");
1390 updateStatus();
1393 private final void dmaEngineContinueTransfer()
1395 dmaPaused = false;
1396 nextSampleTime = clock.getTime();
1397 updateTimer(nextSampleTime);
1398 writeMessage("SBDSP: Continuing DMA transfer.");
1399 updateStatus();
1402 private static final boolean is16Bit(int fmt)
1404 switch(fmt) {
1405 case SNDFMT_16BIT_PCM_LE_SIGNED:
1406 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1407 case SNDFMT_16BIT_PCM_BE_SIGNED:
1408 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1409 return true;
1410 default:
1411 return false;
1415 //Ok, one sample down. Handle us to be recalled if needed.
1416 private final void dmaEngineNextSample()
1418 //Clear remainants of preseent sample.
1419 partialSample = 0;
1420 partialSampleBytes = 0;
1421 wholeSampleBytes = 0;
1423 if(dmaPaused && dmaPauseLeft > 0) {
1424 --dmaPauseLeft;
1425 if(dmaPauseLeft == 0) {
1426 writeMessage("SBDSP: Continuing DMA transfer after timed pause.");
1427 set8BitIRQ(true);
1428 dmaPaused = false;
1429 updateStatus();
1433 if(dmaState == DMA_NONE || dmaPaused) {
1434 if(dmaPaused)
1435 writeMessage("Halting paused transfer.");
1436 updateTimer(TIME_NEVER);
1437 updateStatus();
1438 return;
1441 if(samplesLeft > 0)
1442 samplesLeft -= (stereo ? 2 : 1);
1444 if(samplesLeft <= 0) {
1445 //Block run out.
1446 if(is16Bit(soundFormat))
1447 set16BitIRQ(true);
1448 else
1449 set8BitIRQ(true);
1450 dspProgramNextDMA();
1451 if(dmaState == DMA_CONTINUOUS) {
1452 writeMessage("SBDSP: DMA transfer auto-reinitialized.");
1453 samplesLeft = origSamplesLeft;
1454 } else {
1455 //DMA mode exit.
1456 writeMessage("SBDSP: DMA transfer ended.");
1457 dmaState = DMA_NONE;
1458 updateTimer(TIME_NEVER);
1459 updateStatus();
1460 return;
1464 long timeNow = clock.getTime();
1465 long ist = interSampleTime;
1466 //Some modes output at half rate in stereo mode.
1467 if(stereo && istStereoAdjust)
1468 ist *= 2;
1469 if(dmaRequestTime == timeNow) {
1470 //Timely, schedule by supposed time.
1471 nextSampleTime = nextSampleTime + ist;
1472 } else {
1473 //Late. Schecdule by current time.
1474 nextSampleTime = timeNow + ist;
1476 updateTimer(nextSampleTime);
1479 //Update DMA engine DMA requests.
1480 private final void dmaEngineUpdateDMADREQ()
1482 if(!dmaRequest && partialSampleBytes < wholeSampleBytes) {
1483 dmaRequest = true;
1484 dmaRequestTime = clock.getTime();
1488 boolean highDMAAvailable = is16Bit(soundFormat) && ((dmaMask & 0xF0) != 0) && !e2Mode;
1489 int dmaProg = dmaMask & ~dmaActiveMask;
1490 boolean dmaActive = (partialSampleBytes < wholeSampleBytes) || e2Mode;
1492 if(highDMAAvailable) {
1493 for(int i = 0; i < 4; i++)
1494 if(secondaryDMAController != null && dmaActive && ((((dmaProg >> 4) >> i) & 1) != 0)) {
1495 dmaActiveMask |= ((1 << 4) << i);
1496 secondaryDMAController.holdDmaRequest(i);
1499 for(int i = 0; i < 4; i++)
1500 if(primaryDMAController != null && dmaActive && (((dmaProg >> i) & 1) != 0)) {
1501 dmaActiveMask |= (1 << i);
1502 primaryDMAController.holdDmaRequest(i);
1505 if(partialSampleBytes == wholeSampleBytes && !e2Mode) {
1506 //Drop all transfer requests.
1507 dmaProg = dmaActiveMask;
1509 dmaRequest = false;
1510 for(int i = 0; i < 4; i++) {
1511 if(secondaryDMAController != null && (((dmaProg >> 4) >> i) & 1) != 0) {
1512 secondaryDMAController.releaseDmaRequest(i);
1513 dmaActiveMask &= ~((1 << 4) << i);
1515 if(primaryDMAController != null && ((dmaProg >> i) & 1) != 0) {
1516 primaryDMAController.releaseDmaRequest(i);
1517 dmaActiveMask &= ~(1 << i);
1523 private final void dmaEngineAttention()
1525 if(clock.getTime() < nextSampleTime)
1526 return; //Not yet.
1527 //DMA will set next attention.
1528 updateTimer(TIME_NEVER);
1530 //Update DREQ if not requested yet.
1531 if(!dmaRequest) {
1532 //Count the bytes.
1533 int bytes = 0;
1534 switch(soundFormat) {
1535 case SNDFMT_8BIT_PCM_SIGNED:
1536 case SNDFMT_8BIT_PCM_UNSIGNED:
1537 bytes += (stereo ? 2 : 1);
1538 break;
1539 case SNDFMT_16BIT_PCM_LE_SIGNED:
1540 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1541 case SNDFMT_16BIT_PCM_BE_SIGNED:
1542 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1543 bytes += (stereo ? 4 : 2);
1544 break;
1545 case SNDFMT_2BIT_ADPCM:
1546 case SNDFMT_26BIT_ADPCM:
1547 case SNDFMT_4BIT_ADPCM:
1548 //ADPCM is always mono.
1549 if(byteBufferSamples == 0)
1550 bytes += 1;
1551 break;
1552 case SNDFMT_2BIT_ADPCM_REF:
1553 case SNDFMT_26BIT_ADPCM_REF:
1554 case SNDFMT_4BIT_ADPCM_REF:
1555 //ADPCM is always mono.
1556 bytes += 1; //Reference
1557 if(byteBufferSamples == 0);
1558 bytes += 1;
1559 break;
1561 partialSampleBytes = 0;
1562 partialSample = 0;
1563 if(!dmaPaused) {
1564 wholeSampleBytes = bytes;
1565 dmaEngineUpdateDMADREQ();
1566 if(bytes == 0) {
1567 //The DMA engine can't handle requests for 0 bytes, so call sample available
1568 //immediately to keep the loop running.
1569 dmaEngineSampleAvailable();
1571 } else {
1572 wholeSampleBytes = 0;
1573 dmaEngineSampleAvailable();
1578 //Give attention to DSP.
1579 private final void dspAttention(long time)
1581 dmaEngineAttention();
1584 private final int extractBufferByte()
1586 int value = partialSample & 0xFF;
1587 partialSample = partialSample >>> 8;
1588 partialSampleBytes--;
1589 wholeSampleBytes--;
1590 return value;
1593 private final int nonRefFormatFor(int fmt)
1595 switch(fmt) {
1596 case SNDFMT_2BIT_ADPCM_REF:
1597 return SNDFMT_2BIT_ADPCM;
1598 case SNDFMT_26BIT_ADPCM_REF:
1599 return SNDFMT_26BIT_ADPCM;
1600 case SNDFMT_4BIT_ADPCM_REF:
1601 return SNDFMT_4BIT_ADPCM;
1602 default:
1603 return fmt;
1607 private final boolean hasReference(int fmt)
1609 switch(fmt) {
1610 case SNDFMT_2BIT_ADPCM_REF:
1611 case SNDFMT_26BIT_ADPCM_REF:
1612 case SNDFMT_4BIT_ADPCM_REF:
1613 return true;
1614 default:
1615 return false;
1619 private final int byteBufferSamplesADPCM(int fmt)
1621 switch(fmt) {
1622 case SNDFMT_2BIT_ADPCM:
1623 return 4;
1624 case SNDFMT_26BIT_ADPCM:
1625 return 3;
1626 case SNDFMT_4BIT_ADPCM:
1627 return 2;
1628 default:
1629 return 0;
1634 private final void dmaEngineSampleAvailable()
1636 int sampleL = 0, sampleR = 0;
1637 int levelShift = 0;
1638 long timeNow = clock.getTime();
1641 //There's no data in DMA paused mode. Just schedule next sample.
1642 if(dmaPaused) {
1643 dmaEngineNextSample();
1644 return;
1647 //Load Refrence byte if needed.
1648 if(hasReference(soundFormat)) {
1649 adpcmReference = extractBufferByte();
1650 adpcmScale = ADPCM_SCALE_INIT;
1651 soundFormat = nonRefFormatFor(soundFormat);
1654 //Load byte buffer if needed in ADPCM modes.
1655 switch(soundFormat) {
1656 case SNDFMT_2BIT_ADPCM:
1657 case SNDFMT_26BIT_ADPCM:
1658 case SNDFMT_4BIT_ADPCM:
1659 if(byteBufferSamples == 0) {
1660 byteBuffer = extractBufferByte();
1661 // adpcmScale = ADPCM_SCALE_INIT; //Um, what?
1662 byteBufferSamples = byteBufferSamplesADPCM(soundFormat);
1666 switch(soundFormat) {
1667 case SNDFMT_2BIT_ADPCM:
1668 dmaEngineADPCMDecode((byteBuffer >>> 6) & 3);
1669 byteBuffer = byteBuffer << 2;
1670 byteBufferSamples--;
1671 sampleL = sampleR = 256 * (adpcmReference - 128);
1672 break;
1673 case SNDFMT_26BIT_ADPCM:
1674 dmaEngineADPCMDecode((byteBuffer >>> 5) & 7);
1675 byteBuffer = byteBuffer << 3;
1676 byteBufferSamples--;
1677 sampleL = sampleR = 256 * (adpcmReference - 128);
1678 break;
1679 case SNDFMT_4BIT_ADPCM:
1680 dmaEngineADPCMDecode((byteBuffer >>> 4) & 0xF);
1681 byteBuffer = byteBuffer << 4;
1682 byteBufferSamples--;
1683 sampleL = sampleR = 256 * (adpcmReference - 128);
1684 break;
1685 case SNDFMT_8BIT_PCM_UNSIGNED:
1686 levelShift = 32768;
1687 case SNDFMT_8BIT_PCM_SIGNED:
1688 //Let's exploit integer overflows!
1689 sampleL = 256 * extractBufferByte();
1690 if(stereo)
1691 sampleR = 256 * extractBufferByte();
1692 else
1693 sampleR = sampleL;
1694 break;
1695 case SNDFMT_16BIT_PCM_LE_UNSIGNED:
1696 levelShift = 32768;
1697 case SNDFMT_16BIT_PCM_LE_SIGNED:
1698 //Let's exploit integer overflows!
1699 sampleL = extractBufferByte();
1700 sampleL |= (extractBufferByte() << 8);
1701 if(stereo) {
1702 sampleR = extractBufferByte();
1703 sampleR |= (extractBufferByte() << 8);
1704 } else
1705 sampleR = sampleL;
1706 break;
1707 case SNDFMT_16BIT_PCM_BE_UNSIGNED:
1708 levelShift = 32768;
1709 case SNDFMT_16BIT_PCM_BE_SIGNED:
1710 //Let's exploit integer overflows!
1711 sampleL = (extractBufferByte() << 8);
1712 sampleL |= extractBufferByte();
1713 if(stereo) {
1714 sampleR = (extractBufferByte() << 8);
1715 sampleR |= extractBufferByte();
1716 } else
1717 sampleR = sampleL;
1718 break;
1721 sendPCMSample(timeNow, (short)(sampleL - levelShift), (short)(sampleR - levelShift));
1722 dmaEngineNextSample();
1725 //Write byte to DSP.
1726 private final void dspWrite(int command)
1728 int blockSampleArg = origSamplesLeft - 1;
1730 if(dspCommandState == DSPSTATE_WAIT_COMMAND) {
1731 switch(command) {
1733 case DSPCMD_SC_DMA_8_1:
1734 case DSPCMD_SC_DMA_8_2:
1735 case DSPCMD_SC_DMA_8_3:
1736 dspArgumentRegister = 0;
1737 dspCommandState = DSPSTATE_OLDDMA_LOW;
1738 break;
1739 case DSPCMD_AI_DMA_8_1:
1740 case DSPCMD_AI_DMA_8_2:
1741 dspArgumentRegister = 65536 | ((blockSampleArg & 0xFF) << 8) | ((blockSampleArg & 0xFF00) >> 8);
1742 dspNextDMA = dspArgumentRegister;
1743 break;
1744 case DSPCMD_SC_ADPCM_2:
1745 dspArgumentRegister = 2;
1746 dspCommandState = DSPSTATE_OLDDMA_LOW;
1747 break;
1748 case DSPCMD_SC_ADPCM_2_REF:
1749 dspArgumentRegister = 3;
1750 dspCommandState = DSPSTATE_OLDDMA_LOW;
1751 break;
1752 case DSPCMD_SC_ADPCM_26:
1753 dspArgumentRegister = 4;
1754 dspCommandState = DSPSTATE_OLDDMA_LOW;
1755 break;
1756 case DSPCMD_SC_ADPCM_26_REF:
1757 dspArgumentRegister = 5;
1758 dspCommandState = DSPSTATE_OLDDMA_LOW;
1759 break;
1760 case DSPCMD_SC_ADPCM_4:
1761 dspArgumentRegister = 6;
1762 dspCommandState = DSPSTATE_OLDDMA_LOW;
1763 break;
1764 case DSPCMD_SC_ADPCM_4_REF:
1765 dspArgumentRegister = 7;
1766 dspCommandState = DSPSTATE_OLDDMA_LOW;
1767 break;
1768 case DSPCMD_GENERIC_DMA_0: case DSPCMD_GENERIC_DMA_1: case DSPCMD_GENERIC_DMA_2: case DSPCMD_GENERIC_DMA_3:
1769 case DSPCMD_GENERIC_DMA_4: case DSPCMD_GENERIC_DMA_5: case DSPCMD_GENERIC_DMA_6: case DSPCMD_GENERIC_DMA_7:
1770 case DSPCMD_GENERIC_DMA_8: case DSPCMD_GENERIC_DMA_9: case DSPCMD_GENERIC_DMA_A: case DSPCMD_GENERIC_DMA_B:
1771 case DSPCMD_GENERIC_DMA_C: case DSPCMD_GENERIC_DMA_D: case DSPCMD_GENERIC_DMA_E: case DSPCMD_GENERIC_DMA_F:
1772 case DSPCMD_GENERIC_DMA_G: case DSPCMD_GENERIC_DMA_H: case DSPCMD_GENERIC_DMA_I: case DSPCMD_GENERIC_DMA_J:
1773 case DSPCMD_GENERIC_DMA_K: case DSPCMD_GENERIC_DMA_L: case DSPCMD_GENERIC_DMA_M: case DSPCMD_GENERIC_DMA_N:
1774 case DSPCMD_GENERIC_DMA_O: case DSPCMD_GENERIC_DMA_P: case DSPCMD_GENERIC_DMA_Q: case DSPCMD_GENERIC_DMA_R:
1775 case DSPCMD_GENERIC_DMA_S: case DSPCMD_GENERIC_DMA_T: case DSPCMD_GENERIC_DMA_U: case DSPCMD_GENERIC_DMA_V:
1776 dspArgumentRegister = (command - 0xB0);
1777 dspCommandState = DSPSTATE_NEWDMA_LOW;
1778 break;
1779 case DSPCMD_DIRECT_DAC:
1780 dspCommandState = DSPSTATE_DIRECT_DAC_SAMPLE;
1781 break;
1782 case DSPCMD_SET_BLOCKSIZE:
1783 dspCommandState = DSPSTATE_BLOCKSIZE_LOW;
1784 break;
1785 case DSPCMD_SET_TC:
1786 dspCommandState = DSPSTATE_TC;
1787 break;
1788 case DSPCMD_SET_INPUT_RATE:
1789 case DSPCMD_SET_OUTPUT_RATE:
1790 dspCommandState = DSPSTATE_RATE_LOW;
1791 break;
1792 case DSPCMD_SPEAKER_ON:
1793 speakerConnected = true;
1794 recomputeVolume(clock.getTime());
1795 break;
1796 case DSPCMD_SPEAKER_OFF:
1797 speakerConnected = false;
1798 recomputeVolume(clock.getTime());
1799 break;
1800 case DSPCMD_SPEAKER_STATUS:
1801 if(speakerConnected)
1802 dspOutputPut(0xFF);
1803 else
1804 dspOutputPut(0x00);
1805 break;
1806 case DSPCMD_PAUSE_DMA:
1807 case DSPCMD_PAUSE_DMA_16:
1808 dmaEnginePauseTransfer();
1809 break;
1810 case DSPCMD_CONTINUE_DMA:
1811 case DSPCMD_CONTINUE_DMA_16:
1812 case DSPCMD_CONTINUE_DMA_AI:
1813 case DSPCMD_CONTINUE_DMA_AI_16:
1814 dmaEngineContinueTransfer();
1815 break;
1816 case DSPCMD_SILENCE:
1817 dspCommandState = DSPSTATE_SILENCE_LOW;
1818 dspArgumentRegister = 0;
1819 break;
1820 case DSPCMD_EXIT_DMA:
1821 case DSPCMD_EXIT_DMA_16:
1822 dmaEngineEndTransfer();
1823 break;
1824 case DSPCMD_DSP_IDENTIFY:
1825 dspCommandState = DSPSTATE_IDWRITE;
1826 break;
1827 case DSPCMD_DSP_VERSION:
1828 dspOutputUsed = 0;
1829 dspOutputPut((DSP_VERSION >>> 8) & 0xFF);
1830 dspOutputPut(DSP_VERSION & 0xFF);
1831 break;
1832 case DSPCMD_DMA_IDENTIFY:
1833 dspCommandState = DSPSTATE_DMA_IDENTIFY;
1834 break;
1835 case DSPCMD_COPYRIGHT:
1836 dspOutputUsed = 0;
1837 for(int k = 0; k < copyright.length(); k++)
1838 dspOutputPut((int)copyright.charAt(k));
1839 break;
1840 case DSPCMD_WRITE_TEST:
1841 dspCommandState = DSPSTATE_TESTWRITE;
1842 break;
1843 case DSPCMD_READ_TEST:
1844 dspOutputUsed = 0;
1845 dspOutputPut(dspLastCommand);
1846 break;
1847 case DSPCMD_RAISE_8BIT_IRQ:
1848 set8BitIRQ(true);
1849 break;
1850 case DSPCMD_UNDOCUMENTED1:
1851 //Weird undocumented command.
1852 dspOutputUsed = 0;
1853 dspOutputPut(0);
1854 break;
1855 default:
1856 writeMessage("SBDSP: Received unknown command " + command + ".");
1858 } else if(dspCommandState == DSPSTATE_DIRECT_DAC_SAMPLE) {
1859 writeMessage("SBDSP: Setting direct output to " + command + ".");
1860 sendPCMSample(clock.getTime(), (short)(256 * command - 32768), (short)(256 * command - 32768));
1861 lastPCMWrite = clock.getTime();
1862 updateStatus();
1863 dspCommandState = DSPSTATE_WAIT_COMMAND;
1864 } else if(dspCommandState == DSPSTATE_SILENCE_LOW) {
1865 dspArgumentRegister = command;
1866 dspCommandState = DSPSTATE_SILENCE_HIGH;
1867 } else if(dspCommandState == DSPSTATE_SILENCE_HIGH) {
1868 dspArgumentRegister |= (command << 8);
1869 dmaEnginePauseTransfer(dspArgumentRegister + 1);
1870 dspCommandState = DSPSTATE_WAIT_COMMAND;
1871 } else if(dspCommandState == DSPSTATE_TESTWRITE) {
1872 writeMessage("SBDSP: Writing test register: data=" + command + ".");
1873 dspLastCommand = command;
1874 dspCommandState = DSPSTATE_WAIT_COMMAND;
1875 } else if(dspCommandState == DSPSTATE_IDWRITE) {
1876 dspOutputUsed = 0;
1877 writeMessage("SBDSP: Doing ID write: data=" + command + ".");
1878 dspOutputPut(~command);
1879 dspCommandState = DSPSTATE_WAIT_COMMAND;
1880 } else if(dspCommandState == DSPSTATE_BLOCKSIZE_LOW) {
1881 dspArgumentRegister = command;
1882 dspCommandState = DSPSTATE_BLOCKSIZE_HIGH;
1883 } else if(dspCommandState == DSPSTATE_BLOCKSIZE_HIGH) {
1884 dspArgumentRegister |= (command << 8);
1885 writeMessage("SBDSP: Setting block size to " + (dspArgumentRegister + 1) + " samples.");
1886 origSamplesLeft = dspArgumentRegister + 1;
1887 dspCommandState = DSPSTATE_WAIT_COMMAND;
1888 } else if(dspCommandState == DSPSTATE_RATE_LOW) {
1889 dspArgumentRegister = command << 8;
1890 dspCommandState = DSPSTATE_RATE_HIGH;
1891 } else if(dspCommandState == DSPSTATE_RATE_HIGH) {
1892 dspArgumentRegister |= command;
1893 writeMessage("SBDSP: Setting rate to " + (dspArgumentRegister) + "Hz.");
1894 interSampleTime = 1000000000 / dspArgumentRegister;
1895 istStereoAdjust = false;
1896 dspCommandState = DSPSTATE_WAIT_COMMAND;
1897 } else if(dspCommandState == DSPSTATE_TC) {
1898 writeMessage("SBDSP: Setting time constant to " + command + "(" + (1000000 / (256 - command)) + "Hz mono/" + (500000 / (256 - command)) + "Hz stereo).");
1899 interSampleTime = 1000 * (256 - command);
1900 istStereoAdjust = true;
1901 dspCommandState = DSPSTATE_WAIT_COMMAND;
1902 } else if(dspCommandState == DSPSTATE_OLDDMA_LOW) {
1903 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1904 dspCommandState = DSPSTATE_OLDDMA_HIGH;
1905 } else if(dspCommandState == DSPSTATE_NEWDMA_LOW) {
1906 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1907 dspCommandState = DSPSTATE_NEWDMA_MID;
1908 } else if(dspCommandState == DSPSTATE_NEWDMA_MID) {
1909 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1910 dspCommandState = DSPSTATE_NEWDMA_HIGH;
1911 } else if(dspCommandState == DSPSTATE_OLDDMA_HIGH) {
1912 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1913 dspCommandState = DSPSTATE_WAIT_COMMAND;
1914 dspNextDMA = dspArgumentRegister;
1915 } else if(dspCommandState == DSPSTATE_NEWDMA_HIGH) {
1916 dspArgumentRegister = (dspArgumentRegister << 8) | command;
1917 dspCommandState = DSPSTATE_WAIT_COMMAND;
1918 dspArgumentRegister |= 0x20000000;
1919 dspNextDMA = dspArgumentRegister;
1920 } else if(dspCommandState == DSPSTATE_DMA_IDENTIFY) {
1921 //writeMessage("Old DMA identification is " + e2Value + ".");
1922 for(int i = 0; i < 8; i++)
1923 if(((command >>> i) & 1) != 0) {
1924 if(((E2_MAGIC[e2Count % 4] >>> i) & 1) != 0) {
1925 e2Value -= (byte)(1 << i);
1926 } else {
1927 e2Value += (byte)(1 << i);
1930 e2Value += E2_MAGIC[e2Count % 4];
1931 writeMessage("Sending DMA identification " + e2Value + ".");
1932 e2Count++;
1933 e2Mode = true;
1934 dmaEngineUpdateDMADREQ();
1935 dspCommandState = DSPSTATE_WAIT_COMMAND;
1938 //If no DMA, try to program it immediately. Some games rely on halting DMA to
1939 //be able to program it again immediately.
1940 if(dmaState == DMA_NONE || (dmaPaused && dmaPauseLeft < 0))
1941 dspProgramNextDMA();
1944 private final void dspProgramNextDMA()
1946 int samples;
1947 boolean oldStereoFlag = ((mixerRegisters[MIXER_OUTPUT_CONTROL] & 0x2) != 0);
1948 if(dspNextDMA == -1)
1949 return; //No Next DMA.
1951 //Set number of samples.
1952 samples = 1 + (((dspNextDMA & 0xFF) << 8) | ((dspNextDMA >> 8) & 0xFF));
1953 dspNextDMA = dspNextDMA >>> 16;
1954 if(dspNextDMA < 0x2000) {
1955 switch(dspNextDMA) {
1956 case 0: //8 Bits, Single cycle.
1957 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_8BIT_PCM_UNSIGNED, oldStereoFlag);
1958 break;
1959 case 1: //8 Bits, Auto-init.
1960 dmaEngineStartTransfer(DMA_CONTINUOUS, samples, SNDFMT_8BIT_PCM_UNSIGNED, oldStereoFlag);
1961 break;
1962 case 2: //2 Bit ADPCM, single cycle.
1963 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_2BIT_ADPCM, false);
1964 break;
1965 case 3: //2 Bit ADPCM, single cycle, reference.
1966 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_2BIT_ADPCM_REF, false);
1967 break;
1968 case 4: //2.6 Bit ADPCM, single cycle.
1969 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_26BIT_ADPCM, false);
1970 break;
1971 case 5: //2.6 Bit ADPCM, single cycle, reference.
1972 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_26BIT_ADPCM_REF, false);
1973 break;
1974 case 6: //4 Bit ADPCM, single cycle.
1975 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_4BIT_ADPCM, false);
1976 break;
1977 case 7: //4 Bit ADPCM, single cycle, reference.
1978 dmaEngineStartTransfer(DMA_SINGLE, samples, SNDFMT_4BIT_ADPCM_REF, false);
1979 break;
1980 default:
1981 writeMessage("Trying to program unknown DMA mode " + dspNextDMA + ".");
1983 } else if((dspNextDMA & 0x2000) != 0) {
1984 boolean bits16 = ((dspNextDMA & 0x1000) == 0);
1985 boolean autoinit = ((dspNextDMA & 0x400) != 0);
1986 boolean signed = ((dspNextDMA & 0x10) != 0);
1987 boolean stereoFlag = ((dspNextDMA & 0x20) != 0);
1988 int mode = (autoinit ? DMA_CONTINUOUS : DMA_SINGLE);
1989 if(bits16)
1990 if(signed)
1991 dmaEngineStartTransfer(mode, samples, SNDFMT_16BIT_PCM_LE_SIGNED, stereoFlag);
1992 else
1993 dmaEngineStartTransfer(mode, samples, SNDFMT_16BIT_PCM_LE_UNSIGNED, stereoFlag);
1994 else
1995 if(signed)
1996 dmaEngineStartTransfer(mode, samples, SNDFMT_8BIT_PCM_SIGNED, stereoFlag);
1997 else
1998 dmaEngineStartTransfer(mode, samples, SNDFMT_8BIT_PCM_UNSIGNED, stereoFlag);
1999 } else
2000 writeMessage("Trying to program unknown DMA mode " + dspNextDMA + ".");
2002 //DMA command processed.
2003 dspNextDMA = -1;
2006 private final void dmaEngineADPCMDecode(int sample)
2008 int scaleMax = 0;
2009 byte[] levelShift = null;
2010 int[] levelMult = null;
2011 int[] sampleMult = null;
2013 if(soundFormat == SNDFMT_2BIT_ADPCM) {
2014 scaleMax = ADPCM_2BIT_SCALE_MAX;
2015 levelShift = ADPCM_2BIT_LEVEL_SHIFT;
2016 levelMult = ADPCM_2BIT_LEVEL_MULT;
2017 sampleMult = ADPCM_2BIT_SAMPLE_MULT;
2018 } else if(soundFormat == SNDFMT_26BIT_ADPCM) {
2019 scaleMax = ADPCM_26BIT_SCALE_MAX;
2020 levelShift = ADPCM_26BIT_LEVEL_SHIFT;
2021 levelMult = ADPCM_26BIT_LEVEL_MULT;
2022 sampleMult = ADPCM_26BIT_SAMPLE_MULT;
2023 } else if(soundFormat == SNDFMT_4BIT_ADPCM) {
2024 scaleMax = ADPCM_4BIT_SCALE_MAX;
2025 levelShift = ADPCM_4BIT_LEVEL_SHIFT;
2026 levelMult = ADPCM_4BIT_LEVEL_MULT;
2027 sampleMult = ADPCM_4BIT_SAMPLE_MULT;
2030 int index = adpcmScale;
2031 if(index > scaleMax) {
2032 writeMessage("Error: SB: ADPCM level out of range.", true);
2033 index = scaleMax;
2036 byte adjust = levelShift[sample];
2037 if((index == 0 && adjust < 0) || (index == scaleMax && adjust > 0))
2038 adjust = 0;
2039 adpcmScale += adjust;
2041 adpcmReference += (levelMult[index] * sampleMult[sample] / ((index == 0) ? 2 : 1));
2042 if(adpcmReference < 0)
2043 adpcmReference = 0;
2044 if(adpcmReference > 255)
2045 adpcmReference = 255;
2048 void updateStatus()
2050 if(clock == null) {
2051 STATUS_FM_synth = "offline";
2052 STATUS_PCM_DAC = "offline";
2053 STATUS_PCM_DMA = "offline";
2054 STATUS_PCM_DMA_paused = "no";
2055 return;
2057 long ts = clock.getTime();
2058 if(ts < lastFMWrite + ACTIVITY_TIMEOUT)
2059 STATUS_FM_synth = "online";
2060 else {
2061 lastFMWrite = -2 * ACTIVITY_TIMEOUT;
2062 STATUS_FM_synth = "offline";
2064 if(ts < lastPCMWrite + ACTIVITY_TIMEOUT)
2065 STATUS_PCM_DAC = "online";
2066 else if(dmaState != DMA_NONE && !dmaPaused) {
2067 STATUS_PCM_DAC = "online";
2068 lastPCMWrite = -2 * ACTIVITY_TIMEOUT;
2069 } else {
2070 STATUS_PCM_DAC = "offline";
2071 lastPCMWrite = -2 * ACTIVITY_TIMEOUT;
2073 if(dmaState != DMA_NONE && !dmaPaused)
2074 STATUS_PCM_DMA = "online";
2075 else
2076 STATUS_PCM_DMA = "offline";
2077 if(dmaState != DMA_NONE && dmaPaused)
2078 STATUS_PCM_DMA_paused = "yes";
2079 else
2080 STATUS_PCM_DMA_paused = "no";