diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 4a8c7e091..b3fdaf9c2 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -29,9 +29,12 @@ #include #include +#include "common.h" #include "debug.h" #include "NDSSystem.h" +#ifndef EXPERIMENTAL_GBASLOT #include "cflash.h" +#endif #include "cp15.h" #include "wifi.h" #include "registers.h" @@ -40,6 +43,7 @@ #include "rtc.h" #include "GPU_osd.h" #include "mc.h" +#include "addons.h" #ifdef DO_ASSERT_UNALIGNED #define ASSERT_UNALIGNED(x) assert(x) @@ -341,6 +345,7 @@ const static u32 LCDdata[10][2]= { {0, 0}, {0x6898000, 2}, // Bank H {0x68A0000, 1}}; // Bank I +u8 VRAM_blockEnabled[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0 }; void MMU_Init(void) { int i; @@ -374,6 +379,8 @@ void MMU_Init(void) { mc_alloc(&MMU.bupmem, 1); MMU.bupmem.fp = NULL; rtcInit(); + memset(VRAM_blockEnabled, 0, sizeof(VRAM_blockEnabled)); + addonsInit(); } void MMU_DeInit(void) { @@ -384,6 +391,7 @@ void MMU_DeInit(void) { if (MMU.bupmem.fp) fclose(MMU.bupmem.fp); mc_free(&MMU.bupmem); + addonsClose(); } //Card rom & ram @@ -499,6 +507,8 @@ void MMU_clearMem() } rtcInit(); partie = 1; + memset(VRAM_blockEnabled, 0, sizeof(VRAM_blockEnabled)); + addonsReset(); } // VRAM mapping control @@ -518,11 +528,11 @@ u8 *MMU_RenderMapToLCD(u32 vram_addr) u8 engine_offset = (vram_addr >> 14); u8 block = MMU.VRAM_MAP[engine][engine_offset]; if (block == 7) return (EngineAddr[engine] + vram_addr); // not mapped to LCD + if (!VRAM_blockEnabled[block]) return NULL; vram_addr -= MMU.LCD_VRAM_ADDR[block]; return (LCDdst[block] + vram_addr); } -extern void NDS_Pause(); static FORCEINLINE u32 MMU_LCDmap(u32 addr) { if ((addr < 0x6000000)) return addr; @@ -541,7 +551,6 @@ static FORCEINLINE u32 MMU_LCDmap(u32 addr) u8 engine_offset = (addr >> 14); u8 block = MMU.VRAM_MAP[engine][engine_offset]; if (block == 7) return (save_addr); // not mapped to LCD - addr -= MMU.LCD_VRAM_ADDR[block]; return (addr + LCDdata[block][0]); } @@ -549,7 +558,11 @@ static FORCEINLINE u32 MMU_LCDmap(u32 addr) static inline void MMU_VRAMmapControl(u8 block, u8 VRAMBankCnt) { - if (!(VRAMBankCnt & 0x80)) return; + if ( !(VRAMBankCnt & 0x80) && (VRAMBankCnt & 0x07) ) + { + VRAM_blockEnabled[block] = 0; + return; + } if (!(VRAMBankCnt & 0x07)) return; for (int i = 0; i < 4; i++) @@ -725,10 +738,12 @@ static inline void MMU_VRAMmapControl(u8 block, u8 VRAMBankCnt) //INFO("VRAM %i mapping: eng=%i (offs=%i, size=%i), addr = 0x%X, MST=%i (faddr 0x%X)\n", // block, engine, engine_offset, LCDdata[block][1]*0x4000, MMU.LCD_VRAM_ADDR[block], VRAMBankCnt & 0x07, // vr + 0x6000000); + VRAM_blockEnabled[block] = 1; return; } MMU.LCDCenable[block] = FALSE; + VRAM_blockEnabled[block] = 0; } void MMU_setRom(u8 * rom, u32 mask) @@ -1451,7 +1466,7 @@ struct armcpu_memory_iface arm9_direct_memory_iface = { static INLINE void MMU_IPCSync(u8 proc, u32 val) { //INFO("IPC%s sync 0x%08X\n", proc?"7":"9", val); - u32 IPCSYNC_local = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x180) & 0xFFFF; + u32 IPCSYNC_local = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x180); u32 IPCSYNC_remote = T1ReadLong(MMU.MMU_MEM[proc^1][0x40], 0x180); IPCSYNC_local = (IPCSYNC_local&0x6000)|(val&0xf00)|(IPCSYNC_local&0xf); @@ -1461,7 +1476,7 @@ static INLINE void MMU_IPCSync(u8 proc, u32 val) T1WriteLong(MMU.MMU_MEM[proc^1][0x40], 0x180, IPCSYNC_remote); if ((val & 0x2000) && (IPCSYNC_remote & 0x4000)) - NDS_makeInt(proc^1, 17); + MMU.reg_IF[proc^1] |= ( 1<<17 ); } //================================================================================================== ARM9 * @@ -1484,11 +1499,19 @@ static void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) return ; } +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + { + addon.write08(adr, val); + return; + } +#else // CFlash writing, Mic if ((adr>=0x9000000)&&(adr<0x9900000)) { cflash_write(adr,val); return; } +#endif adr &= 0x0FFFFFFF; @@ -1670,12 +1693,20 @@ static void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) return ; } +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + { + addon.write16(adr, val); + return; + } +#else // CFlash writing, Mic if ((adr>=0x08800000)&&(adr<0x09900000)) { cflash_write(adr,val); return; } +#endif adr &= 0x0FFFFFFF; @@ -2213,12 +2244,20 @@ static void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) T1WriteLong(ARM9Mem.ARM9_ITCM, adr&0x7FFF, val); return ; } - + +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + { + addon.write32(adr, val); + return; + } +#else // CFlash writing, Mic if ((adr>=0x9000000) && (adr<0x9900000)) { cflash_write(adr,val); return; } +#endif adr &= 0x0FFFFFFF; @@ -2709,13 +2748,21 @@ static u8 FASTCALL _MMU_ARM9_read08(u32 adr) if(adr<0x02000000) return T1ReadByte(ARM9Mem.ARM9_ITCM, adr&0x7FFF); +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + return addon.read08(adr); +#else // CFlash reading, Mic if ((adr>=0x9000000)&&(adr<0x9900000)) return (unsigned char)cflash_read(adr); +#endif + #ifdef _MMU_DEBUG mmu_log_debug_ARM9(adr, "(read08) %0x%X", MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF][adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]]); #endif + if ( (adr >= 0xFFFF0020) && (adr <= 0xFFFF00BC) ) + INFO("Read08 at 0x%08X\n", adr); adr = MMU_LCDmap(adr); @@ -2732,10 +2779,17 @@ static u16 FASTCALL _MMU_ARM9_read16(u32 adr) if(adr<0x02000000) return T1ReadWord(ARM9Mem.ARM9_ITCM, adr & 0x7FFF); - + +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + return addon.read16(adr); +#else // CFlash reading, Mic if ((adr>=0x08800000) && (adr<0x09900000)) return (unsigned short)cflash_read(adr); +#endif + if ( (adr >= 0xFFFF0020) && (adr <= 0xFFFF00BC) ) + INFO("Read16 at 0x%08X - 0x%04X\n", adr, T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]) ); adr &= 0x0FFFFFFF; @@ -2797,11 +2851,16 @@ static u32 FASTCALL _MMU_ARM9_read32(u32 adr) if(adr<0x02000000) return T1ReadLong(ARM9Mem.ARM9_ITCM, adr&0x7FFF); - + +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + return addon.read32(adr); +#else // CFlash reading, Mic if ((adr>=0x9000000) && (adr<0x9900000)) return (unsigned long)cflash_read(adr); - +#endif + adr &= 0x0FFFFFFF; // Address is an IO register @@ -2931,12 +2990,20 @@ static u32 FASTCALL _MMU_ARM9_read32(u32 adr) //================================================= MMU ARM7 write 08 static void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val) { +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + { + addon.write08(adr, val); + return; + } +#else // CFlash writing, Mic if ((adr>=0x9000000)&&(adr<0x9900000)) { cflash_write(adr,val); return; } +#endif adr &= 0x0FFFFFFF; // This is bad, remove it @@ -2967,12 +3034,20 @@ static void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val) //================================================= MMU ARM7 write 16 static void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) { +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + { + addon.write16(adr, val); + return; + } +#else // CFlash writing, Mic if ((adr>=0x08800000)&&(adr<0x09900000)) { cflash_write(adr,val); return; } +#endif #ifdef EXPERIMENTAL_WIFI @@ -3000,7 +3075,7 @@ static void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) /* Address is an IO register */ switch(adr) { - case REG_EXMEMCNT: + case REG_EXMEMCNT: { u16 oldval = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0x7F) | (oldval & 0xFF80)); @@ -3354,11 +3429,20 @@ static void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) //================================================= MMU ARM7 write 32 static void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val) { +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + { + addon.write32(adr, val); + return; + } +#else // CFlash writing, Mic if ((adr>=0x9000000)&&(adr<0x9900000)) { cflash_write(adr,val); return; } +#endif + #ifdef EXPERIMENTAL_WIFI if ((adr & 0xFF800000) == 0x04800000) @@ -3609,9 +3693,14 @@ static u8 FASTCALL _MMU_ARM7_read08(u32 adr) } #endif +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + return addon.read08(adr); +#else // CFlash reading, Mic if ((adr>=0x9000000)&&(adr<0x9900000)) return (unsigned char)cflash_read(adr); +#endif if (adr == REG_RTC) return rtcRead(); @@ -3624,16 +3713,21 @@ static u8 FASTCALL _MMU_ARM7_read08(u32 adr) } //================================================= MMU ARM7 read 16 static u16 FASTCALL _MMU_ARM7_read16(u32 adr) -{ +{ #ifdef EXPERIMENTAL_WIFI /* wifi mac access */ if ((adr>=0x04800000)&&(adr<0x05000000)) return WIFI_read16(&wifiMac,adr) ; #endif +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + return addon.read16(adr); +#else // CFlash reading, Mic if ((adr>=0x08800000)&&(adr<0x09900000)) return (unsigned short)cflash_read(adr); +#endif adr &= 0x0FFFFFFF; @@ -3677,9 +3771,15 @@ static u16 FASTCALL _MMU_ARM7_read16(u32 adr) //================================================= MMU ARM7 read 32 static u32 FASTCALL _MMU_ARM7_read32(u32 adr) { +#ifdef EXPERIMENTAL_GBASLOT + if ( (adr >= 0x08000000) && (adr < 0x0A000000) ) + return addon.read32(adr); +#else // CFlash reading, Mic if ((adr>=0x9000000)&&(adr<0x9900000)) return (unsigned long)cflash_read(adr); +#endif + adr &= 0x0FFFFFFF; if((adr >> 24) == 4) diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 6105cf4b3..a5cd9090a 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -23,13 +23,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include +#include "common.h" #include "NDSSystem.h" #include "render3D.h" #include "MMU.h" +#ifndef EXPERIMENTAL_GBASLOT #include "cflash.h" - -#include "MMU.h" -#include "cflash.h" +#endif #include "ROMReader.h" #include "gfx3d.h" #include "utils/decrypt/decrypt.h" @@ -334,8 +334,12 @@ static u32 ones32(u32 x) } #endif +#ifdef EXPERIMENTAL_GBASLOT +int NDS_LoadROM( const char *filename, int bmtype, u32 bmsize) +#else int NDS_LoadROM( const char *filename, int bmtype, u32 bmsize, const char *cflash_disk_image_file) +#endif { int i; int type; @@ -414,16 +418,21 @@ int NDS_LoadROM( const char *filename, int bmtype, u32 bmsize, #ifndef WORDS_BIGENDIAN DecryptSecureArea(data,size); #endif + for (int t = strlen(filename); t>0; t--) + if ( (filename[t] == '\\') || (filename[t] == '/') ) + { + strncpy(szRomPath, filename, t+1); + break; + } MMU_unsetRom(); NDS_SetROM(data, mask); NDS_Reset(); - /* I guess any directory can be used - * so the current one should be ok */ - strncpy(szRomPath, ".", ARRAY_SIZE(szRomPath)); +#ifndef EXPERIMENTAL_GBASLOT cflash_close(); cflash_init( cflash_disk_image_file); +#endif strncpy(szRomBaseName, filename, ARRAY_SIZE(szRomBaseName)); @@ -579,6 +588,7 @@ void NDS_Reset( void) inf = fopen("BiosNds9.ROM","rb"); #else inf = NULL; + //memcpy(ARM9Mem.ARM9_BIOS + 0x20, gba_header_data_0x04, 156); #endif if(inf) { fread(ARM9Mem.ARM9_BIOS,1,4096,inf); diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 9150e2337..84d3a4995 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -194,8 +194,12 @@ void NDS_releaseTouch(void); void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,bool X,bool W,bool E,bool G, bool F); void NDS_setPadFromMovie(u16 pad); +#ifdef EXPERIMENTAL_GBASLOT +int NDS_LoadROM(const char *filename, int bmtype, u32 bmsize); +#else int NDS_LoadROM(const char *filename, int bmtype, u32 bmsize, const char *cflash_disk_image_file); +#endif void NDS_FreeROM(void); void NDS_Reset(void); int NDS_ImportSave(const char *filename); diff --git a/desmume/src/addons.cpp b/desmume/src/addons.cpp new file mode 100644 index 000000000..22b7ec5b6 --- /dev/null +++ b/desmume/src/addons.cpp @@ -0,0 +1,71 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2009 DeSmuME team + + 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 "addons.h" + +char CFlashName[MAX_PATH]; +char CFlashPath[MAX_PATH]; +u8 CFlashUseRomPath = TRUE; +u8 CFlashUsePath = TRUE; + +char GBAgameName[MAX_PATH]; + +extern ADDONINTERFACE addonNone; +extern ADDONINTERFACE addonCFlash; +extern ADDONINTERFACE addonRumblePak; +extern ADDONINTERFACE addonGBAgame; +//extern ADDONINTERFACE addonExternalMic; + +ADDONINTERFACE addonList[NDS_ADDON_COUNT] = { + addonNone, + addonCFlash, + addonRumblePak, + addonGBAgame}; + +ADDONINTERFACE addon = addonCFlash; // default none pak +u8 addon_type = NDS_ADDON_CFLASH; + +BOOL addonsInit() +{ + return addon.init(); +} + +void addonsClose() +{ + addon.close(); +} + +void addonsReset() +{ + addon.reset(); +} + +BOOL addonsChangePak(u8 type) +{ + if (type > NDS_ADDON_COUNT) return FALSE; + addon.close(); + addon = addonList[type]; + addon_type = type; + return addon.init(); +} + diff --git a/desmume/src/addons.h b/desmume/src/addons.h new file mode 100644 index 000000000..a5018bb56 --- /dev/null +++ b/desmume/src/addons.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2009 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __ADDONS_H__ +#define __ADDONS_H__ + +#include "common.h" +#include "types.h" +#include "debug.h" + +typedef struct +{ + // The name of the plugin, this name will appear in the plugins list + const char * name; + + //called once when the plugin starts up + BOOL (*init)(void); + + //called when the emulator resets + void (*reset)(void); + + //called when the plugin shuts down + void (*close)(void); + + //called when the user configurating plugin + void (*config)(void); + + //called when the emulator write to addon + void (*write08)(u32 adr, u8 val); + void (*write16)(u32 adr, u16 val); + void (*write32)(u32 adr, u32 val); + + //called when the emulator read from addon + u8 (*read08)(u32 adr); + u16 (*read16)(u32 adr); + u32 (*read32)(u32 adr); + + //called when the user get info about addon pak (description) + void (*info)(char *info); +} ADDONINTERFACE; + +enum { + NDS_ADDON_NONE, + NDS_ADDON_CFLASH, // compact flash + NDS_ADDON_RUMBLEPAK, // rumble pack + NDS_ADDON_GBAGAME, // gba game in slot + //NDS_ADDON_EXTERNALMIC, + NDS_ADDON_COUNT // use for counter addons - MUST TO BE LAST!!! +}; + +extern ADDONINTERFACE addon; // current pak +extern ADDONINTERFACE addonList[NDS_ADDON_COUNT]; // lists pointer on paks +extern u8 addon_type; // current type pak + +extern char CFlashName[MAX_PATH]; // path to compact flash img file +extern char CFlashPath[MAX_PATH]; // path to compact flash directory +extern u8 CFlashUsePath; // true is used path from CFlashPath for cflash folder +extern u8 CFlashUseRomPath; // true is used path to rom file for cflash folder +extern char GBAgameName[MAX_PATH]; // file name for GBA game (rom) + +extern BOOL addonsInit(); // Init addons +extern void addonsClose(); // Shutdown addons +extern void addonsReset(); // Reset addon +extern BOOL addonsChangePak(u8 type); // change current adddon + +#endif \ No newline at end of file diff --git a/desmume/src/addons/compactFlash.cpp b/desmume/src/addons/compactFlash.cpp new file mode 100644 index 000000000..79c503964 --- /dev/null +++ b/desmume/src/addons/compactFlash.cpp @@ -0,0 +1,1034 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2009 DeSmuME team + + 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 "../addons.h" +#ifdef EXPERIMENTAL_GBASLOT + +#define DEBUG +#define CFLASHDEBUG + +#include "debug.h" +#include +#include +#include +#include + +#include +#include +#ifdef WIN32 +#include +#define OPEN_MODE _O_RDWR | _O_BINARY + +#define OPEN_FN _open +#define CLOSE_FN _close +#define LSEEK_FN _lseek +#define WRITE_FN _write +#define READ_FN _read +#else +#include +#define OPEN_MODE O_RDWR + +#define OPEN_FN open +#define CLOSE_FN close +#define LSEEK_FN lseek +#define WRITE_FN write +#define READ_FN read +#endif + +#include "types.h" +#include "../fat.h" +#include "../fs.h" +#include "MMU.h" +#include "NDSSystem.h" + +typedef struct { + int level,parent,filesInDir; +} FILE_INFO; + +// Set up addresses for GBAMP +#define CF_REG_DATA 0x9000000 +#define CF_REG_ERR 0x9020000 +#define CF_REG_SEC 0x9040000 +#define CF_REG_LBA1 0x9060000 +#define CF_REG_LBA2 0x9080000 +#define CF_REG_LBA3 0x90A0000 +#define CF_REG_LBA4 0x90C0000 +#define CF_REG_CMD 0x90E0000 +#define CF_REG_STS 0x98C0000 + +// CF Card commands +#define CF_CMD_LBA 0xE0 +#define CF_CMD_READ 0x20 +#define CF_CMD_WRITE 0x30 + +static int disk_image = -1; +static off_t file_size; + +static u16 cf_reg_sts, + cf_reg_lba1, + cf_reg_lba2, + cf_reg_lba3, + cf_reg_lba4, + cf_reg_cmd; +static off_t currLBA; + +static const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; + +#define SECPERFAT 128 +#define SECPERCLUS 16 +#define MAXFILES 32768 +#define SECRESV 2 +#define NUMSECTORS 0x80000 +#define NUMCLUSTERS (NUMSECTORS/SECPERCLUS) +#define BYTESPERCLUS (512*SECPERCLUS) +#define DIRENTSPERCLUS ((BYTESPERCLUS)/32) + +static BOOT_RECORD MBR; +static DIR_ENT *files,*dirEntries,**dirEntryPtr; +static FILE_INFO *fileLink,*dirEntryLink; +static u32 filesysFAT,filesysRootDir,filesysData; +static u16 FAT16[SECPERFAT*256]; +static u16 numExtraEntries[SECPERFAT*256]; +static DIR_ENT *extraDirEntries[SECPERFAT*256]; +static int numFiles,maxLevel,numRootFiles; +static int *dirEntriesInCluster, clusterNum, firstDirEntCluster, + lastDirEntCluster, lastFileDataCluster; +static char *sRomPath; +static int activeDirEnt=-1; +static u32 bufferStart; +static u32 fileStartLBA,fileEndLBA; +static u16 freadBuffer[256]; +static FILE * hFile; +static char fpath[255+1]; +static BOOL cflashDeviceEnabled = FALSE; + +// =========================== +BOOL inited; + +static int lfn_checksum( void) +{ + int i; + u8 chk = 0; + + for (i=0; i < (NAME_LEN + EXT_LEN); i++) + { + chk = ((chk & 1) ? 0x80 : 0) + (chk >> 1) + + (i < NAME_LEN ? files[numFiles].name[i] : files[numFiles].ext[i - NAME_LEN]); + } + return chk; +} + +// Add a DIR_ENT for the files +static void add_file(char *fname, FsEntry * entry, int fileLevel) +{ + int i,j,k,n; + u8 chk; + + if (numFiles < MAXFILES-1) + { + if (strcmp(fname,"..") != 0) + { + for (i=strlen(fname)-1; i>=0; i--) + if (fname[i]=='.') break; + if ((i==0)&&(strcmp(fname,".")==0)) i = 1; + if (i<0) i = strlen(fname); + for (j=0; j=strlen(fname)) break; + files[numFiles].ext[j] = fname[j+i+1]; + } + for (; j<3; j++) + files[numFiles].ext[j] = 0x20; + + fileLink[fileLevel].filesInDir += 1; + + // See if LFN entries need to be added + if (strlen(entry->cAlternateFileName)>0) + { + char *p = NULL; + + chk = lfn_checksum(); + k = (strlen(entry->cFileName)/13) + (((strlen(entry->cFileName)%13)!=0)?1:0); + numFiles += k; + + fileLink[fileLevel].filesInDir += k; + + n = 0; + j = 13; + for (i=0; (size_t)icFileName); i++) + { + if (j == 13) + { + n++; + p = (char*)&files[numFiles-n].name[0]; + fileLink[numFiles-n].parent = fileLevel; + p[0] = n; + ((DIR_ENT*)p)->attrib = ATTRIB_LFN; + p[0xD] = chk; + j = 0; + } + *(p + lfnPos[j]) = entry->cFileName[i]; + *(p + lfnPos[j]+1) = 0; + j++; + } + for (; j<13; j++) + { + *(p + lfnPos[j]) = entry->cFileName[i]; + *(p + lfnPos[j]+1) = 0; + } + if (p != NULL) + p[0] |= 0x40; // END + for (i=strlen(fname)-1; i>=0; i--) + if (fname[i]=='.') break; + if ((i==0)&&(strcmp(fname,".")==0)) i = 1; + if (i<0) i = strlen(fname); + for (j=0; j=strlen(fname)) break; + files[numFiles].ext[j] = fname[j+i+1]; + } + for (; j<3; j++) + files[numFiles].ext[j] = 0x20; + } + + files[numFiles].fileSize = entry->fileSize; + + if (entry->flags & FS_IS_DIR) + { + if (strcmp(fname,".")==0) + fileLink[numFiles].level = maxLevel; + else + fileLink[numFiles].level = maxLevel+1; + files[numFiles].attrib = ATTRIB_DIR; + } + else + files[numFiles].attrib = 0; + + fileLink[numFiles].parent = fileLevel; + + numFiles++; + } + else + if (fileLevel > 0) + { + fileLink[fileLevel].filesInDir += 1; + strncpy((char*)&files[numFiles].name[0],".. ",NAME_LEN); + strncpy((char*)&files[numFiles].ext[0]," ",EXT_LEN); + fileLink[numFiles].parent = fileLevel; + files[numFiles].attrib = 0x10; + numFiles++; + } + } +} + +// List all files and subdirectories recursively +static void list_files(const char *filepath) +{ + char DirSpec[255+1], SubDir[255+1]; + FsEntry entry; + void * hFind; + char *fname; + u32 dwError; + int fileLevel; + + maxLevel++; + fileLevel = maxLevel; + + strncpy(DirSpec, filepath, ARRAY_SIZE(DirSpec)); + DirSpec[255] = 0 ; // hard limit the string here + + hFind = FsReadFirst(DirSpec, &entry); + if (hFind == NULL) return; + + fname = (strlen(entry.cAlternateFileName)>0) ? entry.cAlternateFileName : entry.cFileName; + add_file(fname, &entry, fileLevel); + + while (FsReadNext(hFind, &entry) != 0) + { + fname = (strlen(entry.cAlternateFileName)>0) ? entry.cAlternateFileName : entry.cFileName; + add_file(fname, &entry, fileLevel); + + if (numFiles==MAXFILES-1) break; + + if ((entry.flags & FS_IS_DIR) && (strcmp(fname, ".")) && (strcmp(fname, ".."))) + { + if (strlen(fname)+strlen(filepath)+2 < 256) + { + sprintf(SubDir, "%s%c%s", filepath, FS_SEPARATOR, fname); + list_files(SubDir); + } + } + } + + dwError = FsError(); + FsClose(hFind); + if (dwError != FS_ERR_NO_MORE_FILES) return; + + if (numFiles < MAXFILES) + { + fileLink[numFiles].parent = fileLevel; + files[numFiles++].name[0] = 0; + } +} + +// Set up the MBR, FAT and DIR_ENTs +static BOOL cflash_build_fat( void) +{ + int i,j,k,l, + clust,numClusters, + clusterNum2,rootCluster; + int fileLevel; + + numFiles = 0; + fileLevel = -1; + maxLevel = -1; + + if (CFlashUseRomPath) + sRomPath = szRomPath; // From MMU.cpp + else + sRomPath = CFlashPath; + + + files = (DIR_ENT *) malloc(MAXFILES*sizeof(DIR_ENT)); + if (files == NULL) return FALSE; + fileLink = (FILE_INFO *) malloc(MAXFILES*sizeof(FILE_INFO)); + if (fileLink == NULL) + { + free(files); + return FALSE; + } + + for (i=0; i>8; + clust += l; + numClusters += l; + } + } + else + dirEntries[k-1].startCluster = clusterNum; + } + if (i==0) numRootFiles++; + dirEntriesInCluster[clusterNum]++; + if (dirEntriesInCluster[clusterNum]==256) + clusterNum++; + } + } + clusterNum = clusterNum2 + ((fileLink[i].filesInDir)>>8) + 1; + numClusters++; + } + + // Free the file indexing buffer + free(files); + free(fileLink); + + // Set up the MBR + MBR.bytesPerSector = 512; + MBR.numFATs = 1; + // replaced strcpy with strncpy. It doesnt matter here, as the strings are constant + // but we should extingish all unrestricted strcpy,strcat from the project + strncpy((char*)&MBR.OEMName[0],"DESMUM",8); + strncpy((char*)&MBR.fat16.fileSysType[0],"FAT16 ",8); + MBR.reservedSectors = SECRESV; + MBR.numSectors = 524288; + MBR.numSectorsSmall = 0; + MBR.sectorsPerCluster = SECPERCLUS; + MBR.sectorsPerFAT = SECPERFAT; + MBR.rootEntries = 512; + MBR.fat16.signature = 0xAA55; + MBR.mediaDesc = 1; + + filesysFAT = 0 + MBR.reservedSectors; + filesysRootDir = filesysFAT + (MBR.numFATs * MBR.sectorsPerFAT); + filesysData = filesysRootDir + ((MBR.rootEntries * sizeof(DIR_ENT)) / 512); + + // Set up the cluster values for all subdirectories + clust = filesysData / SECPERCLUS; + firstDirEntCluster = clust; + for (i=1; i rootCluster) + dirEntries[i].startCluster += clust-rootCluster; + } + } + lastDirEntCluster = clust+numClusters-1; + + // Set up the cluster values for all files + clust += numClusters; //clusterNum; + for (i=0; i 0) + { + if (dirEntries[i].startCluster+j < MAXFILES) + FAT16[dirEntries[i].startCluster+j] = dirEntries[i].startCluster+j+1; + j++; + l -= (512*16); + } + if ((dirEntries[i].attrib & ATTRIB_DIR)==0) + { + if (dirEntries[i].startCluster+j < MAXFILES) + FAT16[dirEntries[i].startCluster+j] = 0xFFFF; + } + k = dirEntries[i].startCluster+j; + } + } + + for (i=(filesysData/SECPERCLUS); iname[i] == ' ') break; + out[i] = pd->name[i]; + } + if ((pd->attrib & 0x10)==0) + { + out[i++] = '.'; + for (j=0; jext[j] == ' ') break; + out[i++] = pd->ext[j]; + } + } + out[i] = '\0'; +} + +// Resolve the path of a files by working backwards through the directory entries +static void resolve_path(int dirent) +{ + int i; + char dirname[128]; + + while (dirEntryLink[dirent].parent > 0) + { + for (i=0; i= bufferStart + 512)) + { + if (!hFile) + { + CFLASHLOG("fread_buffered with hFile null with offset %lu and bufferStart %lu\n", + offset, bufferStart); + return 0; + } + fseek(hFile, offset, SEEK_SET); + elems_read += fread(&freadBuffer, 1, 512, hFile); + bufferStart = offset; + } + + return freadBuffer[(offset-bufferStart)>>1]; + } + if (activeDirEnt != -1) + fclose(hFile); + + strncpy(fpath,sRomPath,ARRAY_SIZE(fpath)); + strncat(fpath,DIR_SEP,ARRAY_SIZE(fpath)-strlen(fpath)); + + resolve_path(dirent); + + fatstring_to_asciiz(dirent,fname,NULL); + strncat(fpath,fname,ARRAY_SIZE(fpath)-strlen(fpath)); + + hFile = fopen(fpath, "rb"); + if (!hFile) return 0; + bufferStart = offset; + fseek(hFile, offset, SEEK_SET); + elems_read += fread(&freadBuffer, 1, 512, hFile); + + bufferStart = offset; + activeDirEnt = dirent; + fileStartLBA = (dirEntries[dirent].startCluster*512*SECPERCLUS); + fileEndLBA = fileStartLBA + dirEntries[dirent].fileSize; + + return freadBuffer[(offset-bufferStart)>>1]; +} + +unsigned int cflash_read(unsigned int address) +{ + unsigned int ret_value = 0; + size_t elems_read = 0; +#if 0 /* used by next if 0 block */ +#define BUFFERED_BLOCK_SIZE 512 + static u8 block_buffer[BUFFERED_BLOCK_SIZE]; + static s32 buffered_start_index = -1; +#endif + + switch (address) + { + case CF_REG_STS: + ret_value = cf_reg_sts; + break; + + case CF_REG_DATA: + if (cf_reg_cmd == CF_CMD_READ) + { + if (!CFlashUsePath) + { + if ( disk_image != -1) + { + u8 data[2]; +#if 0 + if (currLBA < buffered_start_index || currLBA >= (buffered_start_index + BUFFERED_BLOCK_SIZE)) + { + size_t read_bytes = 0; + LSEEK_FN( disk_image, currLBA, SEEK_SET); + + while (read_bytes < BUFFERED_BLOCK_SIZE) + { + size_t cur_read = READ_FN( disk_image, &block_buffer[read_bytes], + BUFFERED_BLOCK_SIZE - read_bytes); + + if ( cur_read == -1) + { + CFLASHLOG( "Error during read: %s\n", strerror(errno) ); + break; + } + read_bytes += cur_read; + } + + CFLASHLOG( "Read %d bytes\n", read_bytes); + + buffered_start_index = currLBA; + } + data[0] = block_buffer[currLBA - buffered_start_index]; + data[1] = block_buffer[currLBA + 1 - buffered_start_index]; +#else + LSEEK_FN( disk_image, currLBA, SEEK_SET); + elems_read += READ_FN( disk_image, data, 2); +#endif + ret_value = data[1] << 8 | data[0]; + } + currLBA += 2; + } + else // use path + { + unsigned char *p; + int i; + u32 cluster,cluster2,cluster3,fileLBA; + cluster = (currLBA / (512 * SECPERCLUS)); + cluster2 = (((currLBA/512) - filesysData) / SECPERCLUS) + 2; + + // Reading from the MBR + if (currLBA < 512) + { + p = (unsigned char*)&MBR; + ret_value = T1ReadWord(p, currLBA); + + // Reading the FAT + } + else + if (((u32)currLBA >= filesysFAT*512) && ((u32)currLBA < filesysRootDir*512)) + { + p = (unsigned char*)&FAT16[0]; + ret_value = T1ReadWord(p, currLBA - filesysFAT * 512); + + // Reading directory entries + } + else + if (((u32)currLBA >= filesysRootDir*512) && (cluster <= (u32)lastDirEntCluster)) + { + cluster3 = ((currLBA - (SECRESV * 512)) / (512 * SECPERCLUS)); + i = (currLBA-(((cluster3-(filesysRootDir/SECPERCLUS))*SECPERCLUS+filesysRootDir)*512)); //(currLBA - cluster*BYTESPERCLUS); + if (i < (dirEntriesInCluster[cluster3]*32)) + { + p = (unsigned char*)dirEntryPtr[cluster3]; + ret_value = T1ReadWord(p, i); + } + else + { + i /= 32; + i -= dirEntriesInCluster[cluster3]; + if ((i>=0)&&(i (u32)lastDirEntCluster) && (cluster2 <= (u32)lastFileDataCluster)) + { + //else if ((cluster>lastDirEntCluster)&&(cluster<=lastFileDataCluster)) { + fileLBA = currLBA - (filesysData-32)*512; // 32 = # sectors used for the root entries + + // Check if the read is from the currently opened file + if ((fileLBA >= fileStartLBA) && (fileLBA < fileEndLBA)) + { + cluster = (fileLBA / (512 * SECPERCLUS)); + ret_value = fread_buffered(activeDirEnt,cluster-dirEntries[activeDirEnt].startCluster,(fileLBA-fileStartLBA)&(BYTESPERCLUS-1)); + } + else + { + for (i=0; i=(u32)(dirEntries[i].startCluster*512*SECPERCLUS)) && + (fileLBA <(dirEntries[i].startCluster*512*SECPERCLUS)+dirEntries[i].fileSize) && + ((dirEntries[i].attrib & (ATTRIB_DIR|ATTRIB_LFN))==0)) + { + cluster = (fileLBA / (512 * SECPERCLUS)); + ret_value = fread_buffered(i,cluster-dirEntries[i].startCluster,fileLBA&(BYTESPERCLUS-1)); + break; + } + } + } + } + currLBA += 2; + } + } + break; + + case CF_REG_CMD: + break; + + case CF_REG_LBA1: + ret_value = cf_reg_lba1; + break; + } + + return ret_value; +} + +void cflash_write(unsigned int address,unsigned int data) +{ + static u8 sector_data[512]; + static u32 sector_write_index = 0; + + switch (address) + { + case CF_REG_STS: + cf_reg_sts = data&0xFFFF; + break; + + case CF_REG_DATA: + if (cf_reg_cmd == CF_CMD_WRITE) + { + if (!CFlashUsePath) + { + sector_data[sector_write_index] = (data >> 0) & 0xff; + sector_data[sector_write_index + 1] = (data >> 8) & 0xff; + + sector_write_index += 2; + + if (sector_write_index == 512) + { + CFLASHLOG( "Write sector to %ld\n", currLBA); + size_t written = 0; + + if (currLBA + 512 < file_size) + { + if (disk_image != -1) + { + LSEEK_FN( disk_image, currLBA, SEEK_SET); + + while(written < 512) + { + size_t cur_write = + WRITE_FN( disk_image, §or_data[written], 512 - written); + written += cur_write; + + if ( cur_write == (size_t)-1) break; + } + } + } + + CFLASHLOG("Wrote %u bytes\n", written); + } + currLBA += 512; + sector_write_index = 0; + } + else // TODO: write to real partition + { + } + } + break; + + case CF_REG_CMD: + cf_reg_cmd = data&0xFF; + cf_reg_sts = 0x58; // READY + break; + + case CF_REG_LBA1: + cf_reg_lba1 = data&0xFF; + currLBA = (currLBA&0xFFFFFF00)| cf_reg_lba1; + break; + + case CF_REG_LBA2: + cf_reg_lba2 = data&0xFF; + currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8); + break; + + case CF_REG_LBA3: + cf_reg_lba3 = data&0xFF; + currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16); + break; + + case CF_REG_LBA4: + cf_reg_lba4 = data&0xFF; + + if ((cf_reg_lba4 & 0xf0) == CF_CMD_LBA) + { + currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24); + currLBA *= 512; + sector_write_index = 0; + } + break; + } +} + +void cflash_close( void) +{ + if (!inited) return; + if (!CFlashUsePath) + { + if ( disk_image != -1) + { + CLOSE_FN( disk_image); + disk_image = -1; + } + } + else + { + int i; + + if (cflashDeviceEnabled) + { + cflashDeviceEnabled = FALSE; + + for (i=0; i= 0x08000000 && adr < 0x080000C0) + val = rumble_hdr[adr & 0xFF]; + if (adr == 0x0801FFFE) val = 0x45; + + return ((u8)val); +}; + +u16 RumblePak_read16(u32 adr) +{ + u16 val = 0; + + if (adr >= 0x08000000 && adr < 0x080000C0) + val = T1ReadWord(rumble_hdr, adr & 0xFF ); + if (adr == 0x0801FFFE) val = 0x0045; + + return ((u16)val); +}; +u32 RumblePak_read32(u32 adr) +{ + u32 val = 0; + if (adr >= 0x08000000 && adr < 0x080000C0) + val = T1ReadLong(rumble_hdr, adr & 0xFF ); + if (adr == 0x0801FFFE) val = 0x00000045; + + return ((u32)val); +}; +void RumblePak_info(char *info) { strcpy(info, "NDS Rumble Pak (need joystick)"); }; + +ADDONINTERFACE addonRumblePak = { + "Rumble Pak", + RumblePak_init, + RumblePak_reset, + RumblePak_close, + RumblePak_config, + RumblePak_write08, + RumblePak_write16, + RumblePak_write32, + RumblePak_read08, + RumblePak_read16, + RumblePak_read32, + RumblePak_info}; diff --git a/desmume/src/cflash.cpp b/desmume/src/cflash.cpp index 780f6c6c6..492605434 100644 --- a/desmume/src/cflash.cpp +++ b/desmume/src/cflash.cpp @@ -41,6 +41,9 @@ ---------------------- */ +#include "common.h" + +#ifndef EXPERIMENTAL_GBASLOT #include #include @@ -874,3 +877,4 @@ cflash_close( void) { } } +#endif \ No newline at end of file diff --git a/desmume/src/cflash.h b/desmume/src/cflash.h index 5f33ff0d2..862f23fee 100644 --- a/desmume/src/cflash.h +++ b/desmume/src/cflash.h @@ -6,6 +6,9 @@ #ifndef __CFLASH_H__ #define __CFLASH_H__ +#include "common.h" + +#ifndef EXPERIMENTAL_GBASLOT #include "fat.h" typedef struct { @@ -20,5 +23,6 @@ unsigned int cflash_read(unsigned int address); void cflash_write(unsigned int address,unsigned int data); void cflash_close( void); +#endif #endif diff --git a/desmume/src/common.cpp b/desmume/src/common.cpp index b1c24c23f..e8b33f73a 100644 --- a/desmume/src/common.cpp +++ b/desmume/src/common.cpp @@ -23,8 +23,19 @@ #include "common.h" -#ifdef WIN32 +u8 gba_header_data_0x04[156] = { + 0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD, + 0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20, + 0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF, + 0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC, + 0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76, + 0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD, + 0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25, + 0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44, + 0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF, + 0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07}; +#ifdef WIN32 char IniName[MAX_PATH]; void GetINIPath() diff --git a/desmume/src/common.h b/desmume/src/common.h index e890e290e..c2b7e755c 100644 --- a/desmume/src/common.h +++ b/desmume/src/common.h @@ -26,8 +26,11 @@ #include #include "types.h" - + +extern u8 gba_header_data_0x04[156]; + #ifdef WIN32 + #define _WINSOCKAPI_ #include @@ -35,11 +38,26 @@ extern HINSTANCE hAppInst; + extern BOOL romloaded; + extern char IniName[MAX_PATH]; extern void GetINIPath(); extern void WritePrivateProfileInt(char* appname, char* keyname, int val, char* file); + + #define EXPERIMENTAL_GBASLOT 1 + // this is experimental and only tested for windows port + // (I can`t test on another ports) + // + // About GBA game in slot (only for use together with NDS + GBA): + // in real BIOS 9 at offset 0x0020 placed compressed logo + // for comparing with logo in header GBA cartridge. + // so, GBA game in slot work now if using only real BIOS. + // Later need make loading this table in BIOS memory (from gba_header_data_0x04) + // + // in windows ports: + // i added in menu "Emulation" submenu "GBA slot" #endif - extern u8 reverseBitsInByte(u8 x); +extern u8 reverseBitsInByte(u8 x); #endif \ No newline at end of file diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index 2d3511c41..42a2fb377 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -510,6 +510,14 @@ RelativePath=".\FirmConfig.h" > + + + + @@ -804,6 +812,34 @@ + + + + + + + + + + + + + + diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj index a091767fc..dd5e05ace 100644 --- a/desmume/src/windows/DeSmuME_2008.vcproj +++ b/desmume/src/windows/DeSmuME_2008.vcproj @@ -472,6 +472,10 @@ + + @@ -508,6 +512,10 @@ RelativePath="..\FIFO.cpp" > + + @@ -826,6 +834,26 @@ + + + + + + + + + + + + @@ -964,6 +996,10 @@ RelativePath=".\FirmConfig.h" > + + @@ -1020,6 +1056,10 @@ + + @@ -1072,10 +1112,6 @@ RelativePath="..\FIFO.h" > - - diff --git a/desmume/src/windows/DeSmuME_Intel.icproj b/desmume/src/windows/DeSmuME_Intel.icproj index 0ca7b354f..41c906b53 100644 --- a/desmume/src/windows/DeSmuME_Intel.icproj +++ b/desmume/src/windows/DeSmuME_Intel.icproj @@ -5,7 +5,7 @@ Name="DeSmuME_Intel" ProjectGUID="{3DA70B4E-4FE0-428C-9084-F6CE33810F6B}" VCNestedProjectGUID="{9F5F72A1-D3A5-4918-B460-E076B16D10A9}" - VCNestedProjectCRC32="1380849017" + VCNestedProjectCRC32="4289079542" VCNestedProjectFileName="DeSmuME_Intel.vcproj"> + - + + + + + + + + + + @@ -508,6 +512,10 @@ RelativePath="..\FIFO.cpp" > + + @@ -826,6 +834,26 @@ + + + + + + + + + + + + @@ -964,6 +996,10 @@ RelativePath=".\FirmConfig.h" > + + @@ -1020,6 +1056,10 @@ + + @@ -1072,10 +1112,6 @@ RelativePath="..\FIFO.h" > - - diff --git a/desmume/src/windows/gbaslot_config.cpp b/desmume/src/windows/gbaslot_config.cpp new file mode 100644 index 000000000..acb4aef3d --- /dev/null +++ b/desmume/src/windows/gbaslot_config.cpp @@ -0,0 +1,436 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2009 DeSmuME team + + 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 "gbaslot_config.h" +#include +#include "resource.h" +#include "debug.h" +#include "../addons.h" +#include "../NDSSystem.h" +#include + +WNDCLASSEX wc; +HWND wndConfig; +HINSTANCE ghInstance = NULL; +u8 temp_type = 0; +u8 last_type; +char tmp_cflash_filename[MAX_PATH]; +char tmp_cflash_path[MAX_PATH]; +char tmp_gbagame_filename[MAX_PATH]; +u8 tmp_CFlashUsePath; +u8 tmp_CFlashUseRomPath; +HWND OKbutton = NULL; + +BOOL CALLBACK GbaSlotNone(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + EnableWindow(OKbutton, TRUE); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK GbaSlotCFlash(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + SetWindowText(GetDlgItem(dialog, IDC_PATHIMG), tmp_cflash_filename); + SetWindowText(GetDlgItem(dialog, IDC_PATH), tmp_cflash_path); + if (tmp_CFlashUsePath) + { + if (tmp_CFlashUseRomPath) + { + CheckDlgButton(dialog, IDC_PATHDESMUME, BST_CHECKED); + EnableWindow(GetDlgItem(dialog, IDC_PATH), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), FALSE); + EnableWindow(OKbutton, TRUE); + } + else + { + EnableWindow(GetDlgItem(dialog, IDC_PATH), TRUE); + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), TRUE); + if (strlen(tmp_cflash_path)) + EnableWindow(OKbutton, TRUE); + } + EnableWindow(GetDlgItem(dialog, IDC_PATHIMG), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE), FALSE); + CheckDlgButton(dialog, IDC_RFOLDER, BST_CHECKED); + } + else + { + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_PATHDESMUME), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_PATH), FALSE); + if (strlen(tmp_cflash_filename)) + EnableWindow(OKbutton, TRUE); + CheckDlgButton(dialog, IDC_RFILE, BST_CHECKED); + } + return TRUE; + } + + case WM_COMMAND: + { + switch (LOWORD(wparam)) + { + case IDC_BBROWSE: + { + int filterSize = 0, i = 0; + OPENFILENAME ofn; + char filename[MAX_PATH] = "", + fileFilter[512]=""; + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = dialog; + + strncpy (fileFilter, "Compact Flash image (*.img)|*.img||",512 - strlen(fileFilter)); + 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 = "img"; + ofn.Flags = OFN_NOCHANGEDIR | OFN_CREATEPROMPT; + + if(!GetOpenFileName(&ofn)) return FALSE; + + SetWindowText(GetDlgItem(dialog, IDC_PATHIMG), filename); + strcpy(tmp_cflash_filename, filename); + if (!strlen(tmp_cflash_filename)) + EnableWindow(OKbutton, FALSE); + else + EnableWindow(OKbutton, TRUE); + return FALSE; + } + + case IDC_BBROWSE2: + { + BROWSEINFO bp={0}; + + bp.hwndOwner=dialog; + bp.pidlRoot=NULL; + bp.pszDisplayName=NULL; + bp.lpszTitle="Select directory for Compact Flash"; + bp.ulFlags=BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; + bp.lpfn=NULL; + + LPITEMIDLIST tmp = SHBrowseForFolder((LPBROWSEINFO)&bp); + if (tmp!=NULL) + { + memset(tmp_cflash_path, 0, sizeof(tmp_cflash_path)); + SHGetPathFromIDList(tmp, tmp_cflash_path); + if (tmp_cflash_path[strlen(tmp_cflash_path)-1] != '\\') + tmp_cflash_path[strlen(tmp_cflash_path)] = '\\'; + SetWindowText(GetDlgItem(dialog, IDC_PATH), tmp_cflash_path); + } + if (strlen(tmp_cflash_path)) + EnableWindow(OKbutton, TRUE); + else + EnableWindow(OKbutton, FALSE); + break; + } + + case IDC_RFILE: + { + tmp_CFlashUsePath = FALSE; + EnableWindow(GetDlgItem(dialog, IDC_PATHIMG), TRUE); + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE), TRUE); + + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_PATHDESMUME), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_PATH), FALSE); + + if (!strlen(tmp_cflash_filename)) + EnableWindow(OKbutton, FALSE); + break; + } + + case IDC_RFOLDER: + { + tmp_CFlashUsePath = TRUE; + EnableWindow(GetDlgItem(dialog, IDC_PATHIMG), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE), FALSE); + + if (IsDlgButtonChecked(dialog, IDC_PATHDESMUME)) + { + tmp_CFlashUseRomPath = TRUE; + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_PATH), FALSE); + EnableWindow(OKbutton, TRUE); + } + else + { + tmp_CFlashUseRomPath = FALSE; + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), TRUE); + EnableWindow(GetDlgItem(dialog, IDC_PATH), TRUE); + } + + EnableWindow(GetDlgItem(dialog, IDC_PATHDESMUME), TRUE); + break; + } + + case IDC_PATHDESMUME: + { + if (IsDlgButtonChecked(dialog, IDC_PATHDESMUME)) + { + tmp_CFlashUseRomPath = TRUE; + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), FALSE); + EnableWindow(GetDlgItem(dialog, IDC_PATH), FALSE); + EnableWindow(OKbutton, TRUE); + } + else + { + tmp_CFlashUseRomPath = FALSE; + EnableWindow(GetDlgItem(dialog, IDC_BBROWSE2), TRUE); + EnableWindow(GetDlgItem(dialog, IDC_PATH), TRUE); + if (strlen(tmp_cflash_path)) + EnableWindow(OKbutton, TRUE); + else + EnableWindow(OKbutton, FALSE); + } + break; + } + } + break; + } + } + return FALSE; +} + +BOOL CALLBACK GbaSlotRumblePak(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + EnableWindow(OKbutton, TRUE); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK GbaSlotGBAgame(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + SetWindowText(GetDlgItem(dialog, IDC_PATHGAME), tmp_gbagame_filename); + if (!strlen(tmp_gbagame_filename)) + EnableWindow(OKbutton, FALSE); + return TRUE; + } + case WM_COMMAND: + { + switch (LOWORD(wparam)) + { + case IDC_BBROWSE: + { + int filterSize = 0, i = 0; + OPENFILENAME ofn; + char filename[MAX_PATH] = "", + fileFilter[512]=""; + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = dialog; + + // TODO: add another gba file formats and archs + strncpy (fileFilter, "GameBoy Advance ROM (*.gba)|*.gba||",512 - strlen(fileFilter)); + 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 = "gba"; + ofn.Flags = OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; + + if(!GetOpenFileName(&ofn)) return FALSE; + + SetWindowText(GetDlgItem(dialog, IDC_PATHGAME), filename); + strcpy(tmp_gbagame_filename, filename); + if (!strlen(tmp_gbagame_filename)) + EnableWindow(OKbutton, FALSE); + else + EnableWindow(OKbutton, TRUE); + return FALSE; + } + } + break; + } + } + return FALSE; +} + +u32 GBAslot_IDDs[NDS_ADDON_COUNT] = { + IDD_GBASLOT_NONE, + IDD_GBASLOT_CFLASH, + IDD_GBASLOT_RUMBLEPAK, + IDD_GBASLOT_GBAGAME +}; + +DLGPROC GBAslot_Procs[NDS_ADDON_COUNT] = { + GbaSlotNone, + GbaSlotCFlash, + GbaSlotRumblePak, + GbaSlotGBAgame +}; + + +//============================================================================== +BOOL CALLBACK GbaSlotBox_Proc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + OKbutton = GetDlgItem(dialog, IDOK); + for(int i = 0; i < NDS_ADDON_COUNT; i++) + ComboBox_AddString(GetDlgItem(dialog, IDC_ADDONS_LIST), addonList[i].name); + ComboBox_SetCurSel(GetDlgItem(dialog, IDC_ADDONS_LIST), temp_type); + u8 tmp_info[512]; + addonList[temp_type].info((char *)tmp_info); + SetWindowText(GetDlgItem(dialog, IDC_ADDONS_INFO), (char *)tmp_info); + + wndConfig=CreateDialog(ghInstance, MAKEINTRESOURCE(GBAslot_IDDs[temp_type]), + dialog, (DLGPROC)GBAslot_Procs[temp_type]); + if (temp_type == 0) + EnableWindow(OKbutton, TRUE); + return TRUE; + } + + case WM_COMMAND: + { + switch (LOWORD(wparam)) + { + case IDOK: + { + int Msg = IDYES; + if (romloaded) + { + int Msg = MessageBox(dialog, + "After change GBA slot pak game will reset!\nAre you sure to continue?", "DeSmuME", + MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2); + } + if (Msg == IDYES) + { + if (wndConfig) CloseWindow(wndConfig); + EndDialog(dialog, TRUE); + } + } + return TRUE; + case IDCANCEL: + if (wndConfig) CloseWindow(wndConfig); + EndDialog(dialog, FALSE); + return TRUE; + + case IDC_ADDONS_LIST: + if (HIWORD(wparam) == CBN_SELENDOK) + { + temp_type = ComboBox_GetCurSel(GetDlgItem(dialog, IDC_ADDONS_LIST)); + if (temp_type != last_type) + { + if (wndConfig) CloseWindow(wndConfig); + wndConfig=CreateDialog(ghInstance, + MAKEINTRESOURCE(GBAslot_IDDs[temp_type]), dialog, + (DLGPROC)GBAslot_Procs[temp_type]); + u8 tmp_info[512]; + addonList[temp_type].info((char *)tmp_info); + SetWindowText(GetDlgItem(dialog, IDC_ADDONS_INFO), (char *)tmp_info); + last_type = temp_type; + } + } + return TRUE; + } + break; + } + } + return FALSE; +} + +void GBAslotDialog(HWND hwnd, HINSTANCE hInstance) +{ + ghInstance = hInstance; + temp_type = addon_type; + last_type = temp_type; + strcpy(tmp_cflash_filename, CFlashName); + strcpy(tmp_cflash_path, CFlashPath); + strcpy(tmp_gbagame_filename, GBAgameName); + tmp_CFlashUseRomPath = CFlashUseRomPath; + tmp_CFlashUsePath = CFlashUsePath; + u32 res=DialogBox(hInstance, MAKEINTRESOURCE(IDD_GBASLOT), hwnd, (DLGPROC) GbaSlotBox_Proc); + if (res) + { + switch (temp_type) + { + case NDS_ADDON_NONE: + break; + case NDS_ADDON_CFLASH: + CFlashUsePath = tmp_CFlashUsePath; + WritePrivateProfileInt("GBAslot.CFlash","usePath",CFlashUsePath,IniName); + if (tmp_CFlashUsePath) + { + if (tmp_CFlashUseRomPath) + { + CFlashUseRomPath = tmp_CFlashUseRomPath; + WritePrivateProfileInt("GBAslot.CFlash","useRomPath",CFlashUseRomPath,IniName); + break; + } + strcpy(CFlashPath, tmp_cflash_path); + WritePrivateProfileString("GBAslot.CFlash","path",CFlashPath,IniName); + break; + } + strcpy(CFlashName, tmp_cflash_filename); + WritePrivateProfileString("GBAslot.CFlash","filename",CFlashName,IniName); + break; + case NDS_ADDON_RUMBLEPAK: + break; + case NDS_ADDON_GBAGAME: + strcpy(GBAgameName, tmp_gbagame_filename); + WritePrivateProfileString("GBAslot.GBAgame","filename",GBAgameName,IniName); + break; + default: + return; + } + WritePrivateProfileInt("GBAslot","type",temp_type,IniName); + addon_type = temp_type; + addonsChangePak(addon_type); + if (romloaded) + NDS_Reset(); + } +} \ No newline at end of file diff --git a/desmume/src/windows/gbaslot_config.h b/desmume/src/windows/gbaslot_config.h new file mode 100644 index 000000000..99aaa4c2f --- /dev/null +++ b/desmume/src/windows/gbaslot_config.h @@ -0,0 +1,26 @@ +/* + Copyright (C) 2008 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __GBASLOT_CONFIG_H_ +#define __GBASLOT_CONFIG_H_ +#include "../common.h" + +extern void GBAslotDialog(HWND hwnd, HINSTANCE hInstance); +#endif diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index e2902f550..20d701d0d 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -38,7 +38,11 @@ #include "../NDSSystem.h" #include "../debug.h" #include "../saves.h" +#ifndef EXPERIMENTAL_GBASLOT #include "../cflash.h" +#else +#include "../addons.h" +#endif #include "resource.h" #include "memView.h" #include "disView.h" @@ -60,6 +64,7 @@ #include "colorctrl.h" #include "console.h" #include "throttle.h" +#include "gbaslot_config.h" #include "../common.h" @@ -107,9 +112,11 @@ LPDIRECTDRAWCLIPPER lpDDClipBack=NULL; //===================== Input vars INPUTCLASS *input = NULL; +#ifndef EXPERIMENTAL_GBASLOT /* The compact flash disk image file */ static const char *bad_glob_cflash_disk_image_file; static char cflash_filename_buffer[512]; +#endif /* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); @@ -145,7 +152,6 @@ TOOLSCLASS *ViewOAM = NULL; TOOLSCLASS *ViewMatrices = NULL; TOOLSCLASS *ViewLights = NULL; - volatile BOOL execute = FALSE; volatile BOOL paused = TRUE; u32 glock = 0; @@ -256,6 +262,34 @@ fill_configured_features( struct configured_features *config, LPSTR lpszArgument good_args = 0; } } + +#ifdef EXPERIMENTAL_GBASLOT + else if ( wcsncmp( argv[i], L"--cflash=", 9) == 0) + { + char buf[512]; + size_t convert_count = wcstombs(&buf[0], &argv[i][9], 512); + if (convert_count > 0) + { + addon_type = NDS_ADDON_CFLASH; + CFlashUsePath = FALSE; + strcpy(CFlashName, buf); + } + } + else if ( wcsncmp( argv[i], L"--gbagame=", 10) == 0) + { + char buf[512]; + size_t convert_count = wcstombs(&buf[0], &argv[i][9], 512); + if (convert_count > 0) + { + addon_type = NDS_ADDON_GBAGAME; + strcpy(GBAgameName, buf); + } + } + else if ( wcsncmp( argv[i], L"--rumble", 8) == 0) + { + addon_type = NDS_ADDON_RUMBLEPAK; + } +#else 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); @@ -268,6 +302,7 @@ fill_configured_features( struct configured_features *config, LPSTR lpszArgument good_args = 0; } } +#endif } LocalFree( argv); } @@ -1069,12 +1104,20 @@ void StateLoadSlot(int num) Display(); } +#ifdef EXPERIMENTAL_GBASLOT +BOOL LoadROM(char * filename) +#else BOOL LoadROM(char * filename, const char *cflash_disk_image) +#endif { NDS_Pause(); //if (strcmp(filename,"")!=0) INFO("Attempting to load ROM: %s\n",filename); - if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize, cflash_disk_image) > 0) +#ifdef EXPERIMENTAL_GBASLOT + if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize) > 0) +#else + if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize, cflash_disk_image) > 0) +#endif { INFO("Loading %s was successful\n",filename); frameCounter=0; @@ -1235,6 +1278,41 @@ int WINAPI WinMain (HINSTANCE hThisInstance, char text[80]; hAppInst=hThisInstance; + GetINIPath(); +#ifdef EXPERIMENTAL_GBASLOT + addon_type = GetPrivateProfileInt("GBAslot", "type", NDS_ADDON_NONE, IniName); + CFlashUsePath = GetPrivateProfileInt("GBAslot.CFlash", "usePath", 1, IniName); + CFlashUseRomPath = GetPrivateProfileInt("GBAslot.CFlash", "useRomPath", 1, IniName); + GetPrivateProfileString("GBAslot.CFlash", "path", "", CFlashPath, MAX_PATH, IniName); + GetPrivateProfileString("GBAslot.CFlash", "filename", "", CFlashName, MAX_PATH, IniName); + GetPrivateProfileString("GBAslot.GBAgame", "filename", "", GBAgameName, MAX_PATH, IniName); + + switch (addon_type) + { + case NDS_ADDON_NONE: + break; + case NDS_ADDON_CFLASH: + if (!strlen(CFlashPath)) CFlashUseRomPath = TRUE; + if (!strlen(CFlashName)) CFlashUsePath = TRUE; + // TODO: check for file exist + break; + case NDS_ADDON_RUMBLEPAK: + break; + case NDS_ADDON_GBAGAME: + if (!strlen(GBAgameName)) + { + addon_type = NDS_ADDON_NONE; + break; + } + // TODO: check for file exist + break; + default: + addon_type = NDS_ADDON_NONE; + break; + } + addonsChangePak(addon_type); +#endif + init_configured_features( &my_config); if ( !fill_configured_features( &my_config, lpszArgument)) { MessageBox(NULL,"Unable to parse command line arguments","Error",MB_OK); @@ -1242,15 +1320,14 @@ int WINAPI WinMain (HINSTANCE hThisInstance, } ColorCtrl_Register(); - OpenConsole(); // Init debug console - if (!RegClass(WindowProcedure, "DeSmuME")) { MessageBox(NULL, "Error registering windows class", "DeSmuME", MB_OK); exit(-1); } + + OpenConsole(); // Init debug console - GetINIPath(); windowSize = GetPrivateProfileInt("Video","Window Size", 0, IniName); GPU_rotation = GetPrivateProfileInt("Video","Window Rotate", 0, IniName); ForceRatio = GetPrivateProfileInt("Video","Window Force Ratio", 1, IniName); @@ -1278,7 +1355,9 @@ int WINAPI WinMain (HINSTANCE hThisInstance, GetPrivateProfileString("General", "Language", "0", text, 80, IniName); SetLanguage(atoi(text)); +#ifndef EXPERIMENTAL_GBASLOT bad_glob_cflash_disk_image_file = my_config.cflash_disk_image_file; +#endif hAccel = LoadAccelerators(hAppInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL)); @@ -1296,6 +1375,9 @@ int WINAPI WinMain (HINSTANCE hThisInstance, EnableMenuItem(mainMenu, IDM_RESET, MF_GRAYED); EnableMenuItem(mainMenu, IDM_GAME_INFO, MF_GRAYED); EnableMenuItem(mainMenu, IDM_IMPORTBACKUPMEMORY, MF_GRAYED); +#ifndef EXPERIMENTAL_GBASLOT + EnableMenuItem(mainMenu, IDM_GBASLOT, MF_GRAYED); +#endif LOG("Init NDS\n"); @@ -1436,9 +1518,14 @@ int WINAPI WinMain (HINSTANCE hThisInstance, // Make sure any quotes from lpszArgument are removed if (lpszArgument[0] == '\"') sscanf(lpszArgument, "\"%[^\"]\"", lpszArgument); + if (lpszArgument[0]) { +#ifdef EXPERIMENTAL_GBASLOT + if(LoadROM(lpszArgument)) +#else if(LoadROM(lpszArgument, bad_glob_cflash_disk_image_file)) +#endif { EnableMenuItem(mainMenu, IDM_EXEC, MF_GRAYED); EnableMenuItem(mainMenu, IDM_PAUSE, MF_ENABLED); @@ -1615,14 +1702,18 @@ void OpenRecentROM(int listNum) char filename[MAX_PATH]; strcpy(filename, RecentRoms[listNum].c_str()); //LOG("Attempting to load %s\n",filename); +#ifdef EXPERIMENTAL_GBASLOT + if(LoadROM(filename)) +#else if(LoadROM(filename, bad_glob_cflash_disk_image_file)) +#endif { EnableMenuItem(mainMenu, IDM_PAUSE, MF_ENABLED); EnableMenuItem(mainMenu, IDM_RESET, MF_ENABLED); EnableMenuItem(mainMenu, IDM_GAME_INFO, MF_ENABLED); EnableMenuItem(mainMenu, IDM_IMPORTBACKUPMEMORY, MF_ENABLED); romloaded = TRUE; - } + } NDS_UnPause(); } @@ -1730,7 +1821,11 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM char filename[MAX_PATH] = ""; DragQueryFile((HDROP)wParam,0,filename,MAX_PATH); DragFinish((HDROP)wParam); - if(LoadROM(filename, bad_glob_cflash_disk_image_file)) +#ifdef EXPERIMENTAL_GBASLOT + if(LoadROM(filename)) +#else + if(LoadROM(filename, bad_glob_cflash_disk_image_file)) +#endif { EnableMenuItem(mainMenu, IDM_EXEC, MF_GRAYED); EnableMenuItem(mainMenu, IDM_PAUSE, MF_ENABLED); @@ -1856,8 +1951,11 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM } //LOG("%s\r\n", filename); - - if(LoadROM(filename, bad_glob_cflash_disk_image_file)) +#ifdef EXPERIMENTAL_GBASLOT + if(LoadROM(filename)) +#else + if(LoadROM(filename, bad_glob_cflash_disk_image_file)) +#endif { EnableMenuItem(mainMenu, IDM_EXEC, MF_GRAYED); EnableMenuItem(mainMenu, IDM_PAUSE, MF_ENABLED); @@ -2244,6 +2342,10 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM emu_paused ^= 1; MainWindow->checkMenu(IDM_PAUSE, emu_paused ? MF_CHECKED : MF_UNCHECKED); return 0; + + case IDM_GBASLOT: + GBAslotDialog(hwnd, hAppInst); + return 0; case ACCEL_N: //Frame Advance frameAdvance = true; diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index ac6e22be0..2d2b5d2e2 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -21,7 +21,9 @@ #define IDD_3DSETTINGS 111 #define IDM_EXEC 112 #define IDM_PAUSE 113 +#define IDD_GBASLOT 113 #define IDM_RESET 114 +#define IDD_GBASLOT_CFLASH 114 #define IDM_IOREG 115 #define IDM_LOG 116 #define IDM_PAL 117 @@ -221,10 +223,22 @@ #define IDC_TXT_VERSION 1030 #define IDC_SCROLLBAR1 1031 #define IDC_IE7 1032 +#define IDC_ADDONS_CONFIG 1032 #define IDC_IF7 1033 +#define IDC_ADDONS_LIST 1033 #define IDC_IME7 1034 +#define IDC_ADDONS_INFO 1034 #define IDC_IPCSYNC7 1035 +#define IDC_BBROWSE 1035 #define IDC_IPCFIFO7 1036 +#define IDC_PATHIMG 1036 +#define IDC_PATHGAME 1037 +#define IDC_PATH 1037 +#define IDC_RFILE 1038 +#define IDC_RFOLDER 1039 +#define IDC_BBROWSE2 1040 +#define IDC_CHECK1 1041 +#define IDC_PATHDESMUME 1041 #define IDM_FIRMSETTINGS 1100 #define IDD_FIRMSETTINGS 1101 #define IDC_EDIT1 1102 @@ -313,6 +327,9 @@ #define IDC_LIGHT_VIEWER_LIGHT0COLOR_EDIT 1303 #define IDD_MEM_VIEWER9 1303 #define IDC_LIGHT_VIEWER_LIGHT0VECTOR_EDIT 1304 +#define IDD_GBASLOT_NONE 1304 +#define IDD_GBASLOT_RUMBLEPAK 1305 +#define IDD_GBASLOT_GBAGAME 1306 #define IDC_LIGHT_VIWER_LIGHT1_GROUP 1311 #define IDC_LIGHT_VIEWER_LIGHT1COLOR_COLORCTRL 1312 #define IDC_LIGHT_VIEWER_LIGHT1COLOR_EDIT 1313 @@ -369,14 +386,16 @@ #define IDC_SAVETYPE7 40037 #define IDM_DEFSIZE 40038 #define IDM_3DCONFIG 40040 +#define ID_EMULATION_GBASLOT 40041 +#define IDM_GBASLOT 40042 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 113 -#define _APS_NEXT_COMMAND_VALUE 40041 -#define _APS_NEXT_CONTROL_VALUE 1032 +#define _APS_NEXT_RESOURCE_VALUE 115 +#define _APS_NEXT_COMMAND_VALUE 40043 +#define _APS_NEXT_CONTROL_VALUE 1042 #define _APS_NEXT_SYMED_VALUE 112 #endif #endif diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index 84025ab0b..b24ae9b35 100644 --- a/desmume/src/windows/resources.rc +++ b/desmume/src/windows/resources.rc @@ -133,6 +133,8 @@ BEGIN BEGIN MENUITEM "&Pause", IDM_PAUSE MENUITEM "&Genstart", IDM_RESET + MENUITEM SEPARATOR + MENUITEM "GBA &slot", IDM_GBASLOT END POPUP "&Vis" BEGIN @@ -794,6 +796,8 @@ BEGIN BEGIN MENUITEM "&Pause", IDM_PAUSE MENUITEM "&Reset", IDM_RESET + MENUITEM SEPARATOR + MENUITEM "GBA &slot", IDM_GBASLOT END POPUP "&View" BEGIN @@ -1470,10 +1474,10 @@ BEGIN LTEXT "secs",IDC_STATIC,406,5,16,8 END -IDD_3DSETTINGS DIALOG 0, 0, 174, 73 +IDD_3DSETTINGS DIALOGEX 0, 0, 174, 73 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "3D settings" -FONT 8, "MS Sans Serif" +FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN DEFPUSHBUTTON "OK",IDOK,62,52,50,14 PUSHBUTTON "Cancel",IDCANCEL,117,52,50,14 @@ -1482,6 +1486,54 @@ BEGIN COMBOBOX IDC_3DCORE,15,23,146,138,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END +IDD_GBASLOT DIALOGEX 0, 0, 316, 185 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "GBA slot" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + COMBOBOX IDC_ADDONS_LIST,7,7,302,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,205,164,50,14,WS_DISABLED + PUSHBUTTON "Cancel",IDCANCEL,259,164,50,14 + CTEXT "Info",IDC_ADDONS_INFO,7,21,302,23 +END + +IDD_GBASLOT_CFLASH DIALOGEX 7, 48, 302, 109 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "file",IDC_RFILE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,16,26,25,10 + CONTROL "folder",IDC_RFOLDER,"Button",BS_AUTORADIOBUTTON,16,56,35,10 + EDITTEXT IDC_PATHIMG,14,39,223,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Browse...",IDC_BBROWSE,239,38,50,14 + EDITTEXT IDC_PATH,13,67,223,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Browse...",IDC_BBROWSE2,239,67,50,14 + CONTROL "use rom folder",IDC_PATHDESMUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,43,82,62,10 + CTEXT "Select file name or folder for Compact Flash image:",IDC_STATIC,7,7,288,14 + GROUPBOX "",IDC_STATIC,7,19,288,75 +END + +IDD_GBASLOT_NONE DIALOGEX 7, 48, 302, 110 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN +END + +IDD_GBASLOT_RUMBLEPAK DIALOGEX 7, 48, 302, 109 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CTEXT "TODO",IDC_STATIC,7,7,288,26 +END + +IDD_GBASLOT_GBAGAME DIALOGEX 7, 48, 302, 109 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_PATHGAME,7,34,236,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Browse...",IDC_BBROWSE,245,33,50,14 + CTEXT "Select file name for GBA game rom:",IDC_STATIC,7,7,288,14 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -1541,6 +1593,46 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 66 END + + IDD_GBASLOT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 178 + END + + IDD_GBASLOT_CFLASH, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 102 + END + + IDD_GBASLOT_NONE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 103 + END + + IDD_GBASLOT_RUMBLEPAK, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 102 + END + + IDD_GBASLOT_GBAGAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 102 + END END #endif // APSTUDIO_INVOKED @@ -1613,6 +1705,8 @@ BEGIN BEGIN MENUITEM "&Pause", IDM_PAUSE MENUITEM "&Reset", IDM_RESET + MENUITEM SEPARATOR + MENUITEM "GBA &slot", IDM_GBASLOT END POPUP "&View" BEGIN