mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-05 07:51:04 +00:00
660 lines
20 KiB
C++
660 lines
20 KiB
C++
/*
|
|
* audio.cpp - Audio support
|
|
*
|
|
* Basilisk II (C) 1997-2005 Christian Bauer
|
|
* Portions written by Marc Hellwig
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
* SEE ALSO
|
|
* Inside Macintosh: Sound, chapter 5 "Sound Components"
|
|
*/
|
|
|
|
#include "sysdeps.h"
|
|
#include "cpu_emulation.h"
|
|
#include "macos_util.h"
|
|
#include "emul_op.h"
|
|
#include "main.h"
|
|
#include "audio.h"
|
|
#include "audio_defs.h"
|
|
|
|
#define DEBUG 0
|
|
#include "debug.h"
|
|
|
|
|
|
// Supported sample rates, sizes and channels
|
|
vector<uint32> audio_sample_rates;
|
|
vector<uint16> audio_sample_sizes;
|
|
vector<uint16> audio_channel_counts;
|
|
|
|
// Global variables
|
|
struct audio_status AudioStatus; // Current audio status (sample rate etc.)
|
|
bool audio_open = false; // Flag: audio is initialized and ready
|
|
int audio_frames_per_block; // Number of audio frames per block
|
|
uint32 audio_component_flags; // Component feature flags
|
|
uint32 audio_data = 0; // Mac address of global data area
|
|
static int open_count = 0; // Open/close nesting count
|
|
|
|
bool AudioAvailable = false; // Flag: audio output available (from the software point of view)
|
|
|
|
|
|
/*
|
|
* Reset audio emulation
|
|
*/
|
|
|
|
void AudioReset(void)
|
|
{
|
|
audio_data = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Get audio info
|
|
*/
|
|
|
|
static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
|
{
|
|
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));
|
|
M68kRegisters r;
|
|
|
|
switch (selector) {
|
|
case siSampleSize:
|
|
WriteMacInt16(infoPtr, AudioStatus.sample_size);
|
|
break;
|
|
|
|
case siSampleSizeAvailable: {
|
|
r.d[0] = audio_sample_sizes.size() * 2;
|
|
Execute68kTrap(0xa122, &r); // NewHandle()
|
|
uint32 h = r.a[0];
|
|
if (h == 0)
|
|
return memFullErr;
|
|
WriteMacInt16(infoPtr + sil_count, audio_sample_sizes.size());
|
|
WriteMacInt32(infoPtr + sil_infoHandle, h);
|
|
uint32 sp = ReadMacInt32(h);
|
|
for (unsigned i=0; i<audio_sample_sizes.size(); i++)
|
|
WriteMacInt16(sp + i*2, audio_sample_sizes[i]);
|
|
break;
|
|
}
|
|
|
|
case siNumberChannels:
|
|
WriteMacInt16(infoPtr, AudioStatus.channels);
|
|
break;
|
|
|
|
case siChannelAvailable: {
|
|
r.d[0] = audio_channel_counts.size() * 2;
|
|
Execute68kTrap(0xa122, &r); // NewHandle()
|
|
uint32 h = r.a[0];
|
|
if (h == 0)
|
|
return memFullErr;
|
|
WriteMacInt16(infoPtr + sil_count, audio_channel_counts.size());
|
|
WriteMacInt32(infoPtr + sil_infoHandle, h);
|
|
uint32 sp = ReadMacInt32(h);
|
|
for (unsigned i=0; i<audio_channel_counts.size(); i++)
|
|
WriteMacInt16(sp + i*2, audio_channel_counts[i]);
|
|
break;
|
|
}
|
|
|
|
case siSampleRate:
|
|
WriteMacInt32(infoPtr, AudioStatus.sample_rate);
|
|
break;
|
|
|
|
case siSampleRateAvailable: {
|
|
r.d[0] = audio_sample_rates.size() * 4;
|
|
Execute68kTrap(0xa122, &r); // NewHandle()
|
|
uint32 h = r.a[0];
|
|
if (h == 0)
|
|
return memFullErr;
|
|
WriteMacInt16(infoPtr + sil_count, audio_sample_rates.size());
|
|
WriteMacInt32(infoPtr + sil_infoHandle, h);
|
|
uint32 lp = ReadMacInt32(h);
|
|
for (unsigned i=0; i<audio_sample_rates.size(); i++)
|
|
WriteMacInt32(lp + i*4, audio_sample_rates[i]);
|
|
break;
|
|
}
|
|
|
|
case siSpeakerMute:
|
|
WriteMacInt16(infoPtr, audio_get_speaker_mute());
|
|
break;
|
|
|
|
case siSpeakerVolume:
|
|
WriteMacInt32(infoPtr, audio_get_speaker_volume());
|
|
break;
|
|
|
|
case siHardwareMute:
|
|
WriteMacInt16(infoPtr, audio_get_main_mute());
|
|
break;
|
|
|
|
case siHardwareVolume:
|
|
WriteMacInt32(infoPtr, audio_get_main_volume());
|
|
break;
|
|
|
|
case siHardwareVolumeSteps:
|
|
WriteMacInt16(infoPtr, 7);
|
|
break;
|
|
|
|
case siHardwareBusy:
|
|
WriteMacInt16(infoPtr, AudioStatus.num_sources != 0);
|
|
break;
|
|
|
|
case siHardwareFormat:
|
|
WriteMacInt32(infoPtr + scd_flags, 0);
|
|
WriteMacInt32(infoPtr + scd_format, AudioStatus.sample_size == 16 ? FOURCC('t','w','o','s') : FOURCC('r','a','w',' '));
|
|
WriteMacInt16(infoPtr + scd_numChannels, AudioStatus.channels);
|
|
WriteMacInt16(infoPtr + scd_sampleSize, AudioStatus.sample_size);
|
|
WriteMacInt32(infoPtr + scd_sampleRate, AudioStatus.sample_rate);
|
|
WriteMacInt32(infoPtr + scd_sampleCount, audio_frames_per_block);
|
|
WriteMacInt32(infoPtr + scd_buffer, 0);
|
|
WriteMacInt32(infoPtr + scd_reserved, 0);
|
|
break;
|
|
|
|
default: // Delegate to Apple Mixer
|
|
if (AudioStatus.mixer == 0)
|
|
return badComponentSelector;
|
|
M68kRegisters r;
|
|
r.a[0] = infoPtr;
|
|
r.d[0] = selector;
|
|
r.a[1] = sourceID;
|
|
r.a[2] = AudioStatus.mixer;
|
|
Execute68k(audio_data + adatGetInfo, &r);
|
|
D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
|
|
return r.d[0];
|
|
}
|
|
return noErr;
|
|
}
|
|
|
|
|
|
/*
|
|
* Set audio info
|
|
*/
|
|
|
|
static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
|
{
|
|
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));
|
|
M68kRegisters r;
|
|
|
|
switch (selector) {
|
|
case siSampleSize:
|
|
D(bug(" set sample size %08lx\n", infoPtr));
|
|
if (AudioStatus.num_sources)
|
|
return siDeviceBusyErr;
|
|
if (infoPtr == AudioStatus.sample_size)
|
|
return noErr;
|
|
for (unsigned i=0; i<audio_sample_sizes.size(); i++)
|
|
if (audio_sample_sizes[i] == infoPtr) {
|
|
if (audio_set_sample_size(i))
|
|
return noErr;
|
|
else
|
|
return siInvalidSampleSize;
|
|
}
|
|
return siInvalidSampleSize;
|
|
|
|
case siSampleRate:
|
|
D(bug(" set sample rate %08lx\n", infoPtr));
|
|
if (AudioStatus.num_sources)
|
|
return siDeviceBusyErr;
|
|
if (infoPtr == AudioStatus.sample_rate)
|
|
return noErr;
|
|
for (unsigned i=0; i<audio_sample_rates.size(); i++)
|
|
if (audio_sample_rates[i] == infoPtr) {
|
|
if (audio_set_sample_rate(i))
|
|
return noErr;
|
|
else
|
|
return siInvalidSampleRate;
|
|
}
|
|
return siInvalidSampleRate;
|
|
|
|
case siNumberChannels:
|
|
D(bug(" set number of channels %08lx\n", infoPtr));
|
|
if (AudioStatus.num_sources)
|
|
return siDeviceBusyErr;
|
|
if (infoPtr == AudioStatus.channels)
|
|
return noErr;
|
|
for (unsigned i=0; i<audio_channel_counts.size(); i++)
|
|
if (audio_channel_counts[i] == infoPtr) {
|
|
if (audio_set_channels(i))
|
|
return noErr;
|
|
else
|
|
return badChannel;
|
|
}
|
|
return badChannel;
|
|
|
|
case siSpeakerMute:
|
|
audio_set_speaker_mute((uint16)infoPtr);
|
|
break;
|
|
|
|
case siSpeakerVolume:
|
|
D(bug(" set speaker volume %08lx\n", infoPtr));
|
|
audio_set_speaker_volume(infoPtr);
|
|
break;
|
|
|
|
case siHardwareMute:
|
|
audio_set_main_mute((uint16)infoPtr);
|
|
break;
|
|
|
|
case siHardwareVolume:
|
|
D(bug(" set hardware volume %08lx\n", infoPtr));
|
|
audio_set_main_volume(infoPtr);
|
|
break;
|
|
|
|
default: // Delegate to Apple Mixer
|
|
if (AudioStatus.mixer == 0)
|
|
return badComponentSelector;
|
|
r.a[0] = infoPtr;
|
|
r.d[0] = selector;
|
|
r.a[1] = sourceID;
|
|
r.a[2] = AudioStatus.mixer;
|
|
Execute68k(audio_data + adatSetInfo, &r);
|
|
D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
|
|
return r.d[0];
|
|
}
|
|
return noErr;
|
|
}
|
|
|
|
|
|
/*
|
|
* Sound output component dispatch
|
|
*/
|
|
|
|
int32 AudioDispatch(uint32 params, uint32 globals)
|
|
{
|
|
D(bug("AudioDispatch params %08lx (size %d), what %d\n", params, ReadMacInt8(params + cp_paramSize), (int16)ReadMacInt16(params + cp_what)));
|
|
M68kRegisters r;
|
|
uint32 p = params + cp_params;
|
|
int16 selector = (int16)ReadMacInt16(params + cp_what);
|
|
|
|
switch (selector) {
|
|
|
|
// General component functions
|
|
case kComponentOpenSelect:
|
|
if (audio_data == 0) {
|
|
|
|
// Allocate global data area
|
|
r.d[0] = SIZEOF_adat;
|
|
Execute68kTrap(0xa040, &r); // ResrvMem()
|
|
r.d[0] = SIZEOF_adat;
|
|
Execute68kTrap(0xa31e, &r); // NewPtrClear()
|
|
if (r.a[0] == 0)
|
|
return memFullErr;
|
|
audio_data = r.a[0];
|
|
D(bug(" global data at %08lx\n", audio_data));
|
|
|
|
// Put in 68k routines
|
|
int p = audio_data + adatDelegateCall;
|
|
WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
|
|
WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x7024); p += 2; // moveq #$24,d0
|
|
WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
|
|
WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatOpenMixer)
|
|
goto adat_error;
|
|
WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
|
|
WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
|
|
WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x203c); p += 2; // move.l #$06140018,d0
|
|
WriteMacInt32(p, 0x06140018); p+= 4;
|
|
WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
|
|
WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
|
|
WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatCloseMixer)
|
|
goto adat_error;
|
|
WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x203c); p += 2; // move.l #$02180018,d0
|
|
WriteMacInt32(p, 0x02180018); p+= 4;
|
|
WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
|
|
WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
|
|
WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatGetInfo)
|
|
goto adat_error;
|
|
WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
|
|
WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
|
|
WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
|
|
WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0103,-(sp)
|
|
WriteMacInt32(p, 0x000c0103); p+= 4;
|
|
WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
|
|
WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
|
|
WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatSetInfo)
|
|
goto adat_error;
|
|
WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
|
|
WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
|
|
WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
|
|
WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0104,-(sp)
|
|
WriteMacInt32(p, 0x000c0104); p+= 4;
|
|
WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
|
|
WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
|
|
WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatPlaySourceBuffer)
|
|
goto adat_error;
|
|
WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
|
|
WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
|
|
WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
|
|
WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0108,-(sp)
|
|
WriteMacInt32(p, 0x000c0108); p+= 4;
|
|
WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
|
|
WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
|
|
WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatGetSourceData)
|
|
goto adat_error;
|
|
WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
|
|
WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$00040004,-(sp)
|
|
WriteMacInt32(p, 0x00040004); p+= 4;
|
|
WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
|
|
WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
|
|
WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatStartSource)
|
|
goto adat_error;
|
|
WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
|
|
WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
|
|
WriteMacInt16(p, 0x3f00); p += 2; // move.w d0,-(sp)
|
|
WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
|
|
WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$00060105,-(sp)
|
|
WriteMacInt32(p, 0x00060105); p+= 4;
|
|
WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
|
|
WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
|
|
WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
|
|
WriteMacInt16(p, M68K_RTS); p += 2; // rts
|
|
if (p - audio_data != adatData)
|
|
goto adat_error;
|
|
}
|
|
AudioAvailable = true;
|
|
if (open_count == 0)
|
|
audio_enter_stream();
|
|
open_count++;
|
|
return noErr;
|
|
|
|
adat_error: printf("FATAL: audio component data block initialization error\n");
|
|
QuitEmulator();
|
|
return openErr;
|
|
|
|
case kComponentCloseSelect:
|
|
open_count--;
|
|
if (open_count == 0) {
|
|
if (audio_data) {
|
|
if (AudioStatus.mixer) {
|
|
// Close Apple Mixer
|
|
r.a[0] = AudioStatus.mixer;
|
|
Execute68k(audio_data + adatCloseMixer, &r);
|
|
AudioStatus.mixer = 0;
|
|
return r.d[0];
|
|
}
|
|
r.a[0] = audio_data;
|
|
Execute68kTrap(0xa01f, &r); // DisposePtr()
|
|
audio_data = 0;
|
|
}
|
|
AudioStatus.num_sources = 0;
|
|
audio_exit_stream();
|
|
}
|
|
return noErr;
|
|
|
|
case kComponentCanDoSelect:
|
|
switch ((int16)ReadMacInt16(p)) {
|
|
case kComponentOpenSelect:
|
|
case kComponentCloseSelect:
|
|
case kComponentCanDoSelect:
|
|
case kComponentVersionSelect:
|
|
case kComponentRegisterSelect:
|
|
case kSoundComponentInitOutputDeviceSelect:
|
|
case kSoundComponentGetSourceSelect:
|
|
case kSoundComponentGetInfoSelect:
|
|
case kSoundComponentSetInfoSelect:
|
|
case kSoundComponentStartSourceSelect:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
case kComponentVersionSelect:
|
|
return 0x00010003;
|
|
|
|
case kComponentRegisterSelect:
|
|
return noErr;
|
|
|
|
// Sound component functions (not delegated)
|
|
case kSoundComponentInitOutputDeviceSelect:
|
|
D(bug(" InitOutputDevice\n"));
|
|
if (!audio_open)
|
|
return noHardwareErr;
|
|
if (AudioStatus.mixer)
|
|
return noErr;
|
|
|
|
// Init sound component data
|
|
WriteMacInt32(audio_data + adatData + scd_flags, 0);
|
|
WriteMacInt32(audio_data + adatData + scd_format, AudioStatus.sample_size == 16 ? FOURCC('t','w','o','s') : FOURCC('r','a','w',' '));
|
|
WriteMacInt16(audio_data + adatData + scd_numChannels, AudioStatus.channels);
|
|
WriteMacInt16(audio_data + adatData + scd_sampleSize, AudioStatus.sample_size);
|
|
WriteMacInt32(audio_data + adatData + scd_sampleRate, AudioStatus.sample_rate);
|
|
WriteMacInt32(audio_data + adatData + scd_sampleCount, audio_frames_per_block);
|
|
WriteMacInt32(audio_data + adatData + scd_buffer, 0);
|
|
WriteMacInt32(audio_data + adatData + scd_reserved, 0);
|
|
WriteMacInt32(audio_data + adatStreamInfo, 0);
|
|
|
|
// Open Apple Mixer
|
|
r.a[0] = audio_data + adatMixer;
|
|
r.d[0] = 0;
|
|
r.a[1] = audio_data + adatData;
|
|
Execute68k(audio_data + adatOpenMixer, &r);
|
|
AudioStatus.mixer = ReadMacInt32(audio_data + adatMixer);
|
|
D(bug(" OpenMixer() returns %08lx, mixer %08lx\n", r.d[0], AudioStatus.mixer));
|
|
return r.d[0];
|
|
|
|
case kSoundComponentGetSourceSelect:
|
|
D(bug(" GetSource source %08lx\n", ReadMacInt32(p)));
|
|
WriteMacInt32(ReadMacInt32(p), AudioStatus.mixer);
|
|
return noErr;
|
|
|
|
// Sound component functions (delegated)
|
|
case kSoundComponentAddSourceSelect:
|
|
D(bug(" AddSource\n"));
|
|
AudioStatus.num_sources++;
|
|
goto delegate;
|
|
|
|
case kSoundComponentRemoveSourceSelect:
|
|
D(bug(" RemoveSource\n"));
|
|
AudioStatus.num_sources--;
|
|
goto delegate;
|
|
|
|
case kSoundComponentGetInfoSelect:
|
|
return AudioGetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
|
|
|
|
case kSoundComponentSetInfoSelect:
|
|
return AudioSetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
|
|
|
|
case kSoundComponentStartSourceSelect:
|
|
D(bug(" StartSource count %d\n", ReadMacInt16(p + 4)));
|
|
D(bug(" starting Apple Mixer\n"));
|
|
r.d[0] = ReadMacInt16(p + 4);
|
|
r.a[0] = ReadMacInt32(p);
|
|
r.a[1] = AudioStatus.mixer;
|
|
Execute68k(audio_data + adatStartSource, &r);
|
|
D(bug(" returns %08lx\n", r.d[0]));
|
|
return noErr;
|
|
|
|
case kSoundComponentStopSourceSelect:
|
|
D(bug(" StopSource\n"));
|
|
goto delegate;
|
|
|
|
case kSoundComponentPauseSourceSelect:
|
|
D(bug(" PauseSource\n"));
|
|
delegate: // Delegate call to Apple Mixer
|
|
D(bug(" delegating call to Apple Mixer\n"));
|
|
r.a[0] = AudioStatus.mixer;
|
|
r.a[1] = params;
|
|
Execute68k(audio_data + adatDelegateCall, &r);
|
|
D(bug(" returns %08lx\n", r.d[0]));
|
|
return r.d[0];
|
|
|
|
case kSoundComponentPlaySourceBufferSelect:
|
|
D(bug(" PlaySourceBuffer flags %08lx\n", ReadMacInt32(p)));
|
|
r.d[0] = ReadMacInt32(p);
|
|
r.a[0] = ReadMacInt32(p + 4);
|
|
r.a[1] = ReadMacInt32(p + 8);
|
|
r.a[2] = AudioStatus.mixer;
|
|
Execute68k(audio_data + adatPlaySourceBuffer, &r);
|
|
D(bug(" returns %08lx\n", r.d[0]));
|
|
return r.d[0];
|
|
|
|
default:
|
|
if (selector >= 0x100)
|
|
goto delegate;
|
|
else
|
|
return badComponentSelector;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Sound input driver Open() routine
|
|
*/
|
|
|
|
int16 SoundInOpen(uint32 pb, uint32 dce)
|
|
{
|
|
D(bug("SoundInOpen\n"));
|
|
return noErr;
|
|
}
|
|
|
|
|
|
/*
|
|
* Sound input driver Prime() routine
|
|
*/
|
|
|
|
int16 SoundInPrime(uint32 pb, uint32 dce)
|
|
{
|
|
D(bug("SoundInPrime\n"));
|
|
//!!
|
|
return paramErr;
|
|
}
|
|
|
|
|
|
/*
|
|
* Sound input driver Control() routine
|
|
*/
|
|
|
|
int16 SoundInControl(uint32 pb, uint32 dce)
|
|
{
|
|
uint16 code = ReadMacInt16(pb + csCode);
|
|
D(bug("SoundInControl %d\n", code));
|
|
|
|
if (code == 1) {
|
|
D(bug(" SoundInKillIO\n"));
|
|
//!!
|
|
return noErr;
|
|
}
|
|
|
|
if (code != 2)
|
|
return -231; // siUnknownInfoType
|
|
|
|
uint32 *param = (uint32 *)Mac2HostAddr(pb + csParam);
|
|
uint32 selector = param[0];
|
|
D(bug(" selector %c%c%c%c\n", selector >> 24, selector >> 16, selector >> 8, selector));
|
|
|
|
switch (selector) {
|
|
default:
|
|
return -231; // siUnknownInfoType
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Sound input driver Status() routine
|
|
*/
|
|
|
|
int16 SoundInStatus(uint32 pb, uint32 dce)
|
|
{
|
|
uint16 code = ReadMacInt16(pb + csCode);
|
|
D(bug("SoundInStatus %d\n", code));
|
|
if (code != 2)
|
|
return -231; // siUnknownInfoType
|
|
|
|
uint32 *param = (uint32 *)Mac2HostAddr(pb + csParam);
|
|
uint32 selector = param[0];
|
|
D(bug(" selector %c%c%c%c\n", selector >> 24, selector >> 16, selector >> 8, selector));
|
|
switch (selector) {
|
|
#if 0
|
|
case siDeviceName: {
|
|
const char *str = GetString(STR_SOUND_IN_NAME);
|
|
param[0] = 0;
|
|
memcpy((void *)param[1], str, strlen(str));
|
|
return noErr;
|
|
}
|
|
|
|
case siDeviceIcon: {
|
|
M68kRegisters r;
|
|
static const uint8 proc[] = {
|
|
0x55, 0x8f, // subq.l #2,sp
|
|
0xa9, 0x94, // CurResFile
|
|
0x42, 0x67, // clr.w -(sp)
|
|
0xa9, 0x98, // UseResFile
|
|
0x59, 0x8f, // subq.l #4,sp
|
|
0x48, 0x79, 0x49, 0x43, 0x4e, 0x23, // move.l #'ICN#',-(sp)
|
|
0x3f, 0x3c, 0xbf, 0x76, // move.w #-16522,-(sp)
|
|
0xa9, 0xa0, // GetResource
|
|
0x24, 0x5f, // move.l (sp)+,a2
|
|
0xa9, 0x98, // UseResFile
|
|
0x20, 0x0a, // move.l a2,d0
|
|
0x66, 0x04, // bne 1
|
|
0x70, 0x00, // moveq #0,d0
|
|
M68K_RTS >> 8, M68K_RTS & 0xff,
|
|
0x2f, 0x0a, //1 move.l a2,-(sp)
|
|
0xa9, 0x92, // DetachResource
|
|
0x20, 0x4a, // move.l a2,a0
|
|
0xa0, 0x4a, // HNoPurge
|
|
0x70, 0x01, // moveq #1,d0
|
|
M68K_RTS >> 8, M68K_RTS & 0xff
|
|
};
|
|
Execute68k(Host2MacAddr((uint8 *)proc), &r);
|
|
if (r.d[0]) {
|
|
param[0] = 4; // Length of returned data
|
|
param[1] = r.a[2]; // Handle to icon suite
|
|
return noErr;
|
|
} else
|
|
return -192; // resNotFound
|
|
}
|
|
#endif
|
|
default:
|
|
return -231; // siUnknownInfoType
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Sound input driver Close() routine
|
|
*/
|
|
|
|
int16 SoundInClose(uint32 pb, uint32 dce)
|
|
{
|
|
D(bug("SoundInClose\n"));
|
|
return noErr;
|
|
}
|