home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / snd_amiga.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  9KB  |  342 lines

  1. /* 
  2. Copyright (C) 1996-1997 Id Software, Inc. 
  3.  
  4. This program is free software; you can redistribute it and/or 
  5. modify it under the terms of the GNU General Public License 
  6. as published by the Free Software Foundation; either version 2 
  7. of the License, or (at your option) any later version. 
  8.  
  9. This program is distributed in the hope that it will be useful, 
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of 
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   
  12.  
  13. See the GNU General Public License for more details. 
  14.  
  15. You should have received a copy of the GNU General Public License 
  16. along with this program; if not, write to the Free Software 
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
  18.  
  19. */ 
  20.  
  21. /*
  22. **  snd_amiga.c
  23. **
  24. **  Paula sound driver
  25. **
  26. **  Written by Frank Wille <frank@phoenix.owl.de>
  27. **
  28. */
  29.  
  30. #include "quakedef.h"
  31.  
  32. #pragma amiga-align
  33. #include <exec/memory.h>
  34. #include <exec/tasks.h>
  35. #include <exec/interrupts.h>
  36. #include <exec/libraries.h>
  37. #include <devices/audio.h>
  38. #include <clib/exec_protos.h>
  39. #include <clib/alib_protos.h>
  40. #include <clib/dos_protos.h>
  41. #ifdef __PPC__
  42. #include <clib/timer_protos.h>
  43. #ifdef WOS
  44. #include <clib/powerpc_protos.h>
  45. #else
  46. #include <powerup/gcclib/powerup_protos.h>
  47. #endif
  48. #endif
  49. #pragma default-align
  50.  
  51. #ifdef __STORM__
  52. #ifndef PPC
  53. #define PPC
  54. #endif // PPC
  55.  
  56. #include <libraries/powerpc.h>
  57.  
  58. #include <ppcamiga.h>
  59.  
  60. void BeginIOAudioPPC(struct IORequest *arg1)
  61. {
  62.     extern struct Library *AudioBase;
  63.     ULONG regs[16];
  64.     regs[9] = (ULONG) arg1;
  65.     __CallLibrary(AudioBase,-30,regs);
  66. }
  67.  
  68. struct Interrupt *SetIntVectorPPC(long arg1, struct Interrupt *arg2)
  69. {
  70.     extern struct Library *SysBase;
  71.     ULONG regs[16];
  72.     regs[0] = (ULONG) arg1;
  73.     regs[9] = (ULONG) arg2;
  74.     __CallLibrary(SysBase,-162,regs);
  75.     return (struct Interrupt*) regs[0];
  76. }
  77. #endif
  78.  
  79.  
  80. #define NSAMPLES 0x4000
  81.  
  82. extern long sysclock;
  83. extern int desired_speed;
  84. extern int FirstTime2;
  85. extern struct Library *TimerBase;
  86.  
  87. static UBYTE *dmabuf = NULL;
  88. static UWORD period;
  89. static BYTE audio_dev = -1;
  90. static float speed;
  91. static struct MsgPort *audioport1=NULL,*audioport2=NULL;
  92. static struct IOAudio *audio1=NULL,*audio2=NULL;
  93. static struct Interrupt AudioInt;
  94. static struct Interrupt *OldInt;
  95. static short OldINTENA = 0;
  96. struct Library *AudioBase;
  97. static int SyncCounter=0;
  98. static double timediff;
  99.  
  100. static struct {
  101.   struct Library *TimerBase;
  102.   int *FirstTime2;
  103.   double *aud_start_time;
  104. #ifdef __PPC__
  105.   struct Library *MathIeeeDoubBasBase; /* offset 12 */
  106. #endif
  107. } IntData;
  108.  
  109. #ifdef __PPC__
  110. extern struct Library *MathIeeeDoubBasBase;
  111. extern qboolean no68kFPU; /* for LC040/LC060 systems */
  112. extern void AudioIntCodeNoFPU(void);
  113. #endif
  114. extern void AudioIntCode(void);
  115. void (*audintptr)(void) = AudioIntCode;
  116.  
  117.  
  118. void SNDDMA_Shutdown(void)
  119. {
  120.   if (OldINTENA)
  121.         *(short *)0xdff09a = (OldINTENA | 0x8000);
  122.   if (OldInt)
  123.         SetIntVector(7,OldInt);
  124.   if (audio_dev == 0) {
  125.     if (!CheckIO((struct IORequest *)audio1)) {
  126.       AbortIO((struct IORequest *)audio1);
  127.       WaitPort(audioport1);
  128.       while (GetMsg(audioport1));
  129.     }
  130.     if (!CheckIO((struct IORequest *)audio2)) {
  131.       AbortIO((struct IORequest *)audio2);
  132.       WaitPort(audioport2);
  133.       while (GetMsg(audioport2));
  134.     }
  135.     CloseDevice((struct IORequest *)audio1);
  136.   }
  137.   if (audio2)
  138. #ifdef __PPC__
  139. #ifdef WOS
  140.     FreeVecPPC(audio2);
  141. #else
  142.     PPCFreeVec(audio2);
  143. #endif
  144. #else
  145.     FreeMem(audio2,sizeof(struct IOAudio));
  146. #endif
  147.  
  148.   if (audio1)
  149.     DeleteIORequest((struct IORequest *)audio1);
  150.   if (audioport2)
  151.     DeleteMsgPort(audioport2);
  152.   if (audioport1)
  153.     DeleteMsgPort(audioport1);
  154.   if (IntData.aud_start_time)
  155.     FreeMem((void*)(IntData.aud_start_time),sizeof(double));
  156.  
  157.   if (shm)
  158. #ifdef __PPC__
  159. #ifdef WOS
  160.     FreeVecPPC((void*)shm);
  161. #else
  162.     PPCFreeVec((void*)shm);
  163. #endif
  164. #else
  165.     FreeMem((void*)shm,sizeof(dma_t));
  166. #endif
  167.  
  168.   if (dmabuf)
  169.     FreeMem(dmabuf,NSAMPLES);
  170. }
  171.  
  172.  
  173. qboolean SNDDMA_Init(void)
  174. {
  175.   int i;
  176.   UBYTE channelalloc[2] = { 1|2, 4|8 };  /* first try ch. 0/1, then 2/3 */
  177.   int channelnr;
  178.  
  179.   /* evaluate parameters */
  180.   if (i = COM_CheckParm("-audspeed")) {
  181.     period = (UWORD)(sysclock / Q_atoi(com_argv[i+1]));
  182.   }
  183.   else
  184.     period = (UWORD)(sysclock / desired_speed);
  185.  
  186. #ifdef __PPC__
  187.   if (no68kFPU)
  188.     audintptr = AudioIntCodeNoFPU; /* use mathieeedoubbas.library */
  189. #endif
  190.  
  191.   /* allocate dma buffer and sound structure */
  192.   if (!(dmabuf = AllocMem(NSAMPLES,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR))) {
  193.     Con_Printf("Can't allocate Paula DMA buffer\n");
  194.     return (false);
  195.   }
  196. #ifdef __PPC__
  197. #ifdef WOS
  198.   if (!(shm = AllocVecPPC(sizeof(dma_t),MEMF_ANY|MEMF_CLEAR,0))) {
  199. #else
  200.   if (!(shm = PPCAllocVec(sizeof(dma_t),MEMF_ANY|MEMF_CLEAR))) {
  201. #endif
  202. #else
  203.   if (!(shm = AllocMem(sizeof(dma_t),MEMF_ANY|MEMF_CLEAR))) {
  204. #endif
  205.     Con_Printf("Failed to allocate shm\n");
  206.     return (false);
  207.   }
  208.   if (!(IntData.aud_start_time = AllocMem(sizeof(double),MEMF_CHIP|MEMF_CLEAR))) {
  209.     Con_Printf("Failed to allocate 8 bytes of CHIP-RAM buffer\n");
  210.     return (false);
  211.   }
  212.  
  213.   /* init shm */
  214.   shm->buffer = (unsigned char *)dmabuf;
  215.   shm->channels = 1;
  216.   shm->speed = sysclock/(long)period;
  217.   shm->samplebits = 8;
  218.   shm->samples = NSAMPLES;
  219.   shm->submission_chunk = 1;
  220.   speed = (float)shm->speed;
  221.  
  222.  
  223.   /* open audio.device */
  224.   if (audioport1 = CreateMsgPort()) {
  225.     if (audioport2 = CreateMsgPort()) {
  226.         if (audio1 = (struct IOAudio *)CreateIORequest(audioport1,
  227.                       sizeof(struct IOAudio))) {
  228. #ifdef __PPC__
  229. #ifdef WOS
  230.           if (audio2 = (struct IOAudio *)AllocVecPPC(sizeof(struct IOAudio),
  231.                         MEMF_PUBLIC,0)) {
  232. #else
  233.           if (audio2 = (struct IOAudio *)PPCAllocVec(sizeof(struct IOAudio),
  234.                         MEMF_PUBLIC)) {
  235. #endif
  236. #else
  237.           if (audio2 = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  238.                         MEMF_PUBLIC)) {
  239. #endif
  240.               audio1->ioa_Request.io_Message.mn_Node.ln_Pri = ADALLOC_MAXPREC;
  241.               audio1->ioa_Request.io_Command = ADCMD_ALLOCATE;
  242.               audio1->ioa_Request.io_Flags = ADIOF_NOWAIT;
  243.               audio1->ioa_AllocKey = 0;
  244.               audio1->ioa_Data = channelalloc;
  245.               audio1->ioa_Length = sizeof(channelalloc);
  246.               audio_dev = OpenDevice(AUDIONAME,0,
  247.                                      (struct IORequest *)audio1,0);
  248.           }
  249.         }
  250.     }
  251.   }
  252.  
  253.   if (audio_dev == 0) {
  254.     /* set up audio io blocks */
  255.     AudioBase = (struct Library *)audio1->ioa_Request.io_Device;
  256.     audio1->ioa_Request.io_Command = CMD_WRITE;
  257.     audio1->ioa_Request.io_Flags = ADIOF_PERVOL;
  258.     audio1->ioa_Data = dmabuf;
  259.     audio1->ioa_Length = NSAMPLES;
  260.     audio1->ioa_Period = period;
  261.     audio1->ioa_Volume = 64;
  262.     audio1->ioa_Cycles = 0;  /* loop forever */
  263.     *audio2 = *audio1;
  264.     audio2->ioa_Request.io_Message.mn_ReplyPort = audioport2;
  265.     audio1->ioa_Request.io_Unit = (struct Unit *)
  266.                                    ((ULONG)audio1->ioa_Request.io_Unit & 9);
  267.     audio2->ioa_Request.io_Unit = (struct Unit *)
  268.                                    ((ULONG)audio2->ioa_Request.io_Unit & 6);
  269.  
  270.   }
  271.   else {
  272.     Con_Printf("Couldn't open audio.device\n");
  273.     return (false);
  274.   }
  275.   IntData.TimerBase = TimerBase;
  276.   IntData.FirstTime2 = &FirstTime2;
  277. #ifdef __PPC__
  278.   IntData.MathIeeeDoubBasBase = MathIeeeDoubBasBase;
  279. #endif
  280.   AudioInt.is_Node.ln_Type = NT_INTERRUPT;
  281.   AudioInt.is_Node.ln_Pri = 0;
  282.   AudioInt.is_Data = &IntData;
  283.   AudioInt.is_Code = (void(*)())audintptr;
  284.   switch ((ULONG)audio1->ioa_Request.io_Unit) {
  285.     case 1: channelnr = 0;break;
  286.     case 2: channelnr = 1;break;
  287.     case 4: channelnr = 2;break;
  288.     case 8: channelnr = 3;break;
  289.   }
  290. #ifdef __STORM__
  291.   BeginIOAudioPPC((struct IORequest *)audio1);
  292.   BeginIOAudioPPC((struct IORequest *)audio2);
  293. #else
  294.   BeginIO((struct IORequest *)audio1);
  295.   BeginIO((struct IORequest *)audio2);
  296. #endif
  297.   while (*(short *)0xdff01c & (0x0080 << channelnr));
  298. #ifdef __STORM__
  299.   OldInt = SetIntVectorPPC(channelnr+7,&AudioInt);
  300. #else
  301.   OldInt = SetIntVector(channelnr+7,&AudioInt);
  302. #endif
  303.   OldINTENA = *(short *)0xdff01c;
  304.   *IntData.aud_start_time = 0;
  305.   *(short *)0xdff09a = OldINTENA | (0xc000 | (0x0080 << channelnr));
  306.   return (true);
  307. }
  308.  
  309.  
  310. int SNDDMA_GetDMAPos(void)
  311. {
  312.   int pos;
  313. #ifdef __PPC__
  314.   static struct timeval tv;
  315.   double time;
  316.  
  317.   while (!(*IntData.aud_start_time));
  318.   if (SyncCounter == 0)
  319.   {
  320.     GetSysTime(&tv);
  321.     time = ((double)(tv.tv_secs-FirstTime2) + 
  322.             (((double)tv.tv_micro) / 1000000.0));
  323.     timediff = (Sys_FloatTime()) - time;
  324.   }
  325.   SyncCounter = (SyncCounter + 1) % 50;
  326.   pos = (int)((Sys_FloatTime()-(*IntData.aud_start_time+timediff))*speed);
  327.  
  328. #else
  329.   while (!(*IntData.aud_start_time));
  330.   pos = (int)((Sys_FloatTime()-*IntData.aud_start_time)*speed);
  331. #endif
  332.  
  333.   if (pos >= NSAMPLES)
  334.         pos = 0;
  335.   return (shm->samplepos = pos);
  336. }
  337.  
  338.  
  339. void SNDDMA_Submit(void)
  340. {
  341. }
  342.