home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / audio.cpp < prev    next >
C/C++ Source or Header  |  1999-10-20  |  15KB  |  463 lines

  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_speaker_mute());
  117.             break;
  118.  
  119.         case siSpeakerVolume:
  120.             WriteMacInt32(infoPtr, audio_get_speaker_volume());
  121.             break;
  122.  
  123.         case siHeadphoneMute:
  124.             WriteMacInt16(infoPtr, 0);
  125.             break;
  126.  
  127.         case siHeadphoneVolume:
  128.             WriteMacInt32(infoPtr, 0x01000100);
  129.             break;
  130.  
  131.         case siHeadphoneVolumeSteps:
  132.             WriteMacInt16(infoPtr, 13);
  133.             break;
  134.  
  135.         case siHardwareMute:
  136.             WriteMacInt16(infoPtr, audio_get_main_mute());
  137.             break;
  138.  
  139.         case siHardwareVolume:
  140.             WriteMacInt32(infoPtr, audio_get_main_volume());
  141.             break;
  142.  
  143.         case siHardwareVolumeSteps:
  144.             WriteMacInt16(infoPtr, 13);
  145.             break;
  146.  
  147.         case siHardwareBusy:
  148.             WriteMacInt16(infoPtr, AudioStatus.num_sources != 0);
  149.             break;
  150.  
  151.         default:    // Delegate to Apple Mixer
  152.             if (AudioStatus.mixer == 0)
  153.                 return badComponentSelector;
  154.             M68kRegisters r;
  155.             r.a[0] = infoPtr;
  156.             r.d[0] = selector;
  157.             r.a[1] = sourceID;
  158.             r.a[2] = AudioStatus.mixer;
  159.             Execute68k(audio_data + adatGetInfo, &r);
  160.             D(bug("  delegated to Apple Mixer, returns %08lx\n", r.d[0]));
  161.             return r.d[0];
  162.     }
  163.     return noErr;
  164. }
  165.  
  166.  
  167. /*
  168.  *  Set audio info
  169.  */
  170.  
  171. static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
  172. {
  173.     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));
  174.     M68kRegisters r;
  175.     int i;
  176.  
  177.     switch (selector) {
  178.         case siSampleSize:
  179.             D(bug("  set sample size %08lx\n", infoPtr));
  180.             if (AudioStatus.num_sources)
  181.                 return siDeviceBusyErr;
  182.             for (i=0; i<audio_num_sample_sizes; i++)
  183.                 if (audio_sample_sizes[i] == infoPtr) {
  184.                     audio_set_sample_size(i);
  185.                     return noErr;
  186.                 }
  187.             return siInvalidSampleSize;
  188.  
  189.         case siSampleRate:
  190.             D(bug("  set sample rate %08lx\n", infoPtr));
  191.             if (AudioStatus.num_sources)
  192.                 return siDeviceBusyErr;
  193.             for (i=0; i<audio_num_sample_rates; i++)
  194.                 if (audio_sample_rates[i] == infoPtr) {
  195.                     audio_set_sample_rate(i);
  196.                     return noErr;
  197.                 }
  198.             return siInvalidSampleRate;
  199.  
  200.         case siNumberChannels:
  201.             D(bug("  set number of channels %08lx\n", infoPtr));
  202.             if (AudioStatus.num_sources)
  203.                 return siDeviceBusyErr;
  204.             for (i=0; i<audio_num_channel_counts; i++)
  205.                 if (audio_channel_counts[i] == infoPtr) {
  206.                     audio_set_channels(i);
  207.                     return noErr;
  208.                 }
  209.             return badChannel;
  210.  
  211.         case siSpeakerMute:
  212.             audio_set_speaker_mute((uint16)infoPtr);
  213.             break;
  214.  
  215.         case siSpeakerVolume:
  216.             D(bug("  set speaker volume %08lx\n", infoPtr));
  217.             audio_set_speaker_volume(infoPtr);
  218.             break;
  219.  
  220.         case siHeadphoneMute:
  221.         case siHeadphoneVolume:
  222.             break;
  223.  
  224.         case siHardwareMute:
  225.             audio_set_main_mute((uint16)infoPtr);
  226.             break;
  227.  
  228.         case siHardwareVolume:
  229.             D(bug("  set hardware volume %08lx\n", infoPtr));
  230.             audio_set_main_volume(infoPtr);
  231.             break;
  232.  
  233.         default:    // Delegate to Apple Mixer
  234.             if (AudioStatus.mixer == 0)
  235.                 return badComponentSelector;
  236.             r.a[0] = infoPtr;
  237.             r.d[0] = selector;
  238.             r.a[1] = sourceID;
  239.             r.a[2] = AudioStatus.mixer;
  240.             Execute68k(audio_data + adatSetInfo, &r);
  241.             D(bug("  delegated to Apple Mixer, returns %08lx\n", r.d[0]));
  242.             return r.d[0];
  243.     }
  244.     return noErr;
  245. }
  246.  
  247.  
  248. /*
  249.  *  Sound output component dispatch
  250.  */
  251.  
  252. int32 AudioDispatch(uint32 params, uint32 globals)
  253. {
  254.     D(bug("AudioDispatch params %08lx (size %d), what %d\n", params, ReadMacInt8(params + cp_paramSize), (int16)ReadMacInt16(params + cp_what)));
  255.     M68kRegisters r;
  256.     uint32 p = params + cp_params;
  257.  
  258.     switch ((int16)ReadMacInt16(params + cp_what)) {
  259.         // Basic component functions
  260.         case kComponentOpenSelect:
  261.             if (audio_data == 0) {
  262.  
  263.                 // Allocate global data area
  264.                 r.d[0] = SIZEOF_adat;
  265.                 Execute68kTrap(0xa71e, &r);    // NewPtrSysClear()
  266.                 if (r.a[0] == 0)
  267.                     return memFullErr;
  268.                 audio_data = r.a[0];
  269.                 D(bug(" global data at %08lx\n", audio_data));
  270.  
  271.                 // Put in 68k routines
  272.                 int p = audio_data + adatDelegateCall;
  273.                 WriteMacInt16(p, 0x598f); p += 2;    // subq.l    #4,sp
  274.                 WriteMacInt16(p, 0x2f09); p += 2;    // move.l    a1,-(sp)
  275.                 WriteMacInt16(p, 0x2f08); p += 2;    // move.l    a0,-(sp)
  276.                 WriteMacInt16(p, 0x7024); p += 2;    // moveq    #$24,d0
  277.                 WriteMacInt16(p, 0xa82a); p += 2;    // ComponentDispatch
  278.                 WriteMacInt16(p, 0x201f); p += 2;    // move.l    (sp)+,d0
  279.                 WriteMacInt16(p, M68K_RTS); p += 2;    // rts
  280.                 if (p - audio_data != adatOpenMixer)
  281.                     goto adat_error;
  282.                 WriteMacInt16(p, 0x558f); p += 2;    // subq.l    #2,sp
  283.                 WriteMacInt16(p, 0x2f09); p += 2;    // move.l    a1,-(sp)
  284.                 WriteMacInt16(p, 0x2f00); p += 2;    // move.l    d0,-(sp)
  285.                 WriteMacInt16(p, 0x2f08); p += 2;    // move.l    a0,-(sp)
  286.                 WriteMacInt16(p, 0x203c); p += 2;    // move.l    #$06140018,d0
  287.                 WriteMacInt32(p, 0x06140018); p+= 4;
  288.                 WriteMacInt16(p, 0xa800); p += 2;    // SoundDispatch
  289.                 WriteMacInt16(p, 0x301f); p += 2;    // move.w    (sp)+,d0
  290.                 WriteMacInt16(p, 0x48c0); p += 2;    // ext.l    d0
  291.                 WriteMacInt16(p, M68K_RTS); p += 2;    // rts
  292.                 if (p - audio_data != adatCloseMixer)
  293.                     goto adat_error;
  294.                 WriteMacInt16(p, 0x558f); p += 2;    // subq.l    #2,sp
  295.                 WriteMacInt16(p, 0x2f08); p += 2;    // move.l    a0,-(sp)
  296.                 WriteMacInt16(p, 0x203c); p += 2;    // move.l    #$02180018,d0
  297.                 WriteMacInt32(p, 0x02180018); p+= 4;
  298.                 WriteMacInt16(p, 0xa800); p += 2;    // SoundDispatch
  299.                 WriteMacInt16(p, 0x301f); p += 2;    // move.w    (sp)+,d0
  300.                 WriteMacInt16(p, 0x48c0); p += 2;    // ext.l    d0
  301.                 WriteMacInt16(p, M68K_RTS); p += 2;    // rts
  302.                 if (p - audio_data != adatGetInfo)
  303.                     goto adat_error;
  304.                 WriteMacInt16(p, 0x598f); p += 2;    // subq.l    #4,sp
  305.                 WriteMacInt16(p, 0x2f0a); p += 2;    // move.l    a2,-(sp)
  306.                 WriteMacInt16(p, 0x2f09); p += 2;    // move.l    a1,-(sp)
  307.                 WriteMacInt16(p, 0x2f00); p += 2;    // move.l    d0,-(sp)
  308.                 WriteMacInt16(p, 0x2f08); p += 2;    // move.l    a0,-(sp)
  309.                 WriteMacInt16(p, 0x2f3c); p += 2;    // move.l    #$000c0103,-(sp)
  310.                 WriteMacInt32(p, 0x000c0103); p+= 4;
  311.                 WriteMacInt16(p, 0x7000); p += 2;    // moveq    #0,d0
  312.                 WriteMacInt16(p, 0xa82a); p += 2;    // ComponentDispatch
  313.                 WriteMacInt16(p, 0x201f); p += 2;    // move.l    (sp)+,d0
  314.                 WriteMacInt16(p, M68K_RTS); p += 2;    // rts
  315.                 if (p - audio_data != adatSetInfo)
  316.                     goto adat_error;
  317.                 WriteMacInt16(p, 0x598f); p += 2;    // subq.l    #4,sp
  318.                 WriteMacInt16(p, 0x2f0a); p += 2;    // move.l    a2,-(sp)
  319.                 WriteMacInt16(p, 0x2f09); p += 2;    // move.l    a1,-(sp)
  320.                 WriteMacInt16(p, 0x2f00); p += 2;    // move.l    d0,-(sp)
  321.                 WriteMacInt16(p, 0x2f08); p += 2;    // move.l    a0,-(sp)
  322.                 WriteMacInt16(p, 0x2f3c); p += 2;    // move.l    #$000c0104,-(sp)
  323.                 WriteMacInt32(p, 0x000c0104); p+= 4;
  324.                 WriteMacInt16(p, 0x7000); p += 2;    // moveq    #0,d0
  325.                 WriteMacInt16(p, 0xa82a); p += 2;    // ComponentDispatch
  326.                 WriteMacInt16(p, 0x201f); p += 2;    // move.l    (sp)+,d0
  327.                 WriteMacInt16(p, M68K_RTS); p += 2;    // rts
  328.                 if (p - audio_data != adatPlaySourceBuffer)
  329.                     goto adat_error;
  330.                 WriteMacInt16(p, 0x598f); p += 2;    // subq.l    #4,sp
  331.                 WriteMacInt16(p, 0x2f0a); p += 2;    // move.l    a2,-(sp)
  332.                 WriteMacInt16(p, 0x2f09); p += 2;    // move.l    a1,-(sp)
  333.                 WriteMacInt16(p, 0x2f08); p += 2;    // move.l    a0,-(sp)
  334.                 WriteMacInt16(p, 0x2f00); p += 2;    // move.l    d0,-(sp)
  335.                 WriteMacInt16(p, 0x2f3c); p += 2;    // move.l    #$000c0108,-(sp)
  336.                 WriteMacInt32(p, 0x000c0108); p+= 4;
  337.                 WriteMacInt16(p, 0x7000); p += 2;    // moveq    #0,d0
  338.                 WriteMacInt16(p, 0xa82a); p += 2;    // ComponentDispatch
  339.                 WriteMacInt16(p, 0x201f); p += 2;    // move.l    (sp)+,d0
  340.                 WriteMacInt16(p, M68K_RTS); p += 2;    // rts
  341.                 if (p - audio_data != adatGetSourceData)
  342.                     goto adat_error;
  343.                 WriteMacInt16(p, 0x598f); p += 2;    // subq.l    #4,sp
  344.                 WriteMacInt16(p, 0x2f09); p += 2;    // move.l    a1,-(sp)
  345.                 WriteMacInt16(p, 0x2f08); p += 2;    // move.l    a0,-(sp)
  346.                 WriteMacInt16(p, 0x2f3c); p += 2;    // move.l    #$00040004,-(sp)
  347.                 WriteMacInt32(p, 0x00040004); p+= 4;
  348.                 WriteMacInt16(p, 0x7000); p += 2;    // moveq    #0,d0
  349.                 WriteMacInt16(p, 0xa82a); p += 2;    // ComponentDispatch
  350.                 WriteMacInt16(p, 0x201f); p += 2;    // move.l    (sp)+,d0
  351.                 WriteMacInt16(p, M68K_RTS); p += 2;    // rts
  352.                 if (p - audio_data != adatData)
  353.                     goto adat_error;
  354.             }
  355.             AudioAvailable = true;
  356.             if (open_count == 0)
  357.                 audio_enter_stream();
  358.             open_count++;
  359.             return noErr;
  360.  
  361. adat_error:    printf("FATAL: audio component data block initialization error\n");
  362.             QuitEmulator();
  363.             return openErr;
  364.  
  365.         case kComponentCanDoSelect:
  366.         case kComponentRegisterSelect:
  367.             return noErr;
  368.  
  369.         case kComponentVersionSelect:
  370.             return 0x00010003;
  371.  
  372.         case kComponentCloseSelect:
  373.             open_count--;
  374.             if (open_count == 0) {
  375.                 if (AudioStatus.mixer) {
  376.                     // Close Apple Mixer
  377.                     r.a[0] = AudioStatus.mixer;
  378.                     Execute68k(audio_data + adatCloseMixer, &r);
  379.                     AudioStatus.mixer = 0;
  380.                     return r.d[0];
  381.                 }
  382.                 AudioStatus.num_sources = 0;
  383.                 audio_exit_stream();
  384.             }
  385.             return noErr;
  386.  
  387.         // Sound component functions
  388.         case kSoundComponentInitOutputDeviceSelect:
  389.             D(bug(" InitOutputDevice\n"));
  390.             if (!audio_open)
  391.                 return noHardwareErr;
  392.             if (AudioStatus.mixer)
  393.                 return noErr;
  394.  
  395.             // Init sound component data
  396.             WriteMacInt32(audio_data + adatData + scd_flags, 0);
  397.             WriteMacInt32(audio_data + adatData + scd_format, AudioStatus.sample_size == 16 ? 'twos' : 'raw ');
  398.             WriteMacInt16(audio_data + adatData + scd_numChannels, AudioStatus.channels);
  399.             WriteMacInt16(audio_data + adatData + scd_sampleSize, AudioStatus.sample_size);
  400.             WriteMacInt32(audio_data + adatData + scd_sampleRate, AudioStatus.sample_rate);
  401.             WriteMacInt32(audio_data + adatData + scd_sampleCount, audio_frames_per_block);
  402.             WriteMacInt32(audio_data + adatData + scd_buffer, 0);
  403.             WriteMacInt32(audio_data + adatData + scd_reserved, 0);
  404.             WriteMacInt32(audio_data + adatStreamInfo, 0);
  405.  
  406.             // Open Apple Mixer
  407.             r.a[0] = audio_data + adatMixer;
  408.             r.d[0] = 0;
  409.             r.a[1] = audio_data + adatData;
  410.             Execute68k(audio_data + adatOpenMixer, &r);
  411.             AudioStatus.mixer = ReadMacInt32(audio_data + adatMixer);
  412.             D(bug(" OpenMixer() returns %08lx, mixer %08lx\n", r.d[0], AudioStatus.mixer));
  413.             return r.d[0];
  414.  
  415.         case kSoundComponentAddSourceSelect:
  416.             D(bug(" AddSource\n"));
  417.             AudioStatus.num_sources++;
  418.             goto delegate;
  419.  
  420.         case kSoundComponentRemoveSourceSelect:
  421.             D(bug(" RemoveSource\n"));
  422.             AudioStatus.num_sources--;
  423.             goto delegate;
  424.  
  425.         case kSoundComponentStopSourceSelect:
  426.             D(bug(" StopSource\n"));
  427.             goto delegate;
  428.  
  429.         case kSoundComponentPauseSourceSelect:
  430.             D(bug(" PauseSource\n"));
  431. delegate:    // Delegate call to Apple Mixer
  432.             D(bug(" delegating call to Apple Mixer\n"));
  433.             r.a[0] = AudioStatus.mixer;
  434.             r.a[1] = params;
  435.             Execute68k(audio_data + adatDelegateCall, &r);
  436.             D(bug(" returns %08lx\n", r.d[0]));
  437.             return r.d[0];
  438.  
  439.         case kSoundComponentStartSourceSelect:
  440.             D(bug(" StartSource\n"));
  441.             return noErr;
  442.  
  443.         case kSoundComponentGetInfoSelect:
  444.             return AudioGetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
  445.  
  446.         case kSoundComponentSetInfoSelect:
  447.             return AudioSetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
  448.  
  449.         case kSoundComponentPlaySourceBufferSelect:
  450.             D(bug(" PlaySourceBuffer\n"));
  451.             r.d[0] = ReadMacInt32(p);
  452.             r.a[0] = ReadMacInt32(p + 4);
  453.             r.a[1] = ReadMacInt32(p + 8);
  454.             r.a[2] = AudioStatus.mixer;
  455.             Execute68k(audio_data + adatPlaySourceBuffer, &r);
  456.             D(bug(" returns %08lx\n", r.d[0]));
  457.             return r.d[0];
  458.  
  459.         default:
  460.             return badComponentSelector;
  461.     }
  462. }
  463.