-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:
parent
46cc94f44f
commit
175d6e88e9
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
143
desmume/src/mc.c
143
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue