diff --git a/desmume/src/MMU.c b/desmume/src/MMU.c index 3d30b4732..cbc18a6b3 100644 --- a/desmume/src/MMU.c +++ b/desmume/src/MMU.c @@ -263,12 +263,12 @@ void MMUInit(void) { for(i = 0;i < 16;i++) FIFOInit(MMU.fifos + i); - mc_init(&MMU.spi7.fw, MC_TYPE_FLASH); /* init fw device */ - mc_alloc(&MMU.spi7.fw, NDS_FW_SIZE_V1); + mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ + mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); // Init Backup Memory device, this should really be done when the rom is loaded - mc_init(&MMU.spi7.bupmem, MC_TYPE_EEPROM2); - mc_alloc(&MMU.spi7.bupmem, 65536); // For now we're use 512Kbit support. Eventually this should be detected when 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 } void MMUDeInit(void) { @@ -786,7 +786,7 @@ void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) AUX_SPI_CNT = val; if (val == 0) - mc_reset_com(&MMU.spi7.bupmem); /* reset backup memory device communication */ + mc_reset_com(&MMU.bupmem); /* reset backup memory device communication */ return; case CARD_EEPDATA: @@ -795,7 +795,7 @@ void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) AUX_SPI_CMD = val & 0xFF; } - MEM_16(MMU.MMU_MEM[proc], CARD_EEPDATA) = bm_transfer(&MMU.spi7.bupmem, val); /* transfer data to backup memory chip and receive back */ + MEM_16(MMU.MMU_MEM[proc], CARD_EEPDATA) = bm_transfer(&MMU.bupmem, val); /* transfer data to backup memory chip and receive back */ return; case REG_SPICNT : @@ -803,9 +803,9 @@ void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) { SPI_CNT = val; - //MMU.spi7.fw.com == 0; /* reset fw device communication */ + //MMU.fw.com == 0; /* reset fw device communication */ - mc_reset_com(&MMU.spi7.fw); /* reset fw device communication */ + mc_reset_com(&MMU.fw); /* reset fw device communication */ } MEM_16(MMU.MMU_MEM[proc], REG_SPICNT) = val; @@ -832,7 +832,7 @@ void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) MEM_16(MMU.MMU_MEM[proc], REG_SPIDATA) = 0; break; } - MEM_16(MMU.MMU_MEM[proc], REG_SPIDATA) = fw_transfer(&MMU.spi7.fw, val); /* transfer data to fw chip and receive back */ + MEM_16(MMU.MMU_MEM[proc], REG_SPIDATA) = fw_transfer(&MMU.fw, val); /* transfer data to fw chip and receive back */ return; case SPI_DEVICE_TOUCH: diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index 3537fb0f2..9fa7650a4 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -26,7 +26,8 @@ #include "dscard.h" #include "arm9/ARM9.h" -#include "arm7/spi.h" +#include "nds/serial.h" +#include "mc.h" extern char szRomPath[512]; @@ -88,9 +89,10 @@ typedef struct { u32 DMACrt[2][4]; BOOL DMAing[2][4]; - nds7_spi_t spi7; /* NOTICE: arm7 only, perhaps should be moved in an arm7-specific struct */ + memory_chip_t fw; + memory_chip_t bupmem; - nds_dscard dscard[2]; + nds_dscard dscard[2]; } MMU_struct; diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index e70ce3ab3..09235dbcd 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -9,8 +9,7 @@ libdesmume_a_SOURCES = \ debug.c debug.h \ MMU.c MMU.h NDSSystem.c NDSSystem.h \ thumb_instructions.c thumb_instructions.h \ - arm7/fw.c arm7/fw.h \ - arm7/spi.c arm7/spi.h \ + mc.c mc.h \ arm9/GPU.c arm9/GPU.h \ arm9/ARM9.c arm9/ARM9.h \ windows/cflash.c windows/cflash.h fs.h \ diff --git a/desmume/src/mc.c b/desmume/src/mc.c new file mode 100644 index 000000000..fce6c7ba7 --- /dev/null +++ b/desmume/src/mc.c @@ -0,0 +1,245 @@ +#include +#include "debug.h" +#include "types.h" +#include "mc.h" + +#define FW_CMD_READ 0x3 +#define FW_CMD_WRITEDISABLE 0x4 +#define FW_CMD_READSTATUS 0x5 +#define FW_CMD_WRITEENABLE 0x6 +#define FW_CMD_PAGEWRITE 0xA + +#define BM_CMD_WRITESTATUS 0x1 +#define BM_CMD_WRITELOW 0x2 +#define BM_CMD_READLOW 0x3 +#define BM_CMD_WRITEDISABLE 0x4 +#define BM_CMD_READSTATUS 0x5 +#define BM_CMD_WRITEENABLE 0x6 +#define BM_CMD_WRITEHIGH 0xA +#define BM_CMD_READHIGH 0xB + +void mc_init(memory_chip_t *mc, int type) +{ + mc->com = 0; + mc->addr = 0; + mc->addr_shift = 0; + mc->data = NULL; + mc->size = 0; + mc->write_enable = FALSE; + mc->writeable_buffer = FALSE; + mc->type = type; + + switch(mc->type) + { + case MC_TYPE_EEPROM1: + mc->addr_size = 1; + break; + case MC_TYPE_EEPROM2: + mc->addr_size = 2; + break; + case MC_TYPE_FLASH: + mc->addr_size = 3; + break; + default: break; + } +} + +u8 *mc_alloc(memory_chip_t *mc, u32 size) +{ + u8 *buffer; + buffer = malloc(size); + if(!buffer) { return NULL; } + mc->data = buffer; + mc->size = size; + mc->writeable_buffer = TRUE; +} + +void mc_free(memory_chip_t *mc) +{ + if(mc->data) free(mc->data); + mc_init(mc, 0); +} + +void mc_reset_com(memory_chip_t *mc) +{ + mc->com = 0; +} + +u8 fw_transfer(memory_chip_t *mc, u8 data) +{ + if(mc->com == FW_CMD_READ || mc->com == FW_CMD_PAGEWRITE) /* check if we are in a command that needs 3 bytes address */ + { + if(mc->addr_shift > 0) /* if we got a complete address */ + { + mc->addr_shift--; + mc->addr |= data << (mc->addr_shift * 8); /* argument is a byte of address */ + } + else /* if we have received 3 bytes of address, proceed command */ + { + switch(mc->com) + { + case FW_CMD_READ: + if(mc->addr < mc->size) /* check if we can read */ + { + data = mc->data[mc->addr]; /* return byte */ + mc->addr++; /* then increment address */ + } + break; + + case FW_CMD_PAGEWRITE: + if(mc->addr < mc->size) + { + mc->data[mc->addr] = data; /* write byte */ + mc->addr++; + } + break; + } + + } + } + else if(mc->com == FW_CMD_READSTATUS) + { + return 0; + } + else /* finally, check if it's a new command */ + { + switch(data) + { + case 0: break; /* nothing */ + + case FW_CMD_READ: /* read command */ + mc->addr = 0; + mc->addr_shift = 3; + mc->com = FW_CMD_READ; + break; + + case FW_CMD_WRITEENABLE: /* enable writing */ + if(mc->writeable_buffer) { mc->write_enable = TRUE; } + break; + + case FW_CMD_WRITEDISABLE: /* disable writing */ + mc->write_enable = FALSE; + break; + + case FW_CMD_PAGEWRITE: /* write command */ + if(mc->write_enable) + { + mc->addr = 0; + mc->addr_shift = 3; + mc->com = FW_CMD_PAGEWRITE; + } + else { data = 0; } + break; + + case FW_CMD_READSTATUS: /* status register command */ + mc->com = FW_CMD_READSTATUS; + break; + + default: + LOG("Unhandled FW command: %02X\n", data); + break; + } + } + + return data; +} + +u8 bm_transfer(memory_chip_t *mc, u8 data) +{ + 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 */ + { + mc->addr_shift--; + mc->addr |= data << (mc->addr_shift * 8); /* argument is a byte of address */ + } + else /* if we have received all bytes of address, proceed command */ + { + switch(mc->com) + { + case BM_CMD_READLOW: + if(mc->addr < mc->size) /* check if we can read */ + { + LOG("Read Backup Memory addr %08X(%02X)\n", mc->addr, mc->data[mc->addr]); + data = mc->data[mc->addr]; /* return byte */ + mc->addr++; /* then increment address */ + } + break; + + case BM_CMD_WRITELOW: + if(mc->addr < mc->size) + { + LOG("Write Backup Memory addr %08X with %02X\n", mc->addr, data); + mc->data[mc->addr] = data; /* write byte */ + mc->addr++; + } + break; + } + + } + } + else if(mc->com == BM_CMD_READSTATUS) + { + LOG("Backup Memory Read Status: %02X\n", mc->writeable_buffer << 1); + return (mc->writeable_buffer << 1); + } + else /* finally, check if it's a new command */ + { + switch(data) + { + case 0: break; /* nothing */ + + case BM_CMD_WRITELOW: /* write command */ + if(mc->write_enable) + { + mc->addr = 0; + mc->addr_shift = mc->addr_size; + mc->com = BM_CMD_WRITELOW; + } + else { data = 0; } + break; + + case BM_CMD_READLOW: /* read command */ + mc->addr = 0; + mc->addr_shift = mc->addr_size; + mc->com = BM_CMD_READLOW; + break; + + case BM_CMD_WRITEDISABLE: /* disable writing */ + mc->write_enable = FALSE; + break; + + case BM_CMD_READSTATUS: /* status register command */ + mc->com = BM_CMD_READSTATUS; + break; + + case BM_CMD_WRITEENABLE: /* enable writing */ + if(mc->writeable_buffer) { mc->write_enable = TRUE; } + break; + + case BM_CMD_WRITEHIGH: /* write command that's only available on ST M95040-W that I know of */ + if(mc->write_enable) + { + mc->addr = 0x1; + mc->addr_shift = mc->addr_size; + mc->com = BM_CMD_WRITELOW; + } + else { data = 0; } + break; + + case BM_CMD_READHIGH: /* read command that's only available on ST M95040-W that I know of */ + mc->addr = 0x1; + mc->addr_shift = mc->addr_size; + mc->com = BM_CMD_READLOW; + break; + + default: + LOG("Unhandled Backup Memory command: %02X\n", data); + break; + } + } + + return data; +} + diff --git a/desmume/src/mc.h b/desmume/src/mc.h new file mode 100644 index 000000000..bb9f9c53a --- /dev/null +++ b/desmume/src/mc.h @@ -0,0 +1,45 @@ +#ifndef __FW_H__ +#define __FW_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "nds/serial.h" + +#define MC_TYPE_EEPROM1 0x1 +#define MC_TYPE_EEPROM2 0x2 +#define MC_TYPE_FLASH 0x3 + +typedef struct +{ + u8 com; /* persistent command actually handled */ + u32 addr; /* current address for reading/writing */ + u8 addr_shift; /* shift for address (since addresses are transfered by 3 bytes units) */ + u8 addr_size; /* size of addr when writing/reading */ + + BOOL write_enable; /* is write enabled ? */ + + u8 *data; /* memory data */ + u32 size; /* memory size */ + BOOL writeable_buffer; /* is "data" writeable ? */ + int type; /* type of Memory */ +} memory_chip_t; + +#define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */ +#define NDS_FW_SIZE_V2 (512 * 1024) /* size of fw memory on nds v2 */ + +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_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 */ +u8 bm_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from backup memory */ + +#ifdef __cplusplus +} +#endif + +#endif /*__FW_H__*/ +