ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/audio.cpp
Revision: 1.1
Committed: 1999-10-03T14:16:25Z (25 years, 1 month ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * audio.cpp - Audio support
3     *
4     * Basilisk II (C) 1997-1999 Christian Bauer
5     * Portions (C) 1997-1999 Marc Hellwig
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
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.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     /*
23     * SEE ALSO
24     * Inside Macintosh: Sound, chapter 5 "Sound Components"
25     */
26    
27     #include "sysdeps.h"
28     #include "cpu_emulation.h"
29     #include "macos_util.h"
30     #include "emul_op.h"
31     #include "main.h"
32     #include "audio.h"
33     #include "audio_defs.h"
34    
35     #define DEBUG 0
36     #include "debug.h"
37    
38    
39     // Global variables
40     struct audio_status AudioStatus; // Current audio status (sample rate etc.)
41     bool audio_open = false; // Flag: audio is initialized and ready
42     int audio_frames_per_block; // Number of audio frames per block
43     uint32 audio_component_flags; // Component feature flags
44     uint32 audio_data = 0; // Mac address of global data area
45     static int open_count = 0; // Open/close nesting count
46    
47     bool AudioAvailable = false; // Flag: audio output available (from the software point of view)
48    
49    
50     /*
51     * Get audio info
52     */
53    
54     static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
55     {
56     D(bug(" AudioGetInfo %c%c%c%c, infoPtr %08lx, source ID %08lx\n", selector >> 24, (selector >> 16) & 0xff, (selector >> 8) & 0xff, selector & 0xff, infoPtr, sourceID));
57     M68kRegisters r;
58     int i;
59    
60     switch (selector) {
61     case siSampleSize:
62     WriteMacInt16(infoPtr, AudioStatus.sample_size);
63     break;
64    
65     case siSampleSizeAvailable: {
66     r.d[0] = audio_num_sample_sizes * 2;
67     Execute68kTrap(0xa122, &r); // NewHandle()
68     uint32 h = r.a[0];
69     if (h == 0)
70     return memFullErr;
71     WriteMacInt16(infoPtr + sil_count, audio_num_sample_sizes);
72     WriteMacInt32(infoPtr + sil_infoHandle, h);
73     uint32 sp = ReadMacInt32(h);
74     for (i=0; i<audio_num_sample_sizes; i++)
75     WriteMacInt16(sp + i*2, audio_sample_sizes[i]);
76     break;
77     }
78    
79     case siNumberChannels:
80     WriteMacInt16(infoPtr, AudioStatus.channels);
81     break;
82    
83     case siChannelAvailable: {
84     r.d[0] = audio_num_channel_counts * 2;
85     Execute68kTrap(0xa122, &r); // NewHandle()
86     uint32 h = r.a[0];
87     if (h == 0)
88     return memFullErr;
89     WriteMacInt16(infoPtr + sil_count, audio_num_channel_counts);
90     WriteMacInt32(infoPtr + sil_infoHandle, h);
91     uint32 sp = ReadMacInt32(h);
92     for (i=0; i<audio_num_channel_counts; i++)
93     WriteMacInt16(sp + i*2, audio_channel_counts[i]);
94     break;
95     }
96    
97     case siSampleRate:
98     WriteMacInt32(infoPtr, AudioStatus.sample_rate);
99     break;
100    
101     case siSampleRateAvailable: {
102     r.d[0] = audio_num_sample_rates * 4;
103     Execute68kTrap(0xa122, &r); // NewHandle()
104     uint32 h = r.a[0];
105     if (h == 0)
106     return memFullErr;
107     WriteMacInt16(infoPtr + sil_count, audio_num_sample_rates);
108     WriteMacInt32(infoPtr + sil_infoHandle, h);
109     uint32 lp = ReadMacInt32(h);
110     for (i=0; i<audio_num_sample_rates; i++)
111     WriteMacInt32(lp + i*4, audio_sample_rates[i]);
112     break;
113     }
114    
115     case siSpeakerMute:
116     WriteMacInt16(infoPtr, audio_get_main_mute());
117     break;
118    
119     case siSpeakerVolume:
120     WriteMacInt32(infoPtr, audio_get_main_volume());
121     break;
122    
123     case siHardwareMute:
124     WriteMacInt16(infoPtr, audio_get_dac_mute());
125     break;
126    
127     case siHardwareVolume:
128     WriteMacInt32(infoPtr, audio_get_dac_volume());
129     break;
130    
131     case siHardwareBusy:
132     WriteMacInt16(infoPtr, AudioStatus.num_sources != 0);
133     break;
134    
135     case siHardwareVolumeSteps:
136     WriteMacInt16(infoPtr, 64);
137     break;
138    
139     default: // Delegate to Apple Mixer
140     if (AudioStatus.mixer == 0)
141     return badComponentSelector;
142     M68kRegisters r;
143     r.a[0] = infoPtr;
144     r.d[0] = selector;
145     r.a[1] = sourceID;
146     r.a[2] = AudioStatus.mixer;
147     Execute68k(audio_data + adatGetInfo, &r);
148     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
149     return r.d[0];
150     }
151     return noErr;
152     }
153    
154    
155     /*
156     * Set audio info
157     */
158    
159     static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
160     {
161     D(bug(" AudioSetInfo %c%c%c%c, infoPtr %08lx, source ID %08lx\n", selector >> 24, (selector >> 16) & 0xff, (selector >> 8) & 0xff, selector & 0xff, infoPtr, sourceID));
162     M68kRegisters r;
163     int i;
164    
165     switch (selector) {
166     case siSampleSize:
167     D(bug(" set sample size %08lx\n", infoPtr));
168     if (AudioStatus.num_sources)
169     return siDeviceBusyErr;
170     for (i=0; i<audio_num_sample_sizes; i++)
171     if (audio_sample_sizes[i] == infoPtr) {
172     audio_set_sample_size(i);
173     return noErr;
174     }
175     return siInvalidSampleSize;
176    
177     case siSampleRate:
178     D(bug(" set sample rate %08lx\n", infoPtr));
179     if (AudioStatus.num_sources)
180     return siDeviceBusyErr;
181     for (i=0; i<audio_num_sample_rates; i++)
182     if (audio_sample_rates[i] == infoPtr) {
183     audio_set_sample_rate(i);
184     return noErr;
185     }
186     return siInvalidSampleRate;
187    
188     case siNumberChannels:
189     D(bug(" set number of channels %08lx\n", infoPtr));
190     if (AudioStatus.num_sources)
191     return siDeviceBusyErr;
192     for (i=0; i<audio_num_channel_counts; i++)
193     if (audio_channel_counts[i] == infoPtr) {
194     audio_set_channels(i);
195     return noErr;
196     }
197     return badChannel;
198    
199     case siSpeakerMute:
200     audio_set_main_mute((uint16)infoPtr);
201     break;
202    
203     case siSpeakerVolume:
204     D(bug(" set speaker volume %08lx\n", infoPtr));
205     audio_set_main_volume(infoPtr);
206     break;
207    
208     case siHardwareMute:
209     audio_set_dac_mute((uint16)infoPtr);
210     break;
211    
212     case siHardwareVolume:
213     D(bug(" set hardware volume %08lx\n", infoPtr));
214     audio_set_dac_volume(infoPtr);
215     break;
216    
217     default: // Delegate to Apple Mixer
218     if (AudioStatus.mixer == 0)
219     return badComponentSelector;
220     r.a[0] = infoPtr;
221     r.d[0] = selector;
222     r.a[1] = sourceID;
223     r.a[2] = AudioStatus.mixer;
224     Execute68k(audio_data + adatSetInfo, &r);
225     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
226     return r.d[0];
227     }
228     return noErr;
229     }
230    
231    
232     /*
233     * Sound output component dispatch
234     */
235    
236     int32 AudioDispatch(uint32 params, uint32 globals)
237     {
238     D(bug("AudioDispatch params %08lx (size %d), what %d\n", params, ReadMacInt8(params + cp_paramSize), (int16)ReadMacInt16(params + cp_what)));
239     M68kRegisters r;
240     uint32 p = params + cp_params;
241    
242     switch ((int16)ReadMacInt16(params + cp_what)) {
243     // Basic component functions
244     case kComponentOpenSelect:
245     if (audio_data == 0) {
246    
247     // Allocate global data area
248     r.d[0] = SIZEOF_adat;
249     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
250     if (r.a[0] == 0)
251     return memFullErr;
252     audio_data = r.a[0];
253     D(bug(" global data at %08lx\n", audio_data));
254    
255     // Put in 68k routines
256     int p = audio_data + adatDelegateCall;
257     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
258     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
259     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
260     WriteMacInt16(p, 0x7024); p += 2; // moveq #$24,d0
261     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
262     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
263     WriteMacInt16(p, M68K_RTS); p += 2; // rts
264     if (p - audio_data != adatOpenMixer)
265     goto adat_error;
266     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
267     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
268     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
269     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
270     WriteMacInt16(p, 0x203c); p += 2; // move.l #$06140018,d0
271     WriteMacInt32(p, 0x06140018); p+= 4;
272     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
273     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
274     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
275     WriteMacInt16(p, M68K_RTS); p += 2; // rts
276     if (p - audio_data != adatCloseMixer)
277     goto adat_error;
278     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
279     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
280     WriteMacInt16(p, 0x203c); p += 2; // move.l #$02180018,d0
281     WriteMacInt32(p, 0x02180018); p+= 4;
282     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
283     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
284     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
285     WriteMacInt16(p, M68K_RTS); p += 2; // rts
286     if (p - audio_data != adatGetInfo)
287     goto adat_error;
288     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
289     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
290     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
291     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
292     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
293     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0103,-(sp)
294     WriteMacInt32(p, 0x000c0103); p+= 4;
295     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
296     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
297     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
298     WriteMacInt16(p, M68K_RTS); p += 2; // rts
299     if (p - audio_data != adatSetInfo)
300     goto adat_error;
301     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
302     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
303     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
304     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
305     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
306     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0104,-(sp)
307     WriteMacInt32(p, 0x000c0104); p+= 4;
308     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
309     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
310     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
311     WriteMacInt16(p, M68K_RTS); p += 2; // rts
312     if (p - audio_data != adatPlaySourceBuffer)
313     goto adat_error;
314     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
315     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
316     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
317     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
318     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
319     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0108,-(sp)
320     WriteMacInt32(p, 0x000c0108); p+= 4;
321     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
322     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
323     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
324     WriteMacInt16(p, M68K_RTS); p += 2; // rts
325     if (p - audio_data != adatGetSourceData)
326     goto adat_error;
327     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
328     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
329     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
330     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$00040004,-(sp)
331     WriteMacInt32(p, 0x00040004); p+= 4;
332     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
333     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
334     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
335     WriteMacInt16(p, M68K_RTS); p += 2; // rts
336     if (p - audio_data != adatData)
337     goto adat_error;
338     }
339     AudioAvailable = true;
340     if (open_count == 0)
341     audio_enter_stream();
342     open_count++;
343     return noErr;
344    
345     adat_error: printf("FATAL: audio component data block initialization error\n");
346     QuitEmulator();
347     return openErr;
348    
349     case kComponentCanDoSelect:
350     case kComponentRegisterSelect:
351     return noErr;
352    
353     case kComponentVersionSelect:
354     return 0x00010002;
355    
356     case kComponentCloseSelect:
357     open_count--;
358     if (open_count == 0) {
359     if (AudioStatus.mixer) {
360     // Close Apple Mixer
361     r.a[0] = AudioStatus.mixer;
362     Execute68k(audio_data + adatCloseMixer, &r);
363     AudioStatus.mixer = 0;
364     return r.d[0];
365     }
366     AudioStatus.num_sources = 0;
367     audio_exit_stream();
368     }
369     return noErr;
370    
371     // Sound component functions
372     case kSoundComponentInitOutputDeviceSelect:
373     D(bug(" InitOutputDevice\n"));
374     if (!audio_open)
375     return noHardwareErr;
376     if (AudioStatus.mixer)
377     return noErr;
378    
379     // Init sound component data
380     WriteMacInt32(audio_data + adatData + scd_flags, 0);
381     WriteMacInt32(audio_data + adatData + scd_format, AudioStatus.sample_size == 16 ? 'twos' : 'raw ');
382     WriteMacInt16(audio_data + adatData + scd_numChannels, AudioStatus.channels);
383     WriteMacInt16(audio_data + adatData + scd_sampleSize, AudioStatus.sample_size);
384     WriteMacInt32(audio_data + adatData + scd_sampleRate, AudioStatus.sample_rate);
385     WriteMacInt32(audio_data + adatData + scd_sampleCount, audio_frames_per_block);
386     WriteMacInt32(audio_data + adatData + scd_buffer, 0);
387     WriteMacInt32(audio_data + adatData + scd_reserved, 0);
388     WriteMacInt32(audio_data + adatStreamInfo, 0);
389    
390     // Open Apple Mixer
391     r.a[0] = audio_data + adatMixer;
392     r.d[0] = 0;
393     r.a[1] = audio_data + adatData;
394     Execute68k(audio_data + adatOpenMixer, &r);
395     AudioStatus.mixer = ReadMacInt32(audio_data + adatMixer);
396     D(bug(" OpenMixer() returns %08lx, mixer %08lx\n", r.d[0], AudioStatus.mixer));
397     return r.d[0];
398    
399     case kSoundComponentAddSourceSelect:
400     D(bug(" AddSource\n"));
401     AudioStatus.num_sources++;
402     goto delegate;
403    
404     case kSoundComponentRemoveSourceSelect:
405     D(bug(" RemoveSource\n"));
406     AudioStatus.num_sources--;
407     goto delegate;
408    
409     case kSoundComponentStopSourceSelect:
410     D(bug(" StopSource\n"));
411     goto delegate;
412    
413     case kSoundComponentPauseSourceSelect:
414     D(bug(" PauseSource\n"));
415     delegate: // Delegate call to Apple Mixer
416     D(bug(" delegating call to Apple Mixer\n"));
417     r.a[0] = AudioStatus.mixer;
418     r.a[1] = params;
419     Execute68k(audio_data + adatDelegateCall, &r);
420     D(bug(" returns %08lx\n", r.d[0]));
421     return r.d[0];
422    
423     case kSoundComponentStartSourceSelect:
424     D(bug(" StartSource\n"));
425     return noErr;
426    
427     case kSoundComponentGetInfoSelect:
428     return AudioGetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
429    
430     case kSoundComponentSetInfoSelect:
431     return AudioSetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
432    
433     case kSoundComponentPlaySourceBufferSelect:
434     D(bug(" PlaySourceBuffer\n"));
435     r.d[0] = ReadMacInt32(p);
436     r.a[0] = ReadMacInt32(p + 4);
437     r.a[1] = ReadMacInt32(p + 8);
438     r.a[2] = AudioStatus.mixer;
439     Execute68k(audio_data + adatPlaySourceBuffer, &r);
440     D(bug(" returns %08lx\n", r.d[0]));
441     return r.d[0];
442    
443     default:
444     return badComponentSelector;
445     }
446     }