diff --git a/trunk/desmume/src/cli/Makefile.am b/trunk/desmume/src/cli/Makefile.am index d52ee71ea..b902e3f9e 100644 --- a/trunk/desmume/src/cli/Makefile.am +++ b/trunk/desmume/src/cli/Makefile.am @@ -1,4 +1,4 @@ bin_PROGRAMS = desmume-cli -desmume_cli_SOURCES = main.c +desmume_cli_SOURCES = main.c ../sndsdl.c desmume_cli_LDADD = ../libdesmume.a $(SDL_LIBS) desmume_cli_CFLAGS = $(SDL_CFLAGS) diff --git a/trunk/desmume/src/cli/main.c b/trunk/desmume/src/cli/main.c index eb0f9efde..7c8b4e612 100644 --- a/trunk/desmume/src/cli/main.c +++ b/trunk/desmume/src/cli/main.c @@ -7,6 +7,7 @@ #include "../NDSSystem.h" #include "../cflash.h" #include "../debug.h" +#include "../sndsdl.h" BOOL execute = FALSE; @@ -15,6 +16,7 @@ SDL_Surface * surface; SoundInterface_struct *SNDCoreList[] = { &SNDDummy, &SNDFile, +&SNDSDL, NULL }; @@ -121,6 +123,7 @@ int main(int argc, char ** argv) { } } NDS_exec(1120380, FALSE); + SPU_Emulate(); Draw(); } diff --git a/trunk/desmume/src/gtk/Makefile.am b/trunk/desmume/src/gtk/Makefile.am index b7e827bad..696967526 100644 --- a/trunk/desmume/src/gtk/Makefile.am +++ b/trunk/desmume/src/gtk/Makefile.am @@ -1,4 +1,4 @@ bin_PROGRAMS = desmume -desmume_SOURCES = main.c desmume.c dToolsList.c tools/ioregsView.c +desmume_SOURCES = main.c desmume.c dToolsList.c tools/ioregsView.c ../sndsdl.c desmume_LDADD = ../libdesmume.a $(GTK_LIBS) desmume_CFLAGS = $(GTK_CFLAGS) diff --git a/trunk/desmume/src/gtk/desmume.c b/trunk/desmume/src/gtk/desmume.c index d8e342305..a47982048 100644 --- a/trunk/desmume/src/gtk/desmume.c +++ b/trunk/desmume/src/gtk/desmume.c @@ -52,6 +52,7 @@ BOOL desmume_running() void desmume_cycle() { desmume_last_cycle = NDS_exec((560190 << 1) - desmume_last_cycle, FALSE); + SPU_Emulate(); } void desmume_keypad(u16 k) diff --git a/trunk/desmume/src/gtk/main.c b/trunk/desmume/src/gtk/main.c index abbefde79..73144a811 100644 --- a/trunk/desmume/src/gtk/main.c +++ b/trunk/desmume/src/gtk/main.c @@ -10,6 +10,7 @@ #include "../armcpu.h" #include "../NDSSystem.h" #include "../debug.h" +#include "../sndsdl.h" #include "desmume.h" @@ -66,6 +67,7 @@ char * CONFIG_FILE; SoundInterface_struct *SNDCoreList[] = { &SNDDummy, &SNDFile, +&SNDSDL, NULL }; diff --git a/trunk/desmume/src/sndsdl.c b/trunk/desmume/src/sndsdl.c new file mode 100644 index 000000000..48611344a --- /dev/null +++ b/trunk/desmume/src/sndsdl.c @@ -0,0 +1,198 @@ +/* Copyright 2005-2006 Theo Berkau + + This file is part of DeSmuME + + DeSmuME 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. + + Yabause 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 Yabause; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#include "SDL.h" +#include "types.h" +#include "SPU.h" +#include "sndsdl.h" +#include "debug.h" + +int SNDSDLInit(); +void SNDSDLDeInit(); +void SNDSDLUpdateAudio(s16 *buffer, u32 num_samples); +u32 SNDSDLGetAudioSpace(); +void SNDSDLMuteAudio(); +void SNDSDLUnMuteAudio(); +void SNDSDLSetVolume(int volume); + +SoundInterface_struct SNDSDL = { +SNDCORE_SDL, +"SDL Sound Interface", +SNDSDLInit, +SNDSDLDeInit, +SNDSDLUpdateAudio, +SNDSDLGetAudioSpace, +SNDSDLMuteAudio, +SNDSDLUnMuteAudio, +SNDSDLSetVolume +}; + +#define NUMSOUNDBLOCKS 4 + +static u16 *stereodata16; +static u32 soundoffset; +static volatile u32 soundpos; +static u32 soundlen; +static u32 soundbufsize; +static SDL_AudioSpec audiofmt; + +////////////////////////////////////////////////////////////////////////////// + +void MixAudio(void *userdata, Uint8 *stream, int len) { + int i; + Uint8 *soundbuf=(Uint8 *)stereodata16; + + for (i = 0; i < len; i++) + { + if (soundpos >= soundbufsize) + soundpos = 0; + + stream[i] = soundbuf[soundpos]; + soundpos++; + } +} + +////////////////////////////////////////////////////////////////////////////// + +int SNDSDLInit() +{ + SDL_InitSubSystem(SDL_INIT_AUDIO); +// if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0); +// return -1; + + audiofmt.freq = 44100; + audiofmt.format = AUDIO_S16SYS; + audiofmt.channels = 2; + audiofmt.samples = (audiofmt.freq / 60) * 2; + audiofmt.callback = MixAudio; + audiofmt.userdata = NULL; + + //samples should be a power of 2 according to SDL-doc + //so normalize it to the nearest power of 2 here + u32 normSamples = 512; + while (normSamples < audiofmt.samples) + normSamples <<= 1; + + audiofmt.samples = normSamples; + + soundlen = audiofmt.freq / 60; // 60 for NTSC + soundbufsize = soundlen * NUMSOUNDBLOCKS * 2 * 2; + + if (SDL_OpenAudio(&audiofmt, NULL) != 0) + { + return -1; + } + + if ((stereodata16 = (u16 *)malloc(soundbufsize)) == NULL) + return -1; + + memset(stereodata16, 0, soundbufsize); + + soundpos = 0; + + SDL_PauseAudio(0); + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLDeInit() +{ + SDL_CloseAudio(); + + if (stereodata16) + free(stereodata16); +} + +////////////////////////////////////////////////////////////////////////////// + +int SNDSDLReset() +{ + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLUpdateAudio(s16 *buffer, u32 num_samples) +{ + u32 copy1size=0, copy2size=0; + SDL_LockAudio(); + + if ((soundbufsize - soundoffset) < (num_samples * sizeof(s16) * 2)) + { + copy1size = (soundbufsize - soundoffset); + copy2size = (num_samples * sizeof(s16) * 2) - copy1size; + } + else + { + copy1size = (num_samples * sizeof(s16) * 2); + copy2size = 0; + } + + memcpy((((u8 *)stereodata16)+soundoffset), buffer, copy1size); +// ScspConvert32uto16s((s32 *)leftchanbuffer, (s32 *)rightchanbuffer, (s16 *)(((u8 *)stereodata16)+soundoffset), copy1size / sizeof(s16) / 2); + + if (copy2size) + memcpy(stereodata16, buffer+copy1size, copy2size); +// ScspConvert32uto16s((s32 *)leftchanbuffer, (s32 *)rightchanbuffer, (s16 *)stereodata16, copy2size / sizeof(s16) / 2); + + soundoffset += copy1size + copy2size; + soundoffset %= soundbufsize; + + SDL_UnlockAudio(); +} + +////////////////////////////////////////////////////////////////////////////// + +u32 SNDSDLGetAudioSpace() +{ + u32 freespace=0; + + if (soundoffset > soundpos) + freespace = soundbufsize - soundoffset + soundpos; + else + freespace = soundpos - soundoffset; + + return (freespace / sizeof(s16) / 2); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLMuteAudio() +{ + SDL_PauseAudio(1); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLUnMuteAudio() +{ + SDL_PauseAudio(0); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLSetVolume(int volume) +{ +} + +////////////////////////////////////////////////////////////////////////////// diff --git a/trunk/desmume/src/sndsdl.h b/trunk/desmume/src/sndsdl.h new file mode 100644 index 000000000..2561455b5 --- /dev/null +++ b/trunk/desmume/src/sndsdl.h @@ -0,0 +1,26 @@ +/* Copyright 2005-2006 Theo Berkau + + This file is part of DeSmuME. + + DeSmuME 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. + + Yabause 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 Yabause; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SNDSDL_H +#define SNDSDL_H + +#define SNDCORE_SDL 2 + +extern SoundInterface_struct SNDSDL; +#endif diff --git a/trunk/desmume/src/windows/snddx.c b/trunk/desmume/src/windows/snddx.c new file mode 100755 index 000000000..0d999014e --- /dev/null +++ b/trunk/desmume/src/windows/snddx.c @@ -0,0 +1,264 @@ +/* Copyright (C) 2005-2006 Theo Berkau + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include +#ifdef __MINGW32__ +// I have to do this because for some reason because the dxerr8.h header is fubared +const char* __stdcall DXGetErrorString8A(HRESULT hr); +#define DXGetErrorString8 DXGetErrorString8A +const char* __stdcall DXGetErrorDescription8A(HRESULT hr); +#define DXGetErrorDescription8 DXGetErrorDescription8A +#else +#include +#endif +#include "../SPU.h" +#include "snddx.h" + +int SNDDXInit(int buffersize); +void SNDDXDeInit(); +void SNDDXUpdateAudio(s16 *buffer, u32 num_samples); +u32 SNDDXGetAudioSpace(); +void SNDDXMuteAudio(); +void SNDDXUnMuteAudio(); +void SNDDXSetVolume(int volume); + +SoundInterface_struct SNDDIRECTX = { +SNDCORE_DIRECTX, +"Direct Sound Interface", +SNDDXInit, +SNDDXDeInit, +SNDDXUpdateAudio, +SNDDXGetAudioSpace, +SNDDXMuteAudio, +SNDDXUnMuteAudio, +SNDDXSetVolume +}; + +LPDIRECTSOUND8 lpDS8; +LPDIRECTSOUNDBUFFER lpDSB, lpDSB2; +extern HWND hwnd; + +static s16 *stereodata16; +static u32 soundoffset=0; +static u32 soundbufsize; +static LONG soundvolume; +static int issoundmuted; + +////////////////////////////////////////////////////////////////////////////// + +int SNDDXInit(int buffersize) +{ + DSBUFFERDESC dsbdesc; + WAVEFORMATEX wfx; + HRESULT ret; + char tempstr[512]; + + if ((ret = DirectSoundCreate8(NULL, &lpDS8, NULL)) != DS_OK) + { + sprintf(tempstr, "DirectSound8Create error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); + MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); + return -1; + } + + if ((ret = IDirectSound8_SetCooperativeLevel(lpDS8, hwnd, DSSCL_PRIORITY)) != DS_OK) + { + sprintf(tempstr, "IDirectSound8_SetCooperativeLevel error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); + MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); + return -1; + } + + memset(&dsbdesc, 0, sizeof(dsbdesc)); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbdesc.dwBufferBytes = 0; + dsbdesc.lpwfxFormat = NULL; + + if ((ret = IDirectSound8_CreateSoundBuffer(lpDS8, &dsbdesc, &lpDSB, NULL)) != DS_OK) + { + sprintf(tempstr, "Error when creating primary sound buffer: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); + MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); + return -1; + } + + soundbufsize = buffersize * 2 * 2; + + memset(&wfx, 0, sizeof(wfx)); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 2; + wfx.nSamplesPerSec = 44100; + wfx.wBitsPerSample = 16; + wfx.nBlockAlign = (wfx.wBitsPerSample / 8) * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if ((ret = IDirectSoundBuffer8_SetFormat(lpDSB, &wfx)) != DS_OK) + { + sprintf(tempstr, "IDirectSoundBuffer8_SetFormat error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); + MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); + return -1; + } + + memset(&dsbdesc, 0, sizeof(dsbdesc)); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_STICKYFOCUS | + DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | + DSBCAPS_LOCHARDWARE; + dsbdesc.dwBufferBytes = soundbufsize; + dsbdesc.lpwfxFormat = &wfx; + + if ((ret = IDirectSound8_CreateSoundBuffer(lpDS8, &dsbdesc, &lpDSB2, NULL)) != DS_OK) + { + if (ret == DSERR_CONTROLUNAVAIL || + ret == DSERR_INVALIDCALL) + { + // Try using a software buffer instead + dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_STICKYFOCUS | + DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | + DSBCAPS_LOCSOFTWARE; + + if ((ret = IDirectSound8_CreateSoundBuffer(lpDS8, &dsbdesc, &lpDSB2, NULL)) != DS_OK) + { + sprintf(tempstr, "Error when creating secondary sound buffer: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); + MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); + return -1; + } + } + else + { + sprintf(tempstr, "Error when creating secondary sound buffer: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); + MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); + return -1; + } + } + + IDirectSoundBuffer8_Play(lpDSB2, 0, 0, DSBPLAY_LOOPING); + + if ((stereodata16 = (s16 *)malloc(soundbufsize)) == NULL) + return -1; + + memset(stereodata16, 0, soundbufsize); + + soundvolume = DSBVOLUME_MAX; + issoundmuted = 0; + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDXDeInit() +{ + DWORD status=0; + + if (lpDSB2) + { + IDirectSoundBuffer8_GetStatus(lpDSB2, &status); + + if(status == DSBSTATUS_PLAYING) + IDirectSoundBuffer8_Stop(lpDSB2); + + IDirectSoundBuffer8_Release(lpDSB2); + lpDSB2 = NULL; + } + + if (lpDSB) + { + IDirectSoundBuffer8_Release(lpDSB); + lpDSB = NULL; + } + + if (lpDS8) + { + IDirectSound8_Release(lpDS8); + lpDS8 = NULL; + } +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDXUpdateAudio(s16 *buffer, u32 num_samples) +{ + LPVOID buffer1; + LPVOID buffer2; + DWORD buffer1_size, buffer2_size; + DWORD status; + + IDirectSoundBuffer8_GetStatus(lpDSB2, &status); + + if (status & DSBSTATUS_BUFFERLOST) + return; // fix me + + IDirectSoundBuffer8_Lock(lpDSB2, soundoffset, num_samples * sizeof(s16) * 2, &buffer1, &buffer1_size, &buffer2, &buffer2_size, 0); + + memcpy(buffer1, buffer, buffer1_size); + if (buffer2) + memcpy(buffer2, buffer+buffer1_size, buffer2_size); + + soundoffset += buffer1_size + buffer2_size; + soundoffset %= soundbufsize; + + IDirectSoundBuffer8_Unlock(lpDSB2, buffer1, buffer1_size, buffer2, buffer2_size); +} + +////////////////////////////////////////////////////////////////////////////// + +u32 SNDDXGetAudioSpace() +{ + DWORD playcursor, writecursor; + u32 freespace=0; + + if (IDirectSoundBuffer8_GetCurrentPosition (lpDSB2, &playcursor, &writecursor) != DS_OK) + return 0; + + if (soundoffset > playcursor) + freespace = soundbufsize - soundoffset + playcursor; + else + freespace = playcursor - soundoffset; + +// if (freespace > 512) + return (freespace / 2 / 2); +// else +// return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDXMuteAudio() +{ + issoundmuted = 1; + IDirectSoundBuffer8_SetVolume (lpDSB2, DSBVOLUME_MIN); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDXUnMuteAudio() +{ + issoundmuted = 0; + IDirectSoundBuffer8_SetVolume (lpDSB2, soundvolume); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDXSetVolume(int volume) +{ + soundvolume = (((LONG)volume) - 100) * 100; + if (!issoundmuted) + IDirectSoundBuffer8_SetVolume (lpDSB2, soundvolume); +} + diff --git a/trunk/desmume/src/windows/snddx.h b/trunk/desmume/src/windows/snddx.h new file mode 100755 index 000000000..245411751 --- /dev/null +++ b/trunk/desmume/src/windows/snddx.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 Theo Berkau + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SNDDX_H +#define SNDDX_H +#define SNDCORE_DIRECTX 2 + +extern SoundInterface_struct SNDDIRECTX; +#endif