home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / snd_amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  7.9 KB  |  302 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.  
  52. #define NSAMPLES 0x4000
  53.  
  54. extern long sysclock;
  55. extern int desired_speed;
  56. extern int FirstTime2;
  57. extern struct Library *TimerBase;
  58.  
  59. static UBYTE *dmabuf = NULL;
  60. static UWORD period;
  61. static BYTE audio_dev = -1;
  62. static float speed;
  63. static struct MsgPort *audioport1=NULL,*audioport2=NULL;
  64. static struct IOAudio *audio1=NULL,*audio2=NULL;
  65. static struct Interrupt AudioInt;
  66. static struct Interrupt *OldInt;
  67. static short OldINTENA = 0;
  68. struct Library *AudioBase;
  69. static int SyncCounter=0;
  70. static double timediff;
  71.  
  72. static struct {
  73.   struct Library *TimerBase;
  74.   int *FirstTime2;
  75.   double *aud_start_time;
  76. #ifdef __PPC__
  77.   struct Library *MathIeeeDoubBasBase; /* offset 12 */
  78. #endif
  79. } IntData;
  80.  
  81. #ifdef __PPC__
  82. extern struct Library *MathIeeeDoubBasBase;
  83. extern qboolean no68kFPU; /* for LC040/LC060 systems */
  84. extern void AudioIntCodeNoFPU(void);
  85. #endif
  86. extern void AudioIntCode(void);
  87. void (*audintptr)(void) = AudioIntCode;
  88.  
  89.  
  90. void SNDDMA_Shutdown(void)
  91. {
  92.   if (OldINTENA)
  93.         *(short *)0xdff09a = (OldINTENA | 0x8000);
  94.   if (OldInt)
  95.         SetIntVector(7,OldInt);
  96.   if (audio_dev == 0) {
  97.     if (!CheckIO((struct IORequest *)audio1)) {
  98.       AbortIO((struct IORequest *)audio1);
  99.       WaitPort(audioport1);
  100.       while (GetMsg(audioport1));
  101.     }
  102.     if (!CheckIO((struct IORequest *)audio2)) {
  103.       AbortIO((struct IORequest *)audio2);
  104.       WaitPort(audioport2);
  105.       while (GetMsg(audioport2));
  106.     }
  107.     CloseDevice((struct IORequest *)audio1);
  108.   }
  109.   if (audio2)
  110. #ifdef __PPC__
  111. #ifdef WOS
  112.     FreeVecPPC(audio2);
  113. #else
  114.     PPCFreeVec(audio2);
  115. #endif
  116. #else
  117.     FreeMem(audio2,sizeof(struct IOAudio));
  118. #endif
  119.  
  120.   if (audio1)
  121.     DeleteIORequest((struct IORequest *)audio1);
  122.   if (audioport2)
  123.     DeleteMsgPort(audioport2);
  124.   if (audioport1)
  125.     DeleteMsgPort(audioport1);
  126.   if (IntData.aud_start_time)
  127.     FreeMem((void*)(IntData.aud_start_time),sizeof(double));
  128.  
  129.   if (shm)
  130. #ifdef __PPC__
  131. #ifdef WOS
  132.     FreeVecPPC((void*)shm);
  133. #else
  134.     PPCFreeVec((void*)shm);
  135. #endif
  136. #else
  137.     FreeMem((void*)shm,sizeof(dma_t));
  138. #endif
  139.  
  140.   if (dmabuf)
  141.     FreeMem(dmabuf,NSAMPLES);
  142. }
  143.  
  144.  
  145. qboolean SNDDMA_Init(void)
  146. {
  147.   int i;
  148.   UBYTE channelalloc[2] = { 1|2, 4|8 };  /* first try ch. 0/1, then 2/3 */
  149.   int channelnr;
  150.  
  151.   /* evaluate parameters */
  152.   if (i = COM_CheckParm("-audspeed")) {
  153.     period = (UWORD)(sysclock / Q_atoi(com_argv[i+1]));
  154.   }
  155.   else
  156.     period = (UWORD)(sysclock / desired_speed);
  157.  
  158. #ifdef __PPC__
  159.   if (no68kFPU)
  160.     audintptr = AudioIntCodeNoFPU; /* use mathieeedoubbas.library */
  161. #endif
  162.  
  163.   /* allocate dma buffer and sound structure */
  164.   if (!(dmabuf = AllocMem(NSAMPLES,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR))) {
  165.     Con_Printf("Can't allocate Paula DMA buffer");
  166.     return (false);
  167.   }
  168. #ifdef __PPC__
  169. #ifdef WOS
  170.   if (!(shm = AllocVecPPC(sizeof(dma_t),MEMF_ANY|MEMF_CLEAR,0))) {
  171. #else
  172.   if (!(shm = PPCAllocVec(sizeof(dma_t),MEMF_ANY|MEMF_CLEAR))) {
  173. #endif
  174. #else
  175.   if (!(shm = AllocMem(sizeof(dma_t),MEMF_ANY|MEMF_CLEAR))) {
  176. #endif
  177.     Con_Printf("Failed to allocate shm");
  178.     return (false);
  179.   }
  180.   if (!(IntData.aud_start_time = AllocMem(sizeof(double),MEMF_CHIP|MEMF_CLEAR))) {
  181.     Con_Printf("Failed to allocate 8 bytes of CHIP-RAM buffer");
  182.     return (false);
  183.   }
  184.  
  185.   /* init shm */
  186.   shm->buffer = (unsigned char *)dmabuf;
  187.   shm->channels = 1;
  188.   shm->speed = sysclock/(long)period;
  189.   shm->samplebits = 8;
  190.   shm->samples = NSAMPLES;
  191.   shm->submission_chunk = 1;
  192.   speed = (float)shm->speed;
  193.  
  194.  
  195.   /* open audio.device */
  196.   if (audioport1 = CreateMsgPort()) {
  197.     if (audioport2 = CreateMsgPort()) {
  198.         if (audio1 = (struct IOAudio *)CreateIORequest(audioport1,
  199.                       sizeof(struct IOAudio))) {
  200. #ifdef __PPC__
  201. #ifdef WOS
  202.           if (audio2 = (struct IOAudio *)AllocVecPPC(sizeof(struct IOAudio),
  203.                         MEMF_PUBLIC,0)) {
  204. #else
  205.           if (audio2 = (struct IOAudio *)PPCAllocVec(sizeof(struct IOAudio),
  206.                         MEMF_PUBLIC)) {
  207. #endif
  208. #else
  209.           if (audio2 = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  210.                         MEMF_PUBLIC)) {
  211. #endif
  212.               audio1->ioa_Request.io_Message.mn_Node.ln_Pri = ADALLOC_MAXPREC;
  213.               audio1->ioa_Request.io_Command = ADCMD_ALLOCATE;
  214.               audio1->ioa_Request.io_Flags = ADIOF_NOWAIT;
  215.               audio1->ioa_AllocKey = 0;
  216.               audio1->ioa_Data = channelalloc;
  217.               audio1->ioa_Length = sizeof(channelalloc);
  218.               audio_dev = OpenDevice(AUDIONAME,0,
  219.                                      (struct IORequest *)audio1,0);
  220.           }
  221.         }
  222.     }
  223.   }
  224.  
  225.   if (audio_dev == 0) {
  226.     /* set up audio io blocks */
  227.     AudioBase = (struct Library *)audio1->ioa_Request.io_Device;
  228.     audio1->ioa_Request.io_Command = CMD_WRITE;
  229.     audio1->ioa_Request.io_Flags = ADIOF_PERVOL;
  230.     audio1->ioa_Data = dmabuf;
  231.     audio1->ioa_Length = NSAMPLES;
  232.     audio1->ioa_Period = period;
  233.     audio1->ioa_Volume = 64;
  234.     audio1->ioa_Cycles = 0;  /* loop forever */
  235.     *audio2 = *audio1;
  236.     audio2->ioa_Request.io_Message.mn_ReplyPort = audioport2;
  237.     audio1->ioa_Request.io_Unit = (struct Unit *)
  238.                                    ((ULONG)audio1->ioa_Request.io_Unit & 9);
  239.     audio2->ioa_Request.io_Unit = (struct Unit *)
  240.                                    ((ULONG)audio2->ioa_Request.io_Unit & 6);
  241.  
  242.   }
  243.   else {
  244.     Con_Printf("Couldn't open audio.device");
  245.     return (false);
  246.   }
  247.   IntData.TimerBase = TimerBase;
  248.   IntData.FirstTime2 = &FirstTime2;
  249.   AudioInt.is_Node.ln_Type = NT_INTERRUPT;
  250.   AudioInt.is_Node.ln_Pri = 0;
  251.   AudioInt.is_Data = &IntData;
  252.   AudioInt.is_Code = (void(*)())audintptr;
  253.   switch ((ULONG)audio1->ioa_Request.io_Unit) {
  254.     case 1: channelnr = 0;break;
  255.     case 2: channelnr = 1;break;
  256.     case 4: channelnr = 2;break;
  257.     case 8: channelnr = 3;break;
  258.   }
  259.   BeginIO((struct IORequest *)audio1);
  260.   BeginIO((struct IORequest *)audio2);
  261.   while (*(short *)0xdff01c & (0x0080 << channelnr));
  262.   OldInt = SetIntVector(channelnr+7,&AudioInt);
  263.   OldINTENA = *(short *)0xdff01c;
  264.   *IntData.aud_start_time = 0;
  265.   *(short *)0xdff09a = OldINTENA | (0xc000 | (0x0080 << channelnr));
  266.   return (true);
  267. }
  268.  
  269.  
  270. int SNDDMA_GetDMAPos(void)
  271. {
  272.   int pos;
  273. #ifdef __PPC__
  274.   static struct timeval tv;
  275.   double time;
  276.  
  277.   while (!(*IntData.aud_start_time));
  278.   if (SyncCounter == 0)
  279.   {
  280.     GetSysTime(&tv);
  281.     time = ((double)(tv.tv_secs-FirstTime2) + 
  282.             (((double)tv.tv_micro) / 1000000.0));
  283.     timediff = (Sys_DoubleTime()) - time;
  284.   }
  285.   SyncCounter = (SyncCounter + 1) % 50;
  286.   pos = (int)((Sys_DoubleTime()-(*IntData.aud_start_time+timediff))*speed);
  287.  
  288. #else
  289.   while (!(*IntData.aud_start_time));
  290.   pos = (int)((Sys_DoubleTime()-*IntData.aud_start_time)*speed);
  291. #endif
  292.  
  293.   if (pos >= NSAMPLES)
  294.         pos = 0;
  295.   return (shm->samplepos = pos);
  296. }
  297.  
  298.  
  299. void SNDDMA_Submit(void)
  300. {
  301. }
  302.