ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/audio.cpp
Revision: 1.9
Committed: 2001-07-11T19:26:13Z (22 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.8: +6 -8 lines
Log Message:
fixed a couple of compiler warnings

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * audio.cpp - Audio support
3     *
4 cebix 1.7 * Basilisk II (C) 1997-2001 Christian Bauer
5 cebix 1.1 * 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 cebix 1.8 // Supported sample rates, sizes and channels
40     vector<uint32> audio_sample_rates;
41     vector<uint16> audio_sample_sizes;
42     vector<uint16> audio_channel_counts;
43    
44 cebix 1.1 // Global variables
45     struct audio_status AudioStatus; // Current audio status (sample rate etc.)
46     bool audio_open = false; // Flag: audio is initialized and ready
47     int audio_frames_per_block; // Number of audio frames per block
48     uint32 audio_component_flags; // Component feature flags
49     uint32 audio_data = 0; // Mac address of global data area
50     static int open_count = 0; // Open/close nesting count
51    
52     bool AudioAvailable = false; // Flag: audio output available (from the software point of view)
53    
54    
55     /*
56 cebix 1.4 * Reset audio emulation
57     */
58    
59     void AudioReset(void)
60     {
61     audio_data = 0;
62     }
63    
64    
65     /*
66 cebix 1.1 * Get audio info
67     */
68    
69     static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
70     {
71     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));
72     M68kRegisters r;
73    
74     switch (selector) {
75     case siSampleSize:
76     WriteMacInt16(infoPtr, AudioStatus.sample_size);
77     break;
78    
79     case siSampleSizeAvailable: {
80 cebix 1.8 r.d[0] = audio_sample_sizes.size() * 2;
81 cebix 1.1 Execute68kTrap(0xa122, &r); // NewHandle()
82     uint32 h = r.a[0];
83     if (h == 0)
84     return memFullErr;
85 cebix 1.8 WriteMacInt16(infoPtr + sil_count, audio_sample_sizes.size());
86 cebix 1.1 WriteMacInt32(infoPtr + sil_infoHandle, h);
87     uint32 sp = ReadMacInt32(h);
88 cebix 1.9 for (unsigned i=0; i<audio_sample_sizes.size(); i++)
89 cebix 1.1 WriteMacInt16(sp + i*2, audio_sample_sizes[i]);
90     break;
91     }
92    
93     case siNumberChannels:
94     WriteMacInt16(infoPtr, AudioStatus.channels);
95     break;
96    
97     case siChannelAvailable: {
98 cebix 1.8 r.d[0] = audio_channel_counts.size() * 2;
99 cebix 1.1 Execute68kTrap(0xa122, &r); // NewHandle()
100     uint32 h = r.a[0];
101     if (h == 0)
102     return memFullErr;
103 cebix 1.8 WriteMacInt16(infoPtr + sil_count, audio_channel_counts.size());
104 cebix 1.1 WriteMacInt32(infoPtr + sil_infoHandle, h);
105     uint32 sp = ReadMacInt32(h);
106 cebix 1.9 for (unsigned i=0; i<audio_channel_counts.size(); i++)
107 cebix 1.1 WriteMacInt16(sp + i*2, audio_channel_counts[i]);
108     break;
109     }
110    
111     case siSampleRate:
112     WriteMacInt32(infoPtr, AudioStatus.sample_rate);
113     break;
114    
115     case siSampleRateAvailable: {
116 cebix 1.8 r.d[0] = audio_sample_rates.size() * 4;
117 cebix 1.1 Execute68kTrap(0xa122, &r); // NewHandle()
118     uint32 h = r.a[0];
119     if (h == 0)
120     return memFullErr;
121 cebix 1.8 WriteMacInt16(infoPtr + sil_count, audio_sample_rates.size());
122 cebix 1.1 WriteMacInt32(infoPtr + sil_infoHandle, h);
123     uint32 lp = ReadMacInt32(h);
124 cebix 1.9 for (unsigned i=0; i<audio_sample_rates.size(); i++)
125 cebix 1.1 WriteMacInt32(lp + i*4, audio_sample_rates[i]);
126     break;
127     }
128    
129     case siSpeakerMute:
130 cebix 1.2 WriteMacInt16(infoPtr, audio_get_speaker_mute());
131 cebix 1.1 break;
132    
133     case siSpeakerVolume:
134 cebix 1.2 WriteMacInt32(infoPtr, audio_get_speaker_volume());
135     break;
136    
137     case siHeadphoneMute:
138     WriteMacInt16(infoPtr, 0);
139     break;
140    
141     case siHeadphoneVolume:
142     WriteMacInt32(infoPtr, 0x01000100);
143     break;
144    
145     case siHeadphoneVolumeSteps:
146     WriteMacInt16(infoPtr, 13);
147 cebix 1.1 break;
148    
149     case siHardwareMute:
150 cebix 1.2 WriteMacInt16(infoPtr, audio_get_main_mute());
151 cebix 1.1 break;
152    
153     case siHardwareVolume:
154 cebix 1.2 WriteMacInt32(infoPtr, audio_get_main_volume());
155     break;
156    
157     case siHardwareVolumeSteps:
158     WriteMacInt16(infoPtr, 13);
159 cebix 1.1 break;
160    
161     case siHardwareBusy:
162     WriteMacInt16(infoPtr, AudioStatus.num_sources != 0);
163     break;
164    
165     default: // Delegate to Apple Mixer
166     if (AudioStatus.mixer == 0)
167     return badComponentSelector;
168     M68kRegisters r;
169     r.a[0] = infoPtr;
170     r.d[0] = selector;
171     r.a[1] = sourceID;
172     r.a[2] = AudioStatus.mixer;
173     Execute68k(audio_data + adatGetInfo, &r);
174     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
175     return r.d[0];
176     }
177     return noErr;
178     }
179    
180    
181     /*
182     * Set audio info
183     */
184    
185     static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
186     {
187     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));
188     M68kRegisters r;
189    
190     switch (selector) {
191     case siSampleSize:
192     D(bug(" set sample size %08lx\n", infoPtr));
193     if (AudioStatus.num_sources)
194     return siDeviceBusyErr;
195 cebix 1.8 if (infoPtr == AudioStatus.sample_size)
196     return noErr;
197 cebix 1.9 for (unsigned i=0; i<audio_sample_sizes.size(); i++)
198 cebix 1.1 if (audio_sample_sizes[i] == infoPtr) {
199 cebix 1.8 if (audio_set_sample_size(i))
200     return noErr;
201     else
202     return siInvalidSampleSize;
203 cebix 1.1 }
204     return siInvalidSampleSize;
205    
206     case siSampleRate:
207     D(bug(" set sample rate %08lx\n", infoPtr));
208     if (AudioStatus.num_sources)
209     return siDeviceBusyErr;
210 cebix 1.8 if (infoPtr == AudioStatus.sample_rate)
211     return noErr;
212 cebix 1.9 for (unsigned i=0; i<audio_sample_rates.size(); i++)
213 cebix 1.1 if (audio_sample_rates[i] == infoPtr) {
214 cebix 1.8 if (audio_set_sample_rate(i))
215     return noErr;
216     else
217     return siInvalidSampleRate;
218 cebix 1.1 }
219     return siInvalidSampleRate;
220    
221     case siNumberChannels:
222     D(bug(" set number of channels %08lx\n", infoPtr));
223     if (AudioStatus.num_sources)
224     return siDeviceBusyErr;
225 cebix 1.8 if (infoPtr == AudioStatus.channels)
226     return noErr;
227 cebix 1.9 for (unsigned i=0; i<audio_channel_counts.size(); i++)
228 cebix 1.1 if (audio_channel_counts[i] == infoPtr) {
229 cebix 1.8 if (audio_set_channels(i))
230     return noErr;
231     else
232     return badChannel;
233 cebix 1.1 }
234     return badChannel;
235    
236     case siSpeakerMute:
237 cebix 1.2 audio_set_speaker_mute((uint16)infoPtr);
238 cebix 1.1 break;
239    
240     case siSpeakerVolume:
241     D(bug(" set speaker volume %08lx\n", infoPtr));
242 cebix 1.2 audio_set_speaker_volume(infoPtr);
243     break;
244    
245     case siHeadphoneMute:
246     case siHeadphoneVolume:
247 cebix 1.1 break;
248    
249     case siHardwareMute:
250 cebix 1.2 audio_set_main_mute((uint16)infoPtr);
251 cebix 1.1 break;
252    
253     case siHardwareVolume:
254     D(bug(" set hardware volume %08lx\n", infoPtr));
255 cebix 1.2 audio_set_main_volume(infoPtr);
256 cebix 1.1 break;
257    
258     default: // Delegate to Apple Mixer
259     if (AudioStatus.mixer == 0)
260     return badComponentSelector;
261     r.a[0] = infoPtr;
262     r.d[0] = selector;
263     r.a[1] = sourceID;
264     r.a[2] = AudioStatus.mixer;
265     Execute68k(audio_data + adatSetInfo, &r);
266     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
267     return r.d[0];
268     }
269     return noErr;
270     }
271    
272    
273     /*
274     * Sound output component dispatch
275     */
276    
277     int32 AudioDispatch(uint32 params, uint32 globals)
278     {
279     D(bug("AudioDispatch params %08lx (size %d), what %d\n", params, ReadMacInt8(params + cp_paramSize), (int16)ReadMacInt16(params + cp_what)));
280     M68kRegisters r;
281     uint32 p = params + cp_params;
282    
283     switch ((int16)ReadMacInt16(params + cp_what)) {
284     // Basic component functions
285     case kComponentOpenSelect:
286     if (audio_data == 0) {
287    
288     // Allocate global data area
289     r.d[0] = SIZEOF_adat;
290     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
291     if (r.a[0] == 0)
292     return memFullErr;
293     audio_data = r.a[0];
294     D(bug(" global data at %08lx\n", audio_data));
295    
296     // Put in 68k routines
297     int p = audio_data + adatDelegateCall;
298     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
299     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
300     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
301     WriteMacInt16(p, 0x7024); p += 2; // moveq #$24,d0
302     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
303     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
304     WriteMacInt16(p, M68K_RTS); p += 2; // rts
305     if (p - audio_data != adatOpenMixer)
306     goto adat_error;
307     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
308     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
309     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
310     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
311     WriteMacInt16(p, 0x203c); p += 2; // move.l #$06140018,d0
312     WriteMacInt32(p, 0x06140018); p+= 4;
313     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
314     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
315     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
316     WriteMacInt16(p, M68K_RTS); p += 2; // rts
317     if (p - audio_data != adatCloseMixer)
318     goto adat_error;
319     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
320     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
321     WriteMacInt16(p, 0x203c); p += 2; // move.l #$02180018,d0
322     WriteMacInt32(p, 0x02180018); p+= 4;
323     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
324     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
325     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
326     WriteMacInt16(p, M68K_RTS); p += 2; // rts
327     if (p - audio_data != adatGetInfo)
328     goto adat_error;
329     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
330     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
331     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
332     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
333     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
334     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0103,-(sp)
335     WriteMacInt32(p, 0x000c0103); p+= 4;
336     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
337     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
338     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
339     WriteMacInt16(p, M68K_RTS); p += 2; // rts
340     if (p - audio_data != adatSetInfo)
341     goto adat_error;
342     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
343     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
344     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
345     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
346     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
347     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0104,-(sp)
348     WriteMacInt32(p, 0x000c0104); p+= 4;
349     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
350     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
351     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
352     WriteMacInt16(p, M68K_RTS); p += 2; // rts
353     if (p - audio_data != adatPlaySourceBuffer)
354     goto adat_error;
355     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
356     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
357     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
358     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
359     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
360     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0108,-(sp)
361     WriteMacInt32(p, 0x000c0108); p+= 4;
362     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
363     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
364     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
365     WriteMacInt16(p, M68K_RTS); p += 2; // rts
366     if (p - audio_data != adatGetSourceData)
367     goto adat_error;
368     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
369     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
370     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
371     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$00040004,-(sp)
372     WriteMacInt32(p, 0x00040004); p+= 4;
373     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
374     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
375     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
376     WriteMacInt16(p, M68K_RTS); p += 2; // rts
377     if (p - audio_data != adatData)
378     goto adat_error;
379     }
380     AudioAvailable = true;
381     if (open_count == 0)
382     audio_enter_stream();
383     open_count++;
384     return noErr;
385    
386     adat_error: printf("FATAL: audio component data block initialization error\n");
387     QuitEmulator();
388     return openErr;
389    
390     case kComponentCanDoSelect:
391     case kComponentRegisterSelect:
392     return noErr;
393    
394     case kComponentVersionSelect:
395 cebix 1.2 return 0x00010003;
396 cebix 1.1
397     case kComponentCloseSelect:
398     open_count--;
399     if (open_count == 0) {
400     if (AudioStatus.mixer) {
401     // Close Apple Mixer
402     r.a[0] = AudioStatus.mixer;
403     Execute68k(audio_data + adatCloseMixer, &r);
404     AudioStatus.mixer = 0;
405     return r.d[0];
406     }
407     AudioStatus.num_sources = 0;
408     audio_exit_stream();
409     }
410     return noErr;
411    
412     // Sound component functions
413     case kSoundComponentInitOutputDeviceSelect:
414     D(bug(" InitOutputDevice\n"));
415     if (!audio_open)
416     return noHardwareErr;
417     if (AudioStatus.mixer)
418     return noErr;
419    
420     // Init sound component data
421     WriteMacInt32(audio_data + adatData + scd_flags, 0);
422 cebix 1.5 WriteMacInt32(audio_data + adatData + scd_format, AudioStatus.sample_size == 16 ? FOURCC('t','w','o','s') : FOURCC('r','a','w',' '));
423 cebix 1.1 WriteMacInt16(audio_data + adatData + scd_numChannels, AudioStatus.channels);
424     WriteMacInt16(audio_data + adatData + scd_sampleSize, AudioStatus.sample_size);
425     WriteMacInt32(audio_data + adatData + scd_sampleRate, AudioStatus.sample_rate);
426     WriteMacInt32(audio_data + adatData + scd_sampleCount, audio_frames_per_block);
427     WriteMacInt32(audio_data + adatData + scd_buffer, 0);
428     WriteMacInt32(audio_data + adatData + scd_reserved, 0);
429     WriteMacInt32(audio_data + adatStreamInfo, 0);
430    
431     // Open Apple Mixer
432     r.a[0] = audio_data + adatMixer;
433     r.d[0] = 0;
434     r.a[1] = audio_data + adatData;
435     Execute68k(audio_data + adatOpenMixer, &r);
436     AudioStatus.mixer = ReadMacInt32(audio_data + adatMixer);
437     D(bug(" OpenMixer() returns %08lx, mixer %08lx\n", r.d[0], AudioStatus.mixer));
438     return r.d[0];
439    
440     case kSoundComponentAddSourceSelect:
441     D(bug(" AddSource\n"));
442     AudioStatus.num_sources++;
443     goto delegate;
444    
445     case kSoundComponentRemoveSourceSelect:
446     D(bug(" RemoveSource\n"));
447     AudioStatus.num_sources--;
448     goto delegate;
449    
450     case kSoundComponentStopSourceSelect:
451     D(bug(" StopSource\n"));
452     goto delegate;
453    
454     case kSoundComponentPauseSourceSelect:
455     D(bug(" PauseSource\n"));
456     delegate: // Delegate call to Apple Mixer
457     D(bug(" delegating call to Apple Mixer\n"));
458     r.a[0] = AudioStatus.mixer;
459     r.a[1] = params;
460     Execute68k(audio_data + adatDelegateCall, &r);
461     D(bug(" returns %08lx\n", r.d[0]));
462     return r.d[0];
463    
464     case kSoundComponentStartSourceSelect:
465     D(bug(" StartSource\n"));
466     return noErr;
467    
468     case kSoundComponentGetInfoSelect:
469     return AudioGetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
470    
471     case kSoundComponentSetInfoSelect:
472     return AudioSetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
473    
474     case kSoundComponentPlaySourceBufferSelect:
475     D(bug(" PlaySourceBuffer\n"));
476     r.d[0] = ReadMacInt32(p);
477     r.a[0] = ReadMacInt32(p + 4);
478     r.a[1] = ReadMacInt32(p + 8);
479     r.a[2] = AudioStatus.mixer;
480     Execute68k(audio_data + adatPlaySourceBuffer, &r);
481     D(bug(" returns %08lx\n", r.d[0]));
482     return r.d[0];
483    
484     default:
485     return badComponentSelector;
486     }
487     }
488 cebix 1.6
489    
490     /*
491     * Sound input driver Open() routine
492     */
493    
494     int16 SoundInOpen(uint32 pb, uint32 dce)
495     {
496     D(bug("SoundInOpen\n"));
497     return noErr;
498     }
499    
500    
501     /*
502     * Sound input driver Prime() routine
503     */
504    
505     int16 SoundInPrime(uint32 pb, uint32 dce)
506     {
507     D(bug("SoundInPrime\n"));
508     //!!
509     return paramErr;
510     }
511    
512    
513     /*
514     * Sound input driver Control() routine
515     */
516    
517     int16 SoundInControl(uint32 pb, uint32 dce)
518     {
519     uint16 code = ReadMacInt16(pb + csCode);
520     D(bug("SoundInControl %d\n", code));
521    
522     if (code == 1) {
523     D(bug(" SoundInKillIO\n"));
524     //!!
525     return noErr;
526     }
527    
528     if (code != 2)
529     return -231; // siUnknownInfoType
530    
531     uint32 *param = (uint32 *)Mac2HostAddr(pb + csParam);
532     uint32 selector = param[0];
533     D(bug(" selector %c%c%c%c\n", selector >> 24, selector >> 16, selector >> 8, selector));
534    
535     switch (selector) {
536     default:
537     return -231; // siUnknownInfoType
538     }
539     }
540    
541    
542     /*
543     * Sound input driver Status() routine
544     */
545    
546     int16 SoundInStatus(uint32 pb, uint32 dce)
547     {
548     uint16 code = ReadMacInt16(pb + csCode);
549     D(bug("SoundInStatus %d\n", code));
550     if (code != 2)
551     return -231; // siUnknownInfoType
552    
553     uint32 *param = (uint32 *)Mac2HostAddr(pb + csParam);
554     uint32 selector = param[0];
555     D(bug(" selector %c%c%c%c\n", selector >> 24, selector >> 16, selector >> 8, selector));
556     switch (selector) {
557     #if 0
558     case siDeviceName: {
559     const char *str = GetString(STR_SOUND_IN_NAME);
560     param[0] = 0;
561     memcpy((void *)param[1], str, strlen(str));
562     return noErr;
563     }
564    
565     case siDeviceIcon: {
566     M68kRegisters r;
567     static const uint16 proc[] = {
568     0x558f, // subq.l #2,sp
569     0xa994, // CurResFile
570     0x4267, // clr.w -(sp)
571     0xa998, // UseResFile
572     0x598f, // subq.l #4,sp
573     0x4879, 0x4943, 0x4e23, // move.l #'ICN#',-(sp)
574     0x3f3c, 0xbf76, // move.w #-16522,-(sp)
575     0xa9a0, // GetResource
576     0x245f, // move.l (sp)+,a2
577     0xa998, // UseResFile
578     0x200a, // move.l a2,d0
579     0x6604, // bne 1
580     0x7000, // moveq #0,d0
581     M68K_RTS,
582     0x2f0a, //1 move.l a2,-(sp)
583     0xa992, // DetachResource
584     0x204a, // move.l a2,a0
585     0xa04a, // HNoPurge
586     0x7001, // moveq #1,d0
587     M68K_RTS
588     };
589     Execute68k((uint32)proc, &r);
590     if (r.d[0]) {
591     param[0] = 4; // Length of returned data
592     param[1] = r.a[2]; // Handle to icon suite
593     return noErr;
594     } else
595     return -192; // resNotFound
596     }
597     #endif
598     default:
599     return -231; // siUnknownInfoType
600     }
601     }
602    
603    
604     /*
605     * Sound input driver Close() routine
606     */
607    
608     int16 SoundInClose(uint32 pb, uint32 dce)
609     {
610     D(bug("SoundInClose\n"));
611     return noErr;
612     }