gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > gamecard eeprom detection

#173254 - wintermute - Mon Mar 29, 2010 2:11 am

I've just finished rewriting the libnds eeprom detection code which should hopefully work as well as the prior code. I'd still like to get a few more data points to test with though so if you could compile this with svn libnds, or download the prebuilt one from http://davejmurphy.com/files/eepromtest.nds

Code:

#include <nds.h>
#include <stdio.h>

//---------------------------------------------------------------------------------
void pause() {
//---------------------------------------------------------------------------------
   iprintf("Press A ...\n");
   while(1) {
      scanKeys();
      if(keysDown() & KEY_A)
         break;
      swiWaitForVBlank();
   }
   scanKeys();
}

//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
   consoleDemoInit();
   
   sysSetCardOwner(BUS_OWNER_ARM9);

   while(1) {
      int pressed = 0;
      u8 header1[512];
      u8 header2[512];
      
      while(1) {
         cardReadHeader(header1);
         cardReadHeader(header2);
         if (memcmp(header1,header2,32) == 0) break;
         printf("Please eject & reinsert DS card.\n");
         pause();
      }
      header1[32] = 0;
      printf("%s\n", header1);
      
      int sr = cardEepromCommand(EEPROM_RDSR);
      int id = cardEepromReadID();
      
      printf("sr = %02x, id = %06x\n", sr, id);
      
      do {
         swiWaitForVBlank();
         scanKeys();
         pressed = keysDown();
      } while (!pressed);
      if (pressed & KEY_START) break;
   }
   return 0;
}


sr = 0xff, id =0xffffff - no save.
sr = 0xf0, id =0xffffff - 512 byte save.
sr = 0x00, id =0xffffff - 8k/64k save
sr = 0x00, id !=0xffffff - flash with 24 bit address.


I'm particularly interested in devices which have an ID code, sr = 0, id != 0xffffff. The upper byte is a manufacturer id, you can find a list at http://www.idhw.com/textual/chip/jedec_spd_man.html . The second byte is a device code, the third may be a dummy byte or have some special meaning. If we can get a list of the jedec id codes along with save sizes it should help with improving detection.

My MarioKart DS has an id of 0x621600 which is a Sanyo LE25FW203A 2mbit flash.

Someone was also asking me about the new pokemon games recently. These appear to have some sort of controller on the eeprom SPI which switches between IR for the pokewalker and the save chip, not entirely sure how this is done but there's some save related code which issues cardEepromCommand(0x08), expecting a response of 0xAA.

Edit: Just gone through my game collection and added TheLazy1's results

Code:

Band Brothers DX:               sr = 84, id = 202017    m25p64          64mbit
The Sims 2:                     sr = 00, id = 204012    m25p20          2mbit
Spore:Creatures                 sr = 00, id = 204012    m25p20          2mbit
Zelda: Phantom Hourglass        sr = 00, id = 204013    m25p40          4mbit
100 Classic Book Collection     sr = 00, id = 204014    m45pe80         8mbit
DS Browser                      sr = 00, id = 621600    LE25FW203A      2mbit   
Advance Wars: Dual Strike       sr = 00, id = 621600    LE25FW203A      2mbit
Starfox Command                 sr = 00, id = 621600    LE25FW203A      2mbit
Contact                         sr = 00, id = 621600    LE25FW203A      2mbit
Brain age                       sr = 00, id = 621600    LE25FW203A      2mbit
Mariokart DS                    sr = 00, id = 621600    LE25FW203A      2mbit

_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog


Last edited by wintermute on Tue Apr 13, 2010 8:04 pm; edited 2 times in total

#173255 - Lazy1 - Mon Mar 29, 2010 2:24 am

