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 // Handle regular cartridge EEPROM
67 sprintf(eeprom_filename, "%s%08X.eeprom", vjs.EEPROMPath, (unsigned int)jaguarMainROMCRC32);
68 sprintf(cdromEEPROMFilename, "%scdrom.eeprom", vjs.EEPROMPath);
69 FILE * fp = fopen(eeprom_filename, "rb");
73 ReadEEPROMFromFile(fp, eeprom_ram);
75 WriteLog("EEPROM: Loaded from %s\n", eeprom_filename);
79 WriteLog("EEPROM: Could not open file \"%s\"!\n", eeprom_filename);
81 // Handle JagCD EEPROM
82 fp = fopen(cdromEEPROMFilename, "rb");
86 ReadEEPROMFromFile(fp, cdromEEPROM);
88 WriteLog("EEPROM: Loaded from cdrom.eeprom\n");
89 haveCDROMEEPROM = true;
92 WriteLog("EEPROM: Could not open file \"%s\"!\n", cdromEEPROMFilename);
96 void EepromReset(void)
99 memset(eeprom_ram, 0xFF, 64 * sizeof(uint16_t));
101 if (!haveCDROMEEPROM)
102 memset(cdromEEPROM, 0xFF, 64 * sizeof(uint16_t));
106 void EepromDone(void)
108 WriteLog("EEPROM: Done.\n");
112 static void EEPROMSave(void)
114 // Write out regular cartridge EEPROM data
115 FILE * fp = fopen(eeprom_filename, "wb");
119 WriteEEPROMToFile(fp, eeprom_ram);
123 WriteLog("EEPROM: Could not create file \"%s!\"\n", eeprom_filename);
125 // Write out JagCD EEPROM data
126 fp = fopen(cdromEEPROMFilename, "wb");
130 WriteEEPROMToFile(fp, cdromEEPROM);
134 WriteLog("EEPROM: Could not create file \"%s!\"\n", cdromEEPROMFilename);
139 // Read/write EEPROM files to disk in an endian safe manner
141 void ReadEEPROMFromFile(FILE * file, uint16_t * ram)
144 fread(buffer, 1, 128, file);
146 for(int i=0; i<64; i++)
147 ram[i] = (buffer[(i * 2) + 0] << 8) | buffer[(i * 2) + 1];
151 void WriteEEPROMToFile(FILE * file, uint16_t * ram)
155 for(int i=0; i<64; i++)
157 buffer[(i * 2) + 0] = ram[i] >> 8;
158 buffer[(i * 2) + 1] = ram[i] & 0xFF;
161 fwrite(buffer, 1, 128, file);
165 uint8_t EepromReadByte(uint32_t offset)
170 return eeprom_get_do();
176 // default: WriteLog("EEPROM: unmapped 0x%.8x\n", offset); break;
183 uint16_t EepromReadWord(uint32_t offset)
185 return ((uint16_t)EepromReadByte(offset + 0) << 8) | EepromReadByte(offset + 1);
189 void EepromWriteByte(uint32_t offset, uint8_t data)
196 eeprom_set_di(data & 0x01);
201 // default: WriteLog("eeprom: unmapped 0x%.8x\n",offset); break;
206 void EepromWriteWord(uint32_t offset, uint16_t data)
208 EepromWriteByte(offset + 0, (data >> 8) & 0xFF);
209 EepromWriteByte(offset + 1, data & 0xFF);
215 ; Commands specific to the National Semiconductor NM93C14
220 eEWDS equ %100000000 ;Erase/Write disable (default)
221 eWRAL equ %100010000 ;Writes all registers
222 eERAL equ %100100000 ;Erase all registers
223 eEWEN equ %100110000 ;Erase/write Enable
224 eWRITE equ %101000000 ;Write selected register
225 eREAD equ %110000000 ;read from EEPROM
226 eERASE equ %111000000 ;Erase selected register
230 static void eeprom_set_di(uint32_t data)
232 // WriteLog("eeprom: di=%i\n",data);
233 // WriteLog("eeprom: state %i\n",jerry_ee_state);
234 switch (jerry_ee_state)
237 jerry_ee_state = EE_STATE_OP_A;
240 jerry_ee_op = (data << 1);
241 jerry_ee_state = EE_STATE_OP_B;
245 jerry_ee_direct_jump = 0;
246 // WriteLog("eeprom: opcode %i\n",jerry_ee_op);
250 // Opcode 00: eEWEN, eERAL, eWRAL, eEWNDS
251 case 0: jerry_ee_state = EE_STATE_0; break;
252 // Opcode 01: eWRITE (Write selected register)
253 case 1: jerry_ee_state = EE_STATE_1; break;
254 // Opcode 10: eREAD (Read from EEPROM)
255 case 2: jerry_ee_state = EE_STATE_2; break;
256 // Opcode 11: eERASE (Erase selected register)
257 case 3: jerry_ee_state = EE_STATE_3; break;
263 jerry_ee_rstate = EE_STATE_0_0;
264 jerry_ee_state = EE_READ_ADDRESS;
265 jerry_ee_direct_jump = 1;
266 jerry_ee_address_cnt = 6;
267 jerry_ee_address_data = 0;
270 switch ((jerry_ee_address_data >> 4) & 0x03)
272 // Opcode 00 00: eEWDS (Erase/Write disable)
273 case 0: jerry_ee_state=EE_STATE_0_0_0; break;
274 // Opcode 00 01: eWRAL (Write all registers)
275 case 1: jerry_ee_state=EE_STATE_0_0_1; break;
276 // Opcode 00 10: eERAL (Erase all registers)
277 case 2: jerry_ee_state=EE_STATE_0_0_2; break;
278 // Opcode 00 11: eEWEN (Erase/Write enable)
279 case 3: jerry_ee_state=EE_STATE_0_0_3; break;
286 // WriteLog("eeprom: read only\n");
287 jerry_writes_enabled = 0;
288 jerry_ee_state = EE_STATE_START;
292 jerry_ee_rstate = EE_STATE_0_0_1_0;
293 jerry_ee_state = EE_READ_DATA;
294 jerry_ee_data_cnt = 16;
296 jerry_ee_direct_jump = 1;
298 case EE_STATE_0_0_1_0:
299 // WriteLog("eeprom: filling eeprom with 0x%.4x\n",data);
300 if (jerry_writes_enabled)
302 for(int i=0; i<64; i++)
303 eeprom_ram[i] = jerry_ee_data;
305 EEPROMSave(); // Save it NOW!
309 // WriteLog("eeprom: not writing because read only\n");
310 jerry_ee_state = EE_STATE_BUSY;
314 //WriteLog("eeprom: erasing eeprom\n");
315 if (jerry_writes_enabled)
316 for(int i=0; i<64; i++)
317 eeprom_ram[i] = 0xFFFF;
319 jerry_ee_state = EE_STATE_BUSY;
323 //WriteLog("eeprom: read/write\n");
324 jerry_writes_enabled = 1;
325 jerry_ee_state = EE_STATE_START;
328 jerry_ee_rstate = EE_STATE_1_0;
329 jerry_ee_state = EE_READ_ADDRESS;
330 jerry_ee_address_cnt = 6;
331 jerry_ee_address_data = 0;
332 jerry_ee_direct_jump = 1;
335 jerry_ee_rstate = EE_STATE_1_1;
336 jerry_ee_state = EE_READ_DATA;
337 jerry_ee_data_cnt = 16;
339 jerry_ee_direct_jump = 1;
342 //WriteLog("eeprom: writing 0x%.4x at 0x%.2x\n",jerry_ee_data,jerry_ee_address_data);
343 if (jerry_writes_enabled)
345 eeprom_ram[jerry_ee_address_data] = jerry_ee_data;
346 EEPROMSave(); // Save it NOW!
349 jerry_ee_state = EE_STATE_BUSY;
352 jerry_ee_rstate = EE_STATE_2_0;
353 jerry_ee_state = EE_READ_ADDRESS;
354 jerry_ee_address_cnt = 6;
355 jerry_ee_address_data = 0;
356 jerry_ee_data_cnt = 16;
360 jerry_ee_rstate = EE_STATE_3_0;
361 jerry_ee_state = EE_READ_ADDRESS;
362 jerry_ee_address_cnt = 6;
363 jerry_ee_address_data = 0;
364 jerry_ee_direct_jump = 1;
367 //WriteLog("eeprom: erasing 0x%.2x\n",jerry_ee_address_data);
368 if (jerry_writes_enabled)
369 eeprom_ram[jerry_ee_address_data] = 0xFFFF;
371 jerry_ee_state = EE_STATE_BUSY;
374 //WriteLog("eeprom:\t\t\t%i bit %i\n",data,jerry_ee_data_cnt-1);
376 jerry_ee_data |= data;
379 if (!jerry_ee_data_cnt)
381 jerry_ee_state = jerry_ee_rstate;
383 if (jerry_ee_direct_jump)
388 case EE_READ_ADDRESS:
389 jerry_ee_address_data <<= 1;
390 jerry_ee_address_data |= data;
391 jerry_ee_address_cnt--;
392 // WriteLog("eeprom:\t%i bits remaining\n",jerry_ee_address_cnt);
394 if (!jerry_ee_address_cnt)
396 jerry_ee_state = jerry_ee_rstate;
397 //WriteLog("eeprom:\t\tread address 0x%.2x\n",jerry_ee_address_data);
399 if (jerry_ee_direct_jump)
405 jerry_ee_state = EE_STATE_OP_A;
410 static void eeprom_set_cs(uint32_t /*state*/)
412 // WriteLog("eeprom: cs=%i\n",state);
413 jerry_ee_state = EE_STATE_START;
416 jerry_ee_address_data = 0;
417 jerry_ee_address_cnt = 6;
419 jerry_ee_data_cnt = 16;
420 jerry_writes_enabled = 1;
424 static uint32_t eeprom_get_do(void)
428 switch (jerry_ee_state)
434 jerry_ee_state = EE_STATE_START;
439 data = (eeprom_ram[jerry_ee_address_data] >> jerry_ee_data_cnt) & 0x01;
441 if (!jerry_ee_data_cnt)
443 //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());
444 jerry_ee_state = EE_STATE_START;
449 // WriteLog("eeprom: do=%i\n",data);