2 JPC-RR: A x86 PC Hardware Emulator
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
.*;
37 public class SoundCard
extends AbstractHardwareComponent
implements IOPortCapable
, TimerResponsive
, DMATransferCapable
, SoundOutputDevice
39 private int baseIOAddress
;
43 private boolean irq10
;
45 private int dmaRequested
;
46 private boolean ioportRegistered
;
47 private DMAController primaryDMAController
;
48 private DMAController secondaryDMAController
;
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
;
106 private FMChip fmChip
;
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.
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
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
444 baseIOAddress
= 0x220;
448 interSampleTime
= 50000; //Something even reasonably sane.
449 dspNextDMA
= -1 ; //No, don't program DMA on first DSP command.
451 fmChip
= new FMChip();
454 fmNextAttention
= TIME_NEVER
;
455 dspNextAttention
= TIME_NEVER
;
457 dspOutput
= new int[QUEUE_SIZE
];
458 mixerRegisters
= new int[MIXER_REGISTERS
];
459 mixerPrevIndex
= 128;
462 dspCommandState
= DSPSTATE_WAIT_COMMAND
;
464 for(int i
= 0; i
< parameters
.length() + 1; i
++) {
466 if(i
< parameters
.length())
467 ch
= parameters
.charAt(i
);
469 if(ch
>= '0' && ch
<= '9' && mode
!= 0) {
470 tmp
= tmp
* 10 + (ch
- '0');
472 } else if(ch
>= '0' && ch
<= '9' && mode
== 0)
473 throw new IOException("Soundcard: Invalid spec '" + parameters
+ "'.");
476 throw new IOException("Soundcard: Bad I/O port " + tmp
+ ".");
480 if(tmp
!= 2 && tmp
!= 5 && tmp
!= 7 && tmp
!= 10)
481 throw new IOException("Soundcard: Bad IRQ " + tmp
+ ".");
485 if(tmp
!= 0 && tmp
!= 1 && tmp
!= 3)
486 throw new IOException("Soundcard: Bad low DMA " + tmp
+ ".");
491 highDMA
= 0; //Disable high DMA.
492 else if(tmp
!= 5 && tmp
!= 6 || tmp
!= 7)
493 throw new IOException("Soundcard: Bad high DMA " + tmp
+ ".");
496 else if(mode
> 0 || i
> 0)
497 throw new IOException("Soundcard: Invalid setting type '" + mode
+ "'.");
512 dmaMask
= (1 << lowDMA
) | (1 << highDMA
);
514 dmaMask
= (1 << lowDMA
);
519 private final void grabDMAChannels()
521 int toReq
= dmaMask
& ~dmaRequested
;
522 if(primaryDMAController
== null)
524 if(secondaryDMAController
== null)
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
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))
619 output
.println("#" + output
.objectNumber(this) + ": SoundCard:");
620 dumpStatusPartial(output
);
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
;
638 if((component
instanceof DMAController
) && !((DMAController
)component
).isPrimary() && component
.initialised()) {
639 secondaryDMAController
= (DMAController
)component
;
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()
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.");
668 public int getTimerType()
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
);
704 ioWrite(address
- baseIOAddress
- 8, data
);
705 else if(address
>= 0x388 && address
< 0x38C)
706 ioWrite(address
- 0x388, data
);
709 public int ioPortReadByte(int address
)
712 if(address
>= baseIOAddress
&& address
< baseIOAddress
+ 16)
713 if((address
- baseIOAddress
& ~
1) != 8)
714 value
= ioRead(address
- baseIOAddress
);
716 value
= ioRead(address
- baseIOAddress
- 8);
717 else if(address
>= 0x388 && address
< 0x38C)
718 value
= ioRead(address
- 0x388);
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.
731 channel
.writeMemory(buf
, 0, position
, 1);
733 dmaEngineUpdateDMADREQ();
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
));
743 partialSampleBytes
++;
746 dmaEngineUpdateDMADREQ();
747 if(partialSampleBytes
== wholeSampleBytes
)
748 dmaEngineSampleAvailable();
753 public int requestedSoundChannels()
758 public void soundChannelCallback(SoundDigitalOut out
)
760 if(pcmOutput
== null)
762 else if(fmOutput
== null) {
763 fmChip
.setOutput(out
);
766 recomputeVolume(0); //These always happen at zero time.
769 //Set IRQ line status.
770 private final void setIRQ(int status
)
773 irqController
.setIRQ(2, status
);
775 irqController
.setIRQ(5, status
);
777 irqController
.setIRQ(7, status
);
779 irqController
.setIRQ(10, status
);
782 //Read DMA Select register.
783 private final int readDMARegister()
788 //Write DMA Select register.
789 private final void writeDMARegister(int value
)
791 value
= value
& 0xEB; //Mask invalid channels.
796 //Read IRQ select register.
797 private final int readIRQRegister()
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
;
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
;
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
))
861 System
.err
.println("<Last message repeted " + portRepeats
+ " times.>");
862 System
.err
.println(message
);
863 lastMessage
= message
;
868 //Do I/O write. Possible offsets are 0-7 and 10-15.
869 public void ioWrite(int offset
, int dataByte
)
876 //writeMessage("SB: FM write: " + fmIndex + " -> " + dataByte + ".");
877 writeFM(fmIndex
, dataByte
);
880 fmIndex
= 256 + dataByte
;
883 //writeMessage("SB: FM write: " + fmIndex + " -> " + dataByte + ".");
884 writeFM(fmIndex
, dataByte
);
887 mixerPrevIndex
= mixerIndex
;
888 if(!validMixerRegister(mixerPrevIndex
, 0))
889 mixerPrevIndex
|= 0x80;
890 mixerIndex
= dataByte
;
893 writeMixer(mixerIndex
, dataByte
);
896 writeMessage("SB: Resetting card.");
911 writeMessage("SB: Attempted write to port " + offset
+ ".");
917 //Do I/O read. Possible offsets are 0-7 and 10-15.
918 public int ioRead(int offset
)
924 tmp
= readFMStatus();
925 //writeMessage("SB: Read FM status " + (tmp & 0xE0) + ".");
929 writeMessage("SB: Tried to read FM data port.");
930 return 0; //Lets do like opl.cpp does...
932 writeMessage("SB: Read mixer index (" + mixerIndex
+ ").");
935 tmp
= readMixer(mixerIndex
);
936 writeMessage("SB: Read mixer register " + mixerIndex
+ " -> " + tmp
+ ".");
940 writeMessage("SB: Read value " + tmp
+ " from DSP.");
943 return writeBufferStatus();
945 //This is undocumented. What it does?
949 tmp
= dspDataAvailableStatus();
951 writeMessage("SB: Read read buffer status / cleared 8-bit IRQ (no data in buffer).");
953 writeMessage("SB: Read read buffer status / cleared 8-bit IRQ (data in buffer).");
963 writeMessage("SB: Attempted read from port " + offset
+ ".");
964 return 255; //Not readable.
968 public void resetCard()
973 mixerPrevIndex
= 128;
977 speakerConnected
= false;
978 dspCommandState
= DSPSTATE_WAIT_COMMAND
;
980 dmaEngineKillTransfer();
982 e2Value
= (byte)0xAA;
989 ioportRegistered
= false;
991 fmChip
.resetCard(clock
.getTime());
997 private final int writeBufferStatus()
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
)
1012 if(reg
== MIXREG_MASTER
|| reg
== MIXREG_FM
|| reg
== MIXREG_CD
|| reg
== MIXREG_LINEIN
)
1014 if(reg
== MIXREG_IRQSTATUS
&& mode
>= 0)
1016 if(reg
< 0 || reg
> MIXREG_LAST
)
1018 if(reg
== MIXREG_RESET
)
1020 if(reg
== MIXREG_STATUS
)
1022 if(reg
>= MIXREG_SB16_FIRST
)
1027 //Write Mixer data register.
1028 private final void writeMixer(int reg
, int data
)
1030 if(reg
== MIXREG_IRQSELECT
) {
1031 writeIRQRegister(data
);
1034 if(reg
== MIXREG_DMASELECT
) {
1035 writeDMARegister(data
);
1038 if(reg
== MIXREG_RESET
) {
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());
1048 if(reg
== MIXREG_MIC
) {
1049 mixerRegisters
[MIXER_MIC
] = (data
& 0x07) << 5;
1052 if(reg
== MIXREG_OUTPUT_CONTROL
) {
1053 mixerRegisters
[MIXER_OUTPUT_CONTROL
] = data
;
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());
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());
1068 if(reg
== MIXREG_CD
) {
1069 mixerRegisters
[MIXER_CD_LEFT
] = (data
& 0xF0) | 0x08;
1070 mixerRegisters
[MIXER_CD_RIGHT
] = ((data
& 0xF) << 4) | 0x08;
1073 if(reg
== MIXREG_LINEIN
) {
1074 mixerRegisters
[MIXER_LINEIN_LEFT
] = (data
& 0xF0) | 0x08;
1075 mixerRegisters
[MIXER_LINEIN_RIGHT
] = ((data
& 0xF) << 4) | 0x08;
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;
1144 recomputeVolume(clock
.getTime());
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());
1209 private final int dspRead()
1211 int value
= dspOutput
[0];
1212 if(dspOutputUsed
> 1)
1213 System
.arraycopy(dspOutput
, 1, dspOutput
, 0, dspOutputUsed
- 1);
1218 //Write FM synth #1 data register.
1219 private final void writeFM(int reg
, int data
)
1221 fmChip
.write(clock
.getTime(), reg
, data
);
1225 //Write to reset register.
1226 private final void doReset(int resetValue
)
1229 dspOutput
[0] = 0xAA;
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());
1242 if(nextTime
!= TIME_NEVER
) {
1244 timer
.setExpiry(nextTime
);
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 + ".");
1257 // System.err.println("Informational: SB: Clearing next attention.");
1261 public void callback()
1263 long timeNow
= clock
.getTime();
1264 boolean runAny
= true;
1267 if(dspNextAttention
<= timeNow
) {
1268 dspAttention(dspNextAttention
);
1271 long tmp
= fmChip
.nextAttention(clock
.getTime());
1272 if(tmp
<= timeNow
) {
1273 fmChip
.attention(clock
.getTime());
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
)
1298 return "UNKNOWN(" + mode
+ ")";
1301 private final String
interpretFormat(int 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";
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();
1338 samplesLeft
= origSamplesLeft
= samples
;
1339 soundFormat
= format
;
1340 stereo
= stereoFlag
;
1342 partialSampleBytes
= 0;
1343 wholeSampleBytes
= 0;
1345 byteBufferSamples
= 0;
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
;
1359 partialSampleBytes
= wholeSampleBytes
= partialSample
= 0;
1360 dmaEngineUpdateDMADREQ();
1361 updateTimer(TIME_NEVER
);
1362 if(activeChannels
!= 0)
1363 writeMessage("SBDSP: Killed 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()
1379 updateTimer(TIME_NEVER
);
1380 writeMessage("SBDSP: Pausing DMA transfer.");
1383 private final void dmaEnginePauseTransfer(int samples
)
1386 dmaPauseLeft
= samples
;
1387 writeMessage("SBDSP: Pausing DMA transfer for " + samples
+ " samples.");
1390 private final void dmaEngineContinueTransfer()
1393 nextSampleTime
= clock
.getTime();
1394 updateTimer(nextSampleTime
);
1395 writeMessage("SBDSP: Continuing DMA transfer.");
1398 private static final boolean is16Bit(int 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
:
1411 //Ok, one sample down. Handle us to be recalled if needed.
1412 private final void dmaEngineNextSample()
1414 //Clear remainants of preseent sample.
1416 partialSampleBytes
= 0;
1417 wholeSampleBytes
= 0;
1419 if(dmaPaused
&& dmaPauseLeft
> 0) {
1421 if(dmaPauseLeft
== 0) {
1422 writeMessage("SBDSP: Continuing DMA transfer after timed pause.");
1428 if(dmaState
== DMA_NONE
|| dmaPaused
) {
1430 System
.err
.println("Halting paused transfer.");
1431 updateTimer(TIME_NEVER
);
1436 samplesLeft
-= (stereo ?
2 : 1);
1438 if(samplesLeft
<= 0) {
1440 if(is16Bit(soundFormat
))
1444 dspProgramNextDMA();
1445 if(dmaState
== DMA_CONTINUOUS
) {
1446 writeMessage("SBDSP: DMA transfer auto-reinitialized.");
1447 samplesLeft
= origSamplesLeft
;
1450 writeMessage("SBDSP: DMA transfer ended.");
1451 dmaState
= DMA_NONE
;
1452 updateTimer(TIME_NEVER
);
1457 long timeNow
= clock
.getTime();
1458 long ist
= interSampleTime
;
1459 //Some modes output at half rate in stereo mode.
1460 if(stereo
&& istStereoAdjust
)
1462 if(dmaRequestTime
== timeNow
) {
1463 //Timely, schedule by supposed time.
1464 nextSampleTime
= nextSampleTime
+ ist
;
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
) {
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
;
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
)
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.
1532 switch(soundFormat
) {
1533 case SNDFMT_8BIT_PCM_SIGNED
:
1534 case SNDFMT_8BIT_PCM_UNSIGNED
:
1535 bytes
+= (stereo ?
2 : 1);
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);
1543 case SNDFMT_2BIT_ADPCM
:
1544 case SNDFMT_26BIT_ADPCM
:
1545 case SNDFMT_4BIT_ADPCM
:
1546 //ADPCM is always mono.
1547 if(byteBufferSamples
== 0)
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);
1559 partialSampleBytes
= 0;
1562 wholeSampleBytes
= bytes
;
1563 dmaEngineUpdateDMADREQ();
1565 //The DMA engine can't handle requests for 0 bytes, so call sample available
1566 //immediately to keep the loop running.
1567 dmaEngineSampleAvailable();
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
--;
1592 private final int nonRefFormatFor(int 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
;
1606 private final boolean hasReference(int fmt
)
1609 case SNDFMT_2BIT_ADPCM_REF
:
1610 case SNDFMT_26BIT_ADPCM_REF
:
1611 case SNDFMT_4BIT_ADPCM_REF
:
1618 private final int byteBufferSamplesADPCM(int fmt
)
1621 case SNDFMT_2BIT_ADPCM
:
1623 case SNDFMT_26BIT_ADPCM
:
1625 case SNDFMT_4BIT_ADPCM
:
1633 private final void dmaEngineSampleAvailable()
1635 int sampleL
= 0, sampleR
= 0;
1637 long timeNow
= clock
.getTime();
1640 //There's no data in DMA paused mode. Just schedule next sample.
1642 dmaEngineNextSample();
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);
1676 case SNDFMT_26BIT_ADPCM
:
1677 dmaEngineADPCMDecode((byteBuffer
>>> 5) & 7);
1678 byteBuffer
= byteBuffer
<< 3;
1679 byteBufferSamples
--;
1680 sampleL
= sampleR
= 256 * (adpcmReference
- 128);
1682 case SNDFMT_4BIT_ADPCM
:
1683 dmaEngineADPCMDecode((byteBuffer
>>> 4) & 0xF);
1684 byteBuffer
= byteBuffer
<< 4;
1685 byteBufferSamples
--;
1686 sampleL
= sampleR
= 256 * (adpcmReference
- 128);
1688 case SNDFMT_8BIT_PCM_UNSIGNED
:
1690 case SNDFMT_8BIT_PCM_SIGNED
:
1691 //Let's exploit integer overflows!
1692 sampleL
= 256 * extractBufferByte();
1694 sampleR
= 256 * extractBufferByte();
1698 case SNDFMT_16BIT_PCM_LE_UNSIGNED
:
1700 case SNDFMT_16BIT_PCM_LE_SIGNED
:
1701 //Let's exploit integer overflows!
1702 sampleL
= extractBufferByte();
1703 sampleL
|= (extractBufferByte() << 8);
1705 sampleR
= extractBufferByte();
1706 sampleR
|= (extractBufferByte() << 8);
1710 case SNDFMT_16BIT_PCM_BE_UNSIGNED
:
1712 case SNDFMT_16BIT_PCM_BE_SIGNED
:
1713 //Let's exploit integer overflows!
1714 sampleL
= (extractBufferByte() << 8);
1715 sampleL
|= extractBufferByte();
1717 sampleR
= (extractBufferByte() << 8);
1718 sampleR
|= extractBufferByte();
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
) {
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
;
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
;
1751 case DSPCMD_SC_ADPCM_2
:
1752 writeMessage("SBDSP: Received SC_ADPCM_2(" + command
+ ") command.");
1753 dspArgumentRegister
= 2;
1754 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
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
;
1761 case DSPCMD_SC_ADPCM_26
:
1762 writeMessage("SBDSP: Received SC_ADPCM_26(" + command
+ ") command.");
1763 dspArgumentRegister
= 4;
1764 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
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
;
1771 case DSPCMD_SC_ADPCM_4
:
1772 writeMessage("SBDSP: Received SC_ADPCM_4(" + command
+ ") command.");
1773 dspArgumentRegister
= 6;
1774 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
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
;
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
;
1793 case DSPCMD_DIRECT_DAC
:
1794 writeMessage("SBDSP: Received DIRECT_DAC command.");
1795 dspCommandState
= DSPSTATE_DIRECT_DAC_SAMPLE
;
1797 case DSPCMD_SET_BLOCKSIZE
:
1798 writeMessage("SBDSP: Received SET_BLOCKSIZE command.");
1799 dspCommandState
= DSPSTATE_BLOCKSIZE_LOW
;
1802 writeMessage("SBDSP: Received SET_TC command.");
1803 dspCommandState
= DSPSTATE_TC
;
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
;
1810 case DSPCMD_SPEAKER_ON
:
1811 writeMessage("SBDSP: Received SPEAKER_ON command.");
1812 speakerConnected
= true;
1813 recomputeVolume(clock
.getTime());
1815 case DSPCMD_SPEAKER_OFF
:
1816 writeMessage("SBDSP: Received SPEAKER_OFF command.");
1817 speakerConnected
= false;
1818 recomputeVolume(clock
.getTime());
1820 case DSPCMD_SPEAKER_STATUS
:
1821 writeMessage("SBDSP: Received SPEAKER_STATUS command.");
1822 if(speakerConnected
)
1827 case DSPCMD_PAUSE_DMA
:
1828 case DSPCMD_PAUSE_DMA_16
:
1829 writeMessage("SBDSP: Received PAUSE_DMA(" + command
+ ") command.");
1830 dmaEnginePauseTransfer();
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();
1839 case DSPCMD_SILENCE
:
1840 writeMessage("SBDSP: Received SILENCE command.");
1841 dspCommandState
= DSPSTATE_SILENCE_LOW
;
1842 dspArgumentRegister
= 0;
1844 case DSPCMD_EXIT_DMA
:
1845 case DSPCMD_EXIT_DMA_16
:
1846 writeMessage("SBDSP: Received EXIT_DMA command.");
1847 dmaEngineEndTransfer();
1849 case DSPCMD_DSP_IDENTIFY
:
1850 writeMessage("SBDSP: Received DSP_IDENTIFY command.");
1851 dspCommandState
= DSPSTATE_IDWRITE
;
1853 case DSPCMD_DSP_VERSION
:
1854 writeMessage("SBDSP: Received DSP_VERSION command.");
1856 dspOutputPut((DSP_VERSION
>>> 8) & 0xFF);
1857 dspOutputPut(DSP_VERSION
& 0xFF);
1859 case DSPCMD_DMA_IDENTIFY
:
1860 writeMessage("SBDSP: Received DMA_IDENTIFY command.");
1861 dspCommandState
= DSPSTATE_DMA_IDENTIFY
;
1863 case DSPCMD_COPYRIGHT
:
1864 writeMessage("SBDSP: Received COPYRIGHT command.");
1866 for(int k
= 0; k
< copyright
.length(); k
++)
1867 dspOutputPut((int)copyright
.charAt(k
));
1869 case DSPCMD_WRITE_TEST
:
1870 writeMessage("SBDSP: Received WRITE_TEST command.");
1871 dspCommandState
= DSPSTATE_TESTWRITE
;
1873 case DSPCMD_READ_TEST
:
1874 writeMessage("SBDSP: Received READ_TEST command.");
1876 dspOutputPut(dspLastCommand
);
1878 case DSPCMD_RAISE_8BIT_IRQ
:
1879 writeMessage("SBDSP: Received RAISE_IRQ command.");
1882 case DSPCMD_UNDOCUMENTED1
:
1883 //Weird undocumented command.
1884 writeMessage("SBDSP: Received UNDOCUMENTED command.");
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
) {
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
);
1961 e2Value
+= (byte)(1 << i
);
1964 e2Value
+= E2_MAGIC
[e2Count
% 4];
1965 writeMessage("Sending DMA identification " + e2Value
+ ".");
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()
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
);
1993 case 1: //8 Bits, Auto-init.
1994 dmaEngineStartTransfer(DMA_CONTINUOUS
, samples
, SNDFMT_8BIT_PCM_UNSIGNED
, oldStereoFlag
);
1996 case 2: //2 Bit ADPCM, single cycle.
1997 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_2BIT_ADPCM
, false);
1999 case 3: //2 Bit ADPCM, single cycle, reference.
2000 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_2BIT_ADPCM_REF
, false);
2002 case 4: //2.6 Bit ADPCM, single cycle.
2003 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_26BIT_ADPCM
, false);
2005 case 5: //2.6 Bit ADPCM, single cycle, reference.
2006 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_26BIT_ADPCM_REF
, false);
2008 case 6: //4 Bit ADPCM, single cycle.
2009 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_4BIT_ADPCM
, false);
2011 case 7: //4 Bit ADPCM, single cycle, reference.
2012 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_4BIT_ADPCM_REF
, false);
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
);
2025 dmaEngineStartTransfer(mode
, samples
, SNDFMT_16BIT_PCM_LE_SIGNED
, stereoFlag
);
2027 dmaEngineStartTransfer(mode
, samples
, SNDFMT_16BIT_PCM_LE_UNSIGNED
, stereoFlag
);
2030 dmaEngineStartTransfer(mode
, samples
, SNDFMT_8BIT_PCM_SIGNED
, stereoFlag
);
2032 dmaEngineStartTransfer(mode
, samples
, SNDFMT_8BIT_PCM_UNSIGNED
, stereoFlag
);
2034 writeMessage("Trying to program unknown DMA mode " + dspNextDMA
+ ".");
2036 //DMA command processed.
2040 private final void dmaEngineADPCMDecode(int sample
)
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.");
2070 byte adjust
= levelShift
[sample
];
2071 if((index
== 0 && adjust
< 0) || (index
== scaleMax
&& adjust
> 0))
2073 adpcmScale
+= adjust
;
2075 adpcmReference
+= (levelMult
[index
] * sampleMult
[sample
] / ((index
== 0) ?
2 : 1));
2076 if(adpcmReference
< 0)
2078 if(adpcmReference
> 255)
2079 adpcmReference
= 255;