Rhythm Heaven: sr = 00, id = ffffff
GTA Chinatown wars: sr = 00, id = ffffff
Brain age: sr = 00, id = 621600
Mariokart DS: sr = 00, id = 621600
Worms open warfare 2: sr = 00, id = ffffff
The Sims 2: sr = 00, id = 204012
Meteos: sr = 00, id = ffffff
Super Mario 64 DS: sr = 80, id = ffffff

#173271 - Stephanie - Mon Mar 29, 2010 1:11 pm

Edit: I went through all my carts again and discovered that Pokemon SoulSilver returns a different pair of variables every time its queried. It seems almost random.

Code:
Pokemon SS        sr=??        id=??????
DS Training       sr=00        id=204012
DS Browser        sr=00        id=204012
Startrek:TA       sr=00        id=ffffff
D_Survivor        sr=00        id=ffffff
Crossword         sr=00        id=ffffff
Moon              sr=00        id=ffffff
Timeace           sr=f0        id=ffffff
Dementium01       sr=00        id=ffffff


Incidentally, I had disassembled my Pokemon SoulSilver and figured out the eeprom was being controlled by a mystery mcu chip. Some info is here:
http://planetstephanie.net/2010/03/20/pokemon-soulsilver-save-hack/

The NDS Adaptor Plus can write/read the eeprom so there must be some software mehod to address it... some command that tells that mcu to enable the eeprom.

-Stephanie

#173297 - wintermute - Tue Mar 30, 2010 2:59 pm

The 45PE40 is a Numonyx/ST Micro 4mbit flash which should return 0x204013 for the id. The random values are probably either coming from the mcu or data from the IR.

Normmatt found some code in the pokemon games which he thought was antipiracy protection but may actually be an mcu command to switch between IR & eeprom. Not entirely sure what it's expecting but the code added to desmume svn looks like it's sending 0x08 and waiting for a response of 0xaa.

Code:

Index: src/MMU.cpp
===================================================================
--- src/MMU.cpp   (revision 2878)
+++ src/MMU.cpp   (revision 2879)
@@ -2245,7 +2245,7 @@
                MMU.AUX_SPI_CMD = val & 0xFF;
 
             //T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val));
-            T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val));
+            T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val,ARMCPU_ARM9));
             return;
 
          case REG_DISPA_BG0CNT :
@@ -3184,7 +3184,7 @@
                MMU.AUX_SPI_CMD = val & 0xFF;
 
             //T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val));
-            T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val));
+            T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val,ARMCPU_ARM7));
          return;
 
          case REG_SPICNT :
Index: src/mc.h
===================================================================
--- src/mc.h   (revision 2878)
+++ src/mc.h   (revision 2879)
@@ -83,7 +83,7 @@
    
    //commands from mmu
    void reset_command();
-   u8 data_command(u8);
+   u8 data_command(u8,int);
 
    //this info was saved before the last reset (used for savestate compatibility)
    struct SavedInfo
Index: src/mc.cpp
===================================================================
--- src/mc.cpp   (revision 2878)
+++ src/mc.cpp   (revision 2879)
@@ -376,7 +376,7 @@
 
    com = 0;
 }
-u8 BackupDevice::data_command(u8 val)
+u8 BackupDevice::data_command(u8 val, int cpu)
 {
    if(com == BM_CMD_READLOW || com == BM_CMD_WRITELOW)
    {
@@ -440,6 +440,10 @@
       switch(val)
       {
          case 0: break; //??
+
+         case 8:
+            val = 0xAA;
+            break;
          
          case BM_CMD_WRITEDISABLE:
             write_enable = FALSE;
@@ -479,7 +483,7 @@
             break;
 
          default:
-            printf("COMMAND: Unhandled Backup Memory command: %02X\n", val);
+            printf("COMMAND%c: Unhandled Backup Memory command: %02X FROM %08X\n",(cpu==ARMCPU_ARM9)?'9':'7',val, NDS_ARM9.instruct_adr);
             break;
       }
    }
@@ -493,9 +497,9 @@
    if(size<addr)
    {
       data.resize(addr);
+      for(u32 i=size;i<addr;i++)
+         data[i] = kUninitializedSaveDataValue;
    }
-   for(u32 i=size;i<addr;i++)
-      data[i] = kUninitializedSaveDataValue;
 }

