updated EEPROM code, gmv fixed
[picodrive.git] / Pico / Misc.c
index 8e89a4f..38c381d 100644 (file)
@@ -131,54 +131,48 @@ const unsigned short vcounts[] = {
 // rarely used EEPROM SRAM code\r
 // known games which use this:\r
 // Wonder Boy in Monster World, Megaman - The Wily Wars (X24C01, 128 bytes)\r
-// NFL Quarterback Club*, Frank Thomas Big Hurt Baseball (X24C04?)\r
-// College Slam, Blockbuster World Video Game Championship II, NBA Jam (X24C04?)\r
-// HardBall '95\r
 \r
-// the above sports games use addr 0x200000 for SCL line (handled in Memory.c)\r
+// (see Genesis Plus for Wii/GC code and docs for info,\r
+//  full game list and better code).\r
 \r
 unsigned int lastSSRamWrite = 0xffff0000;\r
 \r
-// sram_reg: LAtd sela (L=pending SCL, A=pending SDA, t=type(1==uses 0x200000 for SCL and 2K bytes),\r
+// sram_reg: LAtd sela (L=pending SCL, A=pending SDA, t=(unused),\r
 //                      d=SRAM was detected (header or by access), s=started, e=save is EEPROM, l=old SCL, a=old SDA)\r
 PICO_INTERNAL void SRAMWriteEEPROM(unsigned int d) // ???? ??la (l=SCL, a=SDA)\r
 {\r
-  unsigned int sreg = Pico.m.sram_reg, saddr = Pico.m.sram_addr, scyc = Pico.m.sram_cycle, ssa = Pico.m.sram_slave;\r
+  unsigned int sreg = Pico.m.sram_reg, saddr = Pico.m.eeprom_addr, scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave;\r
 \r
-  //printf("EEPROM write %i\n", d&3);\r
-  sreg |= saddr&0xc000; // we store word count in add reg: dw?a aaaa ...  (d=word count detected, w=words(0==use 2 words, else 1))\r
+  elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1,\r
+    (d&2)>>1, d&1, SekCyclesDoneT()-lastSSRamWrite);\r
   saddr&=0x1fff;\r
 \r
   if(sreg & d & 2) {\r
     // SCL was and is still high..\r
     if((sreg & 1) && !(d&1)) {\r
       // ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter\r
-      //dprintf("-start-");\r
-      if(!(sreg&0x8000) && scyc >= 9) {\r
-        if(scyc != 28) sreg |= 0x4000; // 1 word\r
-        //dprintf("detected word count: %i", scyc==28 ? 2 : 1);\r
-        sreg |= 0x8000;\r
-      }\r
+      elprintf(EL_EEPROM, "eeprom: -start-");\r
       //saddr = 0;\r
       scyc = 0;\r
       sreg |= 8;\r
     } else if(!(sreg & 1) && (d&1)) {\r
       // SDA went high == stop command\r
-      //dprintf("-stop-");\r
+      elprintf(EL_EEPROM, "eeprom: -stop-");\r
       sreg &= ~8;\r
     }\r
   }\r
-  else if((sreg & 8) && !(sreg & 2) && (d&2)) {\r
+  else if((sreg & 8) && !(sreg & 2) && (d&2))\r
+  {\r
     // we are started and SCL went high - next cycle\r
     scyc++; // pre-increment\r
-    if(sreg & 0x20) {\r
+    if(SRam.eeprom_type) {\r
       // X24C02+\r
       if((ssa&1) && scyc == 18) {\r
         scyc = 9;\r
         saddr++; // next address in read mode\r
-        if(sreg&0x4000) saddr&=0xff; else saddr&=0x1fff; // mask\r
+        /*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask\r
       }\r
-      else if((sreg&0x4000) && scyc == 27) scyc = 18;\r
+      else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18;\r
       else if(scyc == 36) scyc = 27;\r
     } else {\r
       // X24C01\r
@@ -187,21 +181,22 @@ PICO_INTERNAL void SRAMWriteEEPROM(unsigned int d) // ???? ??la (l=SCL, a=SDA)
         if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode\r
       }\r
     }\r
-    //dprintf("scyc: %i", scyc);\r
+    elprintf(EL_EEPROM, "eeprom: scyc: %i", scyc);\r
   }\r
-  else if((sreg & 8) && (sreg & 2) && !(d&2)) {\r
+  else if((sreg & 8) && (sreg & 2) && !(d&2))\r
+  {\r
     // we are started and SCL went low (falling edge)\r
-    if(sreg & 0x20) {\r
+    if(SRam.eeprom_type) {\r
       // X24C02+\r
       if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles\r
-      else if( (!(sreg&0x4000) && scyc > 27) || ((sreg&0x4000) && scyc > 18) ) {\r
+      else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) {\r
         if(!(ssa&1)) {\r
           // data write\r
           unsigned char *pm=SRam.data+saddr;\r
           *pm <<= 1; *pm |= d&1;\r
           if(scyc == 26 || scyc == 35) {\r
             saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented\r
-            //dprintf("w done: %02x; addr inc: %x", *pm, saddr);\r
+            elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm);\r
           }\r
           SRam.changed = 1;\r
         }\r
@@ -209,14 +204,17 @@ PICO_INTERNAL void SRAMWriteEEPROM(unsigned int d) // ???? ??la (l=SCL, a=SDA)
         if(!(ssa&1)) {\r
           // we latch another addr bit\r
           saddr<<=1;\r
-          if(sreg&0x4000) saddr&=0xff; else saddr&=0x1fff; // mask\r
+          if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask\r
           saddr|=d&1;\r
-          //if(scyc==17||scyc==26) dprintf("addr reg done: %x", saddr);\r
+          if(scyc==17||scyc==26) {\r
+            elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr);\r
+            if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too\r
+          }\r
         }\r
       } else {\r
         // slave address\r
         ssa<<=1; ssa|=d&1;\r
-        //if(scyc==8) dprintf("slave done: %x", ssa);\r
+        if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa);\r
       }\r
     } else {\r
       // X24C01\r
@@ -228,77 +226,89 @@ PICO_INTERNAL void SRAMWriteEEPROM(unsigned int d) // ???? ??la (l=SCL, a=SDA)
           *pm <<= 1; *pm |= d&1;\r
           if(scyc == 17) {\r
             saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented\r
-            //dprintf("addr inc: %x", saddr>>1);\r
+            elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm);\r
           }\r
           SRam.changed = 1;\r
         }\r
       } else {\r
         // we latch another addr bit\r
         saddr<<=1; saddr|=d&1; saddr&=0xff;\r
-        //if(scyc==8) dprintf("addr done: %x", saddr>>1);\r
+        if(scyc==8) elprintf(EL_EEPROM, "eeprom: addr done: %x", saddr>>1);\r
       }\r
     }\r
   }\r
 \r
   sreg &= ~3; sreg |= d&3; // remember SCL and SDA\r
-  Pico.m.sram_reg  = (unsigned char)  sreg;\r
-  Pico.m.sram_addr = (unsigned short)(saddr|(sreg&0xc000));\r
-  Pico.m.sram_cycle= (unsigned char)  scyc;\r
-  Pico.m.sram_slave= (unsigned char)  ssa;\r
+  Pico.m.sram_reg    = (unsigned char) sreg;\r
+  Pico.m.eeprom_cycle= (unsigned char) scyc;\r
+  Pico.m.eeprom_slave= (unsigned char) ssa;\r
+  Pico.m.eeprom_addr = (unsigned short)saddr;\r
 }\r
 \r
 PICO_INTERNAL_ASM unsigned int SRAMReadEEPROM(void)\r
 {\r
-  unsigned int shift, d=0;\r
-  unsigned int sreg, saddr, scyc, ssa;\r
+  unsigned int shift, d;\r
+  unsigned int sreg, saddr, scyc, ssa, interval;\r
 \r
   // flush last pending write\r
   SRAMWriteEEPROM(Pico.m.sram_reg>>6);\r
 \r
-  sreg = Pico.m.sram_reg; saddr = Pico.m.sram_addr&0x1fff; scyc = Pico.m.sram_cycle; ssa = Pico.m.sram_slave;\r
-//  if(!(sreg & 2) && (sreg&0x80)) scyc++; // take care of raising edge now to compensate lag\r
+  sreg = Pico.m.sram_reg; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave;\r
+  interval = SekCyclesDoneT()-lastSSRamWrite;\r
+  d = (sreg>>6)&1; // use SDA as "open bus"\r
 \r
-  if(SekCyclesDoneT()-lastSSRamWrite < 46) {\r
-    // data was just written, there was no time to respond (used by sports games)\r
-    d = (sreg>>6)&1;\r
-  } else if((sreg & 8) && scyc > 9 && scyc != 18 && scyc != 27) {\r
+  // NBA Jam is nasty enough to read <before> raising the SCL and starting the new cycle.\r
+  // this is probably valid because data changes occur while SCL is low and data can be read\r
+  // before it's actual cycle begins.\r
+  if (!(sreg&0x80) && interval >= 24) {\r
+    elprintf(EL_EEPROM, "eeprom: early read, cycles=%i", interval);\r
+    scyc++;\r
+  }\r
+\r
+  if (!(sreg & 8)); // not started, use open bus\r
+  else if (scyc == 9 || scyc == 18 || scyc == 27) {\r
+    elprintf(EL_EEPROM, "eeprom: r ack");\r
+    d = 0;\r
+  } else if (scyc > 9 && scyc < 18) {\r
     // started and first command word received\r
     shift = 17-scyc;\r
-    if(sreg & 0x20) {\r
+    if (SRam.eeprom_type) {\r
       // X24C02+\r
-      if(ssa&1) {\r
-        //dprintf("read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);\r
+      if (ssa&1) {\r
+        elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);\r
+       if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]);\r
         d = (SRam.data[saddr]>>shift)&1;\r
       }\r
     } else {\r
       // X24C01\r
-      if(saddr&1) {\r
+      if (saddr&1) {\r
+        elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg);\r
+       if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]);\r
         d = (SRam.data[saddr>>1]>>shift)&1;\r
       }\r
     }\r
   }\r
-  //else dprintf("r ack");\r
 \r
-  return d;\r
+  return (d << SRam.eeprom_bit_out);\r
 }\r
 \r
 PICO_INTERNAL void SRAMUpdPending(unsigned int a, unsigned int d)\r
 {\r
-  unsigned int sreg = Pico.m.sram_reg;\r
-\r
-  if(!(a&1)) sreg|=0x20;\r
-\r
-  if(sreg&0x20) { // address through 0x200000\r
-    if(!(a&1)) {\r
-      sreg&=~0x80;\r
-      sreg|=d<<7;\r
-    } else {\r
-      sreg&=~0x40;\r
-      sreg|=(d<<6)&0x40;\r
-    }\r
-  } else {\r
-    sreg&=~0xc0;\r
-    sreg|=d<<6;\r
+  unsigned int d1, sreg = Pico.m.sram_reg;\r
+\r
+  if (!((SRam.eeprom_abits^a)&1))\r
+  {\r
+    // SCL\r
+    sreg &= ~0x80;\r
+    d1 = (d >> SRam.eeprom_bit_cl) & 1;\r
+    sreg |= d1<<7;\r
+  }\r
+  if (!(((SRam.eeprom_abits>>1)^a)&1))\r
+  {\r
+    // SDA in\r
+    sreg &= ~0x40;\r
+    d1 = (d >> SRam.eeprom_bit_in) & 1;\r
+    sreg |= d1<<6;\r
   }\r
 \r
   Pico.m.sram_reg = (unsigned char) sreg;\r