/* * 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" #define DEBUG 0 #include "debug.h" // Supported sample rates, sizes and channels vector audio_sample_rates; vector audio_sample_sizes; vector 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> 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= 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; }