_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#173309 - Ludo6431 - Wed Mar 31, 2010 2:32 am

MP HUNTERS sr=00 id=621600
_________________
Sorry for my poor english, I'm french.

#173462 - yellowstar - Wed Apr 07, 2010 7:58 pm

Spirit Tracks: sr = 00, id = 204014
This EEPROM chip can't be written to the same sequential way as other chips it seems. Backing up seems to work, writing doesn't: bytes are randomly corrupted in the second half of the EEPROM/second save file. I dunno if that could be worked around by rewriting corrupted blocks/sectors, I haven't tried that.

#173463 - wintermute - Wed Apr 07, 2010 9:18 pm

Did you erase the chip before writing to it?
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#173466 - yellowstar - Thu Apr 08, 2010 1:14 am

wintermute wrote:
Did you erase the chip before writing to it?

Yes, I did erase it. The EEPROM gets corrupted with both savsender and a wifi EEPROM app I wrote.

#173541 - zigg - Tue Apr 13, 2010 4:53 pm

Were you aware this doesn't work on a DSi? 00's all 'round. I recall there were similar problems with savsender and probably some of my own stuff.

WarioWare D.I.Y., which I understand from the Iwata Asks interview, has a NAND (Flash?) On my old DS it shows up as

DSMIO
sr = ff, id = ffffff

Band Brothers DX (64mbit Flash):

BANDBROS DX
sr = 84, id = 202017

I have a patched card.c from stuff I was working on last year that can apparently deal with BBDX. I don't think I got around to trying writes, but reading seemed to work OK. I can send it on if you'd like to see, but it was literally just a matter of upping all the limits.

#173542 - wintermute - Tue Apr 13, 2010 8:02 pm

zigg wrote:
Were you aware this doesn't work on a DSi? 00's all 'round. I recall there were similar problems with savsender and probably some of my own stuff.


You can't currently hotswap gamecards on a DSi with homebrew code. Obviously the DSi firmware can so we may be able to figure it out at some point but not from DS mode.

Quote:

WarioWare D.I.Y., which I understand from the Iwata Asks interview, has a NAND (Flash?) On my old DS it shows up as

DSMIO
sr = ff, id = ffffff


WarioWare D.I.Y. appears to be entirely flash - I have it on good authority that the card contains only one chip. This probably uses gamecard commands rather than SPI for NAND access.


Quote:

Band Brothers DX (64mbit Flash):

BANDBROS DX
sr = 84, id = 202017

I have a patched card.c from stuff I was working on last year that can apparently deal with BBDX. I don't think I got around to trying writes, but reading seemed to work OK. I can send it on if you'd like to see, but it was literally just a matter of upping all the limits.


That would be interesting, yes. I think the current code might handle it ok with a couple of modifications though. The chip appears to be an m25p64 and the status register bits say the top two sectors are write protected.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#174820 - zigg - Wed Jul 21, 2010 1:05 pm

wintermute wrote:
You can't currently hotswap gamecards on a DSi with homebrew code. Obviously the DSi firmware can so we may be able to figure it out at some point but not from DS mode.


I had a follow-on question about this... have you (or has anyone else) tried to read/write blindly in DS mode on a DSi? Obviously we can't detect the save type any longer, but if we already knew the correct type, could it be done?

I may try to do this if nobody else has.

#174823 - wintermute - Wed Jul 21, 2010 8:28 pm

It's kind of difficult to read from a flash chip that has no power ...
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#174824 - zigg - Wed Jul 21, 2010 8:39 pm

wintermute wrote:
It's kind of difficult to read from a flash chip that has no power ...


Ooh. Yes, sorry, I had an incomplete understanding of the problem at hand. :)