Language…
9 users online: Alpi_91, Blizzard Buffalo, Chuycraft,  dacin, Diego, Golden Yoshi, MANGOMILK, NiHiL00098, signature_steve - Guests: 146 - Bots: 105
Users: 69,764 (2,526 active)
Latest user: Tomfires007

EEPROM

EEPROM (save files) thread

Will start with a few questions

Tarek and I are trying to mess around with EEPROM stuff. With Nemu's debugger, I had no trouble extending the file offset limit and disabling checksum protection.
Code
rom+0x3436C = 0x10000003 // bypass eeprom checksum comparisons
rom+0xE3B04 = 0x29E10100 // extend the *u8 eeprom offset limit to 16kbits 

(^ these changes require rom main checksum (0x10) nop/update)
With Nemu64, these changes work like a charm; I can make the game save whatever I want to EEPROM+0x7F0 for example.

But I believe Nemu64 makes all EEPROM files 0x800 bytes by default . In PJ64 when you try to start the rom with 16kbit eeprom selected, you're met with a black screen of death.

So we were wondering...
  • Is there an important eeprom size setting/protection somewhere in rom?
  • Would it be possible to replace/extend an eeprom chip on a real cartridge?
  • Why is project64 kill when using the 16kbit setting?





Related functions:
Code
80328AF0 // write 8 bytes to eeprom
80329150 // read 8 bytes from eeprom
802792C0 // eeprom 2byte checksum calculator (returns to V0)


Related areas:
Code
80207700 // eeprom mirror
Will you go to EEPROM with me?

Lol, on a serious note, great find man!
To bump this. You basically just increase the limits in both (or all four functions if we include osEepromLongRead and osEepromLondWrite) to around 0x0100 or higher.

0xE4164 -> Change: (for EEPROM Read subroutine)

Code
SLTI AT, $0041


And change the limit from $0041 to $0100. (If you know, 0x41 is the default eeprom limit. By calculating 0x41 * 8 (as each EEPROM Block is 8 bytes long) you get the EEPROM Address. So, basically it just checks if the address we write is less than 0x41 * 8. If yes, then it works, if not, you won't see your EEPROM being written or anything. Now, as said before, change the limit:

Code
SLTI AT, $0100


You do the same on 0xE3B04 (eeprom write function).

Next thing you need to know is the eeprom ram bank, which starts at 0x80207700. To test out, if our shit worked, we write some test code and write over the 0x41 limit or directly on it. 0x80207908 in our case. I do it in pseudo-code, cause asm seems not to be everyone's strength here:
Code
u16 mycoins = 0x80207908;

main()
{
  printint(20, 60, "COINS %d", mycoins) // this displays mycoins variable in decimal.

  if(d-paddown)
  {
    mycoins += 1;
    temparray[] = {0,0};
    temparray[1] = mycoins;
    osEepromwrite(0x8033AF78, 0x41, temparray);
   }
}


If we press D-Pad Down mycoins is increased by one, the 2nd index of our temp array (2nd 4 byte block, right) is assigned to mycoins and then written to 0x41 * 8 in EEPROM. If you close the game now and look into your EEPROM (which is mostly stored directly in your Project64 1.6/Saves folder or in C:\Users\<YourName>\AppData\Local\VirtualStore\Program Files (x86)\Project64 1.6\Save.

If you open it up and look at 0x208, you should see your saved coin value (in hexadecimal, of course). Like here:



So, basically all you need is an array, which the 2nd index is later assigned to the target variable we want to write to eeprom. We can also read the eeprom with the very same method:

Code
u16 mycoins = 0x80207908;
tempreadarray[] = {0,0}; // Temporary Array for reading EEPROM.

main()
{
  printint(20, 60, "COINS %d", mycoins) // this displays mycoins variable in decimal.

  if(d-paddown)
  {
    mycoins += 1;
    temparray[] = {0,0};
    temparray[1] = mycoins;
    osEepromwrite(0x8033AF78, 0x41, temparray);
   }
   
   if(d-padup)
   {
     osEepromread(0x8033AF78, 0x41, tempreadarray);
     mycoins = tempreadarray[1];
   }
}


We assign mycoins with the 2nd index of tempreadarray obviously, as we stored our write array also with the 2nd index. So we read the 2nd index and assign it to mycoins.

In case you ask, 0x8033AF78 is a pointer to Message Queue. To be more specific, they actually provide a nice communication and synchronization mechanism. So, message queues are often used between threads and events.

To sum it up, you actually don't need to change any settings in PJ64. You can keep it on default.

i dont know what the array stuff is supposed to mean, but this is what i've got:


Originally posted by Tarek
$80329150 ist read
$80328AF0 ist write

(quite important to mention for asm hacker)

A0: allways 8033afa78
A1: offset in EEprom to write to/read from divided by 8
A2: offset in ram to write to/read from