macemu/BasiliskII/src/audio.cpp

917 lines
28 KiB
C++

/*
* audio.cpp - Audio support
*
* Basilisk II (C) 1997-2008 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"
#include "user_strings.h"
#include "cdrom.h"
#define DEBUG 0
#include "debug.h"
// Supported sample rates, sizes and channels
vector<uint32> audio_sample_rates;
vector<uint16> audio_sample_sizes;
vector<uint8> 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) != 0);
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) != 0);
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"));
//!!
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 selector = ReadMacInt32(pb + csParam); // 4-byte selector (should match via FOURCC above)
return noErr;
}
/*
* 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 selector = ReadMacInt32(pb + csParam); // 4-byte selector (should match via FOURCC above)
// 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));
// uint32 selector_flipped = bswap_32(selector); // endianness of selector needs swapping?
switch (selector) {
case siInitializeDriver: {
// If possible, the driver initializes the device to a sampling rate of 22 kHz, a sample size of 8 bits, mono recording, no compression, automatic gain control on, and all other features off.
return noErr;
}
case siCloseDriver: {
// The sound input device driver should stop any recording in progress, deallocate the input hardware, and initialize local variables to default settings.
return noErr;
}
default:
return -231; // siUnknownInfoType
}
}
/*
* Sound input driver Status() routine
*/
int16 SoundInStatus(uint32 pb, uint32 dce) // A0 points to Device Manager parameter block (pb) and A1 to device control entry (dce)
{
uint16 code = ReadMacInt16(pb + csCode);
D(bug("SoundInStatus %d\n", code));
if (code != 2)
return -231; // siUnknownInfoType
// reading directly
uint32 selector = ReadMacInt32(pb + csParam); // 4-byte selector (should match via FOURCC above)
uint32 bufferptr = ReadMacInt32(pb + csParam + 4); // 4-byte address to the buffer in vm memory
// reading through location in memory
// uint32 *param = (uint32 *)Mac2HostAddr(pb + csParam);
// uint32 selector_flipped = param[0];
// uint32 selector = bswap_32(selector_flipped); // endianness of selector needs swapping?
// D(bug(" selector %c%c%c%c\n", selector >> 24, selector >> 16, selector >> 8, selector));
// uint32 bufferptr_flipped = param[1]; // pointer to application-supplied buffer for return data
// uint32 bufferptr = bswap_32(bufferptr_flipped); // endianness of buffer address needs swapping?
// two choices on return
// 1: if under 18 bytes, place # of bytes at (pb+csParam) and write from (pb+csParam+4) on
// 2: if over 18 bytes, place 0 at (pb+csParam) and directly write into buffer pointed to by bufferptr
// uint8 *buffer = Mac2HostAddr(bufferptr);
switch (selector) {
//#if 0
case siDeviceName: { // return name in STR255 format
// const char *str = GetString(STR_SOUND_IN_NAME);
const uint8 str[] = { // size 9
0x08, // 1-byte length
0x42, 0x75, // Bu
0x69, 0x6c, // il
0x74, 0x2d, // t-
0x69, 0x6e // in
};
const uint8 str2[] = { // size 8
0x07, // 1-byte length
0x41, 0x70, // Ap
0x70, 0x6c, // pl
0x65, 0x43, // eC
0x44 // D
};
const uint8 str3[] = { // size 12
0x0b, // byte size indicator (up to 255 length supported)
0x49, 0x6e, // start of string in ASCII, In
0x74, 0x65, // te
0x72, 0x6e, // rn
0x61, 0x6c, // al
0x20, 0x43, // C
0x44, // D
};
const uint8 str4[] = { // size 18
0x10, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x00 // ".AppleSoundInput"
};
WriteMacInt32(pb + csParam, 0); // response will directly be written into buffer
vm_memcpy(bufferptr, str3, 12);
// memcpy(buffer, str, 9);
return noErr;
}
case siDeviceIcon: {
// return -192;
WriteMacInt32(pb + csParam, 0);
WriteMacInt32(bufferptr, CDROMIconAddr);
return noErr;
// attempt to load from external file into emulator
// FILE *fl = fopen("/Emulators/SheepShaver/Shared/SoundIcon.icn", "r");
// fseek(fl, 0, SEEK_END);
// long len = ftell(fl);
// uint32 icnbuffer = Mac_sysalloc(len);
// uint8 *ret = (uint8*)Mac2HostAddr(icnbuffer);
// fseek(fl, 0, SEEK_SET);
// fread(ret, 1, len, fl);
// fclose(fl);
// WriteMacInt32(pb + csParam, 4); // will be the address of the icn in memory
// WriteMacInt32(pb + csParam + 4, icnbuffer);
// WriteMacInt32(bufferptr,icnbuffer);
// return noErr;
// 68k code causes crash in sheep and link error in basilisk
// 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]) {
// WriteMacInt32(pb + csParam, 4); // Length of returned data
// WriteMacInt32(pb + csParam + 4, r.a[2]); // Handle to icon suite
// return noErr;
// } else
// return -192; // resNotFound
}
case siInputSource: {
// uint32 addr = Mac_sysalloc(1);
// WriteMacInt32(addr, 0);
// param[0] = 4;
// param[1] = addr;
// WriteMacInt32(param[1], 0);
// const uint32 opt = 0; // 0 if no options box supported and 1 if so
// const uint8 ind[] = {
// 0x00, 0x00, 0x00, 0x00
// };
// param[0] = 0;s
// memcpy((void *)buffer, ind, 4);
// uint8 *src = (uint8 *)Mac2HostAddr(Mac_sysalloc(1));
// *src = 0x00;
// param[0] = 4;
// param[1] = Host2MacAddr(src);
// return -231;
// uint32 opt = Mac_sysalloc(4);
// WriteMacInt32(opt, 0);
// param[0] = 4;
// param[1] = opt;
// return -231;
WriteMacInt32(pb + csParam, 4);
WriteMacInt32(pb + csParam + 4, 1);
return noErr;
}
case siInputSourceNames: { // list of sources in str# resource format
// return -231;
// const char names[] = {
// '\x00', '\x02',
// '\x0b',
// 'I','n','t','e','r','n','a','l',' ','C','D',
// '\x0a',
// 'M','i','c','r','o','p','h','o','n','e','\0'
// };
// const char names2[] = {
// '\x00', 'e', 'n', 'o', 'h', 'p', 'o', 'r', 'c', 'i', 'M', '\x0a', 'D', 'C', ' ', 'l', 'a', 'n', 'r', 'e', 't', 'n', 'I', '\x0b', '\x02', '\x00'
// };
// SheepVar names_str(26);
// strcpy((char*)Mac2HostAddr(names_str.addr()),names2);
// WriteMacInt32(pb + csParam, 0);
// WriteMacInt32(bufferptr, names_str.addr());
// return noErr;
// SheepString names("\00bInternal CD");
// WriteMacInt32(pb + csParam, 0);
// WriteMacInt32(bufferptr, names.addr());
// return noErr;
// uint32 nameshandle = Mac_sysalloc(14);
// SheepVar names_str(25);
const uint8 str[] = {
0x00, 0x02, // 2-byte count of #strings
0x0b, // byte size indicator (up to 255 length supported)
0x49, 0x6e, // start of string in ASCII, In
0x74, 0x65, // te
0x72, 0x6e, // rn
0x61, 0x6c, // al
0x20, 0x43, // C
0x44, // D
0x0a, // size is 10
0x4d, 0x69, // Mi
0x63, 0x72, // cr
0x6f, 0x70, // op
0x68, 0x6f, // ho
0x6e, 0x65, // ne
};
const char str2[] = {
0x00, 0x01, // 2-byte count of #strings
0x02, // string size is 2
0x43, 0x44, // CD
0x00
};
SheepString names(str2);
// vm_memcpy(names_str.addr(), str, 25);
WriteMacInt32(pb + csParam, 0);
// vm_memcpy(bufferptr, str, 25);
WriteMacInt32(bufferptr, names.addr());
return noErr;
// vm_memcpy(nameshandle, str, 14);
// memcpy(names, str, 14);
// attempt to load from external file into emulator
// FILE *fl = fopen("/Emulators/SheepShaver/Shared/soundnames.rsrc", "r");
// fseek(fl, 0, SEEK_END);
// long len = ftell(fl);
// uint8 *ret = (uint8*)malloc(len);
// fseek(fl, 0, SEEK_SET);
// fread(ret, 1, len, fl);
// fclose(fl);
// SheepVar names_strs(len);
// vm_memcpy(names_strs.addr(), ret, len);
// WriteMacInt32(pb + csParam, 0);
// WriteMacInt32(bufferptr, names_strs.addr());
// return noErr;
// uint32 name = Mac_sysalloc(14);
// Host2Mac_memcpy(name, str, 14);
// uint32 handle = Host2MacAddr(names);
// param[0] = 4;
// memcpy((void *)param[1], str, 14);
// return noErr;
// WriteMacInt16(param[1], 1);
// const char *str = "Internal CD";
//// Host2Mac_memcpy(param[1]+sizeof(uint16), str, strlen(str));
//// uint16 *num = new uint16; // number of sources (2-bytes at start of infoData
//// *num = (uint16) 1;
//// const char *str = "Built-In";//GetString(STR_SOUND_IN_SOURCE);
//// param[0] = sizeof(uint16) + strlen(str);
//// memcpy((void *)param[1], num, sizeof(uint16));
// memcpy((void *)param[1], str, strlen(str));
// return -231; // when only 1 source, return siUnknownInfoType
}
case siOptionsDialog: {
// WriteMacInt32(param[1], 0);
// const uint32 opt = 0; // 0 if no options box supported and 1 if so
// param[0] = 0;
// memcpy((void *)param[1], &opt, sizeof(opt));
// const uint8 ind[] = {
// 0x00, 0x00, 0x00, 0x00
// };
// uint32 opt = Mac_sysalloc(4);
// WriteMacInt32(opt, 0);
// param[0] = 0;
// WriteMacInt32(bufferptr, 0);
WriteMacInt32(pb + csParam, 4);
WriteMacInt32(pb + csParam + 4, 0);
// uint8 *src = (uint8 *)Mac2HostAddr(Mac_sysalloc(1));
// *src = 0x00;
// param[0] = 4;
// param[1] = Host2MacAddr(src);
// uint32 opt = Mac_sysalloc(4);
// WriteMacInt32(opt, 0);
// param[0] = 4;
// param[1] = opt;
return noErr;
}
case siPlayThruOnOff: {
// WriteMacInt32(param[1], 0);
// const uint32 plt = 7; // playthrough volume, 0 is off and 7 is max
// param[0] = 0;
// memcpy((void *)param[1], &plt, sizeof(plt));
// uint32 opt = Mac_sysalloc(4);
// WriteMacInt32(opt, 0);
// param[0] = 0;
// WriteMacInt32(bufferptr, 7);
WriteMacInt32(pb + csParam, 4);
WriteMacInt32(pb + csParam + 4, 7);
// uint32 opt = Mac_sysalloc(4);
// WriteMacInt32(opt, 0);
// param[0] = 4;
// param[1] = opt;
return noErr;
}
//#endif
case FOURCC('p', 't', 'k', 'd'): {
return -231;
WriteMacInt32(pb + csParam, 1);
WriteMacInt8(pb + csParam + 4, 0);
return noErr;
}
case FOURCC('i', 'n', 'p', 't'): {
return -231;
}
default:
return -231; // siUnknownInfoType
}
}
/*
* Sound input driver Close() routine
*/
int16 SoundInClose(uint32 pb, uint32 dce)
{
D(bug("SoundInClose\n"));
return noErr;
}