2 // Jaguar EEPROM handler
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups/enhancements by James Hammons
7 // (C) 2010 Underground Software
9 // JLH = James Hammons <jlhamm@acm.org>
12 // --- ---------- ------------------------------------------------------------
13 // JLH 01/16/2010 Created this log ;-)
19 #include <string.h> // For memset
26 static uint16_t eeprom_ram[64];
27 static uint16_t cdromEEPROM[64];
30 // Private function prototypes
33 static void EEPROMSave(void);
34 static void eeprom_set_di(uint32_t state);
35 static void eeprom_set_cs(uint32_t state);
36 static uint32_t eeprom_get_do(void);
37 void ReadEEPROMFromFile(FILE * file, uint16_t * ram);
38 void WriteEEPROMToFile(FILE * file, uint16_t * ram);
41 enum { EE_STATE_START = 1, EE_STATE_OP_A, EE_STATE_OP_B, EE_STATE_0, EE_STATE_1,
42 EE_STATE_2, EE_STATE_3, EE_STATE_0_0, EE_READ_ADDRESS, EE_STATE_0_0_0,
43 EE_STATE_0_0_1, EE_STATE_0_0_2, EE_STATE_0_0_3, EE_STATE_0_0_1_0, EE_READ_DATA,
44 EE_STATE_BUSY, EE_STATE_1_0, EE_STATE_1_1, EE_STATE_2_0, EE_STATE_3_0 };
46 // Local global variables
48 static uint16_t jerry_ee_state = EE_STATE_START;
49 static uint16_t jerry_ee_op = 0;
50 static uint16_t jerry_ee_rstate = 0;
51 static uint16_t jerry_ee_address_data = 0;
52 static uint16_t jerry_ee_address_cnt = 6;
53 static uint16_t jerry_ee_data = 0;
54 static uint16_t jerry_ee_data_cnt = 16;
55 static uint16_t jerry_writes_enabled = 0;
56 static uint16_t jerry_ee_direct_jump = 0;
58 static char eeprom_filename[MAX_PATH];
59 static char cdromEEPROMFilename[MAX_PATH];
60 static bool haveEEPROM = false;
61 static bool haveCDROMEEPROM = false;
66 // No need for EEPROM for the Memory Track device :-P
67 if (jaguarMainROMCRC32 == 0xFDF37F47)
69 WriteLog("EEPROM: Memory Track device detected...\n");
73 // Handle regular cartridge EEPROM
74 sprintf(eeprom_filename, "%s%08X.eeprom", vjs.EEPROMPath, (unsigned int)jaguarMainROMCRC32);
75 sprintf(cdromEEPROMFilename, "%scdrom.eeprom", vjs.EEPROMPath);
76 FILE * fp = fopen(eeprom_filename, "rb");
80 ReadEEPROMFromFile(fp, eeprom_ram);
82 WriteLog("EEPROM: Loaded from %s\n", eeprom_filename);
86 WriteLog("EEPROM: Could not open file \"%s\"!\n", eeprom_filename);
88 // Handle JagCD EEPROM
89 fp = fopen(cdromEEPROMFilename, "rb");
93 ReadEEPROMFromFile(fp, cdromEEPROM);
95 WriteLog("EEPROM: Loaded from cdrom.eeprom\n");
96 haveCDROMEEPROM = true;
99 WriteLog("EEPROM: Could not open file \"%s\"!\n", cdromEEPROMFilename);
103 void EepromReset(void)
106 memset(eeprom_ram, 0xFF, 64 * sizeof(uint16_t));
108 if (!haveCDROMEEPROM)
109 memset(cdromEEPROM, 0xFF, 64 * sizeof(uint16_t));
113 void EepromDone(void)
115 WriteLog("EEPROM: Done.\n");
119 static void EEPROMSave(void)
121 // Write out regular cartridge EEPROM data
122 FILE * fp = fopen(eeprom_filename, "wb");
126 WriteEEPROMToFile(fp, eeprom_ram);
130 WriteLog("EEPROM: Could not create file \"%s!\"\n", eeprom_filename);
132 // Write out JagCD EEPROM data
133 fp = fopen(cdromEEPROMFilename, "wb");
137 WriteEEPROMToFile(fp, cdromEEPROM);
141 WriteLog("EEPROM: Could not create file \"%s!\"\n", cdromEEPROMFilename);
146 // Read/write EEPROM files to disk in an endian safe manner
148 void ReadEEPROMFromFile(FILE * file, uint16_t * ram)
151 size_t ignored = fread(buffer, 1, 128, file);
153 for(int i=0; i<64; i++)
154 ram[i] = (buffer[(i * 2) + 0] << 8) | buffer[(i * 2) + 1];
158 void WriteEEPROMToFile(FILE * file, uint16_t * ram)
162 for(int i=0; i<64; i++)
164 buffer[(i * 2) + 0] = ram[i] >> 8;
165 buffer[(i * 2) + 1] = ram[i] & 0xFF;
168 fwrite(buffer, 1, 128, file);
172 uint8_t EepromReadByte(uint32_t offset)
177 return eeprom_get_do();
183 // default: WriteLog("EEPROM: unmapped 0x%.8x\n", offset); break;
190 uint16_t EepromReadWord(uint32_t offset)
192 return ((uint16_t)EepromReadByte(offset + 0) << 8) | EepromReadByte(offset + 1);
196 void EepromWriteByte(uint32_t offset, uint8_t data)
203 eeprom_set_di(data & 0x01);
208 // default: WriteLog("eeprom: unmapped 0x%.8x\n",offset); break;
213 void EepromWriteWord(uint32_t offset, uint16_t data)
215 EepromWriteByte(offset + 0, (data >> 8) & 0xFF);
216 EepromWriteByte(offset + 1, data & 0xFF);
222 ; Commands specific to the National Semiconductor NM93C14
227 eEWDS equ %100000000 ;Erase/Write disable (default)
228 eWRAL equ %100010000 ;Writes all registers
229 eERAL equ %100100000 ;Erase all registers
230 eEWEN equ %100110000 ;Erase/write Enable
231 eWRITE equ %101000000 ;Write selected register
232 eREAD equ %110000000 ;read from EEPROM
233 eERASE equ %111000000 ;Erase selected register
237 static void eeprom_set_di(uint32_t data)
239 // WriteLog("eeprom: di=%i\n",data);
240 // WriteLog("eeprom: state %i\n",jerry_ee_state);
241 switch (jerry_ee_state)
244 jerry_ee_state = EE_STATE_OP_A;
247 jerry_ee_op = (data << 1);
248 jerry_ee_state = EE_STATE_OP_B;
252 jerry_ee_direct_jump = 0;
253 // WriteLog("eeprom: opcode %i\n",jerry_ee_op);
257 // Opcode 00: eEWEN, eERAL, eWRAL, eEWNDS
258 case 0: jerry_ee_state = EE_STATE_0; break;
259 // Opcode 01: eWRITE (Write selected register)
260 case 1: jerry_ee_state = EE_STATE_1; break;
261 // Opcode 10: eREAD (Read from EEPROM)
262 case 2: jerry_ee_state = EE_STATE_2; break;
263 // Opcode 11: eERASE (Erase selected register)
264 case 3: jerry_ee_state = EE_STATE_3; break;
270 jerry_ee_rstate = EE_STATE_0_0;
271 jerry_ee_state = EE_READ_ADDRESS;
272 jerry_ee_direct_jump = 1;
273 jerry_ee_address_cnt = 6;
274 jerry_ee_address_data = 0;
277 switch ((jerry_ee_address_data >> 4) & 0x03)
279 // Opcode 00 00: eEWDS (Erase/Write disable)
280 case 0: jerry_ee_state=EE_STATE_0_0_0; break;
281 // Opcode 00 01: eWRAL (Write all registers)
282 case 1: jerry_ee_state=EE_STATE_0_0_1; break;
283 // Opcode 00 10: eERAL (Erase all registers)
284 case 2: jerry_ee_state=EE_STATE_0_0_2; break;
285 // Opcode 00 11: eEWEN (Erase/Write enable)
286 case 3: jerry_ee_state=EE_STATE_0_0_3; break;
293 // WriteLog("eeprom: read only\n");
294 jerry_writes_enabled = 0;
295 jerry_ee_state = EE_STATE_START;
299 jerry_ee_rstate = EE_STATE_0_0_1_0;
300 jerry_ee_state = EE_READ_DATA;
301 jerry_ee_data_cnt = 16;
303 jerry_ee_direct_jump = 1;
305 case EE_STATE_0_0_1_0:
306 // WriteLog("eeprom: filling eeprom with 0x%.4x\n",data);
307 if (jerry_writes_enabled)
309 for(int i=0; i<64; i++)
310 eeprom_ram[i] = jerry_ee_data;
312 EEPROMSave(); // Save it NOW!
316 // WriteLog("eeprom: not writing because read only\n");
317 jerry_ee_state = EE_STATE_BUSY;
321 //WriteLog("eeprom: erasing eeprom\n");
322 if (jerry_writes_enabled)
323 for(int i=0; i<64; i++)
324 eeprom_ram[i] = 0xFFFF;
326 jerry_ee_state = EE_STATE_BUSY;
330 //WriteLog("eeprom: read/write\n");
331 jerry_writes_enabled = 1;
332 jerry_ee_state = EE_STATE_START;
335 jerry_ee_rstate = EE_STATE_1_0;
336 jerry_ee_state = EE_READ_ADDRESS;
337 jerry_ee_address_cnt = 6;
338 jerry_ee_address_data = 0;
339 jerry_ee_direct_jump = 1;
342 jerry_ee_rstate = EE_STATE_1_1;
343 jerry_ee_state = EE_READ_DATA;
344 jerry_ee_data_cnt = 16;
346 jerry_ee_direct_jump = 1;
349 //WriteLog("eeprom: writing 0x%.4x at 0x%.2x\n",jerry_ee_data,jerry_ee_address_data);
350 if (jerry_writes_enabled)
352 eeprom_ram[jerry_ee_address_data] = jerry_ee_data;
353 EEPROMSave(); // Save it NOW!
356 jerry_ee_state = EE_STATE_BUSY;
359 jerry_ee_rstate = EE_STATE_2_0;
360 jerry_ee_state = EE_READ_ADDRESS;
361 jerry_ee_address_cnt = 6;
362 jerry_ee_address_data = 0;
363 jerry_ee_data_cnt = 16;
367 jerry_ee_rstate = EE_STATE_3_0;
368 jerry_ee_state = EE_READ_ADDRESS;
369 jerry_ee_address_cnt = 6;
370 jerry_ee_address_data = 0;
371 jerry_ee_direct_jump = 1;
374 //WriteLog("eeprom: erasing 0x%.2x\n",jerry_ee_address_data);
375 if (jerry_writes_enabled)
376 eeprom_ram[jerry_ee_address_data] = 0xFFFF;
378 jerry_ee_state = EE_STATE_BUSY;
381 //WriteLog("eeprom:\t\t\t%i bit %i\n",data,jerry_ee_data_cnt-1);
383 jerry_ee_data |= data;
386 if (!jerry_ee_data_cnt)
388 jerry_ee_state = jerry_ee_rstate;
390 if (jerry_ee_direct_jump)
395 case EE_READ_ADDRESS:
396 jerry_ee_address_data <<= 1;
397 jerry_ee_address_data |= data;
398 jerry_ee_address_cnt--;
399 // WriteLog("eeprom:\t%i bits remaining\n",jerry_ee_address_cnt);
401 if (!jerry_ee_address_cnt)
403 jerry_ee_state = jerry_ee_rstate;
404 //WriteLog("eeprom:\t\tread address 0x%.2x\n",jerry_ee_address_data);
406 if (jerry_ee_direct_jump)
412 jerry_ee_state = EE_STATE_OP_A;
417 static void eeprom_set_cs(uint32_t /*state*/)
419 // WriteLog("eeprom: cs=%i\n",state);
420 jerry_ee_state = EE_STATE_START;
423 jerry_ee_address_data = 0;
424 jerry_ee_address_cnt = 6;
426 jerry_ee_data_cnt = 16;
427 jerry_writes_enabled = 1;
431 static uint32_t eeprom_get_do(void)
435 switch (jerry_ee_state)
441 jerry_ee_state = EE_STATE_START;
446 data = (eeprom_ram[jerry_ee_address_data] >> jerry_ee_data_cnt) & 0x01;
448 if (!jerry_ee_data_cnt)
450 //WriteLog("eeprom: read 0x%.4x at 0x%.2x cpu %i pc=0x%.8x\n",eeprom_ram[jerry_ee_address_data],jerry_ee_address_data,jaguar_cpu_in_exec,s68000readPC());
451 jerry_ee_state = EE_STATE_START;
456 // WriteLog("eeprom: do=%i\n",data);