-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
This commit is contained in:
cyberwarriorx 2006-11-17 03:12:22 +00:00
parent 46cc94f44f
commit 175d6e88e9
7 changed files with 184 additions and 37 deletions

View File

@ -265,14 +265,22 @@ void MMU_Init(void) {
mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */
mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); 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 // Init Backup Memory device, this should really be done when the rom is loaded
mc_init(&MMU.bupmem, MC_TYPE_EEPROM2); mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT);
mc_alloc(&MMU.bupmem, 65536); // For now we're use 512Kbit support. Eventually this should be detected when rom is loaded mc_alloc(&MMU.bupmem, 1);
} MMU.bupmem.fp = NULL;
}
void MMU_DeInit(void) { void MMU_DeInit(void) {
LOG("MMU deinit\n"); 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 //Card rom & ram

View File

@ -367,6 +367,17 @@ int NDS_LoadROM(const char *filename)
cflash_close(); cflash_close();
cflash_init(); 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; return i;
} }

View File

@ -9,6 +9,7 @@
#define FW_CMD_WRITEENABLE 0x6 #define FW_CMD_WRITEENABLE 0x6
#define FW_CMD_PAGEWRITE 0xA #define FW_CMD_PAGEWRITE 0xA
#define BM_CMD_AUTODETECT 0xFF
#define BM_CMD_WRITESTATUS 0x1 #define BM_CMD_WRITESTATUS 0x1
#define BM_CMD_WRITELOW 0x2 #define BM_CMD_WRITELOW 0x2
#define BM_CMD_READLOW 0x3 #define BM_CMD_READLOW 0x3
@ -37,7 +38,8 @@ void mc_init(memory_chip_t *mc, int type)
mc->write_enable = FALSE; mc->write_enable = FALSE;
mc->writeable_buffer = FALSE; mc->writeable_buffer = FALSE;
mc->type = type; mc->type = type;
mc->autodetectsize = 0;
switch(mc->type) switch(mc->type)
{ {
case MC_TYPE_EEPROM1: case MC_TYPE_EEPROM1:
@ -73,7 +75,80 @@ void mc_free(memory_chip_t *mc)
void mc_reset_com(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) 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); 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"); long size;
if(file == NULL) return; FILE* file = fopen(filename, "rb+");
fread (mc->data, mc->size, 1, file); if(file == NULL)
fclose (file); {
} mc->filename = strdup(filename);
return;
}
void mc_write_file(memory_chip_t *mc, char* filename) fseek(file, 0, SEEK_END);
{ size = ftell(file);
FILE* file = fopen(filename, "wb"); fseek(file, 0, SEEK_SET);
if(file == NULL) return;
fwrite (mc->data, mc->size, 1, file); if (size == MC_SIZE_4KBITS)
fclose (file); 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) 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) 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_WRITELOW) /* check if we are in a command that needs multiple byte address */
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->addr_shift > 0) /* if we got a complete 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) else if(mc->com == BM_CMD_READSTATUS)
{ {
//LOG("Backup Memory Read Status: %02X\n", mc->write_enable << 1); //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 */ case BM_CMD_WRITELOW: /* write command */
if(mc->write_enable) if(mc->write_enable)
{ {
if(mc->type == MC_TYPE_AUTODETECT)
{
mc->com = BM_CMD_AUTODETECT;
break;
}
mc->addr = 0; mc->addr = 0;
mc->addr_shift = mc->addr_size; mc->addr_shift = mc->addr_size;
mc->com = BM_CMD_WRITELOW; 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 */ case BM_CMD_WRITEHIGH: /* write command that's only available on ST M95040-W that I know of */
if(mc->write_enable) if(mc->write_enable)
{ {
if(mc->type == MC_TYPE_AUTODETECT)
{
mc->com = BM_CMD_AUTODETECT;
break;
}
if (mc->type == MC_TYPE_EEPROM1) if (mc->type == MC_TYPE_EEPROM1)
mc->addr = 0x100; mc->addr = 0x100;
else else
@ -282,7 +390,6 @@ u8 bm_transfer(memory_chip_t *mc, u8 data)
} }
} }
// mc_write_file(mc,"test.sav");
return data; return data;
} }

View File

