diff --git a/desmume/ChangeLog b/desmume/ChangeLog index 4d8e263ce..881b0aecb 100644 --- a/desmume/ChangeLog +++ b/desmume/ChangeLog @@ -17,6 +17,8 @@ - Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU). The savestate format is changed, but from now on it is in principle more resilient (it will continue to break though) [zeromus] - Remove 16MB of WRAM at 0x01****** from arm9. Maped to unusued instead. What was this? [zeromus] + - Change SPU to run two spus in parallel. SPU_core is the official one. SPU_user produces output. + This lets us do inaccurate things with SPU_user which might sound better while being more accurate with SPU_core. [zeromus] Mac OS X port: - Fixed: Filenames and paths with unicode characters now work. [Jeff] - Fixed: Load state from file button works again. [Jeff] @@ -62,6 +64,8 @@ - Fix the buggy auto frameskip logic which made the emu slow to a crawl. Now it runs fast! [zeromus] - Fix resizing, rotate & aspect ration of main window. Add save window position and parameters [CrazyMax] - Rewrite all debug tools (autoupdate work now) [CrazyMax] + - Add AVI output [zeromus] + - Remove multithreading from user interface after finding several synchronization issues [zeromus] 0.7.3 -> 0.8 Cocoa: diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index cba68fdbe..45d5c8746 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -169,7 +169,7 @@ int NDS_Init( void) { armcpu_new(&NDS_ARM9,0); #endif - if (SPU_Init(SNDCORE_DUMMY, 735) != 0) + if (SPU_Init(SNDCORE_DUMMY, 740) != 0) return -1; #ifdef EXPERIMENTAL_WIFI diff --git a/desmume/src/SPU.cpp b/desmume/src/SPU.cpp index 2976e51dd..b131860a4 100644 --- a/desmume/src/SPU.cpp +++ b/desmume/src/SPU.cpp @@ -1,22 +1,22 @@ /* Copyright (C) 2006 Theo Berkau - Ideas borrowed from Stephane Dallongeville's SCSP core +Ideas borrowed from Stephane Dallongeville's SCSP core - This file is part of DeSmuME +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 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. +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 +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 @@ -30,7 +30,8 @@ #include "armcpu.h" -SPU_struct *SPU=NULL; +SPU_struct *SPU_core = 0; +SPU_struct *SPU_user = 0; static SoundInterface_struct *SNDCore=NULL; extern SoundInterface_struct *SNDCoreList[]; @@ -40,32 +41,32 @@ extern SoundInterface_struct *SNDCoreList[]; int indextbl[8] = { - -1, -1, -1, -1, 2, 4, 6, 8 + -1, -1, -1, -1, 2, 4, 6, 8 }; int adpcmtbl[89] = { - 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, - 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, - 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, - 0x0061, 0x006B, 0x0076, 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, - 0x00E6, 0x00FD, 0x0117, 0x0133, 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, - 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, - 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, - 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954, - 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, 0x3BB9, - 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF + 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, + 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, + 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, + 0x0061, 0x006B, 0x0076, 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, + 0x00E6, 0x00FD, 0x0117, 0x0133, 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, + 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, + 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, + 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954, + 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, 0x3BB9, + 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF }; s16 wavedutytbl[8][8] = { -{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF }, -{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF }, -{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, -{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, -{ -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, -{ -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, -{ -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, -{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF } + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF } }; FILE *spufp=NULL; @@ -74,59 +75,48 @@ FILE *spufp=NULL; int SPU_ChangeSoundCore(int coreid, int buffersize) { - int i; + int i; - if (SPU->sndbuf) - free(SPU->sndbuf); + delete SPU_user; - if (SPU->outbuf) - free(SPU->outbuf); + // Make sure the old core is freed + if (SNDCore) + SNDCore->DeInit(); - // Make sure the old core is freed - if (SNDCore) - SNDCore->DeInit(); + // So which core do we want? + if (coreid == SNDCORE_DEFAULT) + coreid = 0; // Assume we want the first one - // Allocate memory for sound buffer - if ((SPU->sndbuf = new s32[buffersize * 2]) == NULL) - return -1; + // Go through core list and find the id + for (i = 0; SNDCoreList[i] != NULL; i++) + { + if (SNDCoreList[i]->id == coreid) + { + // Set to current core + SNDCore = SNDCoreList[i]; + break; + } + } - if ((SPU->outbuf = new s16[buffersize * 2]) == NULL) - return -1; + //If the user picked the dummy core, disable the user spu + if(SNDCore == &SNDDummy) + return 0; - memset(SPU->sndbuf, 0, buffersize * 4 * 2); - memset(SPU->outbuf, 0, buffersize * 2 * 2); + //If the core wasnt found in the list for some reason, disable the user spu + if (SNDCore == NULL) + return -1; - SPU->bufsize = buffersize; + // Since it failed, instead of it being fatal, disable the user spu + if (SNDCore->Init(buffersize * 2) == -1) + { + SNDCore = 0; + return -1; + } - // So which core do we want? - if (coreid == SNDCORE_DEFAULT) - coreid = 0; // Assume we want the first one + //enable the user spu + SPU_user = new SPU_struct(buffersize); - // Go through core list and find the id - for (i = 0; SNDCoreList[i] != NULL; i++) - { - if (SNDCoreList[i]->id == coreid) - { - // Set to current core - SNDCore = SNDCoreList[i]; - break; - } - } - - if (SNDCore == NULL) - { - SNDCore = &SNDDummy; - return -1; - } - - if (SNDCore->Init(buffersize * 2) == -1) - { - // Since it failed, instead of it being fatal, we'll just use the dummy - // core instead - SNDCore = &SNDDummy; - } - - return 0; + return 0; } SoundInterface_struct *SPU_SoundCore() @@ -138,566 +128,578 @@ SoundInterface_struct *SPU_SoundCore() int SPU_Init(int coreid, int buffersize) { - if ((SPU = (SPU_struct *)malloc(sizeof(SPU_struct))) == NULL) - return -1; + SPU_core = new SPU_struct(740); + SPU_Reset(); - memset((void *)SPU, 0, sizeof(SPU_struct)); - - SPU_Reset(); - - return SPU_ChangeSoundCore(coreid, buffersize); + return SPU_ChangeSoundCore(coreid, buffersize); } ////////////////////////////////////////////////////////////////////////////// void SPU_Pause(int pause) { - if(pause) - SNDCore->MuteAudio(); - else - SNDCore->UnMuteAudio(); + if(pause) + SNDCore->MuteAudio(); + else + SNDCore->UnMuteAudio(); } ////////////////////////////////////////////////////////////////////////////// void SPU_SetVolume(int volume) { - if (SNDCore) - SNDCore->SetVolume(volume); + if (SNDCore) + SNDCore->SetVolume(volume); } ////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::reset() +{ + memset((void *)channels, 0, sizeof(channel_struct) * 16); +} + void SPU_Reset(void) { - int i; + int i; - memset((void *)SPU->chan, 0, sizeof(channel_struct) * 16); - - // Reset Registers - for (i = 0x400; i < 0x51D; i++) - T1WriteByte(MMU.ARM7_REG, i, 0); + SPU_core->reset(); + if(SPU_user) SPU_user->reset(); + // Reset Registers + for (i = 0x400; i < 0x51D; i++) + T1WriteByte(MMU.ARM7_REG, i, 0); } ////////////////////////////////////////////////////////////////////////////// +SPU_struct::SPU_struct(int buffersize) + : bufpos(0) + , buflength(0) + , sndbuf(0) + , outbuf(0) + , bufsize(buffersize) +{ + reset(); + sndbuf = new s32[buffersize*2]; + outbuf = new s16[buffersize*2]; + memset(sndbuf,0,buffersize*2*4); + memset(outbuf,0,buffersize*2*2); +} + +SPU_struct::~SPU_struct() +{ + if(sndbuf) delete[] sndbuf; + if(outbuf) delete[] outbuf; +} + void SPU_DeInit(void) { - if (SPU->sndbuf) - delete[] SPU->sndbuf; + if(SNDCore) + SNDCore->DeInit(); + SNDCore = 0; - if (SPU->outbuf) - delete[] SPU->outbuf; - - if (SNDCore) - SNDCore->DeInit(); - - if (SPU) - free(SPU); + delete SPU_core; SPU_core=0; + delete SPU_user; SPU_user=0; } ////////////////////////////////////////////////////////////////////////////// -void SPU_KeyOn(int channel) + +void SPU_struct::KeyOn(int channel) { - channel_struct *chan = &SPU->chan[channel]; + channel_struct &thischan = channels[channel]; - chan->sampinc = (16777216 / (0x10000 - (double)chan->timer)) / 44100; + thischan.sampinc = (16777216 / (0x10000 - (double)thischan.timer)) / 44100; -// LOG("Channel %d key on: vol = %d, datashift = %d, hold = %d, pan = %d, waveduty = %d, repeat = %d, format = %d, source address = %07X, timer = %04X, loop start = %04X, length = %06X, MMU.ARM7_REG[0x501] = %02X\n", channel, chan->vol, chan->datashift, chan->hold, chan->pan, chan->waveduty, chan->repeat, chan->format, chan->addr, chan->timer, chan->loopstart, chan->length, T1ReadByte(MMU.ARM7_REG, 0x501)); - switch(chan->format) - { - case 0: // 8-bit - chan->buf8 = (s8*)&MMU.MMU_MEM[1][(chan->addr>>20)&0xFF][(chan->addr & MMU.MMU_MASK[1][(chan->addr >> 20) & 0xFF])]; - chan->loopstart = chan->loopstart << 2; - chan->length = (chan->length << 2) + chan->loopstart; - chan->sampcnt = 0; - break; - case 1: // 16-bit - chan->buf16 = (s16 *)&MMU.MMU_MEM[1][(chan->addr>>20)&0xFF][(chan->addr & MMU.MMU_MASK[1][(chan->addr >> 20) & 0xFF])]; - chan->loopstart = chan->loopstart << 1; - chan->length = (chan->length << 1) + chan->loopstart; - chan->sampcnt = 0; - break; - case 2: // ADPCM - { - u32 temp; + // LOG("Channel %d key on: vol = %d, datashift = %d, hold = %d, pan = %d, waveduty = %d, repeat = %d, format = %d, source address = %07X, timer = %04X, loop start = %04X, length = %06X, MMU.ARM7_REG[0x501] = %02X\n", channel, chan->vol, chan->datashift, chan->hold, chan->pan, chan->waveduty, chan->repeat, chan->format, chan->addr, chan->timer, chan->loopstart, chan->length, T1ReadByte(MMU.ARM7_REG, 0x501)); + switch(thischan.format) + { + case 0: // 8-bit + thischan.buf8 = (s8*)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + thischan.loopstart = thischan.loopstart << 2; + thischan.length = (thischan.length << 2) + thischan.loopstart; + thischan.sampcnt = 0; + break; + case 1: // 16-bit + thischan.buf16 = (s16 *)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + thischan.loopstart = thischan.loopstart << 1; + thischan.length = (thischan.length << 1) + thischan.loopstart; + thischan.sampcnt = 0; + break; + case 2: // ADPCM + { + u32 temp; - chan->buf8 = (s8*)&MMU.MMU_MEM[1][(chan->addr>>20)&0xFF][(chan->addr & MMU.MMU_MASK[1][(chan->addr >> 20) & 0xFF])]; - chan->pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]); - chan->pcm16b_last = 0; - chan->index = chan->buf8[2] & 0x7F; - chan->lastsampcnt = 7; - chan->sampcnt = 8; - chan->loopstart = chan->loopstart << 3; - chan->length = (chan->length << 3) + chan->loopstart; - break; - } - case 3: // PSG - { - break; - } - default: break; - } + thischan.buf8 = (s8*)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + thischan.pcm16b = (s16)((thischan.buf8[1] << 8) | thischan.buf8[0]); + thischan.pcm16b_last = 0; + thischan.index = thischan.buf8[2] & 0x7F; + thischan.lastsampcnt = 7; + thischan.sampcnt = 8; + thischan.loopstart = thischan.loopstart << 3; + thischan.length = (thischan.length << 3) + thischan.loopstart; + break; + } + case 3: // PSG + { + break; + } + default: break; + } } ////////////////////////////////////////////////////////////////////////////// u8 SPU_ReadByte(u32 addr) { - addr &= 0xFFF; + addr &= 0xFFF; - if (addr < 0x500) - { - switch (addr & 0xF) - { - case 0x0: -// LOG("Sound Channel %d Volume read\n", (addr >> 4) & 0xF); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x1: - { -// LOG("Sound Channel %d Data Shift/Hold read\n",(addr >> 4) & 0xF); - return T1ReadByte(MMU.ARM7_REG, addr); - } - case 0x2: -// LOG("Sound Channel %d Panning read\n",(addr >> 4) & 0xF); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x3: -// LOG("Sound Channel %d Wave Duty/Repeat/Format/Start read: %02X\n", (addr >> 4) & 0xF, T1ReadByte(MMU.ARM7_REG, addr)); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x4: - case 0x5: - case 0x6: - case 0x7: -// LOG("Sound Channel %d Data Source Register read: %08X\n",(addr >> 4) & 0xF, addr); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x8: -// LOG("Sound Channel Timer(Low byte) read: %08X\n", addr); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x9: -// LOG("Sound Channel Timer(High byte) read: %08X\n", addr); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0xA: -// LOG("Sound Channel Loop Start(Low byte) read: %08X\n", addr); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0xB: -// LOG("Sound Channel Loop Start(High byte) read: %08X\n", addr); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0xC: - case 0xD: - case 0xE: - case 0xF: -// LOG("Sound Channel %d Length Register read: %08X\n",(addr >> 4) & 0xF, addr); - return T1ReadByte(MMU.ARM7_REG, addr); - default: break; - } - } - else - { - switch (addr & 0x1F) - { - case 0x000: - case 0x001: -// LOG("Sound Control Register read: %08X\n", addr); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x004: - case 0x005: -// LOG("Sound Bias Register read: %08X\n", addr); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x008: -// LOG("Sound Capture 0 Control Register read\n"); - return T1ReadByte(MMU.ARM7_REG, addr); - case 0x009: -// LOG("Sound Capture 1 Control Register read\n"); - return T1ReadByte(MMU.ARM7_REG, addr); - default: break; - } - } + if (addr < 0x500) + { + switch (addr & 0xF) + { + case 0x0: + // LOG("Sound Channel %d Volume read\n", (addr >> 4) & 0xF); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x1: + { + // LOG("Sound Channel %d Data Shift/Hold read\n",(addr >> 4) & 0xF); + return T1ReadByte(MMU.ARM7_REG, addr); + } + case 0x2: + // LOG("Sound Channel %d Panning read\n",(addr >> 4) & 0xF); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x3: + // LOG("Sound Channel %d Wave Duty/Repeat/Format/Start read: %02X\n", (addr >> 4) & 0xF, T1ReadByte(MMU.ARM7_REG, addr)); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x4: + case 0x5: + case 0x6: + case 0x7: + // LOG("Sound Channel %d Data Source Register read: %08X\n",(addr >> 4) & 0xF, addr); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x8: + // LOG("Sound Channel Timer(Low byte) read: %08X\n", addr); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x9: + // LOG("Sound Channel Timer(High byte) read: %08X\n", addr); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0xA: + // LOG("Sound Channel Loop Start(Low byte) read: %08X\n", addr); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0xB: + // LOG("Sound Channel Loop Start(High byte) read: %08X\n", addr); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0xC: + case 0xD: + case 0xE: + case 0xF: + // LOG("Sound Channel %d Length Register read: %08X\n",(addr >> 4) & 0xF, addr); + return T1ReadByte(MMU.ARM7_REG, addr); + default: break; + } + } + else + { + switch (addr & 0x1F) + { + case 0x000: + case 0x001: + // LOG("Sound Control Register read: %08X\n", addr); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x004: + case 0x005: + // LOG("Sound Bias Register read: %08X\n", addr); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x008: + // LOG("Sound Capture 0 Control Register read\n"); + return T1ReadByte(MMU.ARM7_REG, addr); + case 0x009: + // LOG("Sound Capture 1 Control Register read\n"); + return T1ReadByte(MMU.ARM7_REG, addr); + default: break; + } + } - return T1ReadByte(MMU.ARM7_REG, addr); + return T1ReadByte(MMU.ARM7_REG, addr); } ////////////////////////////////////////////////////////////////////////////// u16 SPU_ReadWord(u32 addr) { - addr &= 0xFFF; + addr &= 0xFFF; - if (addr < 0x500) - { - switch (addr & 0xF) - { - case 0x0: -// LOG("Sound Channel %d Volume/data shift/hold word read\n", (addr >> 4) & 0xF); - return T1ReadWord(MMU.ARM7_REG, addr); - case 0x2: - { - channel_struct *chan=&SPU->chan[(addr >> 4) & 0xF]; -// LOG("Sound Channel %d Panning/Wave Duty/Repeat Mode/Format/Start word read\n", (addr >> 4) & 0xF); - return T1ReadWord(MMU.ARM7_REG, addr); - } - case 0x4: - case 0x6: -// LOG("Sound Channel %d Data Source Register word read: %08X\n",(addr >> 4) & 0xF, addr); - return T1ReadWord(MMU.ARM7_REG, addr); - case 0x8: -// LOG("Sound Channel %d Timer Register word read\n", (addr >> 4) & 0xF); - return T1ReadWord(MMU.ARM7_REG, addr); - case 0xA: -// LOG("Sound Channel %d Loop start Register word read\n", (addr >> 4) & 0xF); - return T1ReadWord(MMU.ARM7_REG, addr); - case 0xC: - case 0xE: -// LOG("Sound Channel %d Length Register word read: %08X\n",(addr >> 4) & 0xF, addr); - return T1ReadWord(MMU.ARM7_REG, addr); - default: break; - } - } - else - { - switch (addr & 0x1F) - { - case 0x000: -// LOG("Sound Control Register word read\n"); - return T1ReadWord(MMU.ARM7_REG, addr); - case 0x004: -// LOG("Sound Bias Register word read\n"); - return T1ReadWord(MMU.ARM7_REG, addr); - case 0x008: -// LOG("Sound Capture 0/1 Control Register word read\n"); - return T1ReadWord(MMU.ARM7_REG, addr); - default: break; - } - } + if (addr < 0x500) + { + switch (addr & 0xF) + { + case 0x0: + // LOG("Sound Channel %d Volume/data shift/hold word read\n", (addr >> 4) & 0xF); + break; + case 0x2: + // LOG("Sound Channel %d Panning/Wave Duty/Repeat Mode/Format/Start word read\n", (addr >> 4) & 0xF); + break; + case 0x4: + case 0x6: + // LOG("Sound Channel %d Data Source Register word read: %08X\n",(addr >> 4) & 0xF, addr); + break; + case 0x8: + // LOG("Sound Channel %d Timer Register word read\n", (addr >> 4) & 0xF); + break; + case 0xA: + // LOG("Sound Channel %d Loop start Register word read\n", (addr >> 4) & 0xF); + break; + case 0xC: + case 0xE: + // LOG("Sound Channel %d Length Register word read: %08X\n",(addr >> 4) & 0xF, addr); + break; + default: break; + } + } + else + { + switch (addr & 0x1F) + { + case 0x000: + // LOG("Sound Control Register word read\n"); + break; + case 0x004: + // LOG("Sound Bias Register word read\n"); + break; + case 0x008: + // LOG("Sound Capture 0/1 Control Register word read\n"); + break; + default: break; + } + } - return T1ReadWord(MMU.ARM7_REG, addr); + return T1ReadWord(MMU.ARM7_REG, addr); } ////////////////////////////////////////////////////////////////////////////// u32 SPU_ReadLong(u32 addr) { - addr &= 0xFFF; + addr &= 0xFFF; - if (addr < 0x500) - { - switch (addr & 0xF) - { - case 0x0: -// LOG("Sound Channel %d Control Register long read\n", (addr >> 4) & 0xF); - return T1ReadLong(MMU.ARM7_REG, addr); - case 0x4: -// LOG("Sound Channel %d Data Source Register long read\n"); - return T1ReadLong(MMU.ARM7_REG, addr); - case 0x8: -// LOG("Sound Channel %d Timer/Loop Start Register long read\n", (addr >> 4) & 0xF); - return T1ReadLong(MMU.ARM7_REG, addr); - case 0xC: -// LOG("Sound Channel %d Length Register long read\n", (addr >> 4) & 0xF); - return T1ReadLong(MMU.ARM7_REG, addr); - default: - return T1ReadLong(MMU.ARM7_REG, addr); - } - } - else - { - switch (addr & 0x1F) - { - case 0x000: -// LOG("Sound Control Register long read\n"); - return T1ReadLong(MMU.ARM7_REG, addr); - case 0x004: -// LOG("Sound Bias Register long read\n"); - return T1ReadLong(MMU.ARM7_REG, addr); - case 0x008: -// LOG("Sound Capture 0/1 Control Register long read: %08X\n"); - return T1ReadLong(MMU.ARM7_REG, addr); - default: - return T1ReadLong(MMU.ARM7_REG, addr); - } - } + if (addr < 0x500) + { + switch (addr & 0xF) + { + case 0x0: + // LOG("Sound Channel %d Control Register long read\n", (addr >> 4) & 0xF); + return T1ReadLong(MMU.ARM7_REG, addr); + case 0x4: + // LOG("Sound Channel %d Data Source Register long read\n"); + return T1ReadLong(MMU.ARM7_REG, addr); + case 0x8: + // LOG("Sound Channel %d Timer/Loop Start Register long read\n", (addr >> 4) & 0xF); + return T1ReadLong(MMU.ARM7_REG, addr); + case 0xC: + // LOG("Sound Channel %d Length Register long read\n", (addr >> 4) & 0xF); + return T1ReadLong(MMU.ARM7_REG, addr); + default: + return T1ReadLong(MMU.ARM7_REG, addr); + } + } + else + { + switch (addr & 0x1F) + { + case 0x000: + // LOG("Sound Control Register long read\n"); + return T1ReadLong(MMU.ARM7_REG, addr); + case 0x004: + // LOG("Sound Bias Register long read\n"); + return T1ReadLong(MMU.ARM7_REG, addr); + case 0x008: + // LOG("Sound Capture 0/1 Control Register long read: %08X\n"); + return T1ReadLong(MMU.ARM7_REG, addr); + default: + return T1ReadLong(MMU.ARM7_REG, addr); + } + } - return T1ReadLong(MMU.ARM7_REG, addr); + return T1ReadLong(MMU.ARM7_REG, addr); } ////////////////////////////////////////////////////////////////////////////// +void SPU_struct::WriteByte(u32 addr, u8 val) +{ + channel_struct &thischan=channels[(addr >> 4) & 0xF]; + switch(addr & 0xF) { + case 0x0: + thischan.vol = val & 0x7F; + break; + case 0x1: { + thischan.datashift = val & 0x3; + if (thischan.datashift == 3) + thischan.datashift = 4; + thischan.hold = (val >> 7) & 0x1; + break; + } + case 0x2: + thischan.pan = val & 0x7F; + break; + case 0x3: { + thischan.waveduty = val & 0x7; + thischan.repeat = (val >> 3) & 0x3; + thischan.format = (val >> 5) & 0x3; + thischan.status = (val >> 7) & 0x1; + if(thischan.status) + KeyOn((addr >> 4) & 0xF); + break; + } + } + +} + void SPU_WriteByte(u32 addr, u8 val) { - addr &= 0xFFF; + addr &= 0xFFF; - if (addr < 0x500) - { - switch (addr & 0xF) - { - case 0x0: - SPU->chan[(addr >> 4) & 0xF].vol = val & 0x7F; -// LOG("Sound Channel %d Volume write: %02X\n", (addr >> 4) & 0xF, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0x1: - { - channel_struct *chan=&SPU->chan[(addr >> 4) & 0xF]; + if (addr < 0x500) + { + SPU_core->WriteByte(addr,val); + if(SPU_user) SPU_user->WriteByte(addr,val); -// LOG("Sound Channel %d Data Shift/Hold write: %02X\n",(addr >> 4) & 0xF, val); - chan->datashift = val & 0x3; - if (chan->datashift == 3) - chan->datashift = 4; - chan->hold = (val >> 7) & 0x1; - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - } - case 0x2: -// LOG("Sound Channel %d Panning write: %02X\n",(addr >> 4) & 0xF, val); - SPU->chan[(addr >> 4) & 0xF].pan = val & 0x7F; - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0x3: - { - channel_struct *chan=&SPU->chan[(addr >> 4) & 0xF]; -// LOG("Sound Channel %d Wave Duty/Repeat/Format/Start write: %08X - %02X. ARM7 PC = %08X\n", (addr >> 4) & 0xF, addr, val, NDS_ARM7.instruct_adr); + switch (addr & 0xF) + { + case 0x0: + //LOG("Sound Channel %d Volume write: %02X\n", (addr >> 4) & 0xF, val); + break; + case 0x1: + //LOG("Sound Channel %d Data Shift/Hold write: %02X\n",(addr >> 4) & 0xF, val); + break; + case 0x2: + //LOG("Sound Channel %d Panning write: %02X\n",(addr >> 4) & 0xF, val); + break; + case 0x3: + break; + case 0x4: + case 0x5: + case 0x6: + case 0x7: + //LOG("Sound Channel %d Data Source Register write: %08X %02X\n",(addr >> 4) & 0xF, addr, val); + break; + case 0x8: + //LOG("Sound Channel Timer(Low byte) write: %08X - %02X\n", addr, val); + break; + case 0x9: + //LOG("Sound Channel Timer(High byte) write: %08X - %02X\n", addr, val); + break; + case 0xA: + //LOG("Sound Channel Loop Start(Low byte) write: %08X - %02X\n", addr, val); + break; + case 0xB: + //LOG("Sound Channel Loop Start(High byte) write: %08X - %02X\n", addr, val); + break; + case 0xC: + case 0xD: + case 0xE: + case 0xF: + //LOG("Sound Channel %d Length Register write: %08X %02X\n",(addr >> 4) & 0xF, addr, val); + break; + default: + LOG("Unsupported Sound Register byte write: %08X %02X\n", addr, val); + break; + } + } + else + { + switch (addr & 0x1F) + { + case 0x000: + case 0x001: + //LOG("Sound Control Register write: %08X %02X\n", addr, val); + break; + case 0x004: + case 0x005: + //LOG("Sound Bias Register write: %08X %02X\n", addr, val); + break; + case 0x008: + //LOG("Sound Capture 0 Control Register write: %02X\n", val); + break; + case 0x009: + //LOG("Sound Capture 1 Control Register write: %02X\n", val); + break; + default: break; + } + } - chan->waveduty = val & 0x7; - chan->repeat = (val >> 3) & 0x3; - chan->format = (val >> 5) & 0x3; - chan->status = (val >> 7) & 0x1; - - if (SPU->chan[(addr >> 4) & 0xF].status) - SPU_KeyOn((addr >> 4) & 0xF); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - } - case 0x4: - case 0x5: - case 0x6: - case 0x7: -// LOG("Sound Channel %d Data Source Register write: %08X %02X\n",(addr >> 4) & 0xF, addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0x8: -// LOG("Sound Channel Timer(Low byte) write: %08X - %02X\n", addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0x9: -// LOG("Sound Channel Timer(High byte) write: %08X - %02X\n", addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0xA: -// LOG("Sound Channel Loop Start(Low byte) write: %08X - %02X\n", addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0xB: -// LOG("Sound Channel Loop Start(High byte) write: %08X - %02X\n", addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0xC: - case 0xD: - case 0xE: - case 0xF: -// LOG("Sound Channel %d Length Register write: %08X %02X\n",(addr >> 4) & 0xF, addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - default: - LOG("Unsupported Sound Register byte write: %08X %02X\n", addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - break; - } - } - else - { - switch (addr & 0x1F) - { - case 0x000: - case 0x001: -// LOG("Sound Control Register write: %08X %02X\n", addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0x004: - case 0x005: -// LOG("Sound Bias Register write: %08X %02X\n", addr, val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0x008: -// LOG("Sound Capture 0 Control Register write: %02X\n", val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - case 0x009: -// LOG("Sound Capture 1 Control Register write: %02X\n", val); - T1WriteByte(MMU.ARM7_REG, addr, val); - return; - default: break; - } - } - - T1WriteByte(MMU.ARM7_REG, addr, val); + T1WriteByte(MMU.ARM7_REG, addr, val); } ////////////////////////////////////////////////////////////////////////////// +void SPU_struct::WriteWord(u32 addr, u16 val) +{ + channel_struct &thischan=channels[(addr >> 4) & 0xF]; + switch(addr & 0xF) + { + case 0x0: + thischan.vol = val & 0x7F; + thischan.datashift = (val >> 8) & 0x3; + if (thischan.datashift == 3) + thischan.datashift = 4; + thischan.hold = (val >> 15) & 0x1; + break; + case 0x2: + thischan.pan = val & 0x7F; + thischan.waveduty = (val >> 8) & 0x7; + thischan.repeat = (val >> 11) & 0x3; + thischan.format = (val >> 13) & 0x3; + thischan.status = (val >> 15) & 0x1; + if (thischan.status) + KeyOn((addr >> 4) & 0xF); + break; + case 0x8: + thischan.timer = val & 0xFFFF; + thischan.sampinc = (16777216 / (0x10000 - (double)thischan.timer)) / 44100; + break; + case 0xA: + thischan.loopstart = val; + break; + + } +} + void SPU_WriteWord(u32 addr, u16 val) { - addr &= 0xFFF; + addr &= 0xFFF; - if (addr < 0x500) - { - switch (addr & 0xF) - { - case 0x0: - { - channel_struct *chan=&SPU->chan[(addr >> 4) & 0xF]; -// LOG("Sound Channel %d Volume/data shift/hold write: %04X\n", (addr >> 4) & 0xF, val); - chan->vol = val & 0x7F; - chan->datashift = (val >> 8) & 0x3; - if (chan->datashift == 3) - chan->datashift = 4; - chan->hold = (val >> 15) & 0x1; - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - } - case 0x2: - { - channel_struct *chan=&SPU->chan[(addr >> 4) & 0xF]; -// LOG("Sound Channel %d Panning/Wave Duty/Repeat Mode/Format/Start write: %04X\n", (addr >> 4) & 0xF, val); + if (addr < 0x500) + { + SPU_core->WriteWord(addr,val); + if(SPU_user) SPU_user->WriteWord(addr,val); - chan->pan = val & 0x7F; - chan->waveduty = (val >> 8) & 0x7; - chan->repeat = (val >> 11) & 0x3; - chan->format = (val >> 13) & 0x3; - chan->status = (val >> 15) & 0x1; - if (chan->status) - SPU_KeyOn((addr >> 4) & 0xF); + switch (addr & 0xF) + { + case 0x0: + //LOG("Sound Channel %d Volume/data shift/hold write: %04X\n", (addr >> 4) & 0xF, val); + break; + case 0x2: + //LOG("Sound Channel %d Panning/Wave Duty/Repeat Mode/Format/Start write: %04X\n", (addr >> 4) & 0xF, val); + break; + case 0x4: + case 0x6: + //LOG("Sound Channel %d Data Source Register write: %08X %04X\n",(addr >> 4) & 0xF, addr, val); + break; + case 0x8: + //LOG("Sound Channel %d Timer Register write: %04X\n", (addr >> 4) & 0xF, val); + break; + case 0xA: + //LOG("Sound Channel %d Loop start Register write: %04X\n", (addr >> 4) & 0xF, val); + break; + case 0xC: + case 0xE: + // LOG("Sound Channel %d Length Register write: %08X %04X\n",(addr >> 4) & 0xF, addr, val); + break; + default: + // LOG("Unsupported Sound Register word write: %08X %02X\n", addr, val); + break; + } + } + else + { + switch (addr & 0x1F) + { + case 0x000: + // LOG("Sound Control Register write: %04X\n", val); + break; + case 0x004: + // LOG("Sound Bias Register write: %04X\n", val); + break; + case 0x008: + // LOG("Sound Capture 0/1 Control Register write: %04X\n", val); + break; + } + } - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - } - case 0x4: - case 0x6: -// LOG("Sound Channel %d Data Source Register write: %08X %04X\n",(addr >> 4) & 0xF, addr, val); - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - case 0x8: - { - channel_struct *chan = &SPU->chan[(addr >> 4) & 0xF]; -// LOG("Sound Channel %d Timer Register write: %04X\n", (addr >> 4) & 0xF, val); - chan->timer = val & 0xFFFF; - chan->sampinc = (16777216 / (0x10000 - (double)chan->timer)) / 44100; - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - } - case 0xA: -// LOG("Sound Channel %d Loop start Register write: %04X\n", (addr >> 4) & 0xF, val); - SPU->chan[(addr >> 4) & 0xF].loopstart = val; - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - case 0xC: - case 0xE: -// LOG("Sound Channel %d Length Register write: %08X %04X\n",(addr >> 4) & 0xF, addr, val); - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - default: -// LOG("Unsupported Sound Register word write: %08X %02X\n", addr, val); - T1WriteWord(MMU.ARM7_REG, addr, val); - break; - } - } - else - { - switch (addr & 0x1F) - { - case 0x000: -// LOG("Sound Control Register write: %04X\n", val); - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - case 0x004: -// LOG("Sound Bias Register write: %04X\n", val); - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - case 0x008: -// LOG("Sound Capture 0/1 Control Register write: %04X\n", val); - T1WriteWord(MMU.ARM7_REG, addr, val); - return; - default: break; - } - } - - T1WriteWord(MMU.ARM7_REG, addr, val); + T1WriteWord(MMU.ARM7_REG, addr, val); } ////////////////////////////////////////////////////////////////////////////// +void SPU_struct::WriteLong(u32 addr, u32 val) +{ + channel_struct &thischan=channels[(addr >> 4) & 0xF]; + switch(addr & 0xF) + { + case 0x0: + thischan.vol = val & 0x7F; + thischan.datashift = (val >> 8) & 0x3; + if (thischan.datashift == 3) + thischan.datashift = 4; + thischan.hold = (val >> 15) & 0x1; + thischan.pan = (val >> 16) & 0x7F; + thischan.waveduty = (val >> 24) & 0x7; + thischan.repeat = (val >> 27) & 0x3; + thischan.format = (val >> 29) & 0x3; + thischan.status = (val >> 31) & 0x1; + if (thischan.status) + KeyOn((addr >> 4) & 0xF); + break; + case 0x4: + thischan.addr = val & 0x7FFFFFF; + break; + case 0x8: + thischan.timer = val & 0xFFFF; + thischan.loopstart = val >> 16; + thischan.sampinc = (16777216 / (0x10000 - (double)thischan.timer)) / 44100; + break; + case 0xC: + thischan.length = val & 0x3FFFFF; + break; + } +} + void SPU_WriteLong(u32 addr, u32 val) { - addr &= 0xFFF; + addr &= 0xFFF; - if (addr < 0x500) - { - switch (addr & 0xF) - { - case 0x0: - { - channel_struct *chan=&SPU->chan[(addr >> 4) & 0xF]; -// LOG("Sound Channel %d long write: %08X\n", (addr >> 4) & 0xF, val); - chan->vol = val & 0x7F; - chan->datashift = (val >> 8) & 0x3; - if (chan->datashift == 3) - chan->datashift = 4; - chan->hold = (val >> 15) & 0x1; - chan->pan = (val >> 16) & 0x7F; - chan->waveduty = (val >> 24) & 0x7; - chan->repeat = (val >> 27) & 0x3; - chan->format = (val >> 29) & 0x3; - chan->status = (val >> 31) & 0x1; - if (SPU->chan[(addr >> 4) & 0xF].status) - SPU_KeyOn((addr >> 4) & 0xF); - T1WriteLong(MMU.ARM7_REG, addr, val); - return; - } - case 0x4: -// LOG("Sound Channel %d Data Source Register long write: %08X\n", (addr >> 4) & 0xF, val); - SPU->chan[(addr >> 4) & 0xF].addr = val & 0x7FFFFFF; - T1WriteLong(MMU.ARM7_REG, addr, val); - return; - case 0x8: - { - channel_struct *chan = &SPU->chan[(addr >> 4) & 0xF]; + if (addr < 0x500) + { + SPU_core->WriteLong(addr,val); + if(SPU_user) SPU_user->WriteLong(addr,val); -// LOG("Sound Channel %d Timer/Loop Start Register write: - %08X\n", (addr >> 4) & 0xF, val); - chan->timer = val & 0xFFFF; - chan->loopstart = val >> 16; - chan->sampinc = (16777216 / (0x10000 - (double)chan->timer)) / 44100; - T1WriteLong(MMU.ARM7_REG, addr, val); - return; - } - case 0xC: -// LOG("Sound Channel %d Length Register long write: %08X\n", (addr >> 4) & 0xF, val); - SPU->chan[(addr >> 4) & 0xF].length = val & 0x3FFFFF; - T1WriteLong(MMU.ARM7_REG, addr, val); - return; - default: break; - } - } - else - { - switch (addr & 0x1F) - { - case 0x000: -// LOG("Sound Control Register write: %08X\n", val); - T1WriteLong(MMU.ARM7_REG, addr, val); - return; - case 0x004: -// LOG("Sound Bias Register write: %08X\n", val); - T1WriteLong(MMU.ARM7_REG, addr, val); - return; - case 0x008: -// LOG("Sound Capture 0/1 Control Register write: %08X\n", val); - T1WriteLong(MMU.ARM7_REG, addr, val); - return; - default: break; - } - } + switch (addr & 0xF) + { + case 0x0: + //LOG("Sound Channel %d long write: %08X\n", (addr >> 4) & 0xF, val); + break; + case 0x4: + //LOG("Sound Channel %d Data Source Register long write: %08X\n", (addr >> 4) & 0xF, val); + break; + case 0x8: + //LOG("Sound Channel %d Timer/Loop Start Register write: - %08X\n", (addr >> 4) & 0xF, val); + break; + case 0xC: + //LOG("Sound Channel %d Length Register long write: %08X\n", (addr >> 4) & 0xF, val); + break; + } + } + else + { + switch (addr & 0x1F) + { + case 0x000: + //LOG("Sound Control Register write: %08X\n", val); + break; + case 0x004: + //LOG("Sound Bias Register write: %08X\n", val); + break; + case 0x008: + //LOG("Sound Capture 0/1 Control Register write: %08X\n", val); + break; + } + } - T1WriteLong(MMU.ARM7_REG, addr, val); + T1WriteLong(MMU.ARM7_REG, addr, val); } static s32 Interpolate(s32 a, s32 b, double ratio) @@ -718,9 +720,9 @@ static INLINE void Fetch8BitData(channel_struct *chan, s32 *data) s32 b = (s32)chan->buf8[loc+1] << 8; a = (1-ratio)*a + ratio*b; } - *data = a; + *data = a; #else - *data = (s32)chan->buf8[(int)chan->sampcnt] << 8; + *data = (s32)chan->buf8[(int)chan->sampcnt] << 8; #endif } @@ -736,7 +738,7 @@ static INLINE void Fetch16BitData(channel_struct *chan, s32 *data) s32 b = (s32)chan->buf16[loc+1]; a = (1-ratio)*a + ratio*b; } - *data = a; + *data = a; #else *data = (s32)chan->buf16[(int)chan->sampcnt]; #endif @@ -746,57 +748,57 @@ static INLINE void Fetch16BitData(channel_struct *chan, s32 *data) static INLINE int MinMax(int val, int min, int max) { - if (val < min) - return min; - else if (val > max) - return max; + if (val < min) + return min; + else if (val > max) + return max; - return val; + return val; } ////////////////////////////////////////////////////////////////////////////// static INLINE void FetchADPCMData(channel_struct *chan, s32 *data) { - u8 data4bit; - int diff; - int i; + u8 data4bit; + int diff; + int i; - if (chan->lastsampcnt == (int)chan->sampcnt) - { - // No sense decoding, just return the last sample + if (chan->lastsampcnt == (int)chan->sampcnt) + { + // No sense decoding, just return the last sample #ifdef SPU_INTERPOLATE - *data = Interpolate((s32)chan->pcm16b_last,(s32)chan->pcm16b,chan->sampcnt); + *data = Interpolate((s32)chan->pcm16b_last,(s32)chan->pcm16b,chan->sampcnt); #else - *data = (s32)chan->pcm16b; + *data = (s32)chan->pcm16b; #endif - return; - } + return; + } - for (i = chan->lastsampcnt+1; i < (int)chan->sampcnt+1; i++) - { - if (i & 0x1) - data4bit = (chan->buf8[i >> 1] >> 4) & 0xF; - else - data4bit = chan->buf8[i >> 1] & 0xF; + for (i = chan->lastsampcnt+1; i < (int)chan->sampcnt+1; i++) + { + if (i & 0x1) + data4bit = (chan->buf8[i >> 1] >> 4) & 0xF; + else + data4bit = chan->buf8[i >> 1] & 0xF; - diff = ((data4bit & 0x7) * 2 + 1) * adpcmtbl[chan->index] / 8; - if (data4bit & 0x8) - diff = -diff; + diff = ((data4bit & 0x7) * 2 + 1) * adpcmtbl[chan->index] / 8; + if (data4bit & 0x8) + diff = -diff; #ifdef SPU_INTERPOLATE - chan->pcm16b_last = chan->pcm16b; + chan->pcm16b_last = chan->pcm16b; #endif - chan->pcm16b = (s16)MinMax(chan->pcm16b+diff, -0x8000, 0x7FFF); - chan->index = MinMax(chan->index+indextbl[data4bit & 0x7], 0, 88); - } + chan->pcm16b = (s16)MinMax(chan->pcm16b+diff, -0x8000, 0x7FFF); + chan->index = MinMax(chan->index+indextbl[data4bit & 0x7], 0, 88); + } - chan->lastsampcnt = chan->sampcnt; + chan->lastsampcnt = chan->sampcnt; #ifdef SPU_INTERPOLATE - *data = Interpolate((s32)chan->pcm16b_last,(s32)chan->pcm16b,chan->sampcnt); + *data = Interpolate((s32)chan->pcm16b_last,(s32)chan->pcm16b,chan->sampcnt); #else - *data = (s32)chan->pcm16b; + *data = (s32)chan->pcm16b; #endif } @@ -804,87 +806,89 @@ static INLINE void FetchADPCMData(channel_struct *chan, s32 *data) static INLINE void FetchPSGData(channel_struct *chan, s32 *data) { - *data = (s32)wavedutytbl[chan->waveduty][((int)chan->sampcnt) & 0x7]; + *data = (s32)wavedutytbl[chan->waveduty][((int)chan->sampcnt) & 0x7]; } ////////////////////////////////////////////////////////////////////////////// -static INLINE void MixL(channel_struct *chan, s32 data) +static INLINE void MixL(SPU_struct* SPU, channel_struct *chan, s32 data) { - if (data) - { - data = (data * chan->vol / 127) >> chan->datashift; - SPU->sndbuf[SPU->bufpos<<1] += data; - } + if (data) + { + data = (data * chan->vol / 127) >> chan->datashift; + SPU->sndbuf[SPU->bufpos<<1] += data; + } } ////////////////////////////////////////////////////////////////////////////// -static INLINE void MixR(channel_struct *chan, s32 data) +static INLINE void MixR(SPU_struct* SPU, channel_struct *chan, s32 data) { - if (data) - { - data = (data * chan->vol / 127) >> chan->datashift; - SPU->sndbuf[(SPU->bufpos<<1)+1] += data; - } + if (data) + { + data = (data * chan->vol / 127) >> chan->datashift; + SPU->sndbuf[(SPU->bufpos<<1)+1] += data; + } } ////////////////////////////////////////////////////////////////////////////// -static INLINE void MixLR(channel_struct *chan, s32 data) +static INLINE void MixLR(SPU_struct* SPU, channel_struct *chan, s32 data) { - if (data) - { - data = ((data * chan->vol) / 127) >> chan->datashift; - SPU->sndbuf[SPU->bufpos<<1] += data * (127 - chan->pan) / 127; - SPU->sndbuf[(SPU->bufpos<<1)+1] += data * chan->pan / 127; - } + if (data) + { + data = ((data * chan->vol) / 127) >> chan->datashift; + SPU->sndbuf[SPU->bufpos<<1] += data * (127 - chan->pan) / 127; + SPU->sndbuf[(SPU->bufpos<<1)+1] += data * chan->pan / 127; + } } ////////////////////////////////////////////////////////////////////////////// -static INLINE void TestForLoop(channel_struct *chan) +static INLINE void TestForLoop(SPU_struct *SPU, channel_struct *chan) { - chan->sampcnt += chan->sampinc; + chan->sampcnt += chan->sampinc; - if (chan->sampcnt > (double)chan->length) - { - // Do we loop? Or are we done? - if (chan->repeat == 1) - chan->sampcnt = (double)chan->loopstart; // Is this correct? - else - { - chan->status = CHANSTAT_STOPPED; + if (chan->sampcnt > (double)chan->length) + { + // Do we loop? Or are we done? + if (chan->repeat == 1) + chan->sampcnt = (double)chan->loopstart; // Is this correct? + else + { + chan->status = CHANSTAT_STOPPED; - MMU.ARM7_REG[0x403 + (((chan-SPU->chan) / sizeof(channel_struct)) * 0x10)] &= 0x7F; - SPU->bufpos = SPU->buflength; - } - } + if(SPU == SPU_core) + MMU.ARM7_REG[0x403 + (((chan-SPU->channels) ) * 0x10)] &= 0x7F; + SPU->bufpos = SPU->buflength; + } + } } ////////////////////////////////////////////////////////////////////////////// -static INLINE void TestForLoop2(channel_struct *chan) +static INLINE void TestForLoop2(SPU_struct *SPU, channel_struct *chan) { - chan->sampcnt += chan->sampinc; + chan->sampcnt += chan->sampinc; - if (chan->sampcnt > (double)chan->length) - { - // Do we loop? Or are we done? - if (chan->repeat == 1) - { - chan->sampcnt = (double)chan->loopstart; // Is this correct? - chan->pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]); - chan->index = chan->buf8[2] & 0x7F; - chan->lastsampcnt = 7; - } - else - { - chan->status = CHANSTAT_STOPPED; - MMU.ARM7_REG[0x403 + (((chan-SPU->chan) / sizeof(channel_struct)) * 0x10)] &= 0x7F; - SPU->bufpos = SPU->buflength; - } - } + if (chan->sampcnt > (double)chan->length) + { + // Do we loop? Or are we done? + if (chan->repeat == 1) + { + chan->sampcnt = (double)chan->loopstart; // Is this correct? + chan->pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]); + chan->index = chan->buf8[2] & 0x7F; + chan->lastsampcnt = 7; + } + else + { + chan->status = CHANSTAT_STOPPED; + if(SPU == SPU_core) + MMU.ARM7_REG[0x403 + (((chan-SPU->channels) ) * 0x10)] &= 0x7F; + SPU->bufpos = SPU->buflength; + } + } } ////////////////////////////////////////////////////////////////////////////// @@ -895,308 +899,327 @@ void SPU_ChanUpdateNothing(channel_struct *chan) ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdate8LR(channel_struct *chan) +void SPU_ChanUpdate8LR(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - Fetch8BitData(chan, &data); + // fetch data from source address + Fetch8BitData(chan, &data); - MixLR(chan, data); + MixLR(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdate8L(channel_struct *chan) +void SPU_ChanUpdate8L(SPU_struct *SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - Fetch8BitData(chan, &data); + // fetch data from source address + Fetch8BitData(chan, &data); - MixL(chan, data); + MixL(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdate8R(channel_struct *chan) +void SPU_ChanUpdate8R(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - Fetch8BitData(chan, &data); + // fetch data from source address + Fetch8BitData(chan, &data); - MixR(chan, data); + MixR(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdate16LR(channel_struct *chan) +void SPU_ChanUpdate16LR(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - Fetch16BitData(chan, &data); + // fetch data from source address + Fetch16BitData(chan, &data); - MixLR(chan, data); + MixLR(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdate16L(channel_struct *chan) +void SPU_ChanUpdate16L(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - Fetch16BitData(chan, &data); + // fetch data from source address + Fetch16BitData(chan, &data); - MixL(chan, data); + MixL(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdate16R(channel_struct *chan) +void SPU_ChanUpdate16R(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - Fetch16BitData(chan, &data); + // fetch data from source address + Fetch16BitData(chan, &data); - MixR(chan, data); + MixR(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdateADPCMLR(channel_struct *chan) +void SPU_ChanUpdateADPCMLR(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - FetchADPCMData(chan, &data); + // fetch data from source address + FetchADPCMData(chan, &data); - MixLR(chan, data); + MixLR(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop2(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop2(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdateADPCML(channel_struct *chan) +void SPU_ChanUpdateADPCML(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - FetchADPCMData(chan, &data); + // fetch data from source address + FetchADPCMData(chan, &data); - MixL(chan, data); + MixL(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop2(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop2(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdateADPCMR(channel_struct *chan) +void SPU_ChanUpdateADPCMR(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - FetchADPCMData(chan, &data); + // fetch data from source address + FetchADPCMData(chan, &data); - MixR(chan, data); + MixR(SPU, chan, data); - // check to see if we're passed the length and need to loop, etc. - TestForLoop2(chan); - } + // check to see if we're passed the length and need to loop, etc. + TestForLoop2(SPU, chan); + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdatePSGLR(channel_struct *chan) +void SPU_ChanUpdatePSGLR(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - FetchPSGData(chan, &data); + // fetch data from source address + FetchPSGData(chan, &data); - MixLR(chan, data); + MixLR(SPU, chan, data); - chan->sampcnt += chan->sampinc; - } + chan->sampcnt += chan->sampinc; + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdatePSGL(channel_struct *chan) +void SPU_ChanUpdatePSGL(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - FetchPSGData(chan, &data); + // fetch data from source address + FetchPSGData(chan, &data); - MixL(chan, data); + MixL(SPU, chan, data); - chan->sampcnt += chan->sampinc; - } + chan->sampcnt += chan->sampinc; + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_ChanUpdatePSGR(channel_struct *chan) +void SPU_ChanUpdatePSGR(SPU_struct* SPU, channel_struct *chan) { - for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) - { - s32 data; + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + s32 data; - // fetch data from source address - FetchPSGData(chan, &data); + // fetch data from source address + FetchPSGData(chan, &data); - MixR(chan, data); + MixR(SPU, chan, data); - chan->sampcnt += chan->sampinc; - } + chan->sampcnt += chan->sampinc; + } } ////////////////////////////////////////////////////////////////////////////// -void (*SPU_ChanUpdate[4][3])(channel_struct *chan) = { - { // 8-bit PCM - SPU_ChanUpdate8L, - SPU_ChanUpdate8LR, - SPU_ChanUpdate8R - }, - { // 16-bit PCM - SPU_ChanUpdate16L, - SPU_ChanUpdate16LR, - SPU_ChanUpdate16R - }, - { // IMA-ADPCM - SPU_ChanUpdateADPCML, - SPU_ChanUpdateADPCMLR, - SPU_ChanUpdateADPCMR - }, - { // PSG/White Noise - SPU_ChanUpdatePSGL, - SPU_ChanUpdatePSGLR, - SPU_ChanUpdatePSGR - } +void (*SPU_ChanUpdate[4][3])(SPU_struct* SPU, channel_struct *chan) = { + { // 8-bit PCM + SPU_ChanUpdate8L, + SPU_ChanUpdate8LR, + SPU_ChanUpdate8R + }, + { // 16-bit PCM + SPU_ChanUpdate16L, + SPU_ChanUpdate16LR, + SPU_ChanUpdate16R + }, + { // IMA-ADPCM + SPU_ChanUpdateADPCML, + SPU_ChanUpdateADPCMLR, + SPU_ChanUpdateADPCMR + }, + { // PSG/White Noise + SPU_ChanUpdatePSGL, + SPU_ChanUpdatePSGLR, + SPU_ChanUpdatePSGR + } }; ////////////////////////////////////////////////////////////////////////////// -void SPU_MixAudio(int length) +void SPU_MixAudio(SPU_struct *SPU, int length) { - channel_struct *chan; - u8 vol; - int i; + channel_struct *chan; + u8 vol; + int i; - memset(SPU->sndbuf, 0, length*4*2); + memset(SPU->sndbuf, 0, length*4*2); - // If Master Enable isn't set, don't output audio - if (!(T1ReadByte(MMU.ARM7_REG, 0x501) & 0x80)) - return; + // If Master Enable isn't set, don't output audio + if (!(T1ReadByte(MMU.ARM7_REG, 0x501) & 0x80)) + return; - vol = T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F; + vol = T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F; - for(chan = &(SPU->chan[0]); chan < &(SPU->chan[16]); chan++) - { - if (chan->status != CHANSTAT_PLAY) - continue; + for(int i=0;i<16;i++) + { + channel_struct *chan = &SPU->channels[i]; + + if (chan->status != CHANSTAT_PLAY) + continue; - SPU->bufpos = 0; - SPU->buflength = length; + SPU->bufpos = 0; + SPU->buflength = length; - // Mix audio - if (chan->pan == 0) - SPU_ChanUpdate[chan->format][0](chan); - else if (chan->pan == 127) - SPU_ChanUpdate[chan->format][2](chan); - else - SPU_ChanUpdate[chan->format][1](chan); - } + // Mix audio + if (chan->pan == 0) + SPU_ChanUpdate[chan->format][0](SPU,chan); + else if (chan->pan == 127) + SPU_ChanUpdate[chan->format][2](SPU,chan); + else + SPU_ChanUpdate[chan->format][1](SPU,chan); + } - // convert from 32-bit->16-bit - for (i = 0; i < length*2; i++) - { - // Apply Master Volume - SPU->sndbuf[i] = SPU->sndbuf[i] * vol / 127; + // convert from 32-bit->16-bit + for (i = 0; i < length*2; i++) + { + // Apply Master Volume + SPU->sndbuf[i] = SPU->sndbuf[i] * vol / 127; - if (SPU->sndbuf[i] > 0x7FFF) - SPU->outbuf[i] = 0x7FFF; - else if (SPU->sndbuf[i] < -0x8000) - SPU->outbuf[i] = -0x8000; - else - SPU->outbuf[i] = (s16)SPU->sndbuf[i]; - } + if (SPU->sndbuf[i] > 0x7FFF) + SPU->outbuf[i] = 0x7FFF; + else if (SPU->sndbuf[i] < -0x8000) + SPU->outbuf[i] = -0x8000; + else + SPU->outbuf[i] = (s16)SPU->sndbuf[i]; + } } ////////////////////////////////////////////////////////////////////////////// -void SPU_Emulate(void) + +//emulates one frame of the cpu core. +//this will produce a variable number of samples, calculated to keep a 44100hz output +//in sync with the emulator framerate +static float samples = 0; +static const float time_per_frame = 1.0f/59.8261f; +static const float samples_per_frame = time_per_frame * 44100; +int spu_core_samples = 0; +void SPU_Emulate_core() { - u32 audiosize; + samples += samples_per_frame; + spu_core_samples = (int)(samples); + samples -= spu_core_samples; + + SPU_MixAudio(SPU_core,spu_core_samples); +} - // Check to see how much free space there is - // If there is some, fill up the buffer - audiosize = SNDCore->GetAudioSpace(); +void SPU_Emulate_user() +{ + u32 audiosize; - if (audiosize > 0) - { - if (audiosize > SPU->bufsize) - audiosize = SPU->bufsize; - SPU_MixAudio(audiosize); - SNDCore->UpdateAudio(SPU->outbuf, audiosize); - } + // Check to see how much free space there is + // If there is some, fill up the buffer + audiosize = SNDCore->GetAudioSpace(); + + if (audiosize > 0) + { + if (audiosize > SPU_user->bufsize) + audiosize = SPU_user->bufsize; + SPU_MixAudio(SPU_user,audiosize); + SNDCore->UpdateAudio(SPU_user->outbuf, audiosize); + } } ////////////////////////////////////////////////////////////////////////////// @@ -1212,22 +1235,22 @@ void SNDDummyUnMuteAudio(); void SNDDummySetVolume(int volume); SoundInterface_struct SNDDummy = { -SNDCORE_DUMMY, -"Dummy Sound Interface", -SNDDummyInit, -SNDDummyDeInit, -SNDDummyUpdateAudio, -SNDDummyGetAudioSpace, -SNDDummyMuteAudio, -SNDDummyUnMuteAudio, -SNDDummySetVolume + SNDCORE_DUMMY, + "Dummy Sound Interface", + SNDDummyInit, + SNDDummyDeInit, + SNDDummyUpdateAudio, + SNDDummyGetAudioSpace, + SNDDummyMuteAudio, + SNDDummyUnMuteAudio, + SNDDummySetVolume }; ////////////////////////////////////////////////////////////////////////////// int SNDDummyInit(int buffersize) { - return 0; + return 0; } ////////////////////////////////////////////////////////////////////////////// @@ -1246,7 +1269,7 @@ void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples) u32 SNDDummyGetAudioSpace() { - return 735; + return 740; } ////////////////////////////////////////////////////////////////////////////// @@ -1280,108 +1303,108 @@ void SNDFileUnMuteAudio(); void SNDFileSetVolume(int volume); SoundInterface_struct SNDFile = { -SNDCORE_FILEWRITE, -"WAV Write Sound Interface", -SNDFileInit, -SNDFileDeInit, -SNDFileUpdateAudio, -SNDFileGetAudioSpace, -SNDFileMuteAudio, -SNDFileUnMuteAudio, -SNDFileSetVolume + SNDCORE_FILEWRITE, + "WAV Write Sound Interface", + SNDFileInit, + SNDFileDeInit, + SNDFileUpdateAudio, + SNDFileGetAudioSpace, + SNDFileMuteAudio, + SNDFileUnMuteAudio, + SNDFileSetVolume }; ////////////////////////////////////////////////////////////////////////////// typedef struct { - char id[4]; - u32 size; + char id[4]; + u32 size; } chunk_struct; typedef struct { - chunk_struct riff; - char rifftype[4]; + chunk_struct riff; + char rifftype[4]; } waveheader_struct; typedef struct { - chunk_struct chunk; - u16 compress; - u16 numchan; - u32 rate; - u32 bytespersec; - u16 blockalign; - u16 bitspersample; + chunk_struct chunk; + u16 compress; + u16 numchan; + u32 rate; + u32 bytespersec; + u16 blockalign; + u16 bitspersample; } fmt_struct; ////////////////////////////////////////////////////////////////////////////// int SNDFileInit(int buffersize) { - waveheader_struct waveheader; - fmt_struct fmt; - chunk_struct data; + waveheader_struct waveheader; + fmt_struct fmt; + chunk_struct data; - if ((spufp = fopen("ndsaudio.wav", "wb")) == NULL) - return -1; + if ((spufp = fopen("ndsaudio.wav", "wb")) == NULL) + return -1; - // Do wave header - memcpy(waveheader.riff.id, "RIFF", 4); - waveheader.riff.size = 0; // we'll fix this after the file is closed - memcpy(waveheader.rifftype, "WAVE", 4); - fwrite((void *)&waveheader, 1, sizeof(waveheader_struct), spufp); + // Do wave header + memcpy(waveheader.riff.id, "RIFF", 4); + waveheader.riff.size = 0; // we'll fix this after the file is closed + memcpy(waveheader.rifftype, "WAVE", 4); + fwrite((void *)&waveheader, 1, sizeof(waveheader_struct), spufp); - // fmt chunk - memcpy(fmt.chunk.id, "fmt ", 4); - fmt.chunk.size = 16; // we'll fix this at the end - fmt.compress = 1; // PCM - fmt.numchan = 2; // Stereo - fmt.rate = 44100; - fmt.bitspersample = 16; - fmt.blockalign = fmt.bitspersample / 8 * fmt.numchan; - fmt.bytespersec = fmt.rate * fmt.blockalign; - fwrite((void *)&fmt, 1, sizeof(fmt_struct), spufp); + // fmt chunk + memcpy(fmt.chunk.id, "fmt ", 4); + fmt.chunk.size = 16; // we'll fix this at the end + fmt.compress = 1; // PCM + fmt.numchan = 2; // Stereo + fmt.rate = 44100; + fmt.bitspersample = 16; + fmt.blockalign = fmt.bitspersample / 8 * fmt.numchan; + fmt.bytespersec = fmt.rate * fmt.blockalign; + fwrite((void *)&fmt, 1, sizeof(fmt_struct), spufp); - // data chunk - memcpy(data.id, "data", 4); - data.size = 0; // we'll fix this at the end - fwrite((void *)&data, 1, sizeof(chunk_struct), spufp); + // data chunk + memcpy(data.id, "data", 4); + data.size = 0; // we'll fix this at the end + fwrite((void *)&data, 1, sizeof(chunk_struct), spufp); - return 0; + return 0; } ////////////////////////////////////////////////////////////////////////////// void SNDFileDeInit() { - if (spufp) - { - long length = ftell(spufp); + if (spufp) + { + long length = ftell(spufp); - // Let's fix the riff chunk size and the data chunk size - fseek(spufp, sizeof(waveheader_struct)-0x8, SEEK_SET); - length -= 0x4; - fwrite((void *)&length, 1, 4, spufp); + // Let's fix the riff chunk size and the data chunk size + fseek(spufp, sizeof(waveheader_struct)-0x8, SEEK_SET); + length -= 0x4; + fwrite((void *)&length, 1, 4, spufp); - fseek(spufp, sizeof(waveheader_struct)+sizeof(fmt_struct)+0x4, SEEK_SET); - length -= sizeof(waveheader_struct)+sizeof(fmt_struct); - fwrite((void *)&length, 1, 4, spufp); - fclose(spufp); - } + fseek(spufp, sizeof(waveheader_struct)+sizeof(fmt_struct)+0x4, SEEK_SET); + length -= sizeof(waveheader_struct)+sizeof(fmt_struct); + fwrite((void *)&length, 1, 4, spufp); + fclose(spufp); + } } ////////////////////////////////////////////////////////////////////////////// void SNDFileUpdateAudio(s16 *buffer, u32 num_samples) { - if (spufp) - fwrite((void *)buffer, num_samples*2, 2, spufp); + if (spufp) + fwrite((void *)buffer, num_samples*2, 2, spufp); } ////////////////////////////////////////////////////////////////////////////// u32 SNDFileGetAudioSpace() { - return 735; + return 740; } ////////////////////////////////////////////////////////////////////////////// diff --git a/desmume/src/SPU.h b/desmume/src/SPU.h index e984507ba..c279d88bf 100644 --- a/desmume/src/SPU.h +++ b/desmume/src/SPU.h @@ -42,7 +42,7 @@ typedef struct extern SoundInterface_struct SNDDummy; extern SoundInterface_struct SNDFile; -typedef struct +struct channel_struct { u8 vol; u8 datashift; @@ -64,19 +64,26 @@ typedef struct int lastsampcnt; s16 pcm16b, pcm16b_last; int index; -} channel_struct; +} ; -typedef struct +class SPU_struct { +public: + SPU_struct(int buffersize); u32 bufpos; u32 buflength; s32 *sndbuf; s16 *outbuf; u32 bufsize; - channel_struct chan[16]; -} SPU_struct; + channel_struct channels[16]; -extern SPU_struct *SPU; + void reset(); + ~SPU_struct(); + void KeyOn(int channel); + void WriteByte(u32 addr, u8 val); + void WriteWord(u32 addr, u16 val); + void WriteLong(u32 addr, u32 val); +}; int SPU_ChangeSoundCore(int coreid, int buffersize); SoundInterface_struct *SPU_SoundCore(); @@ -91,6 +98,10 @@ void SPU_WriteByte(u32 addr, u8 val); void SPU_WriteWord(u32 addr, u16 val); void SPU_WriteLong(u32 addr, u32 val); u32 SPU_ReadLong(u32 addr); -void SPU_Emulate(void); +void SPU_Emulate_core(void); +void SPU_Emulate_user(void); + +extern SPU_struct *SPU_core; +extern int spu_core_samples; #endif diff --git a/desmume/src/cli/main.cpp b/desmume/src/cli/main.cpp index e93ef9add..84a15923c 100644 --- a/desmume/src/cli/main.cpp +++ b/desmume/src/cli/main.cpp @@ -760,7 +760,8 @@ int main(int argc, char ** argv) { update_keypad(keypad); /* Update keypad */ last_cycle = NDS_exec((560190 << 1) - last_cycle, FALSE); - SPU_Emulate(); + SPU_Emulate_user(); + SPU_Emulate_core(); #ifdef INCLUDE_OPENGL_2D if ( my_config.opengl_2d) { diff --git a/desmume/src/cocoa/nds_control.mm b/desmume/src/cocoa/nds_control.mm index 217ee2fd4..c0d470925 100644 --- a/desmume/src/cocoa/nds_control.mm +++ b/desmume/src/cocoa/nds_control.mm @@ -1282,7 +1282,10 @@ bool opengl_init() [sound_lock lock]; int x; for(x = 0; x <= frames_to_skip; x++) - SPU_Emulate(); + { + SPU_Emulate_user(); + SPU_Emulate_core(); + } [sound_lock unlock]; [execution_lock unlock]; diff --git a/desmume/src/gtk-glade/desmume.cpp b/desmume/src/gtk-glade/desmume.cpp index b987a70f4..ddcc47ba0 100755 --- a/desmume/src/gtk-glade/desmume.cpp +++ b/desmume/src/gtk-glade/desmume.cpp @@ -117,7 +117,8 @@ void desmume_cycle() update_keypad(keypad); desmume_last_cycle = NDS_exec((560190 << 1) - desmume_last_cycle, FALSE); - SPU_Emulate(); + SPU_Emulate_user(); + SPU_Emulate_core(); } diff --git a/desmume/src/gtk/desmume.cpp b/desmume/src/gtk/desmume.cpp index 07f709820..ba3886f4f 100644 --- a/desmume/src/gtk/desmume.cpp +++ b/desmume/src/gtk/desmume.cpp @@ -82,6 +82,7 @@ void desmume_cycle( void) update_keypad(keypad); desmume_last_cycle = NDS_exec((560190 << 1) - desmume_last_cycle, FALSE); - SPU_Emulate(); + SPU_Emulate_user(); + SPU_Emulate_core(); } diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index 253a1bc69..17f8b2193 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -73,7 +73,7 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -891,14 +895,6 @@ Name="MASM" /> - - - + + + + + diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj index 949fdc82c..e511f4702 100644 --- a/desmume/src/windows/DeSmuME_2008.vcproj +++ b/desmume/src/windows/DeSmuME_2008.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + diff --git a/desmume/src/windows/aviout.cpp b/desmume/src/windows/aviout.cpp new file mode 100644 index 000000000..c982cbdf2 --- /dev/null +++ b/desmume/src/windows/aviout.cpp @@ -0,0 +1,430 @@ +#include "types.h" +#include "windriver.h" +#include "console.h" +#include "gfx3d.h" + +#include +#include +#include + +void EMU_PrintError(const char* msg) { + printlog(msg); +} + +void EMU_PrintMessage(const char* msg) { + printlog(msg); +} + +bool DRV_AviBegin(const char* fname); +void DRV_AviEnd(); +void DRV_AviSoundUpdate(void* soundData, int soundLen); +bool DRV_AviIsRecording(); +void DRV_AviVideoUpdate(const u16* buffer); + +//extern PALETTEENTRY *color_palette; +//extern WAVEFORMATEX wf; +//extern int soundo; + +#define VIDEO_STREAM 0 +#define AUDIO_STREAM 1 + +#define VIDEO_WIDTH 256 + +static struct AVIFile +{ + int valid; + int fps; + int fps_scale; + + int video_added; + BITMAPINFOHEADER bitmap_format; + + int sound_added; + WAVEFORMATEX wave_format; + + AVISTREAMINFO avi_video_header; + AVISTREAMINFO avi_sound_header; + PAVIFILE avi_file; + PAVISTREAM streams[2]; + PAVISTREAM compressed_streams[2]; + + AVICOMPRESSOPTIONS compress_options[2]; + AVICOMPRESSOPTIONS* compress_options_ptr[2]; + + int video_frames; + int sound_samples; + + u8 convert_buffer[256*384*3]; + int start_scanline; + int end_scanline; + + long tBytes, ByteBuffer; +} *avi_file = NULL; + +struct VideoSystemInfo +{ + int start_scanline; + int end_scanline; + int fps; +}; + + +static char saved_cur_avi_fnameandext[MAX_PATH]; +static char saved_avi_fname[MAX_PATH]; +static char saved_avi_ext[MAX_PATH]; +static int avi_segnum=0; +//static FILE* avi_check_file=0; +static struct AVIFile saved_avi_info; +static int use_prev_options=0; +static bool use_sound=false; + + + +static bool truncate_existing(const char* filename) +{ + // this is only here because AVIFileOpen doesn't seem to do it for us + FILE* fd = fopen(filename, "wb"); + if(fd) + { + fclose(fd); + return 1; + } + + return 0; +} + +static void avi_create(struct AVIFile** avi_out) +{ + *avi_out = (struct AVIFile*)malloc(sizeof(struct AVIFile)); + memset(*avi_out, 0, sizeof(struct AVIFile)); + AVIFileInit(); +} + +static void avi_destroy(struct AVIFile** avi_out) +{ + if(!(*avi_out)) + return; + + if((*avi_out)->sound_added) + { + if((*avi_out)->compressed_streams[AUDIO_STREAM]) + { + LONG test = AVIStreamClose((*avi_out)->compressed_streams[AUDIO_STREAM]); + (*avi_out)->compressed_streams[AUDIO_STREAM] = NULL; + (*avi_out)->streams[AUDIO_STREAM] = NULL; // compressed_streams[AUDIO_STREAM] is just a copy of streams[AUDIO_STREAM] + } + } + + if((*avi_out)->video_added) + { + if((*avi_out)->compressed_streams[VIDEO_STREAM]) + { + AVIStreamClose((*avi_out)->compressed_streams[VIDEO_STREAM]); + (*avi_out)->compressed_streams[VIDEO_STREAM] = NULL; + } + + if((*avi_out)->streams[VIDEO_STREAM]) + { + AVIStreamClose((*avi_out)->streams[VIDEO_STREAM]); + (*avi_out)->streams[VIDEO_STREAM] = NULL; + } + } + + if((*avi_out)->avi_file) + { + AVIFileClose((*avi_out)->avi_file); + (*avi_out)->avi_file = NULL; + } + + free(*avi_out); + *avi_out = NULL; +} + +static void set_video_format(const BITMAPINFOHEADER* bitmap_format, struct AVIFile* avi_out) +{ + memcpy(&((*avi_out).bitmap_format), bitmap_format, sizeof(BITMAPINFOHEADER)); + (*avi_out).video_added = 1; +} + +static void set_sound_format(const WAVEFORMATEX* wave_format, struct AVIFile* avi_out) +{ + memcpy(&((*avi_out).wave_format), wave_format, sizeof(WAVEFORMATEX)); + (*avi_out).sound_added = 1; +} + +static int avi_open(const char* filename, const BITMAPINFOHEADER* pbmih, const WAVEFORMATEX* pwfex) +{ + int error = 1; + int result = 0; + + do + { + // close existing first + DRV_AviEnd(); + + if(!truncate_existing(filename)) + break; + + if(!pbmih) + break; + + // create the object + avi_create(&avi_file); + + // set video size and framerate + /*avi_file->start_scanline = vsi->start_scanline; + avi_file->end_scanline = vsi->end_scanline; + avi_file->fps = vsi->fps; + avi_file->fps_scale = 16777216-1; + avi_file->convert_buffer = new u8[256*384*3];*/ + + // open the file + if(FAILED(AVIFileOpen(&avi_file->avi_file, filename, OF_CREATE | OF_WRITE, NULL))) + break; + + // create the video stream + set_video_format(pbmih, avi_file); + + memset(&avi_file->avi_video_header, 0, sizeof(AVISTREAMINFO)); + avi_file->avi_video_header.fccType = streamtypeVIDEO; + avi_file->avi_video_header.dwScale = 65536*256; + avi_file->avi_video_header.dwRate = (int)(59.8261*65536*256); + avi_file->avi_video_header.dwSuggestedBufferSize = avi_file->bitmap_format.biSizeImage; + if(FAILED(AVIFileCreateStream(avi_file->avi_file, &avi_file->streams[VIDEO_STREAM], &avi_file->avi_video_header))) + break; + + if(use_prev_options) + { + avi_file->compress_options[VIDEO_STREAM] = saved_avi_info.compress_options[VIDEO_STREAM]; + avi_file->compress_options_ptr[VIDEO_STREAM] = &avi_file->compress_options[0]; + } + else + { + // get compression options + memset(&avi_file->compress_options[VIDEO_STREAM], 0, sizeof(AVICOMPRESSOPTIONS)); + avi_file->compress_options_ptr[VIDEO_STREAM] = &avi_file->compress_options[0]; +//retryAviSaveOptions: //mbg merge 7/17/06 removed + error = 0; + if(!AVISaveOptions(MainWindow->getHWnd(), 0, 1, &avi_file->streams[VIDEO_STREAM], &avi_file->compress_options_ptr[VIDEO_STREAM])) + break; + error = 1; + } + + // create compressed stream + if(FAILED(AVIMakeCompressedStream(&avi_file->compressed_streams[VIDEO_STREAM], avi_file->streams[VIDEO_STREAM], &avi_file->compress_options[VIDEO_STREAM], NULL))) + break; + + // set the stream format + if(FAILED(AVIStreamSetFormat(avi_file->compressed_streams[VIDEO_STREAM], 0, (void*)&avi_file->bitmap_format, avi_file->bitmap_format.biSize))) + break; + + // add sound (if requested) + if(pwfex) + { + // add audio format + set_sound_format(pwfex, avi_file); + + // create the audio stream + memset(&avi_file->avi_sound_header, 0, sizeof(AVISTREAMINFO)); + avi_file->avi_sound_header.fccType = streamtypeAUDIO; + avi_file->avi_sound_header.dwQuality = (DWORD)-1; + avi_file->avi_sound_header.dwScale = avi_file->wave_format.nBlockAlign; + avi_file->avi_sound_header.dwRate = avi_file->wave_format.nAvgBytesPerSec; + avi_file->avi_sound_header.dwSampleSize = avi_file->wave_format.nBlockAlign; + avi_file->avi_sound_header.dwInitialFrames = 1; + if(FAILED(AVIFileCreateStream(avi_file->avi_file, &avi_file->streams[AUDIO_STREAM], &avi_file->avi_sound_header))) + break; + + // AVISaveOptions doesn't seem to work for audio streams + // so here we just copy the pointer for the compressed stream + avi_file->compressed_streams[AUDIO_STREAM] = avi_file->streams[AUDIO_STREAM]; + + // set the stream format + if(FAILED(AVIStreamSetFormat(avi_file->compressed_streams[AUDIO_STREAM], 0, (void*)&avi_file->wave_format, sizeof(WAVEFORMATEX)))) + break; + } + + // initialize counters + avi_file->video_frames = 0; + avi_file->sound_samples = 0; + avi_file->tBytes = 0; + avi_file->ByteBuffer = 0; + + // success + error = 0; + result = 1; + avi_file->valid = 1; + + } while(0); + + if(!result) + { + avi_destroy(&avi_file); + if(error) + EMU_PrintError("Error writing AVI file"); + } + + return result; +} + +//converts 16bpp to 24bpp and flips +static void do_video_conversion(const u16* buffer) +{ + u8* outbuf = avi_file->convert_buffer + 256*(384-1)*3; + + for(int y=0;y<384;y++) + { + for(int x=0;x<256;x++) + { + u16 col16 = *buffer++; + col16 &=0x7FFF; + u32 col24 = color_15bit_to_24bit[col16]; + *outbuf++ = (col24>>16)&0xFF; + *outbuf++ = (col24>>8)&0xFF; + *outbuf++ = col24&0xFF; + } + + outbuf -= 256*3*2; + } +} + + +static bool AviNextSegment() +{ + char avi_fname[MAX_PATH]; + strcpy(avi_fname,saved_avi_fname); + char avi_fname_temp[MAX_PATH]; + sprintf(avi_fname_temp, "%s_part%d%s", avi_fname, avi_segnum+2, saved_avi_ext); + saved_avi_info=*avi_file; + use_prev_options=1; + avi_segnum++; + bool ret = DRV_AviBegin(avi_fname_temp); + use_prev_options=0; + strcpy(saved_avi_fname,avi_fname); + return ret; +} + + +bool DRV_AviBegin(const char* fname) +{ + DRV_AviEnd(); + + BITMAPINFOHEADER bi; + memset(&bi, 0, sizeof(bi)); + bi.biSize = 0x28; + bi.biPlanes = 1; + bi.biBitCount = 24; + bi.biWidth = 256; + bi.biHeight = 384; + bi.biSizeImage = 3 * 256 * 384; + + WAVEFORMATEX wf; + wf.cbSize = sizeof(WAVEFORMATEX); + wf.nAvgBytesPerSec = 44100 * 4; + wf.nBlockAlign = 4; + wf.nChannels = 2; + wf.nSamplesPerSec = 44100; + wf.wBitsPerSample = 16; + wf.wFormatTag = WAVE_FORMAT_PCM; + + + saved_avi_ext[0]='\0'; + + //mbg 8/10/08 - decide whether there will be sound in this movie + //if this is a new movie.. + /*if(!avi_file) { + if(FSettings.SndRate) + use_sound = true; + else use_sound = false; + }*/ + + //mbg 8/10/08 - if there is no sound in this movie, then dont open the audio stream + WAVEFORMATEX* pwf = &wf; + //if(!use_sound) + // pwf = 0; + + + if(!avi_open(fname, &bi, pwf)) + { + saved_avi_fname[0]='\0'; + return 0; + } + + // Don't display at file splits + if(!avi_segnum) + EMU_PrintMessage("AVI recording started."); + + strncpy(saved_cur_avi_fnameandext,fname,MAX_PATH); + strncpy(saved_avi_fname,fname,MAX_PATH); + char* dot = strrchr(saved_avi_fname, '.'); + if(dot && dot > strrchr(saved_avi_fname, '/') && dot > strrchr(saved_avi_fname, '\\')) + { + strcpy(saved_avi_ext,dot); + dot[0]='\0'; + } + return 1; +} + +void DRV_AviVideoUpdate(const u16* buffer) +{ + if(!avi_file || !avi_file->valid) + return; + + do_video_conversion(buffer); + + if(FAILED(AVIStreamWrite(avi_file->compressed_streams[VIDEO_STREAM], + avi_file->video_frames, 1, avi_file->convert_buffer, + avi_file->bitmap_format.biSizeImage, AVIIF_KEYFRAME, + NULL, &avi_file->ByteBuffer))) + { + avi_file->valid = 0; + return; + } + + avi_file->video_frames++; + avi_file->tBytes += avi_file->ByteBuffer; + + // segment / split AVI when it's almost 2 GB (2000MB, to be precise) + if(!(avi_file->video_frames % 60) && avi_file->tBytes > 2097152000) + AviNextSegment(); +} + +void DRV_AviSoundUpdate(void* soundData, int soundLen) +{ + int nBytes; + + if(!avi_file || !avi_file->valid || !avi_file->sound_added) + return; + + nBytes = soundLen * avi_file->wave_format.nBlockAlign; + if(FAILED(AVIStreamWrite(avi_file->compressed_streams[AUDIO_STREAM], + avi_file->sound_samples, soundLen, + soundData, nBytes, 0, NULL, &avi_file->ByteBuffer))) + { + avi_file->valid = 0; + return; + } + + avi_file->sound_samples += soundLen; + avi_file->tBytes += avi_file->ByteBuffer; +} + +void DRV_AviEnd() +{ + if(!avi_file) + return; + + // Don't display if we're just starting another segment + if(avi_file->tBytes <= 2097152000) + EMU_PrintMessage("AVI recording ended."); + + avi_destroy(&avi_file); +} + +bool DRV_AviIsRecording() +{ + if(avi_file) + return true; + + return false; +} diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 639af9e5c..9f674a882 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -1,102 +1,112 @@ -/* Copyright (C) 2006 yopyop - yopyop156@ifrance.com - yopyop156.ifrance.com - - Copyright 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 -*/ - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include -#include -#include -#include "CWindow.h" -#include "../MMU.h" -#include "../armcpu.h" -#include "../NDSSystem.h" -#include "../debug.h" -#include "../saves.h" -#include "../cflash.h" -#include "resource.h" -#include "memView.h" -#include "disView.h" -#include "ginfo.h" -#include "IORegView.h" -#include "palView.h" -#include "tileView.h" -#include "oamView.h" -#include "mapview.h" -#include "matrixview.h" -#include "lightview.h" -#include "ConfigKeys.h" -#include "FirmConfig.h" -#include "AboutBox.h" -#include "OGLRender.h" -#include "../gfx3d.h" -#include "../render3D.h" -#include "../gdbstub.h" -#include "colorctrl.h" -#include "console.h" -#include "throttle.h" - +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright 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 "windriver.h" +#include +#include +#include +#include +#include +#include +#include "CWindow.h" +#include "../MMU.h" +#include "../armcpu.h" +#include "../NDSSystem.h" +#include "../debug.h" +#include "../saves.h" +#include "../cflash.h" +#include "resource.h" +#include "memView.h" +#include "disView.h" +#include "ginfo.h" +#include "IORegView.h" +#include "palView.h" +#include "tileView.h" +#include "oamView.h" +#include "mapview.h" +#include "matrixview.h" +#include "lightview.h" +#include "ConfigKeys.h" +#include "FirmConfig.h" +#include "AboutBox.h" +#include "OGLRender.h" +#include "../gfx3d.h" +#include "../render3D.h" +#include "../gdbstub.h" +#include "colorctrl.h" +#include "console.h" +#include "throttle.h" + #include "../common.h" -#include "snddx.h" - -#include "directx/ddraw.h" - -#define GPU3D_NULL 0 -#define GPU3D_OPENGL 1 - -//===================== Init DirectDraw -LPDIRECTDRAW7 lpDDraw=NULL; -LPDIRECTDRAWSURFACE7 lpPrimarySurface=NULL; -LPDIRECTDRAWSURFACE7 lpBackSurface=NULL; -DDSURFACEDESC2 ddsd; -LPDIRECTDRAWCLIPPER lpDDClipPrimary=NULL; -LPDIRECTDRAWCLIPPER lpDDClipBack=NULL; - -/* The compact flash disk image file */ -static const char *bad_glob_cflash_disk_image_file; -static char cflash_filename_buffer[512]; - -/* Declare Windows procedure */ -LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); - -/* Make the class name into a global variable */ -char SavName[MAX_PATH] = ""; -char ImportSavName[MAX_PATH] = ""; -char szClassName[ ] = "DeSmuME"; -int romnum = 0; - -DWORD threadID; - +#include "snddx.h" + +#include "directx/ddraw.h" + +#define GPU3D_NULL 0 +#define GPU3D_OPENGL 1 + +//------todo move these into a generic driver api +bool DRV_AviBegin(const char* fname); +void DRV_AviEnd(); +void DRV_AviSoundUpdate(void* soundData, int soundLen); +bool DRV_AviIsRecording(); +void DRV_AviVideoUpdate(const u16* buffer); +//------ + +CRITICAL_SECTION win_sync; +volatile int win_sound_samplecounter = 0; + +//===================== Init DirectDraw +LPDIRECTDRAW7 lpDDraw=NULL; +LPDIRECTDRAWSURFACE7 lpPrimarySurface=NULL; +LPDIRECTDRAWSURFACE7 lpBackSurface=NULL; +DDSURFACEDESC2 ddsd; +LPDIRECTDRAWCLIPPER lpDDClipPrimary=NULL; +LPDIRECTDRAWCLIPPER lpDDClipBack=NULL; + +/* The compact flash disk image file */ +static const char *bad_glob_cflash_disk_image_file; +static char cflash_filename_buffer[512]; + +/* Declare Windows procedure */ +LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); + +/* Make the class name into a global variable */ +char SavName[MAX_PATH] = ""; +char ImportSavName[MAX_PATH] = ""; +char szClassName[ ] = "DeSmuME"; +int romnum = 0; + +DWORD threadID; + WINCLASS *MainWindow=NULL; //HWND hwnd; //HDC hdc; HINSTANCE hAppInst; -RECT MainWindowRect; - +RECT MainWindowRect; + //=========================== view tools TOOLSCLASS *ViewDisasm_ARM7 = NULL; TOOLSCLASS *ViewDisasm_ARM9 = NULL; @@ -111,825 +121,851 @@ TOOLSCLASS *ViewMatrices = NULL; TOOLSCLASS *ViewLights = NULL; -volatile BOOL execute = FALSE; -volatile BOOL paused = TRUE; -u32 glock = 0; - -BOOL click = FALSE; - -BOOL finished = FALSE; -BOOL romloaded = FALSE; - +volatile BOOL execute = FALSE; +volatile BOOL paused = TRUE; +u32 glock = 0; + +BOOL click = FALSE; + +BOOL finished = FALSE; +BOOL romloaded = FALSE; + void SetRotate(HWND hwnd, int rot); - -BOOL ForceRatio = TRUE; -float DefaultWidth; -float DefaultHeight; -float widthTradeOff; -float heightTradeOff; - -HMENU menu; -HANDLE runthread_ready=INVALID_HANDLE_VALUE; -HANDLE runthread=INVALID_HANDLE_VALUE; - -const DWORD DI_tabkey[48] = {DIK_0,DIK_1,DIK_2,DIK_3,DIK_4,DIK_5,DIK_6,DIK_7,DIK_8,DIK_9,DIK_A,DIK_B,DIK_C, - DIK_D,DIK_E,DIK_F,DIK_G,DIK_H,DIK_I,DIK_J,DIK_K,DIK_L,DIK_M,DIK_N,DIK_O,DIK_P, - DIK_Q,DIK_R,DIK_S,DIK_T,DIK_U,DIK_V,DIK_W,DIK_X,DIK_Y,DIK_Z,DIK_SPACE,DIK_UP, - DIK_DOWN,DIK_LEFT,DIK_RIGHT,DIK_TAB,DIK_LSHIFT,DIK_DELETE,DIK_INSERT,DIK_HOME, - DIK_END,DIK_RETURN}; -DWORD ds_up,ds_down,ds_left,ds_right,ds_a,ds_b,ds_x,ds_y,ds_l,ds_r,ds_select,ds_start,ds_debug; + +BOOL ForceRatio = TRUE; +float DefaultWidth; +float DefaultHeight; +float widthTradeOff; +float heightTradeOff; + +HMENU menu; +HANDLE runthread_ready=INVALID_HANDLE_VALUE; +HANDLE runthread=INVALID_HANDLE_VALUE; + +const DWORD DI_tabkey[48] = {DIK_0,DIK_1,DIK_2,DIK_3,DIK_4,DIK_5,DIK_6,DIK_7,DIK_8,DIK_9,DIK_A,DIK_B,DIK_C, + DIK_D,DIK_E,DIK_F,DIK_G,DIK_H,DIK_I,DIK_J,DIK_K,DIK_L,DIK_M,DIK_N,DIK_O,DIK_P, + DIK_Q,DIK_R,DIK_S,DIK_T,DIK_U,DIK_V,DIK_W,DIK_X,DIK_Y,DIK_Z,DIK_SPACE,DIK_UP, + DIK_DOWN,DIK_LEFT,DIK_RIGHT,DIK_TAB,DIK_LSHIFT,DIK_DELETE,DIK_INSERT,DIK_HOME, + DIK_END,DIK_RETURN}; +DWORD ds_up,ds_down,ds_left,ds_right,ds_a,ds_b,ds_x,ds_y,ds_l,ds_r,ds_select,ds_start,ds_debug; //static char IniName[MAX_PATH]; -int sndcoretype=SNDCORE_DIRECTX; -int sndbuffersize=735*4; -int sndvolume=100; - -SoundInterface_struct *SNDCoreList[] = { -&SNDDummy, -&SNDFile, -&SNDDIRECTX, -NULL -}; - -GPU3DInterface *core3DList[] = { -&gpu3DNull, -&gpu3Dgl, -}; - -int autoframeskipenab=1; -int frameskiprate=0; -int emu_paused = 0; -static int backupmemorytype=MC_TYPE_AUTODETECT; -static u32 backupmemorysize=1; -unsigned int frameCounter=0; -bool frameAdvance = false; -bool frameCounterDisplay = false; +int sndcoretype=SNDCORE_DIRECTX; +int sndbuffersize=735*4; +int sndvolume=100; + +SoundInterface_struct *SNDCoreList[] = { +&SNDDummy, +&SNDFile, +&SNDDIRECTX, +NULL +}; + +GPU3DInterface *core3DList[] = { +&gpu3DNull, +&gpu3Dgl, +}; + +int autoframeskipenab=1; +int frameskiprate=0; +int emu_paused = 0; +static int backupmemorytype=MC_TYPE_AUTODETECT; +static u32 backupmemorysize=1; +unsigned int frameCounter=0; +bool frameAdvance = false; +bool frameCounterDisplay = false; bool FpsDisplay = false; -unsigned short windowSize = 0; - -/* the firmware settings */ -struct NDS_fw_config_data win_fw_config; - - -LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, - LPARAM lParam); - -struct configured_features { - u16 arm9_gdb_port; - u16 arm7_gdb_port; - - const char *cflash_disk_image_file; -}; - -static void -init_configured_features( struct configured_features *config) { - config->arm9_gdb_port = 0; - config->arm7_gdb_port = 0; - - config->cflash_disk_image_file = NULL; -} - - -static int -fill_configured_features( struct configured_features *config, LPSTR lpszArgument) { - int good_args = 0; - LPTSTR cmd_line; - LPWSTR *argv; - int argc; - - argv = CommandLineToArgvW( GetCommandLineW(), &argc); - - if ( argv != NULL) { - int i; - good_args = 1; - for ( i = 1; i < argc && good_args; i++) { - if ( wcsncmp( argv[i], L"--arm9gdb=", 10) == 0) { - wchar_t *end_char; - unsigned long port_num = wcstoul( &argv[i][10], &end_char, 10); - - if ( port_num > 0 && port_num < 65536) { - config->arm9_gdb_port = port_num; - } - else { - MessageBox(NULL,"ARM9 GDB stub port must be in the range 1 to 65535","Error",MB_OK); - good_args = 0; - } - } - else if ( wcsncmp( argv[i], L"--arm7gdb=", 10) == 0) { - wchar_t *end_char; - unsigned long port_num = wcstoul( &argv[i][10], &end_char, 10); - - if ( port_num > 0 && port_num < 65536) { - config->arm7_gdb_port = port_num; - } - else { - MessageBox(NULL,"ARM9 GDB stub port must be in the range 1 to 65535","Error",MB_OK); - good_args = 0; - } - } - else if ( wcsncmp( argv[i], L"--cflash=", 9) == 0) { - if ( config->cflash_disk_image_file == NULL) { - size_t convert_count = wcstombs( &cflash_filename_buffer[0], &argv[i][9], 512); - if ( convert_count > 0) { - config->cflash_disk_image_file = cflash_filename_buffer; - } - } - else { - MessageBox(NULL,"CFlash disk image file already set","Error",MB_OK); - good_args = 0; - } - } - } - LocalFree( argv); - } - - return good_args; -} - -// Rotation definitions -short GPU_rotation = 0; -DWORD GPU_width = 256; -DWORD GPU_height = 192*2; -DWORD rotationstartscan = 192; -DWORD rotationscanlines = 192*2; - -void SetWindowClientSize(HWND hwnd, int cx, int cy) //found at: http://blogs.msdn.com/oldnewthing/archive/2003/09/11/54885.aspx -{ - HMENU hmenu = GetMenu(hwnd); - RECT rcWindow = { 0, 0, cx, cy }; - - /* - * First convert the client rectangle to a window rectangle the - * menu-wrap-agnostic way. - */ - AdjustWindowRect(&rcWindow, WS_CAPTION| WS_SYSMENU |WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, hmenu != NULL); - - /* - * If there is a menu, then check how much wrapping occurs - * when we set a window to the width specified by AdjustWindowRect - * and an infinite amount of height. An infinite height allows - * us to see every single menu wrap. - */ - if (hmenu) { - RECT rcTemp = rcWindow; - rcTemp.bottom = 0x7FFF; /* "Infinite" height */ - SendMessage(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rcTemp); - - /* - * Adjust our previous calculation to compensate for menu - * wrapping. - */ - rcWindow.bottom += rcTemp.top; - } - SetWindowPos(hwnd, NULL, 0, 0, rcWindow.right - rcWindow.left, - rcWindow.bottom - rcWindow.top, SWP_NOMOVE | SWP_NOZORDER); - - if (lpBackSurface!=NULL) - { - IDirectDrawSurface7_Release(lpBackSurface); - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - ddsd.dwWidth = cx; - ddsd.dwHeight = cy; - - IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpBackSurface, NULL); - } -} - -void ResizingLimit(int wParam, RECT *rc) -{ - u32 width = (rc->right - rc->left); - u32 height = (rc->bottom - rc->top); - - u32 minX = 256; - u32 minY = 414; - - //printlog("width=%i; height=%i\n", width, height); - - if (GPU_rotation == 90 || GPU_rotation == 270) - { - minX = 390; - minY = 272; - } - switch (wParam) - { - case WMSZ_LEFT: - { - if (widthleft=rc->left+(width-minX); - return; - } - - case WMSZ_RIGHT: - { - if (widthright=rc->left+minX; - return; - } - - case WMSZ_TOP: - { - if (heighttop=rc->top+(height-minY); - return; - } - - case WMSZ_BOTTOM: - { - if (heightbottom=rc->top+minY; - return; - } - - case WMSZ_TOPLEFT: - { - if (heighttop=rc->top+(height-minY); - if (widthleft=rc->left+(width-minX); - return; - } - case WMSZ_BOTTOMLEFT: - { - if (heightbottom=rc->top+minY; - if (widthleft=rc->left+(width-minX); - return; - } - - case WMSZ_TOPRIGHT: - { - if (heighttop=rc->top+(height-minY); - if (widthright=rc->left+minX; - return; - } - - case WMSZ_BOTTOMRIGHT: - { - if (heightbottom=rc->top+minY; - if (widthright=rc->left+minX; - return; - } - } - -} - -void ScallingScreen(HWND hwnd, int wParam, RECT *rc) -{ - float aspect; - u32 width; - u32 height; - u32 width2; - u32 height2; - - width = (rc->right - rc->left - widthTradeOff); - height = (rc->bottom - rc->top - heightTradeOff); - - if (width == height) return; - - if (GPU_rotation == 0 || GPU_rotation == 180) - { - aspect = DefaultWidth / DefaultHeight; - } - else - { - aspect = DefaultHeight / DefaultWidth; - } - - switch (wParam) - { - case WMSZ_LEFT: - case WMSZ_RIGHT: - { - height = (int)(width / aspect); - rc->bottom=rc->top+height+heightTradeOff; - return; - } - - case WMSZ_TOP: - case WMSZ_BOTTOM: - { - width = (int)(height * aspect); - rc->right=rc->left+width+widthTradeOff; - return; - } - - case WMSZ_TOPLEFT: - { - width = (int)(height * aspect); - rc->left=rc->right-width-widthTradeOff; - return; - } - case WMSZ_BOTTOMLEFT: - { - height = (int)(width / aspect); - rc->bottom=rc->top + height + heightTradeOff; - return; - } - - case WMSZ_TOPRIGHT: - case WMSZ_BOTTOMRIGHT: - { - width = (int)(height * aspect); - rc->right=rc->left+width+widthTradeOff; - return; - } - } -} - -void ScaleScreen(HWND hwnd, float factor) -{ - if ((GPU_rotation==0)||(GPU_rotation==180)) - { - SetWindowPos(hwnd, NULL, 0, 0, widthTradeOff + DefaultWidth * factor, - heightTradeOff + DefaultHeight * factor, SWP_NOMOVE | SWP_NOZORDER); - } - else - if ((GPU_rotation==90)||(GPU_rotation==270)) - { - SetWindowPos(hwnd, NULL, 0, 0, heightTradeOff + DefaultHeight * factor, - widthTradeOff + DefaultWidth * factor, SWP_NOMOVE | SWP_NOZORDER); - } -} - -void translateXY(s32 *x, s32*y) -{ - s32 tmp; - switch(GPU_rotation) - { - case 90: - tmp = *x; - *x = *y; - *y = 192*2 -tmp; - break; - case 180: - *x = 256-*x; - *y = 192*2-*y; - break; - case 270: - tmp = *x; - *x = 255-*y; - *y = tmp; - break; - } - *y-=192; -} - - // END Rotation definitions - -void Input_Post() -{ - char txt[255]; - BOOL bPressed; - HRESULT hr; - WORD keys[13][3]={{ds_a,0xFFFE,0x01},{ds_b,0xFFFD,0x02},{ds_select,0xFFFB,0x04},{ds_start,0xFFF7,0x08}, - {ds_right,0xFFEF,0x10},{ds_left,0xFFDF,0x20},{ds_up,0xFFBF,0x40},{ds_down,0xFF7F,0x80}, - {ds_r,0xFEFF,0x100},{ds_l,0xFDFF,0x200}, - {ds_x,0xFFFE,0x01},{ds_y,0xFFFD,0x02},{ds_debug,0xFFFB,0x04}}; - int i; - - for (i=0; i<10; i++) - { - bPressed=FALSE; - if (keys[i][0]<48) - if (g_cDIBuf[DI_tabkey[keys[i][0]]]&0x80) bPressed=TRUE; - if (keys[i][0]>=48) - if (g_cDIBuf[208+keys[i][0]]&0x80) bPressed=TRUE; - if (bPressed) - { - ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1]&=keys[i][1]; - ((u16 *)MMU.ARM7_REG)[0x130>>1]&=keys[i][1]; - } - else - { - ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1]|=keys[i][2]; - ((u16 *)MMU.ARM7_REG)[0x130>>1]|=keys[i][2]; - } - } - for (i=10; i<13; i++) - { - bPressed=FALSE; - if (keys[i][0]<48) - if (g_cDIBuf[DI_tabkey[keys[i][0]]]&0x80) bPressed=TRUE; - if (keys[i][0]>=48) - if (g_cDIBuf[208+keys[i][0]]&0x80) bPressed=TRUE; - if (bPressed) - ((u16 *)MMU.ARM7_REG)[0x136>>1]&=keys[i][1]; - else - ((u16 *)MMU.ARM7_REG)[0x136>>1]|=keys[i][2]; - } -} - -int CreateDDrawBuffers() -{ - if (lpDDClipPrimary!=NULL) IDirectDraw7_Release(lpDDClipPrimary); - if (lpPrimarySurface != NULL) IDirectDraw7_Release(lpPrimarySurface); - if (lpBackSurface != NULL) IDirectDraw7_Release(lpBackSurface); - - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - ddsd.dwFlags = DDSD_CAPS; - if (IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpPrimarySurface, NULL) != DD_OK) return -1; - - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - - if ( (GPU_rotation == 0) || (GPU_rotation == 180) ) - { - ddsd.dwWidth = 256; - ddsd.dwHeight = 384; - } - else - if ( (GPU_rotation == 90) || (GPU_rotation == 270) ) - { - ddsd.dwWidth = 384; - ddsd.dwHeight = 256; - } - - if (IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpBackSurface, NULL) != DD_OK) return -2; - - if (IDirectDraw7_CreateClipper(lpDDraw, 0, &lpDDClipPrimary, NULL) != DD_OK) return -3; +unsigned short windowSize = 0; + +/* the firmware settings */ +struct NDS_fw_config_data win_fw_config; + + +LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, + LPARAM lParam); + +struct configured_features { + u16 arm9_gdb_port; + u16 arm7_gdb_port; + + const char *cflash_disk_image_file; +}; + +static void +init_configured_features( struct configured_features *config) { + config->arm9_gdb_port = 0; + config->arm7_gdb_port = 0; + + config->cflash_disk_image_file = NULL; +} + + +static int +fill_configured_features( struct configured_features *config, LPSTR lpszArgument) { + int good_args = 0; + LPTSTR cmd_line; + LPWSTR *argv; + int argc; + + argv = CommandLineToArgvW( GetCommandLineW(), &argc); + + if ( argv != NULL) { + int i; + good_args = 1; + for ( i = 1; i < argc && good_args; i++) { + if ( wcsncmp( argv[i], L"--arm9gdb=", 10) == 0) { + wchar_t *end_char; + unsigned long port_num = wcstoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm9_gdb_port = port_num; + } + else { + MessageBox(NULL,"ARM9 GDB stub port must be in the range 1 to 65535","Error",MB_OK); + good_args = 0; + } + } + else if ( wcsncmp( argv[i], L"--arm7gdb=", 10) == 0) { + wchar_t *end_char; + unsigned long port_num = wcstoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm7_gdb_port = port_num; + } + else { + MessageBox(NULL,"ARM9 GDB stub port must be in the range 1 to 65535","Error",MB_OK); + good_args = 0; + } + } + else if ( wcsncmp( argv[i], L"--cflash=", 9) == 0) { + if ( config->cflash_disk_image_file == NULL) { + size_t convert_count = wcstombs( &cflash_filename_buffer[0], &argv[i][9], 512); + if ( convert_count > 0) { + config->cflash_disk_image_file = cflash_filename_buffer; + } + } + else { + MessageBox(NULL,"CFlash disk image file already set","Error",MB_OK); + good_args = 0; + } + } + } + LocalFree( argv); + } + + return good_args; +} + +// Rotation definitions +short GPU_rotation = 0; +DWORD GPU_width = 256; +DWORD GPU_height = 192*2; +DWORD rotationstartscan = 192; +DWORD rotationscanlines = 192*2; + +void SetWindowClientSize(HWND hwnd, int cx, int cy) //found at: http://blogs.msdn.com/oldnewthing/archive/2003/09/11/54885.aspx +{ + HMENU hmenu = GetMenu(hwnd); + RECT rcWindow = { 0, 0, cx, cy }; + + /* + * First convert the client rectangle to a window rectangle the + * menu-wrap-agnostic way. + */ + AdjustWindowRect(&rcWindow, WS_CAPTION| WS_SYSMENU |WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, hmenu != NULL); + + /* + * If there is a menu, then check how much wrapping occurs + * when we set a window to the width specified by AdjustWindowRect + * and an infinite amount of height. An infinite height allows + * us to see every single menu wrap. + */ + if (hmenu) { + RECT rcTemp = rcWindow; + rcTemp.bottom = 0x7FFF; /* "Infinite" height */ + SendMessage(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rcTemp); + + /* + * Adjust our previous calculation to compensate for menu + * wrapping. + */ + rcWindow.bottom += rcTemp.top; + } + SetWindowPos(hwnd, NULL, 0, 0, rcWindow.right - rcWindow.left, + rcWindow.bottom - rcWindow.top, SWP_NOMOVE | SWP_NOZORDER); + + if (lpBackSurface!=NULL) + { + IDirectDrawSurface7_Release(lpBackSurface); + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = cx; + ddsd.dwHeight = cy; + + IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpBackSurface, NULL); + } +} + +void ResizingLimit(int wParam, RECT *rc) +{ + u32 width = (rc->right - rc->left); + u32 height = (rc->bottom - rc->top); + + u32 minX = 256; + u32 minY = 414; + + //printlog("width=%i; height=%i\n", width, height); + + if (GPU_rotation == 90 || GPU_rotation == 270) + { + minX = 390; + minY = 272; + } + switch (wParam) + { + case WMSZ_LEFT: + { + if (widthleft=rc->left+(width-minX); + return; + } + + case WMSZ_RIGHT: + { + if (widthright=rc->left+minX; + return; + } + + case WMSZ_TOP: + { + if (heighttop=rc->top+(height-minY); + return; + } + + case WMSZ_BOTTOM: + { + if (heightbottom=rc->top+minY; + return; + } + + case WMSZ_TOPLEFT: + { + if (heighttop=rc->top+(height-minY); + if (widthleft=rc->left+(width-minX); + return; + } + case WMSZ_BOTTOMLEFT: + { + if (heightbottom=rc->top+minY; + if (widthleft=rc->left+(width-minX); + return; + } + + case WMSZ_TOPRIGHT: + { + if (heighttop=rc->top+(height-minY); + if (widthright=rc->left+minX; + return; + } + + case WMSZ_BOTTOMRIGHT: + { + if (heightbottom=rc->top+minY; + if (widthright=rc->left+minX; + return; + } + } + +} + +void ScallingScreen(HWND hwnd, int wParam, RECT *rc) +{ + float aspect; + u32 width; + u32 height; + u32 width2; + u32 height2; + + width = (rc->right - rc->left - widthTradeOff); + height = (rc->bottom - rc->top - heightTradeOff); + + if (width == height) return; + + if (GPU_rotation == 0 || GPU_rotation == 180) + { + aspect = DefaultWidth / DefaultHeight; + } + else + { + aspect = DefaultHeight / DefaultWidth; + } + + switch (wParam) + { + case WMSZ_LEFT: + case WMSZ_RIGHT: + { + height = (int)(width / aspect); + rc->bottom=rc->top+height+heightTradeOff; + return; + } + + case WMSZ_TOP: + case WMSZ_BOTTOM: + { + width = (int)(height * aspect); + rc->right=rc->left+width+widthTradeOff; + return; + } + + case WMSZ_TOPLEFT: + { + width = (int)(height * aspect); + rc->left=rc->right-width-widthTradeOff; + return; + } + case WMSZ_BOTTOMLEFT: + { + height = (int)(width / aspect); + rc->bottom=rc->top + height + heightTradeOff; + return; + } + + case WMSZ_TOPRIGHT: + case WMSZ_BOTTOMRIGHT: + { + width = (int)(height * aspect); + rc->right=rc->left+width+widthTradeOff; + return; + } + } +} + +void ScaleScreen(HWND hwnd, float factor) +{ + + if ((GPU_rotation==0)||(GPU_rotation==180)) + { + SetWindowPos(hwnd, NULL, 0, 0, widthTradeOff + DefaultWidth * factor, + heightTradeOff + DefaultHeight * factor, SWP_NOMOVE | SWP_NOZORDER); + } + else + if ((GPU_rotation==90)||(GPU_rotation==270)) + { + SetWindowPos(hwnd, NULL, 0, 0, heightTradeOff + DefaultHeight * factor, + widthTradeOff + DefaultWidth * factor, SWP_NOMOVE | SWP_NOZORDER); + } +} + +void translateXY(s32 *x, s32*y) +{ + s32 tmp; + switch(GPU_rotation) + { + case 90: + tmp = *x; + *x = *y; + *y = 192*2 -tmp; + break; + case 180: + *x = 256-*x; + *y = 192*2-*y; + break; + case 270: + tmp = *x; + *x = 255-*y; + *y = tmp; + break; + } + *y-=192; +} + + // END Rotation definitions + +void Input_Post() +{ + char txt[255]; + BOOL bPressed; + HRESULT hr; + WORD keys[13][3]={{ds_a,0xFFFE,0x01},{ds_b,0xFFFD,0x02},{ds_select,0xFFFB,0x04},{ds_start,0xFFF7,0x08}, + {ds_right,0xFFEF,0x10},{ds_left,0xFFDF,0x20},{ds_up,0xFFBF,0x40},{ds_down,0xFF7F,0x80}, + {ds_r,0xFEFF,0x100},{ds_l,0xFDFF,0x200}, + {ds_x,0xFFFE,0x01},{ds_y,0xFFFD,0x02},{ds_debug,0xFFFB,0x04}}; + int i; + for (i=0; i<10; i++) + { + bPressed=FALSE; + if (keys[i][0]<48) + if (g_cDIBuf[DI_tabkey[keys[i][0]]]&0x80) bPressed=TRUE; + if (keys[i][0]>=48) + if (g_cDIBuf[208+keys[i][0]]&0x80) bPressed=TRUE; + if (bPressed) + { + ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1]&=keys[i][1]; + ((u16 *)MMU.ARM7_REG)[0x130>>1]&=keys[i][1]; + } + else + { + ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1]|=keys[i][2]; + ((u16 *)MMU.ARM7_REG)[0x130>>1]|=keys[i][2]; + } + } + for (i=10; i<13; i++) + { + bPressed=FALSE; + if (keys[i][0]<48) + if (g_cDIBuf[DI_tabkey[keys[i][0]]]&0x80) bPressed=TRUE; + if (keys[i][0]>=48) + if (g_cDIBuf[208+keys[i][0]]&0x80) bPressed=TRUE; + if (bPressed) + ((u16 *)MMU.ARM7_REG)[0x136>>1]&=keys[i][1]; + else + ((u16 *)MMU.ARM7_REG)[0x136>>1]|=keys[i][2]; + } +} + +int CreateDDrawBuffers() +{ + if (lpDDClipPrimary!=NULL) IDirectDraw7_Release(lpDDClipPrimary); + if (lpPrimarySurface != NULL) IDirectDraw7_Release(lpPrimarySurface); + if (lpBackSurface != NULL) IDirectDraw7_Release(lpBackSurface); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + ddsd.dwFlags = DDSD_CAPS; + if (IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpPrimarySurface, NULL) != DD_OK) return -1; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + + if ( (GPU_rotation == 0) || (GPU_rotation == 180) ) + { + ddsd.dwWidth = 256; + ddsd.dwHeight = 384; + } + else + if ( (GPU_rotation == 90) || (GPU_rotation == 270) ) + { + ddsd.dwWidth = 384; + ddsd.dwHeight = 256; + } + + if (IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpBackSurface, NULL) != DD_OK) return -2; + + if (IDirectDraw7_CreateClipper(lpDDraw, 0, &lpDDClipPrimary, NULL) != DD_OK) return -3; + if (IDirectDrawClipper_SetHWnd(lpDDClipPrimary, 0, MainWindow->getHWnd()) != DD_OK) return -4; - if (IDirectDrawSurface7_SetClipper(lpPrimarySurface, lpDDClipPrimary) != DD_OK) return -5; - - return 1; -} - - -void Display() -{ - int res; - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwFlags=DDSD_ALL; - res=IDirectDrawSurface7_Lock(lpBackSurface,NULL,&ddsd,DDLOCK_WAIT, NULL); - - if (res == DD_OK) + if (IDirectDrawSurface7_SetClipper(lpPrimarySurface, lpDDClipPrimary) != DD_OK) return -5; + + return 1; +} + + +void Display() +{ + int res; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags=DDSD_ALL; + res=IDirectDrawSurface7_Lock(lpBackSurface,NULL,&ddsd,DDLOCK_WAIT, NULL); + + if (res == DD_OK) + { + char* buffer = (char*)ddsd.lpSurface; + + int i, j, sz=256*sizeof(u32); + if (ddsd.ddpfPixelFormat.dwRGBBitCount>16) + { + u16 *tmpGPU_Screen_src=(u16*)GPU_screen; + u32 tmpGPU_screen[98304]; + for(i=0; i<98304; i++) + tmpGPU_screen[i]= (((tmpGPU_Screen_src[i]>>10)&0x1F)<<3)| + (((tmpGPU_Screen_src[i]>>5)&0x1F)<<11)| + (((tmpGPU_Screen_src[i])&0x1F)<<19); + switch (GPU_rotation) + { + case 0: + { + for (i = 0; i < 98304; i+=256) //384*256 + { + memcpy(buffer,tmpGPU_screen+i,sz); + buffer += ddsd.lPitch; + } + break; + } + case 90: + { + u32 start; + memset(buffer,0,384*ddsd.lPitch); + for (j=0; j<256; j++) + { + start=98304+j; + for (i=0; i<384; i++) + { + start-=256; + ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; + } + buffer += ddsd.lPitch; + } + break; + } + case 180: + { + u32 start=98300; + for (j=0; j<384; j++) + { + for (i=0; i<256; i++, --start) + ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; + buffer += ddsd.lPitch; + } + break; + } + case 270: + { + u32 start; + memset(buffer,0,384*ddsd.lPitch); + for (j=0; j<256; j++) + { + start=256-j; + for (i=0; i<384; i++) + { + ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; + start+=256; + } + buffer += ddsd.lPitch; + } + break; + } + } + } + else + printlog("16bit depth color not supported"); + IDirectDrawSurface7_Unlock(lpBackSurface,(LPRECT)ddsd.lpSurface); + + if (IDirectDrawSurface7_Blt(lpPrimarySurface,&MainWindowRect,lpBackSurface,0, DDBLT_WAIT,0)==DDERR_SURFACELOST) + { + printlog("DirectDraw buffers is lost\n"); + if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) + IDirectDrawSurface7_Restore(lpBackSurface); + } + } + else + { + if (res==DDERR_SURFACELOST) + { + printlog("DirectDraw buffers is lost\n"); + if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) + IDirectDrawSurface7_Restore(lpBackSurface); + } + } +} + +void CheckMessages() +{ + MSG msg; + while( PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE ) ) { - char* buffer = (char*)ddsd.lpSurface; - - int i, j, sz=256*sizeof(u32); - if (ddsd.ddpfPixelFormat.dwRGBBitCount>16) - { - u16 *tmpGPU_Screen_src=(u16*)GPU_screen; - u32 tmpGPU_screen[98304]; - for(i=0; i<98304; i++) - tmpGPU_screen[i]= (((tmpGPU_Screen_src[i]>>10)&0x1F)<<3)| - (((tmpGPU_Screen_src[i]>>5)&0x1F)<<11)| - (((tmpGPU_Screen_src[i])&0x1F)<<19); - switch (GPU_rotation) - { - case 0: - { - for (i = 0; i < 98304; i+=256) //384*256 - { - memcpy(buffer,tmpGPU_screen+i,sz); - buffer += ddsd.lPitch; - } - break; - } - case 90: - { - u32 start; - memset(buffer,0,384*ddsd.lPitch); - for (j=0; j<256; j++) - { - start=98304+j; - for (i=0; i<384; i++) - { - start-=256; - ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; - } - buffer += ddsd.lPitch; - } - break; - } - case 180: - { - u32 start=98300; - for (j=0; j<384; j++) - { - for (i=0; i<256; i++, --start) - ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; - buffer += ddsd.lPitch; - } - break; - } - case 270: - { - u32 start; - memset(buffer,0,384*ddsd.lPitch); - for (j=0; j<256; j++) - { - start=256-j; - for (i=0; i<384; i++) - { - ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; - start+=256; - } - buffer += ddsd.lPitch; - } - break; - } - } - } - else - printlog("16bit depth color not supported"); - IDirectDrawSurface7_Unlock(lpBackSurface,(LPRECT)ddsd.lpSurface); - - if (IDirectDrawSurface7_Blt(lpPrimarySurface,&MainWindowRect,lpBackSurface,0, DDBLT_WAIT,0)==DDERR_SURFACELOST) - { - printlog("DirectDraw buffers is lost\n"); - if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) - IDirectDrawSurface7_Restore(lpBackSurface); - } - } - else - { - if (res==DDERR_SURFACELOST) - { - printlog("DirectDraw buffers is lost\n"); - if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) - IDirectDrawSurface7_Restore(lpBackSurface); - } - } -} - - -DWORD WINAPI run( LPVOID lpParameter) -{ - char txt[80]; - u32 cycles = 0; - int wait=0; - u64 freq; - u64 OneFrameTime; - int framestoskip=0; - int framesskipped=0; - int skipnextframe=0; - u64 lastticks=0; - u64 curticks=0; - u64 diffticks=0; - u32 framecount=0; - u64 onesecondticks=0; - int fps=0; - int fpsframecount=0; - u64 fpsticks=0; - int res; + if( GetMessage( &msg, 0, 0, 0)>0 ) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + + +DWORD WINAPI run( LPVOID lpParameter) +{ + char txt[80]; + u32 cycles = 0; + int wait=0; + u64 freq; + u64 OneFrameTime; + int framestoskip=0; + int framesskipped=0; + int skipnextframe=0; + u64 lastticks=0; + u64 curticks=0; + u64 diffticks=0; + u32 framecount=0; + u64 onesecondticks=0; + int fps=0; + int fpsframecount=0; + u64 fpsticks=0; + int res; HWND hwnd = MainWindow->getHWnd(); - - DDCAPS hw_caps, sw_caps; - - InitSpeedThrottle(); - - if (DirectDrawCreateEx(NULL, (LPVOID*)&lpDDraw, IID_IDirectDraw7, NULL) != DD_OK) - { - MessageBox(hwnd,"Unable to initialize DirectDraw","Error",MB_OK); - return -1; - } - - if (IDirectDraw7_SetCooperativeLevel(lpDDraw,hwnd, DDSCL_NORMAL) != DD_OK) - { - MessageBox(hwnd,"Unable to set DirectDraw Cooperative Level","Error",MB_OK); - return -1; - } - - if (CreateDDrawBuffers()<1) - { - MessageBox(hwnd,"Unable to set DirectDraw buffers","Error",MB_OK); - return -1; - } - - NDS_3D_SetDriver (GPU3D_OPENGL); - - if (!gpu3D->NDS_3D_Init ()) - { - MessageBox(hwnd,"Unable to initialize openGL","Error",MB_OK); - return -1; - } - - QueryPerformanceFrequency((LARGE_INTEGER *)&freq); - QueryPerformanceCounter((LARGE_INTEGER *)&lastticks); - OneFrameTime = freq / 60; - - SetEvent(runthread_ready); - - while(!finished) - { - while(execute) - { - cycles = NDS_exec((560190<<1)-cycles,FALSE); - SPU_Emulate(); - Input_Process(); - Input_Post(); - - if (!skipnextframe) - { - Display(); - - fpsframecount++; - QueryPerformanceCounter((LARGE_INTEGER *)&curticks); - bool oneSecond = curticks >= fpsticks + freq; - if(oneSecond) // TODO: print fps on screen in DDraw - { - fps = fpsframecount; - fpsframecount = 0; - QueryPerformanceCounter((LARGE_INTEGER *)&fpsticks); - } - - if(nds.idleFrameCounter==0 || oneSecond) - { - //calculate a 16 frame arm9 load average - int load = 0; - for(int i=0;i<16;i++) - load = load/8 + nds.runCycleCollector[(i+nds.idleFrameCounter)&15]*7/8; - load = std::min(100,std::max(0,(int)(load*100/1120380))); - sprintf(txt,"(%02d%%) %s", load, DESMUME_NAME_AND_VERSION); - SetWindowText(hwnd, txt); + + DDCAPS hw_caps, sw_caps; + + InitSpeedThrottle(); + + if (DirectDrawCreateEx(NULL, (LPVOID*)&lpDDraw, IID_IDirectDraw7, NULL) != DD_OK) + { + MessageBox(hwnd,"Unable to initialize DirectDraw","Error",MB_OK); + return -1; + } + + if (IDirectDraw7_SetCooperativeLevel(lpDDraw,hwnd, DDSCL_NORMAL) != DD_OK) + { + MessageBox(hwnd,"Unable to set DirectDraw Cooperative Level","Error",MB_OK); + return -1; + } + + if (CreateDDrawBuffers()<1) + { + MessageBox(hwnd,"Unable to set DirectDraw buffers","Error",MB_OK); + return -1; + } + + NDS_3D_SetDriver (GPU3D_OPENGL); + + if (!gpu3D->NDS_3D_Init ()) + { + MessageBox(hwnd,"Unable to initialize openGL","Error",MB_OK); + return -1; + } + + QueryPerformanceFrequency((LARGE_INTEGER *)&freq); + QueryPerformanceCounter((LARGE_INTEGER *)&lastticks); + OneFrameTime = freq / 60; + + SetEvent(runthread_ready); + + while(!finished) + { + while(execute) + { + EnterCriticalSection(&win_sync); + cycles = NDS_exec((560190<<1)-cycles,FALSE); + win_sound_samplecounter = 735; + LeaveCriticalSection(&win_sync); + + SPU_Emulate_core(); + //avi writing + DRV_AviSoundUpdate(SPU_core->outbuf,spu_core_samples); + DRV_AviVideoUpdate((u16*)GPU_screen); + + //check win32 messages + CheckMessages(); + + Input_Process(); + Input_Post(); + + if (!skipnextframe) + { + Display(); + + fpsframecount++; + QueryPerformanceCounter((LARGE_INTEGER *)&curticks); + bool oneSecond = curticks >= fpsticks + freq; + if(oneSecond) // TODO: print fps on screen in DDraw + { + fps = fpsframecount; + fpsframecount = 0; + QueryPerformanceCounter((LARGE_INTEGER *)&fpsticks); + } + + if(nds.idleFrameCounter==0 || oneSecond) + { + //calculate a 16 frame arm9 load average + int load = 0; + for(int i=0;i<16;i++) + load = load/8 + nds.runCycleCollector[(i+nds.idleFrameCounter)&15]*7/8; + load = std::min(100,std::max(0,(int)(load*100/1120380))); + sprintf(txt,"(%02d%%) %s", load, DESMUME_NAME_AND_VERSION); + SetWindowText(hwnd, txt); if (FpsDisplay) osd->addFixed(10, 10, "%02d Fps", fps); - } - - framesskipped = 0; - - if (framestoskip > 0) - skipnextframe = 1; - } - else - { - framestoskip--; - - if (framestoskip < 1) - skipnextframe = 0; - else - skipnextframe = 1; - - framesskipped++; - } - - while(SpeedThrottle()) - { - } - - if (autoframeskipenab) - { - framecount++; - - if (framecount > 60) - { - framecount = 1; - onesecondticks = 0; - } - - QueryPerformanceCounter((LARGE_INTEGER *)&curticks); - diffticks = curticks-lastticks; - - if(ThrottleIsBehind() && framesskipped < 9) - { - skipnextframe = 1; - framestoskip = 1; - } - - onesecondticks += diffticks; - lastticks = curticks; - } - else - { - if (framestoskip < 1) - framestoskip += frameskiprate; - } - if (frameAdvance) - { - frameAdvance = false; - execute = FALSE; - SPU_Pause(1); - } - frameCounter++; - if (frameCounterDisplay) osd->addFixed(200, 30, "%d",frameCounter); - } - paused = TRUE; - Sleep(500); - } - if (lpDDClipPrimary!=NULL) IDirectDraw7_Release(lpDDClipPrimary); - if (lpPrimarySurface != NULL) IDirectDraw7_Release(lpPrimarySurface); - if (lpBackSurface != NULL) IDirectDraw7_Release(lpBackSurface); - if (lpDDraw != NULL) IDirectDraw7_Release(lpDDraw); - return 1; -} - -void NDS_Pause() -{ - execute = FALSE; - SPU_Pause(1); - while (!paused) {} - printlog("Paused\n"); -} - -void NDS_UnPause() -{ - paused = FALSE; - execute = TRUE; - SPU_Pause(0); - printlog("Unpaused\n"); -} - -void StateSaveSlot(int num) -{ - NDS_Pause(); - savestate_slot(num); - NDS_UnPause(); -} - -void StateLoadSlot(int num) -{ - BOOL wasPaused = paused; - NDS_Pause(); - loadstate_slot(num); - if(!wasPaused) - NDS_UnPause(); - else - Display(); -} - -BOOL LoadROM(char * filename, const char *cflash_disk_image) -{ - NDS_Pause(); - if (strcmp(filename,"")!=0) printlog("Loading ROM: %s\n",filename); - - if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize, cflash_disk_image) > 0) - return TRUE; - - return FALSE; -} - -/* - * The thread handling functions needed by the GDB stub code. - */ -void * -createThread_gdb( void (APIENTRY *thread_function)( void *data), - void *thread_data) { - void *new_thread = CreateThread( NULL, 0, - (LPTHREAD_START_ROUTINE)thread_function, thread_data, - 0, NULL); - - return new_thread; -} - -void -joinThread_gdb( void *thread_handle) { -} - - -void SetLanguage(int langid) -{ - switch(langid) - { - case 1: - // French - SetThreadLocale(MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), - SORT_DEFAULT)); - break; - case 2: - // Danish - SetThreadLocale(MAKELCID(MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT), - SORT_DEFAULT)); - break; - case 0: - // English - SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - SORT_DEFAULT)); - break; - default: break; - break; - } -} - -void SaveLanguage(int langid) -{ - char text[80]; - - sprintf(text, "%d", langid); - WritePrivateProfileString("General", "Language", text, IniName); -} - -void CheckLanguage(UINT id) -{ - int i; - for (i = IDC_LANGENGLISH; i < IDC_LANGFRENCH+1; i++) + } + + framesskipped = 0; + + if (framestoskip > 0) + skipnextframe = 1; + } + else + { + framestoskip--; + + if (framestoskip < 1) + skipnextframe = 0; + else + skipnextframe = 1; + + framesskipped++; + } + + while(SpeedThrottle()) + { + } + + if (autoframeskipenab) + { + framecount++; + + if (framecount > 60) + { + framecount = 1; + onesecondticks = 0; + } + + QueryPerformanceCounter((LARGE_INTEGER *)&curticks); + diffticks = curticks-lastticks; + + if(ThrottleIsBehind() && framesskipped < 9) + { + skipnextframe = 1; + framestoskip = 1; + } + + onesecondticks += diffticks; + lastticks = curticks; + } + else + { + if (framestoskip < 1) + framestoskip += frameskiprate; + } + if (frameAdvance) + { + frameAdvance = false; + execute = FALSE; + SPU_Pause(1); + } + frameCounter++; + if (frameCounterDisplay) osd->addFixed(200, 30, "%d",frameCounter); + } + paused = TRUE; + Sleep(500); + } + if (lpDDClipPrimary!=NULL) IDirectDraw7_Release(lpDDClipPrimary); + if (lpPrimarySurface != NULL) IDirectDraw7_Release(lpPrimarySurface); + if (lpBackSurface != NULL) IDirectDraw7_Release(lpBackSurface); + if (lpDDraw != NULL) IDirectDraw7_Release(lpDDraw); + return 1; +} + +void NDS_Pause() +{ + execute = FALSE; + paused = TRUE; + SPU_Pause(1); + while (!paused) {} + printlog("Paused\n"); +} + +void NDS_UnPause() +{ + paused = FALSE; + execute = TRUE; + SPU_Pause(0); + printlog("Unpaused\n"); +} + +void StateSaveSlot(int num) +{ + NDS_Pause(); + savestate_slot(num); + NDS_UnPause(); +} + +void StateLoadSlot(int num) +{ + BOOL wasPaused = paused; + NDS_Pause(); + loadstate_slot(num); + if(!wasPaused) + NDS_UnPause(); + else + Display(); +} + +BOOL LoadROM(char * filename, const char *cflash_disk_image) +{ + NDS_Pause(); + if (strcmp(filename,"")!=0) printlog("Loading ROM: %s\n",filename); + + if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize, cflash_disk_image) > 0) + return TRUE; + + return FALSE; +} + +/* + * The thread handling functions needed by the GDB stub code. + */ +void * +createThread_gdb( void (APIENTRY *thread_function)( void *data), + void *thread_data) { + void *new_thread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE)thread_function, thread_data, + 0, NULL); + + return new_thread; +} + +void +joinThread_gdb( void *thread_handle) { +} + + +void SetLanguage(int langid) +{ + switch(langid) + { + case 1: + // French + SetThreadLocale(MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), + SORT_DEFAULT)); + break; + case 2: + // Danish + SetThreadLocale(MAKELCID(MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT), + SORT_DEFAULT)); + break; + case 0: + // English + SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + SORT_DEFAULT)); + break; + default: break; + break; + } +} + +void SaveLanguage(int langid) +{ + char text[80]; + + sprintf(text, "%d", langid); + WritePrivateProfileString("General", "Language", text, IniName); +} + +void CheckLanguage(UINT id) +{ + int i; + for (i = IDC_LANGENGLISH; i < IDC_LANGFRENCH+1; i++) MainWindow->checkMenu(i, MF_BYCOMMAND | MF_UNCHECKED); - + MainWindow->checkMenu(id, MF_BYCOMMAND | MF_CHECKED); -} - -void ChangeLanguage(int id) -{ - HMENU newmenu; - - SetLanguage(id); - newmenu = LoadMenu(hAppInst, "MENU_PRINCIPAL"); +} + +void ChangeLanguage(int id) +{ + HMENU newmenu; + + SetLanguage(id); + newmenu = LoadMenu(hAppInst, "MENU_PRINCIPAL"); SetMenu(MainWindow->getHWnd(), newmenu); - DestroyMenu(menu); - menu = newmenu; -} - + DestroyMenu(menu); + menu = newmenu; +} + int RegClass(WNDPROC Proc, LPCTSTR szName) -{ +{ WNDCLASS wc; wc.style = CS_DBLCLKS; @@ -945,43 +981,51 @@ int RegClass(WNDPROC Proc, LPCTSTR szName) wc.cbClsExtra = 0; wc.cbWndExtra = 0; return RegisterClass(&wc); -} - - -int WINAPI WinMain (HINSTANCE hThisInstance, - HINSTANCE hPrevInstance, - LPSTR lpszArgument, - int nFunsterStil) - -{ -#ifdef GDB_STUB - gdbstub_handle_t arm9_gdb_stub; - gdbstub_handle_t arm7_gdb_stub; - struct armcpu_memory_iface *arm9_memio = &arm9_base_memory_iface; - struct armcpu_memory_iface *arm7_memio = &arm7_base_memory_iface; - struct armcpu_ctrl_iface *arm9_ctrl_iface; - struct armcpu_ctrl_iface *arm7_ctrl_iface; -#endif - struct configured_features my_config; - - extern bool windows_opengl_init(); - oglrender_init = windows_opengl_init; - - - MSG messages; /* Here messages to the application are saved */ - char text[80]; - HACCEL hAccel; - hAppInst=hThisInstance; - +} + +static void ExitRunLoop() +{ + finished = TRUE; + execute = FALSE; +} + + +int WINAPI WinMain (HINSTANCE hThisInstance, + HINSTANCE hPrevInstance, + LPSTR lpszArgument, + int nFunsterStil) + +{ + InitializeCriticalSection(&win_sync); + +#ifdef GDB_STUB + gdbstub_handle_t arm9_gdb_stub; + gdbstub_handle_t arm7_gdb_stub; + struct armcpu_memory_iface *arm9_memio = &arm9_base_memory_iface; + struct armcpu_memory_iface *arm7_memio = &arm7_base_memory_iface; + struct armcpu_ctrl_iface *arm9_ctrl_iface; + struct armcpu_ctrl_iface *arm7_ctrl_iface; +#endif + struct configured_features my_config; + + extern bool windows_opengl_init(); + oglrender_init = windows_opengl_init; + + + MSG messages; /* Here messages to the application are saved */ + char text[80]; + HACCEL hAccel; + hAppInst=hThisInstance; + init_configured_features( &my_config); if ( !fill_configured_features( &my_config, lpszArgument)) { MessageBox(NULL,"Unable to parse command line arguments","Error",MB_OK); return 0; } ColorCtrl_Register(); - - OpenConsole(); // Init debug console - + + OpenConsole(); // Init debug console + if (!RegClass(WindowProcedure, "DeSmuME")) { MessageBox(NULL, "Error registering windows class", "DeSmuME", MB_OK); @@ -996,7 +1040,10 @@ int WINAPI WinMain (HINSTANCE hThisInstance, //sprintf(text, "%s", DESMUME_NAME_AND_VERSION); MainWindow = new WINCLASS(CLASSNAME, hThisInstance); - if (!MainWindow->create(TITLE, CW_USEDEFAULT, CW_USEDEFAULT, 256, 384, + RECT clientRect = {0,0,256,384}; + DWORD dwStyle = WS_CAPTION| WS_SYSMENU | WS_SIZEBOX | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + AdjustWindowRect(&clientRect,dwStyle,TRUE); + if (!MainWindow->create(TITLE, CW_USEDEFAULT, CW_USEDEFAULT, clientRect.right-clientRect.left,clientRect.bottom-clientRect.top, WS_CAPTION| WS_SYSMENU | WS_SIZEBOX | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, NULL)) { @@ -1005,44 +1052,44 @@ int WINAPI WinMain (HINSTANCE hThisInstance, exit(-1); } - /* default the firmware settings, they may get changed later */ - NDS_FillDefaultFirmwareConfigData( &win_fw_config); - - GetPrivateProfileString("General", "Language", "-1", text, 80, IniName); - SetLanguage(atoi(text)); - - bad_glob_cflash_disk_image_file = my_config.cflash_disk_image_file; - - hAccel = LoadAccelerators(hAppInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL)); - -#ifdef DEBUG - LogStart(); -#endif - + /* default the firmware settings, they may get changed later */ + NDS_FillDefaultFirmwareConfigData( &win_fw_config); + + GetPrivateProfileString("General", "Language", "-1", text, 80, IniName); + SetLanguage(atoi(text)); + + bad_glob_cflash_disk_image_file = my_config.cflash_disk_image_file; + + hAccel = LoadAccelerators(hAppInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL)); + +#ifdef DEBUG + LogStart(); +#endif + if (!MainWindow->setMenu(LoadMenu(hThisInstance, "MENU_PRINCIPAL"))) { MessageBox(NULL, "Error creating main menu", "DeSmuME", MB_OK); delete MainWindow; exit(-1); } - - // menu checks + + // menu checks MainWindow->checkMenu(IDC_FORCERATIO, MF_BYCOMMAND | (ForceRatio==1?MF_CHECKED:MF_UNCHECKED)); - + MainWindow->checkMenu(ID_VIEW_DISPLAYFPS, FpsDisplay ? MF_CHECKED : MF_UNCHECKED); - + MainWindow->checkMenu(IDC_WINDOW1X, MF_BYCOMMAND | ((windowSize==1)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW2X, MF_BYCOMMAND | ((windowSize==2)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW3X, MF_BYCOMMAND | ((windowSize==3)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW4X, MF_BYCOMMAND | ((windowSize==4)?MF_CHECKED:MF_UNCHECKED)); - + MainWindow->checkMenu(IDC_ROTATE0, MF_BYCOMMAND | ((GPU_rotation==0)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_ROTATE90, MF_BYCOMMAND | ((GPU_rotation==90)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_ROTATE180, MF_BYCOMMAND | ((GPU_rotation==180)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_ROTATE270, MF_BYCOMMAND | ((GPU_rotation==270)?MF_CHECKED:MF_UNCHECKED)); - + DragAcceptFiles(MainWindow->getHWnd(), TRUE); - + printlog("Init NDS\n"); Input_Init(MainWindow->getHWnd()); @@ -1059,172 +1106,165 @@ int WINAPI WinMain (HINSTANCE hThisInstance, ViewMatrices = new TOOLSCLASS(hThisInstance, IDD_MATRIX_VIEWER, (DLGPROC) ViewMatricesProc); ViewLights = new TOOLSCLASS(hThisInstance, IDD_LIGHT_VIEWER, (DLGPROC) ViewLightsProc); -#ifdef GDB_STUB - if ( my_config.arm9_gdb_port != 0) { - arm9_gdb_stub = createStub_gdb( my_config.arm9_gdb_port, - &arm9_memio, &arm9_direct_memory_iface); - - if ( arm9_gdb_stub == NULL) { - MessageBox(hwnd,"Failed to create ARM9 gdbstub","Error",MB_OK); - return -1; - } - } - if ( my_config.arm7_gdb_port != 0) { - arm7_gdb_stub = createStub_gdb( my_config.arm7_gdb_port, - &arm7_memio, - &arm7_base_memory_iface); - - if ( arm7_gdb_stub == NULL) { - MessageBox(hwnd,"Failed to create ARM7 gdbstub","Error",MB_OK); - return -1; - } - } - - NDS_Init( arm9_memio, &arm9_ctrl_iface, - arm7_memio, &arm7_ctrl_iface); -#else - NDS_Init (); -#endif - - /* - * Activate the GDB stubs - * This has to come after the NDS_Init where the cpus are set up. - */ -#ifdef GDB_STUB - if ( my_config.arm9_gdb_port != 0) { - activateStub_gdb( arm9_gdb_stub, arm9_ctrl_iface); - } - if ( my_config.arm7_gdb_port != 0) { - activateStub_gdb( arm7_gdb_stub, arm7_ctrl_iface); - } -#endif +#ifdef GDB_STUB + if ( my_config.arm9_gdb_port != 0) { + arm9_gdb_stub = createStub_gdb( my_config.arm9_gdb_port, + &arm9_memio, &arm9_direct_memory_iface); + + if ( arm9_gdb_stub == NULL) { + MessageBox(hwnd,"Failed to create ARM9 gdbstub","Error",MB_OK); + return -1; + } + } + if ( my_config.arm7_gdb_port != 0) { + arm7_gdb_stub = createStub_gdb( my_config.arm7_gdb_port, + &arm7_memio, + &arm7_base_memory_iface); + + if ( arm7_gdb_stub == NULL) { + MessageBox(hwnd,"Failed to create ARM7 gdbstub","Error",MB_OK); + return -1; + } + } + + NDS_Init( arm9_memio, &arm9_ctrl_iface, + arm7_memio, &arm7_ctrl_iface); +#else + NDS_Init (); +#endif + + /* + * Activate the GDB stubs + * This has to come after the NDS_Init where the cpus are set up. + */ +#ifdef GDB_STUB + if ( my_config.arm9_gdb_port != 0) { + activateStub_gdb( arm9_gdb_stub, arm9_ctrl_iface); + } + if ( my_config.arm7_gdb_port != 0) { + activateStub_gdb( arm7_gdb_stub, arm7_ctrl_iface); + } +#endif GetPrivateProfileString("General", "Language", "0", text, 80, IniName); //================================================== ??? - CheckLanguage(IDC_LANGENGLISH+atoi(text)); - - GetPrivateProfileString("Video", "FrameSkip", "AUTO", text, 80, IniName); - - if (strcmp(text, "AUTO") == 0) - { - autoframeskipenab=1; - frameskiprate=0; + CheckLanguage(IDC_LANGENGLISH+atoi(text)); + + GetPrivateProfileString("Video", "FrameSkip", "AUTO", text, 80, IniName); + + if (strcmp(text, "AUTO") == 0) + { + autoframeskipenab=1; + frameskiprate=0; MainWindow->checkMenu(IDC_FRAMESKIPAUTO, MF_BYCOMMAND | MF_CHECKED); - } - else - { - autoframeskipenab=0; - frameskiprate=atoi(text); + } + else + { + autoframeskipenab=0; + frameskiprate=atoi(text); MainWindow->checkMenu(frameskiprate + IDC_FRAMESKIP0, MF_BYCOMMAND | MF_CHECKED); - } - -#ifdef BETA_VERSION - EnableMenuItem (menu, IDM_SUBMITBUGREPORT, MF_GRAYED); -#endif - printlog("Init sound core\n"); - sndcoretype = GetPrivateProfileInt("Sound","SoundCore", SNDCORE_DIRECTX, IniName); - sndbuffersize = GetPrivateProfileInt("Sound","SoundBufferSize", 735 * 4, IniName); - - if (SPU_ChangeSoundCore(sndcoretype, sndbuffersize) != 0) - { + } + +#ifdef BETA_VERSION + EnableMenuItem (menu, IDM_SUBMITBUGREPORT, MF_GRAYED); +#endif + printlog("Init sound core\n"); + sndcoretype = GetPrivateProfileInt("Sound","SoundCore", SNDCORE_DIRECTX, IniName); + sndbuffersize = GetPrivateProfileInt("Sound","SoundBufferSize", 735 * 4, IniName); + + if (SPU_ChangeSoundCore(sndcoretype, sndbuffersize) != 0) + { MessageBox(MainWindow->getHWnd(),"Unable to initialize DirectSound","Error",MB_OK); - return -1; - } - - sndvolume = GetPrivateProfileInt("Sound","Volume",100, IniName); - SPU_SetVolume(sndvolume); - - /* Read the firmware settings from the init file */ - win_fw_config.fav_colour = GetPrivateProfileInt("Firmware","favColor", 10, IniName); - win_fw_config.birth_month = GetPrivateProfileInt("Firmware","bMonth", 7, IniName); - win_fw_config.birth_day = GetPrivateProfileInt("Firmware","bDay", 15, IniName); - win_fw_config.language = GetPrivateProfileInt("Firmware","Language", 1, IniName); - - { - /* - * Read in the nickname and message. - * Convert the strings into Unicode UTF-16 characters. - */ - char temp_str[27]; - int char_index; - GetPrivateProfileString("Firmware","nickName", "yopyop", temp_str, 11, IniName); - win_fw_config.nickname_len = strlen( temp_str); - - if ( win_fw_config.nickname_len == 0) { - strcpy( temp_str, "yopyop"); - win_fw_config.nickname_len = strlen( temp_str); - } - - for ( char_index = 0; char_index < win_fw_config.nickname_len; char_index++) { - win_fw_config.nickname[char_index] = temp_str[char_index]; - } - - GetPrivateProfileString("Firmware","Message", "DeSmuME makes you happy!", temp_str, 27, IniName); - win_fw_config.message_len = strlen( temp_str); - for ( char_index = 0; char_index < win_fw_config.message_len; char_index++) { - win_fw_config.message[char_index] = temp_str[char_index]; - } - } - - /* Create the dummy firmware */ - NDS_CreateDummyFirmware( &win_fw_config); - - runthread_ready = CreateEvent(NULL,TRUE,FALSE,0); - runthread = CreateThread(NULL, 0, run, NULL, 0, &threadID); - - //wait for the run thread to signal that it is initialized and ready to run - WaitForSingleObject(runthread_ready,INFINITE); - - // Make sure any quotes from lpszArgument are removed - if (lpszArgument[0] == '\"') - sscanf(lpszArgument, "\"%[^\"]\"", lpszArgument); - - if(LoadROM(lpszArgument, bad_glob_cflash_disk_image_file)) - { - EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); - EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); - EnableMenuItem(menu, IDM_RESET, MF_ENABLED); - EnableMenuItem(menu, IDM_GAME_INFO, MF_ENABLED); - EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_ENABLED); - romloaded = TRUE; - NDS_UnPause(); - } - else - { - EnableMenuItem(menu, IDM_EXEC, MF_ENABLED); - EnableMenuItem(menu, IDM_PAUSE, MF_GRAYED); - EnableMenuItem(menu, IDM_RESET, MF_GRAYED); - EnableMenuItem(menu, IDM_GAME_INFO, MF_GRAYED); - EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_GRAYED); - } - + return -1; + } + + sndvolume = GetPrivateProfileInt("Sound","Volume",100, IniName); + SPU_SetVolume(sndvolume); + + /* Read the firmware settings from the init file */ + win_fw_config.fav_colour = GetPrivateProfileInt("Firmware","favColor", 10, IniName); + win_fw_config.birth_month = GetPrivateProfileInt("Firmware","bMonth", 7, IniName); + win_fw_config.birth_day = GetPrivateProfileInt("Firmware","bDay", 15, IniName); + win_fw_config.language = GetPrivateProfileInt("Firmware","Language", 1, IniName); + + { + /* + * Read in the nickname and message. + * Convert the strings into Unicode UTF-16 characters. + */ + char temp_str[27]; + int char_index; + GetPrivateProfileString("Firmware","nickName", "yopyop", temp_str, 11, IniName); + win_fw_config.nickname_len = strlen( temp_str); + + if ( win_fw_config.nickname_len == 0) { + strcpy( temp_str, "yopyop"); + win_fw_config.nickname_len = strlen( temp_str); + } + + for ( char_index = 0; char_index < win_fw_config.nickname_len; char_index++) { + win_fw_config.nickname[char_index] = temp_str[char_index]; + } + + GetPrivateProfileString("Firmware","Message", "DeSmuME makes you happy!", temp_str, 27, IniName); + win_fw_config.message_len = strlen( temp_str); + for ( char_index = 0; char_index < win_fw_config.message_len; char_index++) { + win_fw_config.message[char_index] = temp_str[char_index]; + } + } + + /* Create the dummy firmware */ + NDS_CreateDummyFirmware( &win_fw_config); + + //runthread_ready = CreateEvent(NULL,TRUE,FALSE,0); + //runthread = CreateThread(NULL, 0, run, NULL, 0, &threadID); + + //wait for the run thread to signal that it is initialized and ready to run + //WaitForSingleObject(runthread_ready,INFINITE); + + // Make sure any quotes from lpszArgument are removed + if (lpszArgument[0] == '\"') + sscanf(lpszArgument, "\"%[^\"]\"", lpszArgument); + + if(LoadROM(lpszArgument, bad_glob_cflash_disk_image_file)) + { + EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); + EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); + EnableMenuItem(menu, IDM_RESET, MF_ENABLED); + EnableMenuItem(menu, IDM_GAME_INFO, MF_ENABLED); + EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_ENABLED); + romloaded = TRUE; + NDS_UnPause(); + } + else + { + EnableMenuItem(menu, IDM_EXEC, MF_ENABLED); + EnableMenuItem(menu, IDM_PAUSE, MF_GRAYED); + EnableMenuItem(menu, IDM_RESET, MF_GRAYED); + EnableMenuItem(menu, IDM_GAME_INFO, MF_GRAYED); + EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_GRAYED); + } + MainWindow->checkMenu(IDC_SAVETYPE1, MF_BYCOMMAND | MF_CHECKED); MainWindow->checkMenu(IDC_SAVETYPE2, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(IDC_SAVETYPE3, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(IDC_SAVETYPE4, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(IDC_SAVETYPE5, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(IDC_SAVETYPE6, MF_BYCOMMAND | MF_UNCHECKED); - - MainWindow->Show(SW_NORMAL); - - while (GetMessage (&messages, NULL, 0, 0)) - { - if (TranslateAccelerator(MainWindow->getHWnd(), hAccel, &messages) == 0) - { - // Translate virtual-key messages into character messages - TranslateMessage(&messages); - // Send message to WindowProcedure - DispatchMessage(&messages); - } - } - { - HRESULT hr=Input_DeInit(); -#ifdef DEBUG - if(FAILED(hr)) LOG("DirectInput deinit failed (0x%08X)\n",hr); - else LOG("DirectInput deinit\n"); -#endif - } -#ifdef DEBUG - LogStop(); -#endif + + MainWindow->Show(SW_NORMAL); + run(0); + DRV_AviEnd(); + + //------SHUTDOWN + { + HRESULT hr=Input_DeInit(); +#ifdef DEBUG + if(FAILED(hr)) LOG("DirectInput deinit failed (0x%08X)\n",hr); + else LOG("DirectInput deinit\n"); +#endif + } +#ifdef DEBUG + LogStop(); +#endif if (ViewLights!=NULL) delete ViewLights; if (ViewMatrices!=NULL) delete ViewMatrices; if (ViewOAM!=NULL) delete ViewOAM; @@ -1239,483 +1279,545 @@ int WINAPI WinMain (HINSTANCE hThisInstance, delete MainWindow; - CloseConsole(); - /* The program return-value is 0 - The value that PostQuitMessage() gave */ - return messages.wParam; -} - -void GetWndRect(HWND hwnd) -{ - POINT ptClient; - RECT rc; - - GetClientRect(hwnd,&rc); - ptClient.x=rc.left; - ptClient.y=rc.top; - ClientToScreen(hwnd,&ptClient); - MainWindowRect.left=ptClient.x; - MainWindowRect.top=ptClient.y; - ptClient.x=rc.right; - ptClient.y=rc.bottom; - ClientToScreen(hwnd,&ptClient); - MainWindowRect.right=ptClient.x; - MainWindowRect.bottom=ptClient.y; -} - -//======================================================================================== + CloseConsole(); + + return 0; +} + +void GetWndRect(HWND hwnd) +{ + POINT ptClient; + RECT rc; + + GetClientRect(hwnd,&rc); + ptClient.x=rc.left; + ptClient.y=rc.top; + ClientToScreen(hwnd,&ptClient); + MainWindowRect.left=ptClient.x; + MainWindowRect.top=ptClient.y; + ptClient.x=rc.right; + ptClient.y=rc.bottom; + ClientToScreen(hwnd,&ptClient); + MainWindowRect.right=ptClient.x; + MainWindowRect.bottom=ptClient.y; +} + +//======================================================================================== void SetRotate(HWND hwnd, int rot) -{ - GPU_rotation = rot; - - switch (rot) - { - case 0: - GPU_width = 256; - GPU_height = 192*2; - rotationstartscan = 192; - rotationscanlines = 192*2; - break; - - case 90: - GPU_rotation = 90; - GPU_width = 192*2; - GPU_height = 256; - rotationstartscan = 0; - rotationscanlines = 256; - break; - - case 180: - GPU_rotation = 180; - GPU_width = 256; - GPU_height = 192*2; - rotationstartscan = 0; - rotationscanlines = 192*2; - break; - - case 270: - GPU_rotation = 270; - GPU_width = 192*2; - GPU_height = 256; - rotationstartscan = 0; - rotationscanlines = 256; - break; - } - - SetWindowClientSize(hwnd, GPU_width, GPU_height); +{ + GPU_rotation = rot; + + switch (rot) + { + case 0: + GPU_width = 256; + GPU_height = 192*2; + rotationstartscan = 192; + rotationscanlines = 192*2; + break; + + case 90: + GPU_rotation = 90; + GPU_width = 192*2; + GPU_height = 256; + rotationstartscan = 0; + rotationscanlines = 256; + break; + + case 180: + GPU_rotation = 180; + GPU_width = 256; + GPU_height = 192*2; + rotationstartscan = 0; + rotationscanlines = 192*2; + break; + + case 270: + GPU_rotation = 270; + GPU_width = 192*2; + GPU_height = 256; + rotationstartscan = 0; + rotationscanlines = 256; + break; + } + + SetWindowClientSize(hwnd, GPU_width, GPU_height); MainWindow->checkMenu(IDC_ROTATE0, MF_BYCOMMAND | ((GPU_rotation==0)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_ROTATE90, MF_BYCOMMAND | ((GPU_rotation==90)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_ROTATE180, MF_BYCOMMAND | ((GPU_rotation==180)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_ROTATE270, MF_BYCOMMAND | ((GPU_rotation==270)?MF_CHECKED:MF_UNCHECKED)); - WritePrivateProfileInt("Video","Window Rotate",GPU_rotation,IniName); -} -//======================================================================================== -LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - static int tmp_execute; - switch (message) // handle the messages - { - /*case WM_ENTERMENULOOP: // temporally removed it (freezes) - { - if (execute) - { - NDS_Pause(); - tmp_execute=2; - } else tmp_execute=-1; - return 0; - } - case WM_EXITMENULOOP: - { - if (tmp_execute==2) NDS_UnPause(); - return 0; - }*/ + WritePrivateProfileInt("Video","Window Rotate",GPU_rotation,IniName); +} + +static void AviEnd() +{ + NDS_Pause(); + DRV_AviEnd(); + NDS_UnPause(); +} + +//Shows an Open File menu and starts recording an AVI +static void AviRecordTo() +{ + NDS_Pause(); - case WM_CREATE: - { - RECT clientSize, fullSize; - GetClientRect(hwnd, &clientSize); - GetWindowRect(hwnd, &fullSize); - DefaultWidth = clientSize.right - clientSize.left; - DefaultHeight = clientSize.bottom - clientSize.top; - widthTradeOff = (fullSize.right - fullSize.left) - (clientSize.right - clientSize.left); - heightTradeOff = (fullSize.bottom - fullSize.top) - (clientSize.bottom - clientSize.top); + OPENFILENAME ofn; + char szChoice[MAX_PATH] = {0}; - if ( (windowSize < 1) || (windowSize > 4) ) - { - int w=GetPrivateProfileInt("Video","Window width", 0, IniName); - int h=GetPrivateProfileInt("Video","Window height", 0, IniName); - if (w && h) - { - RECT fullSize = {0, 0, w, h}; - ResizingLimit(WMSZ_RIGHT, &fullSize); + ////if we are playing a movie, construct the filename from the current movie. + ////else construct it from the filename. + //if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD)) + //{ + // extern char curMovieFilename[]; + // strcpy(szChoice, curMovieFilename); + // char* dot = strrchr(szChoice,'.'); - if (ForceRatio) - ScallingScreen(hwnd, WMSZ_RIGHT, &fullSize); - SetWindowPos(hwnd, NULL, 0, 0, fullSize.right - fullSize.left, - fullSize.bottom - fullSize.top, SWP_NOMOVE | SWP_NOZORDER); - } - else - windowSize=1; - } - if ( (windowSize > 0) && (windowSize < 5) ) ScaleScreen(hwnd, windowSize); - - return 0; - - } - case WM_DESTROY: - case WM_CLOSE: - { - NDS_Pause(); - finished = TRUE; + // if (dot) + // { + // *dot='\0'; + // } - WritePrivateProfileInt("Video","Window Size",windowSize,IniName); - if (windowSize==0) - { - WritePrivateProfileInt("Video","Window width",MainWindowRect.right-MainWindowRect.left+widthTradeOff,IniName); - WritePrivateProfileInt("Video","Window height",MainWindowRect.bottom-MainWindowRect.top+heightTradeOff,IniName); - } + // strcat(szChoice, ".avi"); + //} + //else + //{ + // extern char FileBase[]; + // sprintf(szChoice, "%s.avi", FileBase); + //} - if (runthread != INVALID_HANDLE_VALUE) - { - if (WaitForSingleObject(runthread,INFINITE) == WAIT_TIMEOUT) - { - // Couldn't close thread cleanly - TerminateThread(runthread,0); - } - CloseHandle(runthread); - } + // avi record file browser + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = MainWindow->getHWnd(); + ofn.lpstrFilter = "AVI Files (*.avi)\0*.avi\0\0"; + ofn.lpstrFile = szChoice; + ofn.lpstrDefExt = "avi"; + ofn.lpstrTitle = "Save AVI as"; - NDS_DeInit(); - PostMessage(hwnd, WM_QUIT, 0, 0); - return 0; - } - case WM_MOVE: - GetWndRect(hwnd); - return 0; - case WM_SIZING: - { - RECT *rc=(RECT *)lParam; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; - windowSize=0; - ResizingLimit(wParam, rc); - if (ForceRatio) - ScallingScreen(hwnd, wParam, rc); - //printlog("sizing: width=%i; height=%i\n", rc->right - rc->left, rc->bottom - rc->top); - } - break; - case WM_SIZE: - if (ForceRatio) { - if ( windowSize != 0 ) ScaleScreen(hwnd, windowSize); - } - GetWndRect(hwnd); - return 0; - case WM_DROPFILES: - { - char filename[MAX_PATH] = ""; - DragQueryFile((HDROP)wParam,0,filename,MAX_PATH); - DragFinish((HDROP)wParam); - if(LoadROM(filename, bad_glob_cflash_disk_image_file)) - { - EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); - EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); - EnableMenuItem(menu, IDM_RESET, MF_ENABLED); - EnableMenuItem(menu, IDM_GAME_INFO, MF_ENABLED); - EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_ENABLED); - romloaded = TRUE; - NDS_UnPause(); - } - } - return 0; - case WM_MOUSEMOVE: - if (wParam & MK_LBUTTON) - { - RECT r ; - s32 x = (s32)((s16)LOWORD(lParam)); - s32 y = (s32)((s16)HIWORD(lParam)); - GetClientRect(hwnd,&r) ; - /* translate from scaling (screen reoltution to 256x384 or 512x192) */ - switch (GPU_rotation) - { - case 0: - case 180: - x = (x*256) / (r.right - r.left) ; - y = (y*384) / (r.bottom - r.top) ; - break ; - case 90: - case 270: - x = (x*512) / (r.right - r.left) ; - y = (y*192) / (r.bottom - r.top) ; - break ; - } - /* translate for rotation */ - if (GPU_rotation != 0) - translateXY(&x,&y); - else - y-=192; - if(x<0) x = 0; else if(x>255) x = 255; - if(y<0) y = 0; else if(y>192) y = 192; - NDS_setTouchPos(x, y); - return 0; - } - NDS_releasTouch(); - return 0; - case WM_LBUTTONDOWN: - if(HIWORD(lParam)>=192) - { - RECT r ; - s32 x = (s32)((s16)LOWORD(lParam)); - s32 y = (s32)((s16)HIWORD(lParam)); - GetClientRect(hwnd,&r) ; - /* translate from scaling (screen reoltution to 256x384 or 512x192) */ - switch (GPU_rotation) - { - case 0: - case 180: - x = (x*256) / (r.right - r.left) ; - y = (y*384) / (r.bottom - r.top) ; - break ; - case 90: - case 270: - x = (x*512) / (r.right - r.left) ; - y = (y*192) / (r.bottom - r.top) ; - break ; - } - /* translate for rotation */ - if (GPU_rotation != 0) - translateXY(&x,&y); - else - y-=192; - if(y>=0) - { - SetCapture(hwnd); - if(x<0) x = 0; else if(x>255) x = 255; - if(y<0) y = 0; else if(y>192) y = 192; - NDS_setTouchPos(x, y); - click = TRUE; - } - } - return 0; - case WM_LBUTTONUP: - if(click) - ReleaseCapture(); - NDS_releasTouch(); - return 0; + if(GetSaveFileName(&ofn)) + { + DRV_AviBegin(szChoice); + } - case WM_COMMAND: - switch(LOWORD(wParam)) - { + NDS_UnPause(); +} + +//======================================================================================== +LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static int tmp_execute; + switch (message) // handle the messages + { + /*case WM_ENTERMENULOOP: // temporally removed it (freezes) + { + if (execute) + { + NDS_Pause(); + tmp_execute=2; + } else tmp_execute=-1; + return 0; + } + case WM_EXITMENULOOP: + { + if (tmp_execute==2) NDS_UnPause(); + return 0; + }*/ + + case WM_CREATE: + { + RECT clientSize, fullSize; + GetClientRect(hwnd, &clientSize); + GetWindowRect(hwnd, &fullSize); + DefaultWidth = clientSize.right - clientSize.left; + DefaultHeight = clientSize.bottom - clientSize.top; + widthTradeOff = (fullSize.right - fullSize.left) - (clientSize.right - clientSize.left); + heightTradeOff = (fullSize.bottom - fullSize.top) - (clientSize.bottom - clientSize.top); + + if ( (windowSize < 1) || (windowSize > 4) ) + { + int w=GetPrivateProfileInt("Video","Window width", 0, IniName); + int h=GetPrivateProfileInt("Video","Window height", 0, IniName); + if (w && h) + { + RECT fullSize = {0, 0, w, h}; + ResizingLimit(WMSZ_RIGHT, &fullSize); + + if (ForceRatio) + ScallingScreen(hwnd, WMSZ_RIGHT, &fullSize); + SetWindowPos(hwnd, NULL, 0, 0, fullSize.right - fullSize.left, + fullSize.bottom - fullSize.top, SWP_NOMOVE | SWP_NOZORDER); + } + else + windowSize=1; + } + if ( (windowSize > 0) && (windowSize < 5) ) ScaleScreen(hwnd, windowSize); + + return 0; + + } + case WM_DESTROY: + case WM_CLOSE: + { + NDS_Pause(); + + WritePrivateProfileInt("Video","Window Size",windowSize,IniName); + if (windowSize==0) + { + WritePrivateProfileInt("Video","Window width",MainWindowRect.right-MainWindowRect.left+widthTradeOff,IniName); + WritePrivateProfileInt("Video","Window height",MainWindowRect.bottom-MainWindowRect.top+heightTradeOff,IniName); + } + + if (runthread != INVALID_HANDLE_VALUE) + { + if (WaitForSingleObject(runthread,INFINITE) == WAIT_TIMEOUT) + { + // Couldn't close thread cleanly + TerminateThread(runthread,0); + } + CloseHandle(runthread); + } + + NDS_DeInit(); + ExitRunLoop();; + return 0; + } + case WM_MOVE: + GetWndRect(hwnd); + return 0; + case WM_SIZING: + { + RECT *rc=(RECT *)lParam; + + windowSize=0; + ResizingLimit(wParam, rc); + if (ForceRatio) + ScallingScreen(hwnd, wParam, rc); + //printlog("sizing: width=%i; height=%i\n", rc->right - rc->left, rc->bottom - rc->top); + } + break; + case WM_SIZE: + if (ForceRatio) { + if ( windowSize != 0 ) ScaleScreen(hwnd, windowSize); + } + GetWndRect(hwnd); + return 0; + case WM_DROPFILES: + { + char filename[MAX_PATH] = ""; + DragQueryFile((HDROP)wParam,0,filename,MAX_PATH); + DragFinish((HDROP)wParam); + if(LoadROM(filename, bad_glob_cflash_disk_image_file)) + { + EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); + EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); + EnableMenuItem(menu, IDM_RESET, MF_ENABLED); + EnableMenuItem(menu, IDM_GAME_INFO, MF_ENABLED); + EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_ENABLED); + romloaded = TRUE; + NDS_UnPause(); + } + } + return 0; + case WM_MOUSEMOVE: + if (wParam & MK_LBUTTON) + { + RECT r ; + s32 x = (s32)((s16)LOWORD(lParam)); + s32 y = (s32)((s16)HIWORD(lParam)); + GetClientRect(hwnd,&r) ; + /* translate from scaling (screen reoltution to 256x384 or 512x192) */ + switch (GPU_rotation) + { + case 0: + case 180: + x = (x*256) / (r.right - r.left) ; + y = (y*384) / (r.bottom - r.top) ; + break ; + case 90: + case 270: + x = (x*512) / (r.right - r.left) ; + y = (y*192) / (r.bottom - r.top) ; + break ; + } + /* translate for rotation */ + if (GPU_rotation != 0) + translateXY(&x,&y); + else + y-=192; + if(x<0) x = 0; else if(x>255) x = 255; + if(y<0) y = 0; else if(y>192) y = 192; + NDS_setTouchPos(x, y); + return 0; + } + NDS_releasTouch(); + return 0; + case WM_LBUTTONDOWN: + if(HIWORD(lParam)>=192) + { + RECT r ; + s32 x = (s32)((s16)LOWORD(lParam)); + s32 y = (s32)((s16)HIWORD(lParam)); + GetClientRect(hwnd,&r) ; + /* translate from scaling (screen reoltution to 256x384 or 512x192) */ + switch (GPU_rotation) + { + case 0: + case 180: + x = (x*256) / (r.right - r.left) ; + y = (y*384) / (r.bottom - r.top) ; + break ; + case 90: + case 270: + x = (x*512) / (r.right - r.left) ; + y = (y*192) / (r.bottom - r.top) ; + break ; + } + /* translate for rotation */ + if (GPU_rotation != 0) + translateXY(&x,&y); + else + y-=192; + if(y>=0) + { + SetCapture(hwnd); + if(x<0) x = 0; else if(x>255) x = 255; + if(y<0) y = 0; else if(y>192) y = 192; + NDS_setTouchPos(x, y); + click = TRUE; + } + } + return 0; + case WM_LBUTTONUP: + if(click) + ReleaseCapture(); + NDS_releasTouch(); + return 0; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { case IDM_QUIT: PostMessage(hwnd, WM_QUIT, 0, 0); return 0; - case IDM_OPEN: - { - int filterSize = 0, i = 0; - OPENFILENAME ofn; - char filename[MAX_PATH] = "", - fileFilter[512]=""; - NDS_Pause(); //Stop emulation while opening new rom - - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - - // To avoid #ifdef hell, we'll do a little trick, as lpstrFilter - // needs 0 terminated string, and standard string library, of course, - // can't help us with string creation: just put a '|' were a string end - // should be, and later transform prior assigning to the OPENFILENAME structure - strncpy (fileFilter, "NDS ROM file (*.nds)|*.nds|NDS/GBA ROM File (*.ds.gba)|*.ds.gba|",512); -#ifdef HAVE_LIBZZIP - strncat (fileFilter, "Zipped NDS ROM file (*.zip)|*.zip|",512 - strlen(fileFilter)); -#endif -#ifdef HAVE_LIBZ - strncat (fileFilter, "GZipped NDS ROM file (*.gz)|*.gz|",512 - strlen(fileFilter)); -#endif - strncat (fileFilter, "Any file (*.*)|*.*||",512 - strlen(fileFilter)); - - filterSize = strlen(fileFilter); - for (i = 0; i < filterSize; i++) - { - if (fileFilter[i] == '|') fileFilter[i] = '\0'; - } - ofn.lpstrFilter = fileFilter; - ofn.nFilterIndex = 1; - ofn.lpstrFile = filename; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrDefExt = "nds"; - - if(!GetOpenFileName(&ofn)) - { - if (romloaded) - NDS_UnPause(); //Restart emulation if no new rom chosen - return 0; - } - - LOG("%s\r\n", filename); - - if(LoadROM(filename, bad_glob_cflash_disk_image_file)) - { - EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); - EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); - EnableMenuItem(menu, IDM_RESET, MF_ENABLED); - EnableMenuItem(menu, IDM_GAME_INFO, MF_ENABLED); - EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_ENABLED); - romloaded = TRUE; - NDS_UnPause(); - } - } - return 0; - case IDM_PRINTSCREEN: - { - OPENFILENAME ofn; - char filename[MAX_PATH] = ""; - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - ofn.lpstrFilter = "Bmp file (*.bmp)\0*.bmp\0Any file (*.*)\0*.*\0\0"; - ofn.nFilterIndex = 1; - ofn.lpstrFile = filename; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrDefExt = "bmp"; - ofn.Flags = OFN_OVERWRITEPROMPT; - GetSaveFileName(&ofn); - NDS_WriteBMP(filename); - } - return 0; - case IDM_QUICK_PRINTSCREEN: - { - NDS_WriteBMP("./printscreen.bmp"); - } - return 0; - case IDM_STATE_LOAD: - { - OPENFILENAME ofn; - NDS_Pause(); - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - ofn.lpstrFilter = "DeSmuME Savestate (*.dst)\0*.dst\0\0"; - ofn.nFilterIndex = 1; - ofn.lpstrFile = SavName; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrDefExt = "dst"; - - if(!GetOpenFileName(&ofn)) - { - NDS_UnPause(); - return 0; - } - - savestate_load(SavName); - NDS_UnPause(); - } - return 0; - case IDM_STATE_SAVE: - { - OPENFILENAME ofn; - NDS_Pause(); - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - ofn.lpstrFilter = "DeSmuME Savestate (*.dst)\0*.dst\0\0"; - ofn.nFilterIndex = 1; - ofn.lpstrFile = SavName; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrDefExt = "dst"; - - if(!GetSaveFileName(&ofn)) - { - return 0; - } - - savestate_save(SavName); - NDS_UnPause(); - } - return 0; - case IDM_STATE_SAVE_F1: - StateSaveSlot(1); - return 0; - case IDM_STATE_SAVE_F2: - StateSaveSlot(2); - return 0; - case IDM_STATE_SAVE_F3: - StateSaveSlot(3); - return 0; - case IDM_STATE_SAVE_F4: - StateSaveSlot(4); - return 0; - case IDM_STATE_SAVE_F5: - StateSaveSlot(5); - return 0; - case IDM_STATE_SAVE_F6: - StateSaveSlot(6); - return 0; - case IDM_STATE_SAVE_F7: - StateSaveSlot(7); - return 0; - case IDM_STATE_SAVE_F8: - StateSaveSlot(8); - return 0; - case IDM_STATE_SAVE_F9: - StateSaveSlot(9); - return 0; - case IDM_STATE_SAVE_F10: - StateSaveSlot(10); - return 0; - case IDM_STATE_LOAD_F1: - StateLoadSlot(1); - return 0; - case IDM_STATE_LOAD_F2: - StateLoadSlot(2); - return 0; - case IDM_STATE_LOAD_F3: - StateLoadSlot(3); - return 0; - case IDM_STATE_LOAD_F4: - StateLoadSlot(4); - return 0; - case IDM_STATE_LOAD_F5: - StateLoadSlot(5); - return 0; - case IDM_STATE_LOAD_F6: - StateLoadSlot(6); - return 0; - case IDM_STATE_LOAD_F7: - StateLoadSlot(7); - return 0; - case IDM_STATE_LOAD_F8: - StateLoadSlot(8); - return 0; - case IDM_STATE_LOAD_F9: - StateLoadSlot(9); - return 0; - case IDM_STATE_LOAD_F10: - StateLoadSlot(10); - return 0; - case IDM_IMPORTBACKUPMEMORY: - { - OPENFILENAME ofn; - NDS_Pause(); - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - ofn.lpstrFilter = "All supported types\0*.duc;*.sav\0Action Replay DS Save (*.duc)\0*.duc\0DS-Xtreme Save (*.sav)\0*.sav\0\0"; - ofn.nFilterIndex = 1; - ofn.lpstrFile = ImportSavName; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrDefExt = "duc"; - - if(!GetOpenFileName(&ofn)) - { - NDS_UnPause(); - return 0; - } - - if (!NDS_ImportSave(ImportSavName)) - MessageBox(hwnd,"Save was not successfully imported","Error",MB_OK); - NDS_UnPause(); - return 0; - } - case IDM_SOUNDSETTINGS: - { + case IDM_OPEN: + { + int filterSize = 0, i = 0; + OPENFILENAME ofn; + char filename[MAX_PATH] = "", + fileFilter[512]=""; + NDS_Pause(); //Stop emulation while opening new rom + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + + // To avoid #ifdef hell, we'll do a little trick, as lpstrFilter + // needs 0 terminated string, and standard string library, of course, + // can't help us with string creation: just put a '|' were a string end + // should be, and later transform prior assigning to the OPENFILENAME structure + strncpy (fileFilter, "NDS ROM file (*.nds)|*.nds|NDS/GBA ROM File (*.ds.gba)|*.ds.gba|",512); +#ifdef HAVE_LIBZZIP + strncat (fileFilter, "Zipped NDS ROM file (*.zip)|*.zip|",512 - strlen(fileFilter)); +#endif +#ifdef HAVE_LIBZ + strncat (fileFilter, "GZipped NDS ROM file (*.gz)|*.gz|",512 - strlen(fileFilter)); +#endif + strncat (fileFilter, "Any file (*.*)|*.*||",512 - strlen(fileFilter)); + + filterSize = strlen(fileFilter); + for (i = 0; i < filterSize; i++) + { + if (fileFilter[i] == '|') fileFilter[i] = '\0'; + } + ofn.lpstrFilter = fileFilter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = "nds"; + + if(!GetOpenFileName(&ofn)) + { + if (romloaded) + NDS_UnPause(); //Restart emulation if no new rom chosen + return 0; + } + + LOG("%s\r\n", filename); + + if(LoadROM(filename, bad_glob_cflash_disk_image_file)) + { + EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); + EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); + EnableMenuItem(menu, IDM_RESET, MF_ENABLED); + EnableMenuItem(menu, IDM_GAME_INFO, MF_ENABLED); + EnableMenuItem(menu, IDM_IMPORTBACKUPMEMORY, MF_ENABLED); + romloaded = TRUE; + NDS_UnPause(); + } + } + return 0; + case IDM_PRINTSCREEN: + { + OPENFILENAME ofn; + char filename[MAX_PATH] = ""; + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = "Bmp file (*.bmp)\0*.bmp\0Any file (*.*)\0*.*\0\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = "bmp"; + ofn.Flags = OFN_OVERWRITEPROMPT; + GetSaveFileName(&ofn); + NDS_WriteBMP(filename); + } + return 0; + case IDM_QUICK_PRINTSCREEN: + { + NDS_WriteBMP("./printscreen.bmp"); + } + return 0; + case IDM_FILE_RECORDAVI: + AviRecordTo(); + break; + case IDM_FILE_STOPAVI: + AviEnd(); + break; + case IDM_STATE_LOAD: + { + OPENFILENAME ofn; + NDS_Pause(); + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = "DeSmuME Savestate (*.dst)\0*.dst\0\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = SavName; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = "dst"; + + if(!GetOpenFileName(&ofn)) + { + NDS_UnPause(); + return 0; + } + + savestate_load(SavName); + NDS_UnPause(); + } + return 0; + case IDM_STATE_SAVE: + { + OPENFILENAME ofn; + NDS_Pause(); + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = "DeSmuME Savestate (*.dst)\0*.dst\0\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = SavName; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = "dst"; + + if(!GetSaveFileName(&ofn)) + { + return 0; + } + + savestate_save(SavName); + NDS_UnPause(); + } + return 0; + case IDM_STATE_SAVE_F1: + StateSaveSlot(1); + return 0; + case IDM_STATE_SAVE_F2: + StateSaveSlot(2); + return 0; + case IDM_STATE_SAVE_F3: + StateSaveSlot(3); + return 0; + case IDM_STATE_SAVE_F4: + StateSaveSlot(4); + return 0; + case IDM_STATE_SAVE_F5: + StateSaveSlot(5); + return 0; + case IDM_STATE_SAVE_F6: + StateSaveSlot(6); + return 0; + case IDM_STATE_SAVE_F7: + StateSaveSlot(7); + return 0; + case IDM_STATE_SAVE_F8: + StateSaveSlot(8); + return 0; + case IDM_STATE_SAVE_F9: + StateSaveSlot(9); + return 0; + case IDM_STATE_SAVE_F10: + StateSaveSlot(10); + return 0; + case IDM_STATE_LOAD_F1: + StateLoadSlot(1); + return 0; + case IDM_STATE_LOAD_F2: + StateLoadSlot(2); + return 0; + case IDM_STATE_LOAD_F3: + StateLoadSlot(3); + return 0; + case IDM_STATE_LOAD_F4: + StateLoadSlot(4); + return 0; + case IDM_STATE_LOAD_F5: + StateLoadSlot(5); + return 0; + case IDM_STATE_LOAD_F6: + StateLoadSlot(6); + return 0; + case IDM_STATE_LOAD_F7: + StateLoadSlot(7); + return 0; + case IDM_STATE_LOAD_F8: + StateLoadSlot(8); + return 0; + case IDM_STATE_LOAD_F9: + StateLoadSlot(9); + return 0; + case IDM_STATE_LOAD_F10: + StateLoadSlot(10); + return 0; + case IDM_IMPORTBACKUPMEMORY: + { + OPENFILENAME ofn; + NDS_Pause(); + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = "All supported types\0*.duc;*.sav\0Action Replay DS Save (*.duc)\0*.duc\0DS-Xtreme Save (*.sav)\0*.sav\0\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = ImportSavName; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = "duc"; + + if(!GetOpenFileName(&ofn)) + { + NDS_UnPause(); + return 0; + } + + if (!NDS_ImportSave(ImportSavName)) + MessageBox(hwnd,"Save was not successfully imported","Error",MB_OK); + NDS_UnPause(); + return 0; + } + case IDM_SOUNDSETTINGS: + { bool tpaused=false; if (execute) { @@ -1725,30 +1827,30 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_SOUNDSETTINGS), hwnd, (DLGPROC)SoundSettingsDlgProc); if (tpaused) NDS_UnPause(); - } - return 0; - case IDM_GAME_INFO: - { - CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_GAME_INFO), hwnd, GinfoView_Proc); - } - return 0; + } + return 0; + case IDM_GAME_INFO: + { + CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_GAME_INFO), hwnd, GinfoView_Proc); + } + return 0; //========================================================= Tools - case IDM_PAL: + case IDM_PAL: ViewPalette->open(); return 0; - case IDM_TILE: - { + case IDM_TILE: + { ViewTiles->regClass("TileViewBox", TileViewBoxProc); ViewTiles->regClass("MiniTileViewBox", MiniTileViewBoxProc, true); if (!ViewTiles->open()) ViewTiles->unregClass(); - } - return 0; - case IDM_IOREG: - ViewRegisters->open(); - return 0; - case IDM_MEMORY: + } + return 0; + case IDM_IOREG: + ViewRegisters->open(); + return 0; + case IDM_MEMORY: ViewMem_ARM7->regClass("MemViewBox7", ViewMem_ARM7BoxProc); if (!ViewMem_ARM7->open()) ViewMem_ARM7->unregClass(); @@ -1756,150 +1858,150 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM if (!ViewMem_ARM9->open()) ViewMem_ARM9->unregClass(); return 0; - case IDM_DISASSEMBLER: + case IDM_DISASSEMBLER: ViewDisasm_ARM7->regClass("DesViewBox7",ViewDisasm_ARM7BoxProc); if (!ViewDisasm_ARM7->open()) ViewDisasm_ARM7->unregClass(); - + ViewDisasm_ARM9->regClass("DesViewBox9",ViewDisasm_ARM9BoxProc); if (!ViewDisasm_ARM9->open()) ViewDisasm_ARM9->unregClass(); return 0; - case IDM_MAP: + case IDM_MAP: ViewMaps->open(); return 0; - case IDM_OAM: + case IDM_OAM: ViewOAM->regClass("OAMViewBox", ViewOAMBoxProc); if (!ViewOAM->open()) ViewOAM->unregClass(); return 0; - - case IDM_MATRIX_VIEWER: + + case IDM_MATRIX_VIEWER: ViewMatrices->open(); return 0; - - case IDM_LIGHT_VIEWER: + + case IDM_LIGHT_VIEWER: ViewLights->open(); return 0; //========================================================== Tools end - - case IDM_MBG0 : - if(MainScreen.gpu->dispBG[0]) - { - GPU_remove(MainScreen.gpu, 0); + + case IDM_MBG0 : + if(MainScreen.gpu->dispBG[0]) + { + GPU_remove(MainScreen.gpu, 0); MainWindow->checkMenu(IDM_MBG0, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(MainScreen.gpu, 0); + } + else + { + GPU_addBack(MainScreen.gpu, 0); MainWindow->checkMenu(IDM_MBG0, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDM_MBG1 : - if(MainScreen.gpu->dispBG[1]) - { - GPU_remove(MainScreen.gpu, 1); + } + return 0; + case IDM_MBG1 : + if(MainScreen.gpu->dispBG[1]) + { + GPU_remove(MainScreen.gpu, 1); MainWindow->checkMenu(IDM_MBG1, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(MainScreen.gpu, 1); + } + else + { + GPU_addBack(MainScreen.gpu, 1); MainWindow->checkMenu(IDM_MBG1, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDM_MBG2 : - if(MainScreen.gpu->dispBG[2]) - { - GPU_remove(MainScreen.gpu, 2); + } + return 0; + case IDM_MBG2 : + if(MainScreen.gpu->dispBG[2]) + { + GPU_remove(MainScreen.gpu, 2); MainWindow->checkMenu(IDM_MBG2, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(MainScreen.gpu, 2); + } + else + { + GPU_addBack(MainScreen.gpu, 2); MainWindow->checkMenu(IDM_MBG2, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDM_MBG3 : - if(MainScreen.gpu->dispBG[3]) - { - GPU_remove(MainScreen.gpu, 3); + } + return 0; + case IDM_MBG3 : + if(MainScreen.gpu->dispBG[3]) + { + GPU_remove(MainScreen.gpu, 3); MainWindow->checkMenu(IDM_MBG3, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(MainScreen.gpu, 3); + } + else + { + GPU_addBack(MainScreen.gpu, 3); MainWindow->checkMenu(IDM_MBG3, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDM_SBG0 : - if(SubScreen.gpu->dispBG[0]) - { - GPU_remove(SubScreen.gpu, 0); + } + return 0; + case IDM_SBG0 : + if(SubScreen.gpu->dispBG[0]) + { + GPU_remove(SubScreen.gpu, 0); MainWindow->checkMenu(IDM_SBG0, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(SubScreen.gpu, 0); + } + else + { + GPU_addBack(SubScreen.gpu, 0); MainWindow->checkMenu(IDM_SBG0, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDM_SBG1 : - if(SubScreen.gpu->dispBG[1]) - { - GPU_remove(SubScreen.gpu, 1); + } + return 0; + case IDM_SBG1 : + if(SubScreen.gpu->dispBG[1]) + { + GPU_remove(SubScreen.gpu, 1); MainWindow->checkMenu(IDM_SBG1, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(SubScreen.gpu, 1); + } + else + { + GPU_addBack(SubScreen.gpu, 1); MainWindow->checkMenu(IDM_SBG1, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDM_SBG2 : - if(SubScreen.gpu->dispBG[2]) - { - GPU_remove(SubScreen.gpu, 2); + } + return 0; + case IDM_SBG2 : + if(SubScreen.gpu->dispBG[2]) + { + GPU_remove(SubScreen.gpu, 2); MainWindow->checkMenu(IDM_SBG2, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(SubScreen.gpu, 2); + } + else + { + GPU_addBack(SubScreen.gpu, 2); MainWindow->checkMenu(IDM_SBG2, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDM_SBG3 : - if(SubScreen.gpu->dispBG[3]) - { - GPU_remove(SubScreen.gpu, 3); + } + return 0; + case IDM_SBG3 : + if(SubScreen.gpu->dispBG[3]) + { + GPU_remove(SubScreen.gpu, 3); MainWindow->checkMenu(IDM_SBG3, MF_BYCOMMAND | MF_UNCHECKED); - } - else - { - GPU_addBack(SubScreen.gpu, 3); + } + else + { + GPU_addBack(SubScreen.gpu, 3); MainWindow->checkMenu(IDM_SBG3, MF_BYCOMMAND | MF_CHECKED); - } - return 0; - - case ACCEL_SPACEBAR: - case IDM_PAUSE: - if (emu_paused) NDS_UnPause(); - else NDS_Pause(); - emu_paused ^= 1; + } + return 0; + + case ACCEL_SPACEBAR: + case IDM_PAUSE: + if (emu_paused) NDS_UnPause(); + else NDS_Pause(); + emu_paused ^= 1; MainWindow->checkMenu(IDM_PAUSE, emu_paused ? MF_CHECKED : MF_UNCHECKED); - return 0; - - case ACCEL_N: //Frame Advance - frameAdvance = true; - execute = TRUE; - emu_paused = 1; + return 0; + + case ACCEL_N: //Frame Advance + frameAdvance = true; + execute = TRUE; + emu_paused = 1; MainWindow->checkMenu(IDM_PAUSE, emu_paused ? MF_CHECKED : MF_UNCHECKED); - return 0; - - case ID_VIEW_FRAMECOUNTER: - frameCounterDisplay ^= 1; + return 0; + + case ID_VIEW_FRAMECOUNTER: + frameCounterDisplay ^= 1; MainWindow->checkMenu(ID_VIEW_FRAMECOUNTER, frameCounterDisplay ? MF_CHECKED : MF_UNCHECKED); - return 0; - + return 0; + case ID_VIEW_DISPLAYFPS: FpsDisplay ^= 1; MainWindow->checkMenu(ID_VIEW_DISPLAYFPS, FpsDisplay ? MF_CHECKED : MF_UNCHECKED); @@ -1907,45 +2009,45 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM osd->clear(); return 0; - #define saver(one,two,three,four,five, six) \ + #define saver(one,two,three,four,five, six) \ MainWindow->checkMenu(IDC_SAVETYPE1, MF_BYCOMMAND | one); \ MainWindow->checkMenu(IDC_SAVETYPE2, MF_BYCOMMAND | two); \ MainWindow->checkMenu(IDC_SAVETYPE3, MF_BYCOMMAND | three); \ MainWindow->checkMenu(IDC_SAVETYPE4, MF_BYCOMMAND | four); \ MainWindow->checkMenu(IDC_SAVETYPE5, MF_BYCOMMAND | five); \ MainWindow->checkMenu(IDC_SAVETYPE6, MF_BYCOMMAND | six); - - case IDC_SAVETYPE1: - saver(MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); - mmu_select_savetype(0,&backupmemorytype,&backupmemorysize); - return 0; - case IDC_SAVETYPE2: - saver(MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); - mmu_select_savetype(1,&backupmemorytype,&backupmemorysize); - return 0; - case IDC_SAVETYPE3: - saver(MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); - mmu_select_savetype(2,&backupmemorytype,&backupmemorysize); - return 0; - case IDC_SAVETYPE4: - saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED); - mmu_select_savetype(3,&backupmemorytype,&backupmemorysize); - return 0; - case IDC_SAVETYPE5: - saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED); - mmu_select_savetype(4,&backupmemorytype,&backupmemorysize); - return 0; - case IDC_SAVETYPE6: - saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED); - mmu_select_savetype(5,&backupmemorytype,&backupmemorysize); - return 0; - - case IDM_RESET: - NDS_Reset(); - frameCounter=0; - return 0; - case IDM_CONFIG: - { + + case IDC_SAVETYPE1: + saver(MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); + mmu_select_savetype(0,&backupmemorytype,&backupmemorysize); + return 0; + case IDC_SAVETYPE2: + saver(MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); + mmu_select_savetype(1,&backupmemorytype,&backupmemorysize); + return 0; + case IDC_SAVETYPE3: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); + mmu_select_savetype(2,&backupmemorytype,&backupmemorysize); + return 0; + case IDC_SAVETYPE4: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED); + mmu_select_savetype(3,&backupmemorytype,&backupmemorysize); + return 0; + case IDC_SAVETYPE5: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED); + mmu_select_savetype(4,&backupmemorytype,&backupmemorysize); + return 0; + case IDC_SAVETYPE6: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED); + mmu_select_savetype(5,&backupmemorytype,&backupmemorysize); + return 0; + + case IDM_RESET: + NDS_Reset(); + frameCounter=0; + return 0; + case IDM_CONFIG: + { bool tpaused=false; if (execute) { @@ -1955,9 +2057,9 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM InputConfig(hwnd); if (tpaused) NDS_UnPause(); - } - return 0; - case IDM_FIRMSETTINGS: + } + return 0; + case IDM_FIRMSETTINGS: { bool tpaused=false; if (execute) @@ -1971,32 +2073,32 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM return 0; } - case IDC_FRAMESKIPAUTO: - case IDC_FRAMESKIP0: - case IDC_FRAMESKIP1: - case IDC_FRAMESKIP2: - case IDC_FRAMESKIP3: - case IDC_FRAMESKIP4: - case IDC_FRAMESKIP5: - case IDC_FRAMESKIP6: - case IDC_FRAMESKIP7: - case IDC_FRAMESKIP8: - case IDC_FRAMESKIP9: - { - if(LOWORD(wParam) == IDC_FRAMESKIPAUTO) - { - autoframeskipenab = 1; - WritePrivateProfileString("Video", "FrameSkip", "AUTO", IniName); - } - else - { - char text[80]; - autoframeskipenab = 0; - frameskiprate = LOWORD(wParam) - IDC_FRAMESKIP0; - sprintf(text, "%d", frameskiprate); - WritePrivateProfileString("Video", "FrameSkip", text, IniName); - } - + case IDC_FRAMESKIPAUTO: + case IDC_FRAMESKIP0: + case IDC_FRAMESKIP1: + case IDC_FRAMESKIP2: + case IDC_FRAMESKIP3: + case IDC_FRAMESKIP4: + case IDC_FRAMESKIP5: + case IDC_FRAMESKIP6: + case IDC_FRAMESKIP7: + case IDC_FRAMESKIP8: + case IDC_FRAMESKIP9: + { + if(LOWORD(wParam) == IDC_FRAMESKIPAUTO) + { + autoframeskipenab = 1; + WritePrivateProfileString("Video", "FrameSkip", "AUTO", IniName); + } + else + { + char text[80]; + autoframeskipenab = 0; + frameskiprate = LOWORD(wParam) - IDC_FRAMESKIP0; + sprintf(text, "%d", frameskiprate); + WritePrivateProfileString("Video", "FrameSkip", text, IniName); + } + MainWindow->checkMenu(IDC_FRAMESKIPAUTO, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(IDC_FRAMESKIP0, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(IDC_FRAMESKIP1, MF_BYCOMMAND | MF_UNCHECKED); @@ -2009,32 +2111,32 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM MainWindow->checkMenu(IDC_FRAMESKIP8, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(IDC_FRAMESKIP9, MF_BYCOMMAND | MF_UNCHECKED); MainWindow->checkMenu(LOWORD(wParam), MF_BYCOMMAND | MF_CHECKED); - } - return 0; - case IDC_LANGENGLISH: - SaveLanguage(0); - ChangeLanguage(0); - CheckLanguage(LOWORD(wParam)); - return 0; - case IDC_LANGFRENCH: - SaveLanguage(1); - ChangeLanguage(1); - CheckLanguage(LOWORD(wParam)); - return 0; - case IDC_LANGDANISH: - SaveLanguage(1); - ChangeLanguage(2); - CheckLanguage(LOWORD(wParam)); - return 0; - case IDM_WEBSITE: - ShellExecute(NULL, "open", "http://desmume.sourceforge.net", NULL, NULL, SW_SHOWNORMAL); - return 0; - - case IDM_FORUM: - ShellExecute(NULL, "open", "http://forums.desmume.org/index.php", NULL, NULL, SW_SHOWNORMAL); - return 0; - - case IDM_ABOUT: + } + return 0; + case IDC_LANGENGLISH: + SaveLanguage(0); + ChangeLanguage(0); + CheckLanguage(LOWORD(wParam)); + return 0; + case IDC_LANGFRENCH: + SaveLanguage(1); + ChangeLanguage(1); + CheckLanguage(LOWORD(wParam)); + return 0; + case IDC_LANGDANISH: + SaveLanguage(1); + ChangeLanguage(2); + CheckLanguage(LOWORD(wParam)); + return 0; + case IDM_WEBSITE: + ShellExecute(NULL, "open", "http://desmume.sourceforge.net", NULL, NULL, SW_SHOWNORMAL); + return 0; + + case IDM_FORUM: + ShellExecute(NULL, "open", "http://forums.desmume.org/index.php", NULL, NULL, SW_SHOWNORMAL); + return 0; + + case IDM_ABOUT: { bool tpaused=false; if (execute) @@ -2048,192 +2150,192 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM return 0; } - -#ifndef BETA_VERSION - case IDM_SUBMITBUGREPORT: - ShellExecute(NULL, "open", "http://sourceforge.net/tracker/?func=add&group_id=164579&atid=832291", NULL, NULL, SW_SHOWNORMAL); - return 0; -#endif - - case IDC_ROTATE0: + +#ifndef BETA_VERSION + case IDM_SUBMITBUGREPORT: + ShellExecute(NULL, "open", "http://sourceforge.net/tracker/?func=add&group_id=164579&atid=832291", NULL, NULL, SW_SHOWNORMAL); + return 0; +#endif + + case IDC_ROTATE0: SetRotate(hwnd, 0); - return 0; - case IDC_ROTATE90: + return 0; + case IDC_ROTATE90: SetRotate(hwnd, 90); - return 0; - case IDC_ROTATE180: + return 0; + case IDC_ROTATE180: SetRotate(hwnd, 180); - return 0; - case IDC_ROTATE270: + return 0; + case IDC_ROTATE270: SetRotate(hwnd, 270); - return 0; - - case IDC_WINDOW1X: - windowSize=1; - ScaleScreen(hwnd, windowSize); - WritePrivateProfileInt("Video","Window Size",windowSize,IniName); - + return 0; + + case IDC_WINDOW1X: + windowSize=1; + ScaleScreen(hwnd, windowSize); + WritePrivateProfileInt("Video","Window Size",windowSize,IniName); + MainWindow->checkMenu(IDC_WINDOW1X, MF_BYCOMMAND | ((windowSize==1)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW2X, MF_BYCOMMAND | ((windowSize==2)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW3X, MF_BYCOMMAND | ((windowSize==3)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW4X, MF_BYCOMMAND | ((windowSize==4)?MF_CHECKED:MF_UNCHECKED)); - break; - case IDC_WINDOW2X: - windowSize=2; - ScaleScreen(hwnd, windowSize); - WritePrivateProfileInt("Video","Window Size",windowSize,IniName); - + break; + case IDC_WINDOW2X: + windowSize=2; + ScaleScreen(hwnd, windowSize); + WritePrivateProfileInt("Video","Window Size",windowSize,IniName); + MainWindow->checkMenu(IDC_WINDOW1X, MF_BYCOMMAND | ((windowSize==1)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW2X, MF_BYCOMMAND | ((windowSize==2)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW3X, MF_BYCOMMAND | ((windowSize==3)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW4X, MF_BYCOMMAND | ((windowSize==4)?MF_CHECKED:MF_UNCHECKED)); - break; - case IDC_WINDOW3X: - windowSize=3; - ScaleScreen(hwnd, windowSize); - WritePrivateProfileInt("Video","Window Size",windowSize,IniName); - + break; + case IDC_WINDOW3X: + windowSize=3; + ScaleScreen(hwnd, windowSize); + WritePrivateProfileInt("Video","Window Size",windowSize,IniName); + MainWindow->checkMenu(IDC_WINDOW1X, MF_BYCOMMAND | ((windowSize==1)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW2X, MF_BYCOMMAND | ((windowSize==2)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW3X, MF_BYCOMMAND | ((windowSize==3)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW4X, MF_BYCOMMAND | ((windowSize==4)?MF_CHECKED:MF_UNCHECKED)); - break; - case IDC_WINDOW4X: - windowSize=4; - ScaleScreen(hwnd, windowSize); - WritePrivateProfileInt("Video","Window Size",windowSize,IniName); - + break; + case IDC_WINDOW4X: + windowSize=4; + ScaleScreen(hwnd, windowSize); + WritePrivateProfileInt("Video","Window Size",windowSize,IniName); + MainWindow->checkMenu(IDC_WINDOW1X, MF_BYCOMMAND | ((windowSize==1)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW2X, MF_BYCOMMAND | ((windowSize==2)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW3X, MF_BYCOMMAND | ((windowSize==3)?MF_CHECKED:MF_UNCHECKED)); MainWindow->checkMenu(IDC_WINDOW4X, MF_BYCOMMAND | ((windowSize==4)?MF_CHECKED:MF_UNCHECKED)); - break; - - case IDC_FORCERATIO: - if (ForceRatio) { + break; + + case IDC_FORCERATIO: + if (ForceRatio) { MainWindow->checkMenu(IDC_FORCERATIO, MF_BYCOMMAND | MF_UNCHECKED); - ForceRatio = FALSE; - WritePrivateProfileInt("Video","Window Force Ratio",0,IniName); - } - else { - RECT fullSize; - GetWindowRect(hwnd, &fullSize); - ScallingScreen(hwnd, WMSZ_RIGHT, &fullSize); - SetWindowPos(hwnd, NULL, 0, 0, fullSize.right - fullSize.left, - fullSize.bottom - fullSize.top, SWP_NOMOVE | SWP_NOZORDER); - //ScaleScreen(hwnd, (fullSize.bottom - fullSize.top - heightTradeOff) / DefaultHeight); + ForceRatio = FALSE; + WritePrivateProfileInt("Video","Window Force Ratio",0,IniName); + } + else { + RECT fullSize; + GetWindowRect(hwnd, &fullSize); + ScallingScreen(hwnd, WMSZ_RIGHT, &fullSize); + SetWindowPos(hwnd, NULL, 0, 0, fullSize.right - fullSize.left, + fullSize.bottom - fullSize.top, SWP_NOMOVE | SWP_NOZORDER); + //ScaleScreen(hwnd, (fullSize.bottom - fullSize.top - heightTradeOff) / DefaultHeight); MainWindow->checkMenu(IDC_FORCERATIO, MF_BYCOMMAND | MF_CHECKED); - ForceRatio = TRUE; - WritePrivateProfileInt("Video","Window Force Ratio",1,IniName); - } - break; - - } - return 0; - default: /* for messages that we don't deal with */ - return DefWindowProc (hwnd, message, wParam, lParam); - } - - return 0; -} - -LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, - LPARAM lParam) -{ - static int timerid=0; - switch (uMsg) - { - case WM_INITDIALOG: - { - int i; - char tempstr[MAX_PATH]; - // Setup Sound Core Combo box - SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_RESETCONTENT, 0, 0); - SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_ADDSTRING, 0, (LPARAM)"None"); - - for (i = 1; SNDCoreList[i] != NULL; i++) - SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_ADDSTRING, 0, (LPARAM)SNDCoreList[i]->Name); - - // Set Selected Sound Core - for (i = 0; SNDCoreList[i] != NULL; i++) - { - if (sndcoretype == SNDCoreList[i]->id) - SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_SETCURSEL, i, 0); - } - - // Setup Sound Buffer Size Edit Text - sprintf(tempstr, "%d", sndbuffersize); - SetDlgItemText(hDlg, IDC_SOUNDBUFFERET, tempstr); - - // Setup Volume Slider - SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_SETRANGE, 0, MAKELONG(0, 100)); - - // Set Selected Volume - SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_SETPOS, TRUE, sndvolume); - - timerid = SetTimer(hDlg, 1, 500, NULL); - return TRUE; - } - case WM_TIMER: - { - if (timerid == wParam) - { - int setting; - setting = SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_GETPOS, 0, 0); - SPU_SetVolume(setting); - break; - } - break; - } - case WM_COMMAND: - { - switch (LOWORD(wParam)) - { - case IDOK: - { - char tempstr[MAX_PATH]; - - EndDialog(hDlg, TRUE); - - // Write Sound core type - sndcoretype = SNDCoreList[SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_GETCURSEL, 0, 0)]->id; - sprintf(tempstr, "%d", sndcoretype); - WritePrivateProfileString("Sound", "SoundCore", tempstr, IniName); - - // Write Sound Buffer size - GetDlgItemText(hDlg, IDC_SOUNDBUFFERET, tempstr, 6); - sscanf(tempstr, "%d", &sndbuffersize); - WritePrivateProfileString("Sound", "SoundBufferSize", tempstr, IniName); - - SPU_ChangeSoundCore(sndcoretype, sndbuffersize); - - // Write Volume - sndvolume = SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_GETPOS, 0, 0); - sprintf(tempstr, "%d", sndvolume); - WritePrivateProfileString("Sound", "Volume", tempstr, IniName); - SPU_SetVolume(sndvolume); - - return TRUE; - } - case IDCANCEL: - { - EndDialog(hDlg, FALSE); - return TRUE; - } - default: break; - } - - break; - } - case WM_DESTROY: - { - if (timerid != 0) - KillTimer(hDlg, timerid); - break; - } - } - - return FALSE; -} - - + ForceRatio = TRUE; + WritePrivateProfileInt("Video","Window Force Ratio",1,IniName); + } + break; + + } + return 0; + default: /* for messages that we don't deal with */ + return DefWindowProc (hwnd, message, wParam, lParam); + } + + return 0; +} + +LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, + LPARAM lParam) +{ + static int timerid=0; + switch (uMsg) + { + case WM_INITDIALOG: + { + int i; + char tempstr[MAX_PATH]; + // Setup Sound Core Combo box + SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_ADDSTRING, 0, (LPARAM)"None"); + + for (i = 1; SNDCoreList[i] != NULL; i++) + SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_ADDSTRING, 0, (LPARAM)SNDCoreList[i]->Name); + + // Set Selected Sound Core + for (i = 0; SNDCoreList[i] != NULL; i++) + { + if (sndcoretype == SNDCoreList[i]->id) + SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_SETCURSEL, i, 0); + } + + // Setup Sound Buffer Size Edit Text + sprintf(tempstr, "%d", sndbuffersize); + SetDlgItemText(hDlg, IDC_SOUNDBUFFERET, tempstr); + + // Setup Volume Slider + SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_SETRANGE, 0, MAKELONG(0, 100)); + + // Set Selected Volume + SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_SETPOS, TRUE, sndvolume); + + timerid = SetTimer(hDlg, 1, 500, NULL); + return TRUE; + } + case WM_TIMER: + { + if (timerid == wParam) + { + int setting; + setting = SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_GETPOS, 0, 0); + SPU_SetVolume(setting); + break; + } + break; + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDOK: + { + char tempstr[MAX_PATH]; + + EndDialog(hDlg, TRUE); + + // Write Sound core type + sndcoretype = SNDCoreList[SendDlgItemMessage(hDlg, IDC_SOUNDCORECB, CB_GETCURSEL, 0, 0)]->id; + sprintf(tempstr, "%d", sndcoretype); + WritePrivateProfileString("Sound", "SoundCore", tempstr, IniName); + + // Write Sound Buffer size + GetDlgItemText(hDlg, IDC_SOUNDBUFFERET, tempstr, 6); + sscanf(tempstr, "%d", &sndbuffersize); + WritePrivateProfileString("Sound", "SoundBufferSize", tempstr, IniName); + + SPU_ChangeSoundCore(sndcoretype, sndbuffersize); + + // Write Volume + sndvolume = SendDlgItemMessage(hDlg, IDC_SLVOLUME, TBM_GETPOS, 0, 0); + sprintf(tempstr, "%d", sndvolume); + WritePrivateProfileString("Sound", "Volume", tempstr, IniName); + SPU_SetVolume(sndvolume); + + return TRUE; + } + case IDCANCEL: + { + EndDialog(hDlg, FALSE); + return TRUE; + } + default: break; + } + + break; + } + case WM_DESTROY: + { + if (timerid != 0) + KillTimer(hDlg, timerid); + break; + } + } + + return FALSE; +} + + diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index c2d52aa44..d926b338e 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -324,13 +324,17 @@ #define ID_VIEW_DISPLAYFPS 40010 #define ID_VIS_DISPLAYFPS 40011 #define ID_VIEW_DISPLAYFPS40012 40012 +#define ID_FILE_RECORDAVI 40013 +#define ID_FILE_STOPAVI 40014 +#define IDM_FILE_RECORDAVI 40015 +#define IDM_FILE_STOPAVI 40016 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 107 -#define _APS_NEXT_COMMAND_VALUE 40013 +#define _APS_NEXT_COMMAND_VALUE 40017 #define _APS_NEXT_CONTROL_VALUE 1013 #define _APS_NEXT_SYMED_VALUE 112 #endif diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index 6325e3be3..f33d8cc4b 100644 --- a/desmume/src/windows/resources.rc +++ b/desmume/src/windows/resources.rc @@ -706,6 +706,9 @@ BEGIN MENUITEM "Save Screenshot &As", IDM_PRINTSCREEN MENUITEM "&Quick Screenshot", IDM_QUICK_PRINTSCREEN MENUITEM SEPARATOR + MENUITEM "Record AVI", IDM_FILE_RECORDAVI + MENUITEM "Stop AVI", IDM_FILE_STOPAVI + MENUITEM SEPARATOR MENUITEM "&Quit", IDM_QUIT END POPUP "&Emulation" diff --git a/desmume/src/windows/snddx.cpp b/desmume/src/windows/snddx.cpp index bf176991a..6f1026943 100755 --- a/desmume/src/windows/snddx.cpp +++ b/desmume/src/windows/snddx.cpp @@ -65,6 +65,23 @@ static int issoundmuted; ////////////////////////////////////////////////////////////////////////////// +static volatile bool terminate; +static volatile bool terminated; + +extern CRITICAL_SECTION win_sync; +extern volatile int win_sound_samplecounter; + +DWORD WINAPI SNDDXThread( LPVOID lpParameter) +{ + for(;;) { + if(terminate) break; + SPU_Emulate_user(); + Sleep(10); + } + terminated = true; + return 0; +} + int SNDDXInit(int buffersize) { DSBUFFERDESC dsbdesc; @@ -161,6 +178,10 @@ int SNDDXInit(int buffersize) soundvolume = DSBVOLUME_MAX; issoundmuted = 0; + terminate = false; + terminated = false; + CreateThread(0,0,SNDDXThread,0,0,0); + return 0; } @@ -169,6 +190,11 @@ int SNDDXInit(int buffersize) void SNDDXDeInit() { DWORD status=0; + + terminate = true; + while(!terminated) { + Sleep(1); + } if (lpDSB2) { @@ -203,6 +229,11 @@ void SNDDXUpdateAudio(s16 *buffer, u32 num_samples) DWORD buffer1_size, buffer2_size; DWORD status; + EnterCriticalSection(&win_sync); + int samplecounter = win_sound_samplecounter -= num_samples; + LeaveCriticalSection(&win_sync); + bool silence = (samplecounter<-44100*15/60); //behind by more than a quarter second -> silence + IDirectSoundBuffer8_GetStatus(lpDSB2, &status); if (status & DSBSTATUS_BUFFERLOST) @@ -210,9 +241,17 @@ void SNDDXUpdateAudio(s16 *buffer, u32 num_samples) 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, ((u8 *)buffer)+buffer1_size, buffer2_size); + if(silence) { + memset(buffer1, 0, buffer1_size); + if(buffer2) + memset(buffer2, 0, buffer2_size); + } + else + { + memcpy(buffer1, buffer, buffer1_size); + if (buffer2) + memcpy(buffer2, ((u8 *)buffer)+buffer1_size, buffer2_size); + } soundoffset += buffer1_size + buffer2_size; soundoffset %= soundbufsize; diff --git a/desmume/src/windows/windriver.h b/desmume/src/windows/windriver.h new file mode 100644 index 000000000..fe3b16119 --- /dev/null +++ b/desmume/src/windows/windriver.h @@ -0,0 +1,10 @@ +#ifndef _WINDRIVER_H_ +#define _WINDRIVER_H_ + +#define WIN32_LEAN_AND_MEAN +#include +#include "CWindow.h" + +extern WINCLASS *MainWindow; + +#endif \ No newline at end of file