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
.output
.*;
34 import org
.jpc
.modulesaux
.*;
35 import org
.jpc
.emulator
.motherboard
.*;
38 public class SoundCard
extends AbstractHardwareComponent
implements IOPortCapable
, TimerResponsive
, DMATransferCapable
, SoundOutputDevice
40 private int baseIOAddress
;
44 private boolean irq10
;
46 private int dmaRequested
;
47 private boolean ioportRegistered
;
48 private DMAController primaryDMAController
;
49 private DMAController secondaryDMAController
;
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
;
112 private FMChip fmChip
;
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.
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
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
;
447 if(input
.objectEndsHere())
449 lastPCMWrite
= input
.loadLong();
450 lastFMWrite
= input
.loadLong();
454 public SoundCard(String parameters
) throws IOException
459 baseIOAddress
= 0x220;
463 interSampleTime
= 50000; //Something even reasonably sane.
464 dspNextDMA
= -1 ; //No, don't program DMA on first DSP command.
466 fmChip
= new FMChip();
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;
479 dspCommandState
= DSPSTATE_WAIT_COMMAND
;
481 for(int i
= 0; i
< parameters
.length() + 1; i
++) {
483 if(i
< parameters
.length())
484 ch
= parameters
.charAt(i
);
486 if(ch
>= '0' && ch
<= '9' && mode
!= 0) {
487 tmp
= tmp
* 10 + (ch
- '0');
489 } else if(ch
>= '0' && ch
<= '9' && mode
== 0)
490 throw new IOException("Soundcard: Invalid spec '" + parameters
+ "'.");
493 throw new IOException("Soundcard: Bad I/O port " + tmp
+ ".");
497 if(tmp
!= 2 && tmp
!= 5 && tmp
!= 7 && tmp
!= 10)
498 throw new IOException("Soundcard: Bad IRQ " + tmp
+ ".");
502 if(tmp
!= 0 && tmp
!= 1 && tmp
!= 3)
503 throw new IOException("Soundcard: Bad low DMA " + tmp
+ ".");
508 highDMA
= 0; //Disable high DMA.
509 else if(tmp
!= 5 && tmp
!= 6 || tmp
!= 7)
510 throw new IOException("Soundcard: Bad high DMA " + tmp
+ ".");
513 else if(mode
> 0 || i
> 0)
514 throw new IOException("Soundcard: Invalid setting type '" + mode
+ "'.");
529 dmaMask
= (1 << lowDMA
) | (1 << highDMA
);
531 dmaMask
= (1 << lowDMA
);
537 private final void grabDMAChannels()
539 int toReq
= dmaMask
& ~dmaRequested
;
540 if(primaryDMAController
== null)
542 if(secondaryDMAController
== null)
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
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))
635 output
.println("#" + output
.objectNumber(this) + ": SoundCard:");
636 dumpStatusPartial(output
);
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
;
661 if((component
instanceof DMAController
) && !((DMAController
)component
).isPrimary() && component
.initialised()) {
662 secondaryDMAController
= (DMAController
)component
;
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()
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;
690 public int getTimerType()
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
);
726 ioWrite(address
- baseIOAddress
- 8, data
);
727 else if(address
>= 0x388 && address
< 0x38C)
728 ioWrite(address
- 0x388, data
);
731 public int ioPortReadByte(int address
)
734 if(address
>= baseIOAddress
&& address
< baseIOAddress
+ 16)
735 if((address
- baseIOAddress
& ~
1) != 8)
736 value
= ioRead(address
- baseIOAddress
);
738 value
= ioRead(address
- baseIOAddress
- 8);
739 else if(address
>= 0x388 && address
< 0x38C)
740 value
= ioRead(address
- 0x388);
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.
753 channel
.writeMemory(buf
, 0, position
, 1);
755 dmaEngineUpdateDMADREQ();
759 while(avail
> 0 && partialSampleBytes
< wholeSampleBytes
) {
760 channel
.readMemory(buf
, 0, position
, 1);
761 partialSample
|= (((int)buf
[0] & 0xFF) << (8 * partialSampleBytes
));
763 partialSampleBytes
++;
766 dmaEngineUpdateDMADREQ();
767 if(partialSampleBytes
== wholeSampleBytes
)
768 dmaEngineSampleAvailable();
773 public int requestedSoundChannels()
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
);
787 recomputeVolume(0); //These always happen at zero time.
790 //Set IRQ line status.
791 private final void setIRQ(int status
)
794 irqController
.setIRQ(2, status
);
796 irqController
.setIRQ(5, status
);
798 irqController
.setIRQ(7, status
);
800 irqController
.setIRQ(10, status
);
803 //Read DMA Select register.
804 private final int readDMARegister()
809 //Write DMA Select register.
810 private final void writeDMARegister(int value
)
812 value
= value
& 0xEB; //Mask invalid channels.
817 //Read IRQ select register.
818 private final int readIRQRegister()
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
;
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
;
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
)
875 if(!soundDebuggingEnabled
)
878 message
= "Informational: " + message
;
880 if(message
.equals(lastMessage
))
884 System
.err
.println("<Last message repeted " + portRepeats
+ " times.>");
885 System
.err
.println(message
);
886 lastMessage
= message
;
891 //Do I/O write. Possible offsets are 0-7 and 10-15.
892 public void ioWrite(int offset
, int dataByte
)
899 writeFM(fmIndex
, dataByte
);
902 fmIndex
= 256 + dataByte
;
905 writeFM(fmIndex
, dataByte
);
908 mixerPrevIndex
= mixerIndex
;
909 if(!validMixerRegister(mixerPrevIndex
, 0))
910 mixerPrevIndex
|= 0x80;
911 mixerIndex
= dataByte
;
914 writeMixer(mixerIndex
, dataByte
);
917 writeMessage("SB: Resetting card.");
932 writeMessage("SB: Attempted write to port " + offset
+ ".");
938 //Do I/O read. Possible offsets are 0-7 and 10-15.
939 public int ioRead(int offset
)
945 tmp
= readFMStatus();
949 writeMessage("SB: Tried to read FM data port.");
950 return 0; //Lets do like opl.cpp does...
954 tmp
= readMixer(mixerIndex
);
960 return writeBufferStatus();
962 //This is undocumented. What it does?
966 tmp
= dspDataAvailableStatus();
976 writeMessage("SB: Attempted read from port " + offset
+ ".");
977 return 255; //Not readable.
981 public void resetCard()
986 mixerPrevIndex
= 128;
990 speakerConnected
= false;
991 dspCommandState
= DSPSTATE_WAIT_COMMAND
;
993 dmaEngineKillTransfer();
995 e2Value
= (byte)0xAA;
997 lastPCMWrite
= -2 * ACTIVITY_TIMEOUT
;
998 lastFMWrite
= -2 * ACTIVITY_TIMEOUT
;
1005 ioportRegistered
= false;
1007 fmChip
.resetCard(clock
.getTime());
1009 fmChip
.resetCard(0);
1013 private final int writeBufferStatus()
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
)
1028 if(reg
== MIXREG_MASTER
|| reg
== MIXREG_FM
|| reg
== MIXREG_CD
|| reg
== MIXREG_LINEIN
)
1030 if(reg
== MIXREG_IRQSTATUS
&& mode
>= 0)
1032 if(reg
< 0 || reg
> MIXREG_LAST
)
1034 if(reg
== MIXREG_RESET
)
1036 if(reg
== MIXREG_STATUS
)
1038 if(reg
>= MIXREG_SB16_FIRST
)
1043 //Write Mixer data register.
1044 private final void writeMixer(int reg
, int data
)
1046 if(reg
== MIXREG_IRQSELECT
) {
1047 writeIRQRegister(data
);
1050 if(reg
== MIXREG_DMASELECT
) {
1051 writeDMARegister(data
);
1054 if(reg
== MIXREG_RESET
) {
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());
1064 if(reg
== MIXREG_MIC
) {
1065 mixerRegisters
[MIXER_MIC
] = (data
& 0x07) << 5;
1068 if(reg
== MIXREG_OUTPUT_CONTROL
) {
1069 mixerRegisters
[MIXER_OUTPUT_CONTROL
] = data
;
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());
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());
1084 if(reg
== MIXREG_CD
) {
1085 mixerRegisters
[MIXER_CD_LEFT
] = (data
& 0xF0) | 0x08;
1086 mixerRegisters
[MIXER_CD_RIGHT
] = ((data
& 0xF) << 4) | 0x08;
1089 if(reg
== MIXREG_LINEIN
) {
1090 mixerRegisters
[MIXER_LINEIN_LEFT
] = (data
& 0xF0) | 0x08;
1091 mixerRegisters
[MIXER_LINEIN_RIGHT
] = ((data
& 0xF) << 4) | 0x08;
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;
1160 recomputeVolume(clock
.getTime());
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());
1200 private final int dspRead()
1202 int value
= dspOutput
[0];
1203 if(dspOutputUsed
> 1)
1204 System
.arraycopy(dspOutput
, 1, dspOutput
, 0, dspOutputUsed
- 1);
1209 //Write FM synth #1 data register.
1210 private final void writeFM(int reg
, int data
)
1212 long ts
= clock
.getTime();
1215 fmChip
.write(ts
, reg
, data
);
1219 //Write to reset register.
1220 private final void doReset(int resetValue
)
1223 dspOutput
[0] = 0xAA;
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
;
1235 if(dspNextAttention
< nextTime
)
1236 nextTime
= dspNextAttention
;
1237 long tmp
= fmChip
.nextAttention(ts
);
1240 if(nextTime
!= TIME_NEVER
) {
1242 timer
.setExpiry(nextTime
);
1248 //Recompute value for timer expiry, setting DSP timer expiry.
1249 private final void updateTimer(long dspExpiry
)
1251 dspNextAttention
= dspExpiry
;
1255 public void callback()
1257 long timeNow
= clock
.getTime();
1258 boolean runAny
= true;
1261 if((lastPCMWrite
>= 0 && timeNow
>= lastPCMWrite
+ ACTIVITY_TIMEOUT
) ||
1262 (lastFMWrite
>= 0 && timeNow
>= lastFMWrite
+ ACTIVITY_TIMEOUT
)) {
1266 if(dspNextAttention
<= timeNow
) {
1267 dspAttention(dspNextAttention
);
1270 long tmp
= fmChip
.nextAttention(clock
.getTime());
1271 if(tmp
<= timeNow
) {
1272 fmChip
.attention(clock
.getTime());
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
)
1297 return "UNKNOWN(" + mode
+ ")";
1300 private final String
interpretFormat(int 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";
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();
1337 samplesLeft
= origSamplesLeft
= samples
;
1338 soundFormat
= format
;
1339 stereo
= stereoFlag
;
1341 partialSampleBytes
= 0;
1342 wholeSampleBytes
= 0;
1344 byteBufferSamples
= 0;
1346 nextSampleTime
= timeNow
;
1347 updateTimer(nextSampleTime
);
1348 writeMessage("SBDSP: Starting DMA: mode=" + interpretMode(mode
) + " samples=" + samples
+ " format=" +
1349 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.");
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()
1380 updateTimer(TIME_NEVER
);
1381 writeMessage("SBDSP: Pausing DMA transfer.");
1385 private final void dmaEnginePauseTransfer(int samples
)
1388 dmaPauseLeft
= samples
;
1389 writeMessage("SBDSP: Pausing DMA transfer for " + samples
+ " samples.");
1393 private final void dmaEngineContinueTransfer()
1396 nextSampleTime
= clock
.getTime();
1397 updateTimer(nextSampleTime
);
1398 writeMessage("SBDSP: Continuing DMA transfer.");
1402 private static final boolean is16Bit(int 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
:
1415 //Ok, one sample down. Handle us to be recalled if needed.
1416 private final void dmaEngineNextSample()
1418 //Clear remainants of preseent sample.
1420 partialSampleBytes
= 0;
1421 wholeSampleBytes
= 0;
1423 if(dmaPaused
&& dmaPauseLeft
> 0) {
1425 if(dmaPauseLeft
== 0) {
1426 writeMessage("SBDSP: Continuing DMA transfer after timed pause.");
1433 if(dmaState
== DMA_NONE
|| dmaPaused
) {
1435 writeMessage("Halting paused transfer.");
1436 updateTimer(TIME_NEVER
);
1442 samplesLeft
-= (stereo ?
2 : 1);
1444 if(samplesLeft
<= 0) {
1446 if(is16Bit(soundFormat
))
1450 dspProgramNextDMA();
1451 if(dmaState
== DMA_CONTINUOUS
) {
1452 writeMessage("SBDSP: DMA transfer auto-reinitialized.");
1453 samplesLeft
= origSamplesLeft
;
1456 writeMessage("SBDSP: DMA transfer ended.");
1457 dmaState
= DMA_NONE
;
1458 updateTimer(TIME_NEVER
);
1464 long timeNow
= clock
.getTime();
1465 long ist
= interSampleTime
;
1466 //Some modes output at half rate in stereo mode.
1467 if(stereo
&& istStereoAdjust
)
1469 if(dmaRequestTime
== timeNow
) {
1470 //Timely, schedule by supposed time.
1471 nextSampleTime
= nextSampleTime
+ ist
;
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
) {
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
;
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
)
1527 //DMA will set next attention.
1528 updateTimer(TIME_NEVER
);
1530 //Update DREQ if not requested yet.
1534 switch(soundFormat
) {
1535 case SNDFMT_8BIT_PCM_SIGNED
:
1536 case SNDFMT_8BIT_PCM_UNSIGNED
:
1537 bytes
+= (stereo ?
2 : 1);
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);
1545 case SNDFMT_2BIT_ADPCM
:
1546 case SNDFMT_26BIT_ADPCM
:
1547 case SNDFMT_4BIT_ADPCM
:
1548 //ADPCM is always mono.
1549 if(byteBufferSamples
== 0)
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);
1561 partialSampleBytes
= 0;
1564 wholeSampleBytes
= bytes
;
1565 dmaEngineUpdateDMADREQ();
1567 //The DMA engine can't handle requests for 0 bytes, so call sample available
1568 //immediately to keep the loop running.
1569 dmaEngineSampleAvailable();
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
--;
1593 private final int nonRefFormatFor(int 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
;
1607 private final boolean hasReference(int fmt
)
1610 case SNDFMT_2BIT_ADPCM_REF
:
1611 case SNDFMT_26BIT_ADPCM_REF
:
1612 case SNDFMT_4BIT_ADPCM_REF
:
1619 private final int byteBufferSamplesADPCM(int fmt
)
1622 case SNDFMT_2BIT_ADPCM
:
1624 case SNDFMT_26BIT_ADPCM
:
1626 case SNDFMT_4BIT_ADPCM
:
1634 private final void dmaEngineSampleAvailable()
1636 int sampleL
= 0, sampleR
= 0;
1638 long timeNow
= clock
.getTime();
1641 //There's no data in DMA paused mode. Just schedule next sample.
1643 dmaEngineNextSample();
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);
1673 case SNDFMT_26BIT_ADPCM
:
1674 dmaEngineADPCMDecode((byteBuffer
>>> 5) & 7);
1675 byteBuffer
= byteBuffer
<< 3;
1676 byteBufferSamples
--;
1677 sampleL
= sampleR
= 256 * (adpcmReference
- 128);
1679 case SNDFMT_4BIT_ADPCM
:
1680 dmaEngineADPCMDecode((byteBuffer
>>> 4) & 0xF);
1681 byteBuffer
= byteBuffer
<< 4;
1682 byteBufferSamples
--;
1683 sampleL
= sampleR
= 256 * (adpcmReference
- 128);
1685 case SNDFMT_8BIT_PCM_UNSIGNED
:
1687 case SNDFMT_8BIT_PCM_SIGNED
:
1688 //Let's exploit integer overflows!
1689 sampleL
= 256 * extractBufferByte();
1691 sampleR
= 256 * extractBufferByte();
1695 case SNDFMT_16BIT_PCM_LE_UNSIGNED
:
1697 case SNDFMT_16BIT_PCM_LE_SIGNED
:
1698 //Let's exploit integer overflows!
1699 sampleL
= extractBufferByte();
1700 sampleL
|= (extractBufferByte() << 8);
1702 sampleR
= extractBufferByte();
1703 sampleR
|= (extractBufferByte() << 8);
1707 case SNDFMT_16BIT_PCM_BE_UNSIGNED
:
1709 case SNDFMT_16BIT_PCM_BE_SIGNED
:
1710 //Let's exploit integer overflows!
1711 sampleL
= (extractBufferByte() << 8);
1712 sampleL
|= extractBufferByte();
1714 sampleR
= (extractBufferByte() << 8);
1715 sampleR
|= extractBufferByte();
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
) {
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
;
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
;
1744 case DSPCMD_SC_ADPCM_2
:
1745 dspArgumentRegister
= 2;
1746 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
1748 case DSPCMD_SC_ADPCM_2_REF
:
1749 dspArgumentRegister
= 3;
1750 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
1752 case DSPCMD_SC_ADPCM_26
:
1753 dspArgumentRegister
= 4;
1754 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
1756 case DSPCMD_SC_ADPCM_26_REF
:
1757 dspArgumentRegister
= 5;
1758 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
1760 case DSPCMD_SC_ADPCM_4
:
1761 dspArgumentRegister
= 6;
1762 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
1764 case DSPCMD_SC_ADPCM_4_REF
:
1765 dspArgumentRegister
= 7;
1766 dspCommandState
= DSPSTATE_OLDDMA_LOW
;
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
;
1779 case DSPCMD_DIRECT_DAC
:
1780 dspCommandState
= DSPSTATE_DIRECT_DAC_SAMPLE
;
1782 case DSPCMD_SET_BLOCKSIZE
:
1783 dspCommandState
= DSPSTATE_BLOCKSIZE_LOW
;
1786 dspCommandState
= DSPSTATE_TC
;
1788 case DSPCMD_SET_INPUT_RATE
:
1789 case DSPCMD_SET_OUTPUT_RATE
:
1790 dspCommandState
= DSPSTATE_RATE_LOW
;
1792 case DSPCMD_SPEAKER_ON
:
1793 speakerConnected
= true;
1794 recomputeVolume(clock
.getTime());
1796 case DSPCMD_SPEAKER_OFF
:
1797 speakerConnected
= false;
1798 recomputeVolume(clock
.getTime());
1800 case DSPCMD_SPEAKER_STATUS
:
1801 if(speakerConnected
)
1806 case DSPCMD_PAUSE_DMA
:
1807 case DSPCMD_PAUSE_DMA_16
:
1808 dmaEnginePauseTransfer();
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();
1816 case DSPCMD_SILENCE
:
1817 dspCommandState
= DSPSTATE_SILENCE_LOW
;
1818 dspArgumentRegister
= 0;
1820 case DSPCMD_EXIT_DMA
:
1821 case DSPCMD_EXIT_DMA_16
:
1822 dmaEngineEndTransfer();
1824 case DSPCMD_DSP_IDENTIFY
:
1825 dspCommandState
= DSPSTATE_IDWRITE
;
1827 case DSPCMD_DSP_VERSION
:
1829 dspOutputPut((DSP_VERSION
>>> 8) & 0xFF);
1830 dspOutputPut(DSP_VERSION
& 0xFF);
1832 case DSPCMD_DMA_IDENTIFY
:
1833 dspCommandState
= DSPSTATE_DMA_IDENTIFY
;
1835 case DSPCMD_COPYRIGHT
:
1837 for(int k
= 0; k
< copyright
.length(); k
++)
1838 dspOutputPut((int)copyright
.charAt(k
));
1840 case DSPCMD_WRITE_TEST
:
1841 dspCommandState
= DSPSTATE_TESTWRITE
;
1843 case DSPCMD_READ_TEST
:
1845 dspOutputPut(dspLastCommand
);
1847 case DSPCMD_RAISE_8BIT_IRQ
:
1850 case DSPCMD_UNDOCUMENTED1
:
1851 //Weird undocumented command.
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();
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
) {
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
);
1927 e2Value
+= (byte)(1 << i
);
1930 e2Value
+= E2_MAGIC
[e2Count
% 4];
1931 writeMessage("Sending DMA identification " + e2Value
+ ".");
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()
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
);
1959 case 1: //8 Bits, Auto-init.
1960 dmaEngineStartTransfer(DMA_CONTINUOUS
, samples
, SNDFMT_8BIT_PCM_UNSIGNED
, oldStereoFlag
);
1962 case 2: //2 Bit ADPCM, single cycle.
1963 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_2BIT_ADPCM
, false);
1965 case 3: //2 Bit ADPCM, single cycle, reference.
1966 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_2BIT_ADPCM_REF
, false);
1968 case 4: //2.6 Bit ADPCM, single cycle.
1969 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_26BIT_ADPCM
, false);
1971 case 5: //2.6 Bit ADPCM, single cycle, reference.
1972 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_26BIT_ADPCM_REF
, false);
1974 case 6: //4 Bit ADPCM, single cycle.
1975 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_4BIT_ADPCM
, false);
1977 case 7: //4 Bit ADPCM, single cycle, reference.
1978 dmaEngineStartTransfer(DMA_SINGLE
, samples
, SNDFMT_4BIT_ADPCM_REF
, false);
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
);
1991 dmaEngineStartTransfer(mode
, samples
, SNDFMT_16BIT_PCM_LE_SIGNED
, stereoFlag
);
1993 dmaEngineStartTransfer(mode
, samples
, SNDFMT_16BIT_PCM_LE_UNSIGNED
, stereoFlag
);
1996 dmaEngineStartTransfer(mode
, samples
, SNDFMT_8BIT_PCM_SIGNED
, stereoFlag
);
1998 dmaEngineStartTransfer(mode
, samples
, SNDFMT_8BIT_PCM_UNSIGNED
, stereoFlag
);
2000 writeMessage("Trying to program unknown DMA mode " + dspNextDMA
+ ".");
2002 //DMA command processed.
2006 private final void dmaEngineADPCMDecode(int sample
)
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);
2036 byte adjust
= levelShift
[sample
];
2037 if((index
== 0 && adjust
< 0) || (index
== scaleMax
&& adjust
> 0))
2039 adpcmScale
+= adjust
;
2041 adpcmReference
+= (levelMult
[index
] * sampleMult
[sample
] / ((index
== 0) ?
2 : 1));
2042 if(adpcmReference
< 0)
2044 if(adpcmReference
> 255)
2045 adpcmReference
= 255;
2051 STATUS_FM_synth
= "offline";
2052 STATUS_PCM_DAC
= "offline";
2053 STATUS_PCM_DMA
= "offline";
2054 STATUS_PCM_DMA_paused
= "no";
2057 long ts
= clock
.getTime();
2058 if(ts
< lastFMWrite
+ ACTIVITY_TIMEOUT
)
2059 STATUS_FM_synth
= "online";
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
;
2070 STATUS_PCM_DAC
= "offline";
2071 lastPCMWrite
= -2 * ACTIVITY_TIMEOUT
;
2073 if(dmaState
!= DMA_NONE
&& !dmaPaused
)
2074 STATUS_PCM_DMA
= "online";
2076 STATUS_PCM_DMA
= "offline";
2077 if(dmaState
!= DMA_NONE
&& dmaPaused
)
2078 STATUS_PCM_DMA_paused
= "yes";
2080 STATUS_PCM_DMA_paused
= "no";