@ -5,9 +5,11 @@
extern "C" { extern "C" {
#endif #endif
#include <stdio.h>
#include "types.h" #include "types.h"
#include "nds/serial.h" #include "nds/serial.h"
#define MC_TYPE_AUTODETECT 0x0
#define MC_TYPE_EEPROM1 0x1 #define MC_TYPE_EEPROM1 0x1
#define MC_TYPE_EEPROM2 0x2 #define MC_TYPE_EEPROM2 0x2
#define MC_TYPE_FLASH 0x3 #define MC_TYPE_FLASH 0x3
@ -37,6 +39,10 @@ typedef struct
u32 size; /* memory size */ u32 size; /* memory size */
BOOL writeable_buffer; /* is "data" writeable ? */ BOOL writeable_buffer; /* is "data" writeable ? */
int type; /* type of Memory */ int type; /* type of Memory */
char *filename;
FILE *fp;
u8 autodetectbuf[32768];
int autodetectsize;
} memory_chip_t; } memory_chip_t;
#define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */ #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 */ 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 */ 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_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_free(memory_chip_t *mc); /* delete mc memory */
void mc_reset_com(memory_chip_t *mc); /* reset communication with mc */ 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 */ u8 fw_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from firmware */

View File

@ -285,6 +285,13 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
EnableMenuItem(menu, IDM_PAUSE, MF_GRAYED); 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)) while (GetMessage (&messages, NULL, 0, 0))
{ {
// Translate virtual-key messages into character messages // Translate virtual-key messages into character messages
@ -820,31 +827,36 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
NDS_Pause(); NDS_Pause();
return 0; 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_SAVETYPE1, MF_BYCOMMAND | one); \
CheckMenuItem(menu, IDC_SAVETYPE2, MF_BYCOMMAND | two); \ CheckMenuItem(menu, IDC_SAVETYPE2, MF_BYCOMMAND | two); \
CheckMenuItem(menu, IDC_SAVETYPE3, MF_BYCOMMAND | three); \ CheckMenuItem(menu, IDC_SAVETYPE3, MF_BYCOMMAND | three); \
CheckMenuItem(menu, IDC_SAVETYPE4, MF_BYCOMMAND | four); \ 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: 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); mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM1,MC_SIZE_4KBITS);
return 0; return 0;
case IDC_SAVETYPE2: case IDC_SAVETYPE3:
saver(MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED); saver(MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED);
mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM2,MC_SIZE_64KBITS); mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM2,MC_SIZE_64KBITS);
return 0; return 0;
case IDC_SAVETYPE3: case IDC_SAVETYPE4:
saver(MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED); saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED,MF_UNCHECKED);
mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM2,MC_SIZE_512KBITS); mc_realloc(&MMU.bupmem, MC_TYPE_EEPROM2,MC_SIZE_512KBITS);
return 0; return 0;
case IDC_SAVETYPE4: case IDC_SAVETYPE5:
saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED); saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED,MF_UNCHECKED);
mc_realloc(&MMU.bupmem, MC_TYPE_FRAM,MC_SIZE_256KBITS); mc_realloc(&MMU.bupmem, MC_TYPE_FRAM,MC_SIZE_256KBITS);
return 0; return 0;
case IDC_SAVETYPE5: case IDC_SAVETYPE6:
saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED); saver(MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_UNCHECKED,MF_CHECKED);
mc_realloc(&MMU.bupmem, MC_TYPE_FLASH,MC_SIZE_2MBITS); mc_realloc(&MMU.bupmem, MC_TYPE_FLASH,MC_SIZE_2MBITS);
return 0; return 0;

View File

@ -92,6 +92,7 @@ void refreshAll();
#define IDC_SAVETYPE3 184 #define IDC_SAVETYPE3 184
#define IDC_SAVETYPE4 185 #define IDC_SAVETYPE4 185
#define IDC_SAVETYPE5 186 #define IDC_SAVETYPE5 186
#define IDC_SAVETYPE6 187
#define IDD_MEM_VIEWER 301 #define IDD_MEM_VIEWER 301
#define IDC_8_BIT 302 #define IDC_8_BIT 302

View File

@ -312,11 +312,12 @@ MENU_PRINCIPAL MENU
{ {
POPUP "&Save Type" POPUP "&Save Type"
{ {
MENUITEM "&EEPROM 4kbit", IDC_SAVETYPE1 MENUITEM "Autodetect", IDC_SAVETYPE1
MENUITEM "&EEPROM 64kbit", IDC_SAVETYPE2 MENUITEM "EEPROM 4kbit", IDC_SAVETYPE2
MENUITEM "&EEPROM 512kbit", IDC_SAVETYPE3 MENUITEM "EEPROM 64kbit", IDC_SAVETYPE3
MENUITEM "&FRAM 256kbit", IDC_SAVETYPE4 MENUITEM "EEPROM 512kbit", IDC_SAVETYPE4
MENUITEM "&FLASH 2mbit", IDC_SAVETYPE5 MENUITEM "FRAM 256kbit", IDC_SAVETYPE5
MENUITEM "FLASH 2mbit", IDC_SAVETYPE6
} }
} }
POPUP "&Tools" POPUP "&Tools"