diff --git a/desmume/src/mc.cpp b/desmume/src/mc.cpp
index 432b144b5..06dd4cc49 100644
--- a/desmume/src/mc.cpp
+++ b/desmume/src/mc.cpp
@@ -1035,7 +1035,7 @@ void BackupDevice::loadfile()
{
if (advsc.isLoaded())
{
- info.type = advsc.getSaveType() + 1; // skip autodetect description in save_types[] struct
+ info.type = advsc.getSaveType();
if (info.type != 0xFF && info.type != 0xFE)
{
u32 adv_size = save_types[info.type+1].size;
diff --git a/desmume/src/mic.cpp b/desmume/src/mic.cpp
index a7e3c84a4..ac9368e0a 100644
--- a/desmume/src/mic.cpp
+++ b/desmume/src/mic.cpp
@@ -1,417 +1,208 @@
-/*
- Copyright (C) 2008-2009 DeSmuME team
+/* mic.cpp - this file is part of DeSmuME
+ *
+ * Copyright (C) 2009-2011 DeSmuME Team
+ *
+ * This file 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, or (at your option)
+ * any later version.
+ *
+ * This file 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
- This file 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 file 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 the this software. If not, see .
-*/
-
-/*
- The NDS microphone produces 8-bit sound sampled at 16khz.
- The sound data must be read sample-by-sample through the
- ARM7 SPI device (touchscreen controller, channel 6).
-
- Note : I added these notes because the microphone isn't
- documented on GBATek.
-*/
+#ifndef WIN32
+#include
+#include "mic.h"
#include "NDSSystem.h"
-#include "../types.h"
-#include "../debug.h"
-#include "../mic.h"
-#include "../movie.h"
#include "readwrite.h"
-#include
-#include
-int MicDisplay;
-int SampleLoaded=0;
+#define MIC_NULL_SAMPLE_VALUE 0
+#define MIC_MAX_BUFFER_SAMPLES 320
+#define MIC_BUFFER_SIZE (sizeof(u8) * MIC_MAX_BUFFER_SAMPLES)
+#define NUM_INTERNAL_NOISE_SAMPLES 32
-#define MIC_CHECKERR(hr) if(hr != MMSYSERR_NOERROR) return FALSE;
+static u8 *micSampleBuffer = NULL; // Pointer to the internal sample buffer.
+static u8 *micReadPosition = NULL; // Pointer to the read position of the internal sample buffer.
+static u8 *micWritePosition = NULL; // Pointer to the write position of the internal sample buffer.
+static unsigned int micBufferFillCount; // The number of readable samples in the internal sample buffer.
-#define MIC_BUFSIZE 4096
-
-static BOOL Mic_Inited = FALSE;
-
-static u8 Mic_TempBuf[MIC_BUFSIZE];
-static u8 Mic_Buffer[2][MIC_BUFSIZE];
-static u16 Mic_BufPos;
-static u8 Mic_WriteBuf;
-static u8 Mic_PlayBuf;
-
-static int micReadSamplePos=0;
-
-static HWAVEIN waveIn;
-static WAVEHDR waveHdr;
-
-static int CALLBACK waveInProc(HWAVEIN wavein, UINT msg, DWORD instance, DWORD_PTR param1, DWORD_PTR param2)
+static void Mic_BufferClear(void)
{
- LPWAVEHDR lpWaveHdr;
- HRESULT hr;
-
- if(!Mic_Inited)
- return 1;
-
- if(msg == WIM_DATA)
- {
- lpWaveHdr = (LPWAVEHDR)param1;
-
- memcpy(Mic_Buffer[Mic_WriteBuf], lpWaveHdr->lpData, MIC_BUFSIZE);
- Mic_WriteBuf ^= 1;
-
- hr = waveInAddBuffer(waveIn, lpWaveHdr, sizeof(WAVEHDR));
- if(hr != MMSYSERR_NOERROR)
- return 1;
- }
-
- return 0;
-}
-
-static char* samplebuffer = NULL;
-static int samplebuffersize = 0;
-static FILE* fp = NULL;
-
-EMUFILE_MEMORY newWavData;
-
-static bool dataChunk(EMUFILE* inf)
-{
- bool found = false;
-
- // seek to just after the RIFF header
- inf->fseek(12,SEEK_SET);
-
- // search for a format chunk
- for (;;) {
- char chunk_id[4];
- u32 chunk_length;
-
- if(inf->eof()) return found;
- if(inf->fread(chunk_id, 4) != 4) return found;
- if(!read32le(&chunk_length, inf)) return found;
-
- // if we found a data chunk, excellent!
- if (memcmp(chunk_id, "data", 4) == 0) {
- found = true;
- u8* temp = new u8[chunk_length];
- if(inf->fread(temp,chunk_length) != chunk_length) {
- delete[] temp;
- return false;
- }
- newWavData.fwrite(temp,chunk_length);
- delete[] temp;
- chunk_length = 0;
- }
-
- inf->fseek(chunk_length,SEEK_CUR);
- }
-
- return found;
-}
-
-static bool formatChunk(EMUFILE* inf)
-{
- // seek to just after the RIFF header
- inf->fseek(12,SEEK_SET);
-
- // search for a format chunk
- for (;;) {
- char chunk_id[4];
- u32 chunk_length;
-
- inf->fread(chunk_id, 4);
- if(!read32le(&chunk_length, inf)) return false;
-
- // if we found a format chunk, excellent!
- if (memcmp(chunk_id, "fmt ", 4) == 0 && chunk_length >= 16) {
-
- // read format chunk
- u16 format_tag;
- u16 channel_count;
- u32 samples_per_second;
- //u32 bytes_per_second = read32_le(chunk + 8);
- //u16 block_align = read16_le(chunk + 12);
- u16 bits_per_sample;
-
- if(read16le(&format_tag,inf)!=1) return false;
- if(read16le(&channel_count,inf)!=1) return false;
- if(read32le(&samples_per_second,inf)!=1) return false;
- inf->fseek(6,SEEK_CUR);
- if(read16le(&bits_per_sample,inf)!=1) return false;
-
- chunk_length -= 16;
-
- // format_tag must be 1 (WAVE_FORMAT_PCM)
- // we only support mono 8bit
- if (format_tag != 1 ||
- channel_count != 1 ||
- bits_per_sample != 8) {
- MessageBox(0,"not a valid RIFF WAVE file; must be 8bit mono pcm",0,0);
- return false;
- }
-
- return true;
- }
-
- inf->fseek(chunk_length,SEEK_CUR);
- }
- return false;
-}
-
-bool LoadSample(const char *name)
-{
- SampleLoaded = 0;
- if(!name) return true;
-
- EMUFILE_FILE inf(name,"rb");
- if(inf.fail()) return false;
-
- //wav reading code adapted from AUDIERE (LGPL)
-
- // read the RIFF header
- u8 riff_id[4];
- u32 riff_length;
- u8 riff_datatype[4];
-
- inf.fread(riff_id, 4);
- read32le(&riff_length,&inf);
- inf.fread(riff_datatype, 4);
-
- if (inf.size() < 12 ||
- memcmp(riff_id, "RIFF", 4) != 0 ||
- riff_length == 0 ||
- memcmp(riff_datatype, "WAVE", 4) != 0) {
- MessageBox(0,"not a valid RIFF WAVE file",0,0);
- return false;
- }
-
- if (!formatChunk(&inf))
- return false;
-
- if(!dataChunk(&inf)) {
- MessageBox(0,"not a valid WAVE file. some unknown problem.",0,0);
- return false;
- }
-
- delete[] samplebuffer;
- samplebuffersize = (int)newWavData.size();
- samplebuffer = new char[samplebuffersize];
- memcpy(samplebuffer,newWavData.buf(),samplebuffersize);
- new(&newWavData) EMUFILE_MEMORY();
-
- SampleLoaded=1;
-
- return true;
-}
-
-BOOL Mic_DeInit_Physical()
-{
- if(!Mic_Inited)
- return TRUE;
-
- INFO("win32 microphone DEinit OK\n");
-
- Mic_Inited = FALSE;
-
- waveInReset(waveIn);
- waveInClose(waveIn);
-
- return TRUE;
-}
-
-BOOL Mic_Init_Physical()
-{
- if(Mic_Inited)
- return TRUE;
-
- Mic_Inited = FALSE;
-
- HRESULT hr;
- WAVEFORMATEX wfx;
-
- memset(Mic_TempBuf, 0x80, MIC_BUFSIZE);
- memset(Mic_Buffer[0], 0x80, MIC_BUFSIZE);
- memset(Mic_Buffer[1], 0x80, MIC_BUFSIZE);
- Mic_BufPos = 0;
-
- Mic_WriteBuf = 0;
- Mic_PlayBuf = 1;
-
- memset(&wfx, 0, sizeof(wfx));
- wfx.cbSize = 0;
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = 1;
- wfx.nSamplesPerSec = 16000;
- wfx.nBlockAlign = 1;
- wfx.nAvgBytesPerSec = 16000;
- wfx.wBitsPerSample = 8;
-
- hr = waveInOpen(&waveIn, WAVE_MAPPER, &wfx, (DWORD_PTR)waveInProc, 0, CALLBACK_FUNCTION);
- MIC_CHECKERR(hr)
-
- memset(&waveHdr, 0, sizeof(waveHdr));
- waveHdr.lpData = (LPSTR)Mic_TempBuf;
- waveHdr.dwBufferLength = MIC_BUFSIZE;
-
- hr = waveInPrepareHeader(waveIn, &waveHdr, sizeof(WAVEHDR));
- MIC_CHECKERR(hr)
-
- hr = waveInAddBuffer(waveIn, &waveHdr, sizeof(WAVEHDR));
- MIC_CHECKERR(hr)
-
- hr = waveInStart(waveIn);
- MIC_CHECKERR(hr)
-
- Mic_Inited = TRUE;
- INFO("win32 microphone init OK\n");
-
- return TRUE;
-}
-
-BOOL Mic_Init() {
-
- micReadSamplePos = 0;
-
- return TRUE;
-}
-
-void Mic_Reset()
-{
- micReadSamplePos = 0;
-
- if(!Mic_Inited)
+ if (micSampleBuffer == NULL) {
return;
+ }
- //reset physical
- memset(Mic_TempBuf, 0x80, MIC_BUFSIZE);
- memset(Mic_Buffer[0], 0x80, MIC_BUFSIZE);
- memset(Mic_Buffer[1], 0x80, MIC_BUFSIZE);
- Mic_BufPos = 0;
-
- Mic_WriteBuf = 0;
- Mic_PlayBuf = 1;
+ memset(micSampleBuffer, MIC_NULL_SAMPLE_VALUE, MIC_BUFFER_SIZE);
+ micReadPosition = micSampleBuffer;
+ micWritePosition = micSampleBuffer;
+ micBufferFillCount = 0;
}
-void Mic_DeInit()
+BOOL Mic_Init(void)
{
+ BOOL result = FALSE;
+
+ u8 *newBuffer = (u8 *)malloc(MIC_BUFFER_SIZE);
+ if (newBuffer == NULL) {
+ return result;
+ }
+
+ micSampleBuffer = newBuffer;
+ Mic_BufferClear();
+ result = TRUE;
+
+ return result;
}
-static const u8 random[32] =
+void Mic_DeInit(void)
{
- 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF,
- 0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01,
-} ;
-
-
-
-u8 Mic_ReadSample()
-{
- u8 ret;
- u8 tmp;
- if(CommonSettings.micMode == TCommonSettings::Physical)
- {
- if(movieMode == MOVIEMODE_INACTIVE)
- {
- //normal mic behavior
- tmp = (u8)Mic_Buffer[Mic_PlayBuf][Mic_BufPos >> 1];
- }
- else
- {
- //since we're not recording Mic_Buffer to the movie, use silence
- tmp = 0x80;
- }
- }
- else
- {
- if(NDS_getFinalUserInput().mic.micButtonPressed)
- {
- if(SampleLoaded)
- {
- //use a sample
- //TODO: what if a movie is active?
- // for now I'm going to hope that if anybody records a movie with a sample loaded,
- // either they know what they're doing and plan to distribute the sample,
- // or they're playing a game where it doesn't even matter or they never press the mic button.
- tmp = samplebuffer[micReadSamplePos >> 1];
- micReadSamplePos++;
- if(micReadSamplePos == samplebuffersize*2)
- micReadSamplePos=0;
- }
- else
- {
- //use the "random" values
- if(CommonSettings.micMode == TCommonSettings::InternalNoise)
- tmp = random[micReadSamplePos >> 1];
- else tmp = rand();
- micReadSamplePos++;
- if(micReadSamplePos == ARRAY_SIZE(random)*2)
- micReadSamplePos=0;
- }
- }
- else
- {
- tmp = 0x80;
-
- //reset mic button buffer pos if not pressed
- micReadSamplePos=0;
- }
- }
-
- if(Mic_BufPos & 0x1)
- {
- ret = ((tmp & 0x1) << 7);
- }
- else
- {
- ret = ((tmp & 0xFE) >> 1);
- }
-
- MicDisplay = tmp;
-
- Mic_BufPos++;
- if(Mic_BufPos >= (MIC_BUFSIZE << 1))
- {
- Mic_BufPos = 0;
- Mic_PlayBuf ^= 1;
- }
-
- return ret;
+ free(micSampleBuffer);
+ micSampleBuffer = NULL;
+}
+
+void Mic_Reset(void)
+{
+ *micReadPosition = MIC_NULL_SAMPLE_VALUE;
+ micWritePosition = micReadPosition;
+ micBufferFillCount = 0;
+}
+
+static bool Mic_GetActivate(void)
+{
+ return NDS_getFinalUserInput().mic.micButtonPressed;
+}
+
+static bool Mic_IsBufferFull(void)
+{
+ return (micBufferFillCount >= MIC_MAX_BUFFER_SAMPLES);
+}
+
+static bool Mic_IsBufferEmpty(void)
+{
+ return (micBufferFillCount == 0);
+}
+
+static u8 Mic_DefaultBufferRead(void)
+{
+ u8 theSample = MIC_NULL_SAMPLE_VALUE;
+
+ if (micSampleBuffer == NULL) {
+ return theSample;
+ }
+
+ theSample = *micReadPosition;
+
+ if (Mic_IsBufferEmpty()) {
+ return theSample;
+ }
+
+ micReadPosition++;
+ micBufferFillCount--;
+
+ // Move the pointer back to start if we reach the end of the memory block.
+ if (micReadPosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) {
+ micReadPosition = micSampleBuffer;
+ }
+
+ return theSample;
+}
+
+u8 Mic_ReadSample(void)
+{
+ // All mic modes other than Physical must have the mic hotkey pressed in order
+ // to work.
+ if (CommonSettings.micMode != TCommonSettings::Physical && !Mic_GetActivate()) {
+ return MIC_NULL_SAMPLE_VALUE;
+ }
+
+ return Mic_DefaultBufferRead();
+}
+
+static void Mic_DefaultBufferWrite(u8 theSample)
+{
+ if (micSampleBuffer == NULL || Mic_IsBufferFull()) {
+ return;
+ }
+
+ *micWritePosition = theSample;
+ micWritePosition++;
+ micBufferFillCount++;
+
+ // Move the pointer back to start if we reach the end of the memory block.
+ if (micWritePosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) {
+ micWritePosition = micSampleBuffer;
+ }
+}
+
+static u8 Mic_GenerateInternalNoiseSample(void)
+{
+ const u8 noiseSample[NUM_INTERNAL_NOISE_SAMPLES] =
+ {
+ 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF,
+ 0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01
+ };
+ static unsigned int i = 0;
+
+ if (++i >= NUM_INTERNAL_NOISE_SAMPLES) {
+ i = 0;
+ }
+
+ return noiseSample[i];
+}
+
+static u8 Mic_GenerateWhiteNoiseSample(void)
+{
+ return (u8)(rand() & 0xFF);
+}
+
+static u8 Mic_GenerateNullSample(void)
+{
+ return MIC_NULL_SAMPLE_VALUE;
+}
+
+void Mic_DoNoise(BOOL noise)
+{
+ u8 (*generator) (void) = NULL;
+
+ if (micSampleBuffer == NULL) {
+ return;
+ }
+
+ if (!noise) {
+ generator = &Mic_GenerateNullSample;
+ } else if (CommonSettings.micMode == TCommonSettings::InternalNoise) {
+ generator = &Mic_GenerateInternalNoiseSample;
+ } else if (CommonSettings.micMode == TCommonSettings::Random) {
+ generator = &Mic_GenerateWhiteNoiseSample;
+ }
+
+ if (generator == NULL) {
+ return;
+ }
+
+ while (micBufferFillCount < MIC_MAX_BUFFER_SAMPLES) {
+ Mic_DefaultBufferWrite(generator());
+ }
}
-// maybe a bit paranoid...
void mic_savestate(EMUFILE* os)
{
- //version
- write32le(1,os);
- assert(MIC_BUFSIZE == 4096); // else needs new version
-
- os->fwrite((char*)Mic_Buffer[0], MIC_BUFSIZE);
- os->fwrite((char*)Mic_Buffer[1], MIC_BUFSIZE);
- write16le(Mic_BufPos,os);
- write8le(Mic_WriteBuf,os); // seems OK to save...
- write8le(Mic_PlayBuf,os);
- write32le(micReadSamplePos,os);
+ write32le(-1,os);
}
+
bool mic_loadstate(EMUFILE* is, int size)
{
- u32 version;
- if(read32le(&version,is) != 1) return false;
- if(version > 1 || version == 0) { is->fseek(size-4, SEEK_CUR); return true; }
-
- is->fread((char*)Mic_Buffer[0], MIC_BUFSIZE);
- is->fread((char*)Mic_Buffer[1], MIC_BUFSIZE);
- read16le(&Mic_BufPos,is);
- read8le(&Mic_WriteBuf,is);
- read8le(&Mic_PlayBuf,is);
- read32le(&micReadSamplePos,is);
- return true;
+ is->fseek(size, SEEK_CUR);
+ return TRUE;
}
+#endif