diff src/audio/nds/SDL_ndsaudio.c @ 3976:8582c6a5ca16 SDL-1.2

Added initial support for Nintendo DS, based on the work by Troy Davis (GPF)
author Sam Lantinga <slouken@libsdl.org>
date Mon, 25 Jun 2007 00:50:20 +0000
parents
children a1b03ba2fcd0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/nds/SDL_ndsaudio.c	Mon Jun 25 00:50:20 2007 +0000
@@ -0,0 +1,335 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2006 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+/* Allow access to a raw mixing buffer */
+#include <nds.h>
+#include "SDL.h"
+#include "SDL_endian.h"
+#include "SDL_timer.h"
+#include "SDL_audio.h"
+#include "../SDL_audiomem.h"
+#include "../SDL_audio_c.h"
+#include "SDL_ndsaudio.h"
+#include "soundcommon.h"
+
+
+/* Audio driver functions */
+static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec);
+static void NDS_WaitAudio(_THIS);
+static void NDS_PlayAudio(_THIS);
+static Uint8 *NDS_GetAudioBuf(_THIS);
+static void NDS_CloseAudio(_THIS);
+
+/* Audio driver bootstrap functions */
+
+u32 framecounter = 0,soundoffset = 0;
+static SDL_AudioDevice *sdl_nds_audiodevice; 
+
+//void SoundMixCallback(void *stream,u32 size)
+//{
+//	//printf("SoundMixCallback\n");
+//	
+//	Uint8 *buffer;
+//	 
+// 	buffer = sdl_nds_audiodevice->hidden->mixbuf;
+//	memset(buffer, sdl_nds_audiodevice->spec.silence, size);
+//	
+//	if (!sdl_nds_audiodevice->paused){ 
+//		 
+//
+//	//if (sdl_nds_audiodevice->convert.needed) {
+//	//	int silence;
+//
+//	//	if (sdl_nds_audiodevice->convert.src_format == AUDIO_U8 ) { 
+//	//		silence = 0x80;
+//	//	} else {
+//	//		silence =  0; 
+//	//	}
+//	//	memset(sdl_nds_audiodevice->convert.buf, silence, sdl_nds_audiodevice->convert.len);
+//	//	sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata,
+//	//		(Uint8 *)sdl_nds_audiodevice->convert.buf,sdl_nds_audiodevice->convert.len);
+//	//	SDL_ConvertAudio(&sdl_nds_audiodevice->convert);
+//	//	memcpy(buffer, sdl_nds_audiodevice->convert.buf, sdl_nds_audiodevice->convert.len_cvt);
+//	//} else 
+//	{
+//		sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, buffer, size);
+//		//memcpy((Sint16 *)stream,buffer, size);
+//	}
+//
+//	}
+//
+//	if(soundsystem->format == 8)
+//	{
+//		int i;
+//		s32 *buffer32 = (s32 *)buffer; 
+//		s32 *stream32 = (s32 *)stream;
+//		for(i=0;i<size/4;i++){ *stream32++ = buffer32[i] ^ 0x80808080;}
+//		//for(i = 0; i < size; i++)
+//		//	((s8*)stream)[i]=(buffer[i]^0x80);
+//	}
+//	else
+//	{
+//		int i;
+//		for(i = 0; i < size; i++){
+//			//((short*)stream)[i] =(short)buffer[i] << 8;				// sound 8bit ---> buffer 16bit
+//			//if (buffer[i] &0x80)
+//				//((Sint16*)stream)[i] = 0xff00 | buffer[i];
+//			((Sint16*)stream)[i] = (buffer[i] - 128) << 8;
+//
+//			//else
+//			//	((Sint16*)stream)[i] = buffer[i];
+//		}
+//		//register signed char *pSrc =buffer;
+//		//register short *pDest =stream;
+//		//int x;
+//		//			for (x=size; x>0; x--)
+//		//			{
+//		//				register short temp = (((short)*pSrc)-128)<<8;
+//		//				pSrc++;
+//		//				*pDest++ = temp;
+//		//			}
+//
+//		//memcpy((Sint16 *)stream,buffer, size);
+//	}
+//}
+
+void SoundMixCallback(void *stream,u32 len)
+{
+	SDL_AudioDevice *audio = (SDL_AudioDevice *)sdl_nds_audiodevice;
+
+	/* Silence the buffer, since it's ours */
+	SDL_memset(stream, audio->spec.silence, len);
+
+	/* Only do soemthing if audio is enabled */
+	if ( ! audio->enabled )
+		return;
+
+	if ( ! audio->paused ) {
+		if ( audio->convert.needed ) {
+			//fprintf(stderr,"converting audio\n");
+			SDL_mutexP(audio->mixer_lock);
+			(*audio->spec.callback)(audio->spec.userdata,
+				(Uint8 *)audio->convert.buf,audio->convert.len);
+			SDL_mutexV(audio->mixer_lock);
+			SDL_ConvertAudio(&audio->convert);
+			SDL_memcpy(stream,audio->convert.buf,audio->convert.len_cvt);
+		} else {
+			SDL_mutexP(audio->mixer_lock);
+			(*audio->spec.callback)(audio->spec.userdata,
+						(Uint8 *)stream, len);
+			SDL_mutexV(audio->mixer_lock);
+		}
+	}
+	return;
+}
+void MixSound(void)
+{
+	int remain;
+
+	if(soundsystem->format == 8)
+	{
+		if((soundsystem->soundcursor + soundsystem->numsamples) > soundsystem->buffersize)
+		{
+			SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->buffersize - soundsystem->soundcursor);
+			remain = soundsystem->numsamples - (soundsystem->buffersize - soundsystem->soundcursor);
+			SoundMixCallback(soundsystem->mixbuffer,remain);
+		}
+		else
+		{
+			SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->numsamples);
+		}
+	}
+	else
+	{
+		if((soundsystem->soundcursor + soundsystem->numsamples) > (soundsystem->buffersize >> 1))
+		{
+			SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],(soundsystem->buffersize >> 1) - soundsystem->soundcursor);
+			remain = soundsystem->numsamples - ((soundsystem->buffersize >> 1) - soundsystem->soundcursor);
+			SoundMixCallback(soundsystem->mixbuffer,remain);
+		}
+		else
+		{
+			SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],soundsystem->numsamples);
+		}
+	}
+}
+
+void InterruptHandler(void)
+{
+	framecounter++;
+}
+void FiFoHandler(void)
+{
+	u32 command;
+	while ( !(REG_IPC_FIFO_CR & (IPC_FIFO_RECV_EMPTY)) ) 
+	{
+		command = REG_IPC_FIFO_RX;
+
+		switch(command)
+		{
+		case FIFO_NONE:
+			break;
+		case UPDATEON_ARM9:
+			REG_IME = 0;
+			MixSound();
+			REG_IME = 1;
+			SendCommandToArm7(MIXCOMPLETE_ONARM9);
+			break;
+		}
+	}
+}
+
+
+
+
+
+static int Audio_Available(void)
+{
+	return(1);
+}
+
+static void Audio_DeleteDevice(SDL_AudioDevice *device)
+{
+}
+
+static SDL_AudioDevice *Audio_CreateDevice(int devindex)
+{
+	
+	SDL_AudioDevice *this;
+
+	/* Initialize all variables that we clean on shutdown */
+	this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
+	if ( this ) {
+		SDL_memset(this, 0, (sizeof *this));
+		this->hidden = (struct SDL_PrivateAudioData *)
+				SDL_malloc((sizeof *this->hidden));
+	}
+	if ( (this == NULL) || (this->hidden == NULL) ) {
+		SDL_OutOfMemory();
+		if ( this ) {
+			SDL_free(this);
+		}
+		return(0);
+	}
+	SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+	/* Set the function pointers */
+	this->OpenAudio = NDS_OpenAudio;
+	this->WaitAudio = NDS_WaitAudio;
+	this->PlayAudio = NDS_PlayAudio;
+	this->GetAudioBuf = NDS_GetAudioBuf;
+	this->CloseAudio = NDS_CloseAudio;
+
+	this->free = Audio_DeleteDevice;
+//fprintf(stderr,"Audio_CreateDevice\n");
+	return this;
+}
+
+AudioBootStrap NDSAUD_bootstrap = {
+	"nds", "NDS audio",
+	Audio_Available, Audio_CreateDevice
+};
+
+
+void static NDS_WaitAudio(_THIS)
+{
+	//printf("NDS_WaitAudio\n");
+}
+
+static void NDS_PlayAudio(_THIS)
+{
+	//printf("playing audio\n");
+	if (this->paused)
+		return;
+	
+}
+
+static Uint8 *NDS_GetAudioBuf(_THIS)
+{
+	return NULL;//(this->hidden->mixbuf); 
+}
+
+static void NDS_CloseAudio(_THIS)
+{
+/*	if ( this->hidden->mixbuf != NULL ) {
+		SDL_FreeAudioMem(this->hidden->mixbuf);
+		this->hidden->mixbuf = NULL;
+	}*/ 
+}
+
+static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec)
+{
+	//printf("NDS_OpenAudio\n");
+	int format = 0;
+	//switch(spec->format&0xff) {
+	//case  8: spec->format = AUDIO_S8;format=8; break;
+	//case 16: spec->format = AUDIO_S16LSB;format=16; break;
+	//default:
+	//	SDL_SetError("Unsupported audio format");
+	//	return(-1);
+	//}
+	switch (spec->format&~0x1000) {
+		case AUDIO_S8:
+			/* Signed 8-bit audio supported */
+			format=8;
+			break;
+		case AUDIO_U8:
+			spec->format ^= 0x80;format=8;
+			break;
+		case AUDIO_U16:
+			/* Unsigned 16-bit audio unsupported, convert to S16 */
+			spec->format ^=0x8000;format=16;
+		case AUDIO_S16:
+			/* Signed 16-bit audio supported */
+			format=16;
+			break;
+	}
+	/* Update the fragment size as size in bytes */
+	SDL_CalculateAudioSpec(spec);
+
+	/* Allocate mixing buffer */
+	//this->hidden->mixlen = spec->size;
+	//this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+	//if ( this->hidden->mixbuf == NULL ) {
+	//	SDL_SetError("Out of Memory");
+	//	return(-1);
+	//} 
+
+	SDL_NDSAudio_mutex = 0; 
+	sdl_nds_audiodevice=this;
+	
+	irqInit();
+	irqSet(IRQ_VBLANK,&InterruptHandler);
+	irqSet(IRQ_FIFO_NOT_EMPTY,&FiFoHandler);
+	irqEnable(IRQ_FIFO_NOT_EMPTY);
+	
+	REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR | IPC_FIFO_RECV_IRQ;
+
+
+
+	SoundSystemInit(spec->freq,spec->size,0,format);
+	SoundStartMixer();
+
+	
+	return(1);
+}