home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (C) 1996-1997 Id Software, Inc.
-
- 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.
-
- */
- // snd_amiga.c
-
- #include <exec/exec.h>
- #include <dos/dos.h>
- #include <graphics/gfxbase.h>
- #include <devices/audio.h>
-
- #include <powerpc/powerpc.h>
- #include <powerpc/powerpc_protos.h>
- extern struct GfxBase *GfxBase;
-
- #include <powerup/ppcproto/exec.h>
- #include <powerup/ppcproto/dos.h>
- #include <powerup/ppcproto/graphics.h>
-
- #include "quakedef.h"
-
- #define BeginIO(ioRequest) _BeginIO(ioRequest)
- __inline void
- _BeginIO(struct IORequest *ioRequest)
- {
- struct PPCArgs args;
- memset(&args,0,sizeof(args));
- args.PP_Code =(APTR) ioRequest->io_Device;
- args.PP_Offset = (-30);
- args.PP_Flags = 0;
- args.PP_Regs[PPREG_A1] =(ULONG) ioRequest;
- args.PP_Regs[PPREG_A6] =(ULONG) ioRequest->io_Device;
- Run68K (&args);
- }
-
- /**********************************************************************/
-
- extern int desired_speed;
- extern int desired_bits;
-
- /**********************************************************************/
-
- #define MAXNUMCHANNELS 4 /* max number of Amiga sound channels */
- /* #define BUFFERSIZE 16384 */
- #define BUFFERSIZE 4096
-
- struct channel_info {
- struct MsgPort *audio_mp;
- struct IOAudio *audio_io;
- double starttime;
- BOOL sound_in_progress;
- };
-
- static struct channel_info channel_info[MAXNUMCHANNELS] = {
- {NULL, NULL, FALSE},
- {NULL, NULL, FALSE},
- {NULL, NULL, FALSE},
- {NULL, NULL, FALSE},
- };
-
- static int size;
-
- static struct MsgPort *audio_mp = NULL;
- static struct IOAudio *audio_io = NULL;
- static BOOL audio_is_open = FALSE;
- static ULONG clock_constant; /* see Amiga Hardware Manual page 141 */
- static UWORD period;
- static double twice_real_speed;
-
- /**********************************************************************/
- // Stops a sound channel.
-
- static void stopsound (int cnum)
- {
- if (!audio_is_open)
- return;
- if (channel_info[cnum].sound_in_progress) {
- AbortIO ((struct IORequest *)channel_info[cnum].audio_io);
- WaitPort (channel_info[cnum].audio_mp);
- GetMsg (channel_info[cnum].audio_mp);
- channel_info[cnum].sound_in_progress = FALSE;
- }
- }
-
- /**********************************************************************/
- // Starts a sound in a particular sound channel.
-
- static int startsound (int cnum, char *buffer, int length)
- {
- struct channel_info *c;
-
- if (!audio_is_open)
- return 1;
- stopsound (cnum);
- c = &channel_info[cnum];
- c->audio_io->ioa_Request.io_Command = CMD_WRITE;
- c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
- c->audio_io->ioa_Data = buffer;
- c->audio_io->ioa_Length = length;
- c->audio_io->ioa_Period = period;
- c->audio_io->ioa_Volume = 64;
- c->audio_io->ioa_Cycles = 0;
- BeginIO ((struct IORequest *)c->audio_io);
- c->starttime = Sys_FloatTime ();
- c->sound_in_progress = TRUE;
- return cnum;
- }
-
- /**********************************************************************/
-
- qboolean SNDDMA_Init (void)
- {
- int i;
- struct channel_info *c;
- UBYTE chans[1];
-
- // printf ("SNDDMA_Init()\n");
-
- if ((shm = (dma_t *)malloc (sizeof(dma_t))) == NULL)
- Sys_Error ("malloc() failed");
- memset((void*)shm, 0, sizeof(dma_t));
-
- if ((shm->buffer = AllocMem (BUFFERSIZE, MEMF_CHIP | MEMF_CLEAR)) == NULL)
- Sys_Error ("Out of CHIP memory for sound");
- // memset(shm->buffer, 0x80, BUFFERSIZE);
-
- // printf ("Sound buffer at 0x%08x\n", shm->buffer);
-
- shm->channels = 2;
- shm->speed = desired_speed;
- shm->samplebits = 8;
- shm->samples = BUFFERSIZE / (shm->samplebits / 8);
- shm->submission_chunk = 1;
-
- if ((audio_mp = CreateMsgPort ()) == NULL ||
- (audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
- MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
- Sys_Error ("CreateMsgPort() or AllocMem() failed");
-
- chans[0] = (1 << shm->channels) - 1; /* shm->channels Amiga audio channels */
- audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
- audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
- audio_io->ioa_AllocKey = 0;
- audio_io->ioa_Data = chans;
- audio_io->ioa_Length = sizeof(chans);
-
- if (OpenDevice (AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0)
- Sys_Error ("OpenDevice(\"audio.device\") failed");
- audio_is_open = TRUE;
-
- for (i = 0; i < shm->channels; i++) {
- c = &channel_info[i];
- if ((c->audio_mp = CreateMsgPort ()) == NULL ||
- (c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
- MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
- Sys_Error ("CreateMsgPort() or AllocMem() failed");
- *c->audio_io = *audio_io;
- c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
- c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
- }
-
- if ((GfxBase->DisplayFlags & REALLY_PAL) == 0)
- clock_constant = 3579545; /* NTSC */
- else
- clock_constant = 3546895; /* PAL */
-
- period = ((clock_constant << 1) + shm->speed) / ((shm->speed) << 1);
-
- twice_real_speed = 2.0 * ((double)clock_constant) / (double)period;
-
- startsound (0, shm->buffer, BUFFERSIZE >> 1);
- startsound (1, shm->buffer + (BUFFERSIZE >> 1), BUFFERSIZE >> 1);
-
- return 1;
- }
-
- /**********************************************************************/
-
- int SNDDMA_GetDMAPos (void)
- {
- if (shm == NULL || shm->buffer == NULL || !channel_info[0].sound_in_progress)
- return 0;
-
- shm->samplepos = ((int)((Sys_FloatTime() - channel_info[0].starttime)
- * twice_real_speed + 0.5))
- & (BUFFERSIZE - 1);
-
- // shm->samplepos = (int)(realtime*shm->speed*shm->channels) & (shm->samples-1);
-
- // if (pos < 0 || pos >= BUFFERSIZE)
- // Sys_Error ("pos = %d is out of range\n");
- return shm->samplepos;
- }
-
- /**********************************************************************/
-
- void SNDDMA_Shutdown (void)
- {
- int i;
-
- // printf ("SNDDMA_Shutdown()\n");
-
- if (audio_is_open) {
- if (shm != NULL) {
- for (i = 0; i < shm->channels; i++)
- stopsound (i);
- audio_io->ioa_Request.io_Unit = (struct Unit *)
- ((1 << shm->channels) - 1); /* free shm->channels channels */
- }
- CloseDevice ((struct IORequest *)audio_io);
- audio_is_open = FALSE;
- }
- for (i = 0; i < MAXNUMCHANNELS; i++) {
- if (channel_info[i].audio_io != NULL) {
- FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
- channel_info[i].audio_io = NULL;
- }
- if (channel_info[i].audio_mp != NULL) {
- DeleteMsgPort (channel_info[i].audio_mp);
- channel_info[i].audio_mp = NULL;
- }
- }
- if (audio_io != NULL) {
- FreeMem (audio_io, sizeof(struct IOAudio));
- audio_io = NULL;
- }
- if (audio_mp != NULL) {
- DeleteMsgPort (audio_mp);
- audio_mp = NULL;
- }
- if (shm != NULL) {
- if (shm->buffer != NULL) {
- FreeMem (shm->buffer, BUFFERSIZE);
- shm->buffer = NULL;
- }
- free ((char *)shm);
- shm = NULL;
- }
- }
-
- void SNDDMA_Submit (void)
- {
- // printf ("SNDDMA_Submit()\n");
- }
-
- /**********************************************************************/
-