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);