From 175d6e88e961206c57ea7fd07c0a6a74f016b704 Mon Sep 17 00:00:00 2001 From: cyberwarriorx Date: Fri, 17 Nov 2006 03:12:22 +0000 Subject: [PATCH] -Added Backup Memory autodetection. Almost perfect, there may be a few odd games that still need to manually picked -Backup Memory is now loaded from file at the same time the rom is loaded. -A slightly better algorithm for saving Backup Memory is being used, but it certainly needs improvement. -Autodetection is now used by default -Added menu option in windows port for autodetection --- desmume/src/MMU.c | 14 ++- desmume/src/NDSSystem.c | 11 +++ desmume/src/mc.c | 143 +++++++++++++++++++++++++++---- desmume/src/mc.h | 7 ++ desmume/src/windows/main.c | 34 +++++--- desmume/src/windows/resource.h | 1 + desmume/src/windows/resources.rc | 11 +-- 7 files changed, 184 insertions(+), 37 deletions(-) diff --git a/desmume/src/MMU.c b/desmume/src/MMU.c index 2f6add488..5679cc742 100644 --- a/desmume/src/MMU.c +++ b/desmume/src/MMU.c @@ -265,14 +265,22 @@ void MMU_Init(void) { mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); + MMU.fw.fp = NULL; // Init Backup Memory device, this should really be done when the rom is loaded - mc_init(&MMU.bupmem, MC_TYPE_EEPROM2); - mc_alloc(&MMU.bupmem, 65536); // For now we're use 512Kbit support. Eventually this should be detected when rom is loaded -} + mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT); + mc_alloc(&MMU.bupmem, 1); + MMU.bupmem.fp = NULL; +} void MMU_DeInit(void) { LOG("MMU deinit\n"); + if (MMU.fw.fp) + fclose(MMU.fw.fp); + mc_free(&MMU.fw); + if (MMU.bupmem.fp) + fclose(MMU.bupmem.fp); + mc_free(&MMU.bupmem); } //Card rom & ram diff --git a/desmume/src/NDSSystem.c b/desmume/src/NDSSystem.c index 1f3ce66b0..8992d3030 100644 --- a/desmume/src/NDSSystem.c +++ b/desmume/src/NDSSystem.c @@ -367,6 +367,17 @@ int NDS_LoadROM(const char *filename) cflash_close(); cflash_init(); + // Setup Backup Memory + p = strdup(filename); + + if(type == ROM_DSGBA) + strcpy(p+strlen(p)-strlen(DSGBA_EXTENSTION), ".sav"); + else + strcpy(p+strlen(p)-4, ".sav"); + + mc_load_file(&MMU.bupmem, p); + free(p); + return i; } diff --git a/desmume/src/mc.c b/desmume/src/mc.c index 93c0c0411..1d6871fd9 100644 --- a/desmume/src/mc.c +++ b/desmume/src/mc.c @@ -9,6 +9,7 @@ #define FW_CMD_WRITEENABLE 0x6 #define FW_CMD_PAGEWRITE 0xA +#define BM_CMD_AUTODETECT 0xFF #define BM_CMD_WRITESTATUS 0x1 #define BM_CMD_WRITELOW 0x2 #define BM_CMD_READLOW 0x3 @@ -37,7 +38,8 @@ void mc_init(memory_chip_t *mc, int type) mc->write_enable = FALSE; mc->writeable_buffer = FALSE; mc->type = type; - + mc->autodetectsize = 0; + switch(mc->type) { case MC_TYPE_EEPROM1: @@ -73,7 +75,80 @@ void mc_free(memory_chip_t *mc) void mc_reset_com(memory_chip_t *mc) { - mc->com = 0; + if (mc->type == MC_TYPE_AUTODETECT && mc->com == BM_CMD_AUTODETECT) + { + u32 i; + u32 addr, size; + + if (mc->autodetectsize == (32768+2)) + { + // FRAM + addr = (mc->autodetectbuf[0] << 8) | mc->autodetectbuf[1]; + mc->type = MC_TYPE_FRAM; + mc->size = MC_SIZE_256KBITS; + } + else if (mc->autodetectsize == (256+3)) + { + // Flash + addr = (mc->autodetectbuf[0] << 16) | + (mc->autodetectbuf[1] << 8) | + mc->autodetectbuf[2]; + mc->type = MC_TYPE_FLASH; + mc->size = MC_SIZE_2MBITS; + } + else if (mc->autodetectsize == (128+2)) + { + // 512 Kbit EEPROM + addr = (mc->autodetectbuf[0] << 8) | mc->autodetectbuf[1]; + mc->type = MC_TYPE_EEPROM2; + mc->size = MC_SIZE_512KBITS; + } + else if (mc->autodetectsize == (32+2)) + { + // 64 Kbit EEPROM + addr = (mc->autodetectbuf[0] << 8) | mc->autodetectbuf[1]; + mc->type = MC_TYPE_EEPROM2; + mc->size = MC_SIZE_64KBITS; + } + else if (mc->autodetectsize == (16+1)) + { + // 4 Kbit EEPROM + addr = mc->autodetectbuf[0]; + mc->type = MC_TYPE_EEPROM1; + mc->size = MC_SIZE_4KBITS; + } + else + { + // Assume it's a Flash non-page write + LOG("Flash detected(guessed). autodetectsize = %d\n", mc->autodetectsize); + addr = (mc->autodetectbuf[0] << 16) | + (mc->autodetectbuf[1] << 8) | + mc->autodetectbuf[2]; + mc->type = MC_TYPE_FLASH; + mc->size = MC_SIZE_2MBITS; + } + + size = mc->autodetectsize; + mc_realloc(mc, mc->type, mc->size); + memcpy(mc->data+addr, mc->autodetectbuf+mc->addr_size, size-mc->addr_size); + mc->autodetectsize = 0; + mc->write_enable = FALSE; + + // Generate file + if ((mc->fp = fopen(mc->filename, "wb+")) != NULL) + fwrite((void *)mc->data, 1, mc->size, mc->fp); + } + else if (mc->com == BM_CMD_WRITELOW) + { + if (mc->fp) + { + fseek(mc->fp, 0, SEEK_SET); + fwrite((void *)mc->data, 1, mc->size, mc->fp); // fix me + } + mc->write_enable = FALSE; + } + + mc->com = 0; } void mc_realloc(memory_chip_t *mc, int type, u32 size) @@ -83,20 +158,36 @@ void mc_realloc(memory_chip_t *mc, int type, u32 size) mc_alloc(mc, size); } -void mc_read_file(memory_chip_t *mc, char* filename) +void mc_load_file(memory_chip_t *mc, const char* filename) { - FILE* file = fopen(filename, "rb"); - if(file == NULL) return; - fread (mc->data, mc->size, 1, file); - fclose (file); -} + long size; + FILE* file = fopen(filename, "rb+"); + if(file == NULL) + { + mc->filename = strdup(filename); + return; + } -void mc_write_file(memory_chip_t *mc, char* filename) -{ - FILE* file = fopen(filename, "wb"); - if(file == NULL) return; - fwrite (mc->data, mc->size, 1, file); - fclose (file); + fseek(file, 0, SEEK_END); + size = ftell(file); + fseek(file, 0, SEEK_SET); + + if (size == MC_SIZE_4KBITS) + mc->type = MC_TYPE_EEPROM1; + else if (size == MC_SIZE_64KBITS) + mc->type = MC_TYPE_EEPROM2; + else if (size == MC_SIZE_256KBITS) + mc->type = MC_TYPE_FRAM; + else if (size == MC_SIZE_512KBITS) + mc->type = MC_TYPE_EEPROM2; + else if (size >= MC_SIZE_2MBITS) + mc->type = MC_TYPE_FLASH; + + mc->size = size; + + mc_realloc(mc, mc->type, mc->size); + fread (mc->data, 1, mc->size, file); + mc->fp = file; } u8 fw_transfer(memory_chip_t *mc, u8 data) @@ -180,9 +271,7 @@ u8 fw_transfer(memory_chip_t *mc, u8 data) u8 bm_transfer(memory_chip_t *mc, u8 data) { -// mc_read_file(mc,"test.sav"); - if(mc->com == BM_CMD_READLOW || mc->com == BM_CMD_READHIGH || - mc->com == BM_CMD_WRITELOW || mc->com == BM_CMD_WRITEHIGH) /* check if we are in a command that needs multiple byte address */ + if(mc->com == BM_CMD_READLOW || mc->com == BM_CMD_WRITELOW) /* check if we are in a command that needs multiple byte address */ { if(mc->addr_shift > 0) /* if we got a complete address */ { @@ -214,6 +303,13 @@ u8 bm_transfer(memory_chip_t *mc, u8 data) } } + else if(mc->com == BM_CMD_AUTODETECT) + { + // Store everything in a temporary + mc->autodetectbuf[mc->autodetectsize] = data; + mc->autodetectsize++; + return 0; + } else if(mc->com == BM_CMD_READSTATUS) { //LOG("Backup Memory Read Status: %02X\n", mc->write_enable << 1); @@ -228,6 +324,12 @@ u8 bm_transfer(memory_chip_t *mc, u8 data) case BM_CMD_WRITELOW: /* write command */ if(mc->write_enable) { + if(mc->type == MC_TYPE_AUTODETECT) + { + mc->com = BM_CMD_AUTODETECT; + break; + } + mc->addr = 0; mc->addr_shift = mc->addr_size; mc->com = BM_CMD_WRITELOW; @@ -256,6 +358,12 @@ u8 bm_transfer(memory_chip_t *mc, u8 data) case BM_CMD_WRITEHIGH: /* write command that's only available on ST M95040-W that I know of */ if(mc->write_enable) { + if(mc->type == MC_TYPE_AUTODETECT) + { + mc->com = BM_CMD_AUTODETECT; + break; + } + if (mc->type == MC_TYPE_EEPROM1) mc->addr = 0x100; else @@ -282,7 +390,6 @@ u8 bm_transfer(memory_chip_t *mc, u8 data) } } -// mc_write_file(mc,"test.sav"); return data; } diff --git a/desmume/src/mc.h b/desmume/src/mc.h index 93dd5ae63..16098dd4f 100644 --- a/desmume/src/mc.h +++ b/desmume/src/mc.h @@ -5,9 +5,11 @@ extern "C" { #endif +#include #include "types.h" #include "nds/serial.h" +#define MC_TYPE_AUTODETECT 0x0 #define MC_TYPE_EEPROM1 0x1 #define MC_TYPE_EEPROM2 0x2 #define MC_TYPE_FLASH 0x3 @@ -37,6 +39,10 @@ typedef struct u32 size; /* memory size */ BOOL writeable_buffer; /* is "data" writeable ? */ int type; /* type of Memory */ + char *filename; + FILE *fp; + u8 autodetectbuf[32768]; + int autodetectsize; } memory_chip_t; #define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */ @@ -45,6 +51,7 @@ typedef struct void mc_init(memory_chip_t *mc, int type); /* reset and init values for memory struct */ u8 *mc_alloc(memory_chip_t *mc, u32 size); /* alloc mc memory */ void mc_realloc(memory_chip_t *mc, int type, u32 size); /* realloc mc memory */ +void mc_load_file(memory_chip_t *mc, const char* filename); /* load save file and setup fp */ void mc_free(memory_chip_t *mc); /* delete mc memory */ void mc_reset_com(memory_chip_t *mc); /* reset communication with mc */ u8 fw_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from firmware */ diff --git a/desmume/src/windows/main.c b/desmume/src/windows/main.c index 803babaec..574a03fbe 100644 --- a/desmume/src/windows/main.c +++ b/desmume/src/windows/main.c @@ -285,6 +285,13 @@ int WINAPI WinMain (HINSTANCE hThisInstance, EnableMenuItem(menu, IDM_PAUSE, MF_GRAYED); } + CheckMenuItem(menu, IDC_SAVETYPE1, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menu, IDC_SAVETYPE2, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menu, IDC_SAVETYPE3, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menu, IDC_SAVETYPE4, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menu, IDC_SAVETYPE5, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menu, IDC_SAVETYPE6, MF_BYCOMMAND | MF_UNCHECKED); + while (GetMessage (&messages, NULL, 0, 0)) { // Translate virtual-key messages into character messages @@ -820,31 +827,36 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM NDS_Pause(); return 0; - #define saver(one,two,three,four,five) \ + #define saver(one,two,three,four,five, six) \ CheckMenuItem(menu, IDC_SAVETYPE1, MF_BYCOMMAND | one); \ CheckMenuItem(menu, IDC_SAVETYPE2, MF_BYCOMMAND | two); \ CheckMenuItem(menu, IDC_SAVETYPE3, MF_BYCOMMAND | three); \ CheckMenuItem(menu, IDC_SAVETYPE4, MF_BYCOMMAND | four); \ - CheckMenuItem(menu, IDC_SAVETYPE5, MF_BYCOMMAND | five); + CheckMenuItem(menu, IDC_SAVETYPE5, MF_BYCOMMAND | five); \ + CheckMenuItem(menu, IDC_SAVETYPE6, MF_BYCOMMAND | six); case IDC_SAVETYPE1: - saver(MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); + saver(MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); + mc_realloc(&MMU.bupmem, MC_TYPE_AUTODETECT,1); + return 0; + case IDC_SAVETYPE2: + saver(MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM1,MC_SIZE_4KBITS); return 0; - case IDC_SAVETYPE2: - saver(MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); + case IDC_SAVETYPE3: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM2,MC_SIZE_64KBITS); return 0; - case IDC_SAVETYPE3: - saver(MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED); + case IDC_SAVETYPE4: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED); mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM2,MC_SIZE_512KBITS); return 0; - case IDC_SAVETYPE4: - saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED); + case IDC_SAVETYPE5: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED); mc_realloc(&MMU.bupmem, MC_TYPE_FRAM,MC_SIZE_256KBITS); return 0; - case IDC_SAVETYPE5: - saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED); + case IDC_SAVETYPE6: + saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED); mc_realloc(&MMU.bupmem, MC_TYPE_FLASH,MC_SIZE_2MBITS); return 0; diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index 816c3af71..33e5506ac 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -92,6 +92,7 @@ void refreshAll(); #define IDC_SAVETYPE3 184 #define IDC_SAVETYPE4 185 #define IDC_SAVETYPE5 186 +#define IDC_SAVETYPE6 187 #define IDD_MEM_VIEWER 301 #define IDC_8_BIT 302 diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index a288ed2cc..edc2daf6b 100644 --- a/desmume/src/windows/resources.rc +++ b/desmume/src/windows/resources.rc @@ -312,11 +312,12 @@ MENU_PRINCIPAL MENU { POPUP "&Save Type" { - MENUITEM "&EEPROM 4kbit", IDC_SAVETYPE1 - MENUITEM "&EEPROM 64kbit", IDC_SAVETYPE2 - MENUITEM "&EEPROM 512kbit", IDC_SAVETYPE3 - MENUITEM "&FRAM 256kbit", IDC_SAVETYPE4 - MENUITEM "&FLASH 2mbit", IDC_SAVETYPE5 + MENUITEM "Autodetect", IDC_SAVETYPE1 + MENUITEM "EEPROM 4kbit", IDC_SAVETYPE2 + MENUITEM "EEPROM 64kbit", IDC_SAVETYPE3 + MENUITEM "EEPROM 512kbit", IDC_SAVETYPE4 + MENUITEM "FRAM 256kbit", IDC_SAVETYPE5 + MENUITEM "FLASH 2mbit", IDC_SAVETYPE6 } } POPUP "&Tools"