// 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
-void SRAMWriteEEPROM(unsigned int d) // ???? ??la (l=SCL, a=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
- //dprintf("[%02x]", d);\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
- }\r
- else if((sreg&0x4000) && scyc == 27) scyc = 18;\r
- else if(scyc == 36) scyc = 27;\r
- } else {\r
- // X24C01\r
+ if((ssa&1) && scyc == 18) {\r
+ scyc = 9;\r
+ saddr++; // next address in read mode\r
+ /*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask\r
+ }\r
+ else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18;\r
+ else if(scyc == 36) scyc = 27;\r
+ } else {\r
+ // X24C01\r
if(scyc == 18) {\r
scyc = 9; // wrap\r
if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode\r
- }\r
- }\r
- //dprintf("scyc: %i", scyc);\r
+ }\r
+ }\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
- // X24C02+\r
- if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles\r
- else if( (!(sreg&0x4000) && scyc > 27) || ((sreg&0x4000) && scyc > 18) ) {\r
+ if(SRam.eeprom_type) {\r
+ // X24C02+\r
+ if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles\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
} else if(scyc > 9) {\r
if(!(ssa&1)) {\r
// we latch another addr bit\r
- saddr<<=1;\r
- if(sreg&0x4000) saddr&=0xff; else saddr&=0x1fff; // mask\r
- saddr|=d&1;\r
- //if(scyc==17||scyc==26) dprintf("addr reg done: %x", saddr);\r
- }\r
+ saddr<<=1;\r
+ if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask\r
+ saddr|=d&1;\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
+ // slave address\r
+ ssa<<=1; ssa|=d&1;\r
+ if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa);\r
}\r
- } else {\r
- // X24C01\r
+ } else {\r
+ // X24C01\r
if(scyc == 9); // ACK cycle, do nothing\r
else if(scyc > 9) {\r
if(!(saddr&1)) {\r
*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
\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
-unsigned int SRAMReadEEPROM()\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
+ // 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(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
+ 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
- // X24C02+\r
- if(ssa&1) {\r
- //dprintf("read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);\r
- d = (SRam.data[saddr]>>shift)&1;\r
- }\r
- } else {\r
- // X24C01\r
- if(saddr&1) {\r
- d = (SRam.data[saddr>>1]>>shift)&1;\r
- }\r
- }\r
+ if (SRam.eeprom_type) {\r
+ // X24C02+\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
+ 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
-void SRAMUpdPending(unsigned int a, unsigned int d)\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
+ unsigned int d1, sreg = Pico.m.sram_reg;\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
+ 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
\r
\r
#ifndef _ASM_MISC_C\r
-void memcpy16(unsigned short *dest, unsigned short *src, int count)\r
+typedef struct\r
+{\r
+ int b0;\r
+ int b1;\r
+ int b2;\r
+ int b3;\r
+ int b4;\r
+ int b5;\r
+ int b6;\r
+ int b7;\r
+} intblock;\r
+\r
+PICO_INTERNAL_ASM void memcpy16(unsigned short *dest, unsigned short *src, int count)\r
{\r
+ if ((((int)dest | (int)src) & 3) == 0)\r
+ {\r
+ if (count >= 32) {\r
+ memcpy32((int *)dest, (int *)src, count/2);\r
+ count&=1;\r
+ } else {\r
+ for (; count >= 2; count -= 2, dest+=2, src+=2)\r
+ *(int *)dest = *(int *)src;\r
+ }\r
+ }\r
while (count--)\r
*dest++ = *src++;\r
}\r
\r
\r
-void memcpy32(int *dest, int *src, int count)\r
+PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count)\r
+{\r
+ unsigned char *src_ = src;\r
+\r
+ for (; count; count--, src_ += 2)\r
+ *dest++ = (src_[0] << 8) | src_[1];\r
+}\r
+\r
+#ifndef _ASM_MISC_C_AMIPS\r
+PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count)\r
{\r
+ intblock *bd = (intblock *) dest, *bs = (intblock *) src;\r
+\r
+ for (; count >= sizeof(*bd)/4; count -= sizeof(*bd)/4)\r
+ *bd++ = *bs++;\r
+\r
+ dest = (int *)bd; src = (int *)bs;\r
while (count--)\r
*dest++ = *src++;\r
}\r
\r
\r
-void memset32(int *dest, int c, int count)\r
+PICO_INTERNAL_ASM void memset32(int *dest, int c, int count)\r
{\r
+ for (; count >= 8; count -= 8, dest += 8)\r
+ dest[0] = dest[1] = dest[2] = dest[3] =\r
+ dest[4] = dest[5] = dest[6] = dest[7] = c;\r
+\r
while (count--)\r
*dest++ = c;\r
}\r
+void memset32_uncached(int *dest, int c, int count) { memset32(dest, c, count); }\r
+#endif\r
#endif\r
\r