rlm@1: #include rlm@1: rlm@1: #include "GBA.h" // for SAVE_GAME_VERSION_3 rlm@1: #include "EEprom.h" rlm@1: #include "../common/System.h" rlm@1: #include "../common/Util.h" rlm@1: rlm@1: extern int32 cpuDmaCount; rlm@1: rlm@1: int32 eepromMode = EEPROM_IDLE; rlm@1: int32 eepromByte = 0; rlm@1: int32 eepromBits = 0; rlm@1: int32 eepromAddress = 0; rlm@1: u8 eepromData[0x2000]; rlm@1: u8 eepromBuffer[16]; rlm@1: bool8 eepromInUse = false; rlm@1: int32 eepromSize = 512; rlm@1: rlm@1: variable_desc eepromSaveData[] = { rlm@1: { &eepromMode, sizeof(int32) }, rlm@1: { &eepromByte, sizeof(int32) }, rlm@1: { &eepromBits, sizeof(int32) }, rlm@1: { &eepromAddress, sizeof(int32) }, rlm@1: { &eepromInUse, sizeof(bool8) }, rlm@1: { &eepromData[0], 512 }, rlm@1: { &eepromBuffer[0], 16 }, rlm@1: { NULL, 0 } rlm@1: }; rlm@1: rlm@1: void eepromReset() rlm@1: { rlm@1: eepromMode = EEPROM_IDLE; rlm@1: eepromByte = 0; rlm@1: eepromBits = 0; rlm@1: eepromAddress = 0; rlm@1: eepromInUse = false; rlm@1: eepromSize = 512; rlm@1: } rlm@1: rlm@1: void eepromErase() rlm@1: { rlm@1: memset(eepromData, 0, 0x2000*sizeof(u8)); rlm@1: eepromMode = EEPROM_IDLE; rlm@1: eepromByte = 0; rlm@1: eepromBits = 0; rlm@1: eepromAddress = 0; rlm@1: memset(eepromBuffer, 0, 16*sizeof(u8)); rlm@1: eepromInUse = false; rlm@1: eepromSize = 512; rlm@1: } rlm@1: rlm@1: void eepromSaveGame(gzFile gzFile) rlm@1: { rlm@1: utilWriteData(gzFile, eepromSaveData); rlm@1: utilWriteInt(gzFile, eepromSize); rlm@1: utilGzWrite(gzFile, eepromData, 0x2000); rlm@1: } rlm@1: rlm@1: void eepromReadGame(gzFile gzFile, int version) rlm@1: { rlm@1: utilReadData(gzFile, eepromSaveData); rlm@1: if (version >= SAVE_GAME_VERSION_3) rlm@1: { rlm@1: eepromSize = utilReadInt(gzFile); rlm@1: utilGzRead(gzFile, eepromData, 0x2000); rlm@1: } rlm@1: else rlm@1: { rlm@1: // prior to 0.7.1, only 4K EEPROM was supported rlm@1: eepromSize = 512; rlm@1: } rlm@1: } rlm@1: rlm@1: int eepromRead(u32 /* address */) rlm@1: { rlm@1: switch (eepromMode) rlm@1: { rlm@1: case EEPROM_IDLE: rlm@1: case EEPROM_READADDRESS: rlm@1: case EEPROM_WRITEDATA: rlm@1: return 1; rlm@1: case EEPROM_READDATA: rlm@1: { rlm@1: eepromBits++; rlm@1: if (eepromBits == 4) rlm@1: { rlm@1: eepromMode = EEPROM_READDATA2; rlm@1: eepromBits = 0; rlm@1: eepromByte = 0; rlm@1: } rlm@1: return 0; rlm@1: } rlm@1: case EEPROM_READDATA2: rlm@1: { rlm@1: int data = 0; rlm@1: int address = eepromAddress << 3; rlm@1: int mask = 1 << (7 - (eepromBits & 7)); rlm@1: data = (eepromData[address+eepromByte] & mask) ? 1 : 0; rlm@1: eepromBits++; rlm@1: if ((eepromBits & 7) == 0) rlm@1: eepromByte++; rlm@1: if (eepromBits == 0x40) rlm@1: eepromMode = EEPROM_IDLE; rlm@1: return data; rlm@1: } rlm@1: default: rlm@1: return 0; rlm@1: } rlm@1: return 1; rlm@1: } rlm@1: rlm@1: void eepromWrite(u32 /* address */, u8 value) rlm@1: { rlm@1: if (cpuDmaCount == 0) rlm@1: return; rlm@1: int bit = value & 1; rlm@1: switch (eepromMode) rlm@1: { rlm@1: case EEPROM_IDLE: rlm@1: eepromByte = 0; rlm@1: eepromBits = 1; rlm@1: eepromBuffer[eepromByte] = bit; rlm@1: eepromMode = EEPROM_READADDRESS; rlm@1: break; rlm@1: case EEPROM_READADDRESS: rlm@1: eepromBuffer[eepromByte] <<= 1; rlm@1: eepromBuffer[eepromByte] |= bit; rlm@1: eepromBits++; rlm@1: if ((eepromBits & 7) == 0) rlm@1: { rlm@1: eepromByte++; rlm@1: } rlm@1: if (cpuDmaCount == 0x11 || cpuDmaCount == 0x51) rlm@1: { rlm@1: if (eepromBits == 0x11) rlm@1: { rlm@1: eepromInUse = true; rlm@1: eepromSize = 0x2000; rlm@1: eepromAddress = ((eepromBuffer[0] & 0x3F) << 8) | rlm@1: ((eepromBuffer[1] & 0xFF)); rlm@1: if (!(eepromBuffer[0] & 0x40)) rlm@1: { rlm@1: eepromBuffer[0] = bit; rlm@1: eepromBits = 1; rlm@1: eepromByte = 0; rlm@1: eepromMode = EEPROM_WRITEDATA; rlm@1: } rlm@1: else rlm@1: { rlm@1: eepromMode = EEPROM_READDATA; rlm@1: eepromByte = 0; rlm@1: eepromBits = 0; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: if (eepromBits == 9) rlm@1: { rlm@1: eepromInUse = true; rlm@1: eepromAddress = (eepromBuffer[0] & 0x3F); rlm@1: if (!(eepromBuffer[0] & 0x40)) rlm@1: { rlm@1: eepromBuffer[0] = bit; rlm@1: eepromBits = 1; rlm@1: eepromByte = 0; rlm@1: eepromMode = EEPROM_WRITEDATA; rlm@1: } rlm@1: else rlm@1: { rlm@1: eepromMode = EEPROM_READDATA; rlm@1: eepromByte = 0; rlm@1: eepromBits = 0; rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: case EEPROM_READDATA: rlm@1: case EEPROM_READDATA2: rlm@1: // should we reset here? rlm@1: eepromMode = EEPROM_IDLE; rlm@1: break; rlm@1: case EEPROM_WRITEDATA: rlm@1: eepromBuffer[eepromByte] <<= 1; rlm@1: eepromBuffer[eepromByte] |= bit; rlm@1: eepromBits++; rlm@1: if ((eepromBits & 7) == 0) rlm@1: { rlm@1: eepromByte++; rlm@1: } rlm@1: if (eepromBits == 0x40) rlm@1: { rlm@1: eepromInUse = true; rlm@1: // write data; rlm@1: for (int i = 0; i < 8; i++) rlm@1: { rlm@1: eepromData[(eepromAddress << 3) + i] = eepromBuffer[i]; rlm@1: } rlm@1: systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; rlm@1: } rlm@1: else if (eepromBits == 0x41) rlm@1: { rlm@1: eepromMode = EEPROM_IDLE; rlm@1: eepromByte = 0; rlm@1: eepromBits = 0; rlm@1: } rlm@1: break; rlm@1: } rlm@1: } rlm@1: