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>
10 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
13 // --- ---------- ------------------------------------------------------------
14 // JLH 01/16/2010 Created this log ;-)
15 // JPM 10/11/2017 Directory detection and creation if missing
21 #include <string.h> // For memset
28 static uint16_t eeprom_ram
[64];
29 static uint16_t cdromEEPROM
[64];
32 // Private function prototypes
35 static void EEPROMSave(void);
36 static void eeprom_set_di(uint32_t state
);
37 static void eeprom_set_cs(uint32_t state
);
38 static uint32_t eeprom_get_do(void);
39 void ReadEEPROMFromFile(FILE * file
, uint16_t * ram
);
40 void WriteEEPROMToFile(FILE * file
, uint16_t * ram
);
43 enum { EE_STATE_START
= 1, EE_STATE_OP_A
, EE_STATE_OP_B
, EE_STATE_0
, EE_STATE_1
,
44 EE_STATE_2
, EE_STATE_3
, EE_STATE_0_0
, EE_READ_ADDRESS
, EE_STATE_0_0_0
,
45 EE_STATE_0_0_1
, EE_STATE_0_0_2
, EE_STATE_0_0_3
, EE_STATE_0_0_1_0
, EE_READ_DATA
,
46 EE_STATE_BUSY
, EE_STATE_1_0
, EE_STATE_1_1
, EE_STATE_2_0
, EE_STATE_3_0
};
48 // Local global variables
50 static uint16_t jerry_ee_state
= EE_STATE_START
;
51 static uint16_t jerry_ee_op
= 0;
52 static uint16_t jerry_ee_rstate
= 0;
53 static uint16_t jerry_ee_address_data
= 0;
54 static uint16_t jerry_ee_address_cnt
= 6;
55 static uint16_t jerry_ee_data
= 0;
56 static uint16_t jerry_ee_data_cnt
= 16;
57 static uint16_t jerry_writes_enabled
= 0;
58 static uint16_t jerry_ee_direct_jump
= 0;
60 static char eeprom_filename
[MAX_PATH
];
61 static char cdromEEPROMFilename
[MAX_PATH
];
62 static bool haveEEPROM
= false;
63 static bool haveCDROMEEPROM
= false;
66 // EEPROM initialisations
71 // No need for EEPROM for the Memory Track device :-P
72 if (jaguarMainROMCRC32
== 0xFDF37F47)
74 WriteLog("EEPROM: Memory Track device detected...\n");
78 // Handle regular cartridge EEPROM
79 sprintf(eeprom_filename
, "%s%08X.eeprom", vjs
.EEPROMPath
, (unsigned int)jaguarMainROMCRC32
);
80 fp
= fopen(eeprom_filename
, "rb");
84 ReadEEPROMFromFile(fp
, eeprom_ram
);
86 WriteLog("EEPROM: Loaded from %s\n", eeprom_filename
);
91 WriteLog("EEPROM: Could not open file \"%s\"!\n", eeprom_filename
);
94 // Handle JagCD EEPROM
95 sprintf(cdromEEPROMFilename
, "%scdrom.eeprom", vjs
.EEPROMPath
);
96 fp
= fopen(cdromEEPROMFilename
, "rb");
100 ReadEEPROMFromFile(fp
, cdromEEPROM
);
102 WriteLog("EEPROM: Loaded from cdrom.eeprom\n");
103 haveCDROMEEPROM
= true;
107 WriteLog("EEPROM: Could not open file \"%s\"!\n", cdromEEPROMFilename
);
114 void EepromReset(void)
117 memset(eeprom_ram
, 0xFF, 64 * sizeof(uint16_t));
119 if (!haveCDROMEEPROM
)
120 memset(cdromEEPROM
, 0xFF, 64 * sizeof(uint16_t));
125 void EepromDone(void)
127 WriteLog("EEPROM: Done.\n");
132 static void EEPROMSave(void)
136 // Check if EEPROM directory exists and try to create it if not
137 if (_mkdir(vjs
.EEPROMPath
))
139 WriteLog("EEPROM: Could not create directory \"%s!\"\n", vjs
.EEPROMPath
);
142 // Write out regular cartridge EEPROM data
143 fp
= fopen(eeprom_filename
, "wb");
146 WriteEEPROMToFile(fp
, eeprom_ram
);
151 WriteLog("EEPROM: Could not create file \"%s!\"\n", eeprom_filename
);
154 // Write out JagCD EEPROM data
155 fp
= fopen(cdromEEPROMFilename
, "wb");
158 WriteEEPROMToFile(fp
, cdromEEPROM
);
163 WriteLog("EEPROM: Could not create file \"%s!\"\n", cdromEEPROMFilename
);
169 // Read/write EEPROM files to disk in an endian safe manner
171 void ReadEEPROMFromFile(FILE * file
, uint16_t * ram
)
174 size_t ignored
= fread(buffer
, 1, 128, file
);
176 for(int i
=0; i
<64; i
++)
177 ram
[i
] = (buffer
[(i
* 2) + 0] << 8) | buffer
[(i
* 2) + 1];
181 void WriteEEPROMToFile(FILE * file
, uint16_t * ram
)
185 for(int i
=0; i
<64; i
++)
187 buffer
[(i
* 2) + 0] = ram
[i
] >> 8;
188 buffer
[(i
* 2) + 1] = ram
[i
] & 0xFF;
191 fwrite(buffer
, 1, 128, file
);
195 uint8_t EepromReadByte(uint32_t offset
)
200 return eeprom_get_do();
208 WriteLog("EEPROM: unmapped 0x%.8x\n", offset
);
217 uint16_t EepromReadWord(uint32_t offset
)
219 return ((uint16_t)EepromReadByte(offset
+ 0) << 8) | EepromReadByte(offset
+ 1);
223 void EepromWriteByte(uint32_t offset
, uint8_t data
)
230 eeprom_set_di(data
& 0x01);
237 WriteLog("eeprom: unmapped 0x%.8x\n",offset
);
244 void EepromWriteWord(uint32_t offset
, uint16_t data
)
246 EepromWriteByte(offset
+ 0, (data
>> 8) & 0xFF);
247 EepromWriteByte(offset
+ 1, data
& 0xFF);
253 ; Commands specific to the National Semiconductor NM93C14
258 eEWDS equ %100000000 ;Erase/Write disable (default)
259 eWRAL equ %100010000 ;Writes all registers
260 eERAL equ %100100000 ;Erase all registers
261 eEWEN equ %100110000 ;Erase/write Enable
262 eWRITE equ %101000000 ;Write selected register
263 eREAD equ %110000000 ;read from EEPROM
264 eERASE equ %111000000 ;Erase selected register
268 static void eeprom_set_di(uint32_t data
)
271 WriteLog("eeprom: di=%i\n",data
);
272 WriteLog("eeprom: state %i\n",jerry_ee_state
);
275 switch (jerry_ee_state
)
278 jerry_ee_state
= EE_STATE_OP_A
;
281 jerry_ee_op
= (data
<< 1);
282 jerry_ee_state
= EE_STATE_OP_B
;
286 jerry_ee_direct_jump
= 0;
288 WriteLog("eeprom: opcode %i\n",jerry_ee_op
);
293 // Opcode 00: eEWEN, eERAL, eWRAL, eEWNDS
294 case 0: jerry_ee_state
= EE_STATE_0
; break;
295 // Opcode 01: eWRITE (Write selected register)
296 case 1: jerry_ee_state
= EE_STATE_1
; break;
297 // Opcode 10: eREAD (Read from EEPROM)
298 case 2: jerry_ee_state
= EE_STATE_2
; break;
299 // Opcode 11: eERASE (Erase selected register)
300 case 3: jerry_ee_state
= EE_STATE_3
; break;
306 jerry_ee_rstate
= EE_STATE_0_0
;
307 jerry_ee_state
= EE_READ_ADDRESS
;
308 jerry_ee_direct_jump
= 1;
309 jerry_ee_address_cnt
= 6;
310 jerry_ee_address_data
= 0;
313 switch ((jerry_ee_address_data
>> 4) & 0x03)
315 // Opcode 00 00: eEWDS (Erase/Write disable)
316 case 0: jerry_ee_state
=EE_STATE_0_0_0
; break;
317 // Opcode 00 01: eWRAL (Write all registers)
318 case 1: jerry_ee_state
=EE_STATE_0_0_1
; break;
319 // Opcode 00 10: eERAL (Erase all registers)
320 case 2: jerry_ee_state
=EE_STATE_0_0_2
; break;
321 // Opcode 00 11: eEWEN (Erase/Write enable)
322 case 3: jerry_ee_state
=EE_STATE_0_0_3
; break;
330 WriteLog("eeprom: read only\n");
332 jerry_writes_enabled
= 0;
333 jerry_ee_state
= EE_STATE_START
;
337 jerry_ee_rstate
= EE_STATE_0_0_1_0
;
338 jerry_ee_state
= EE_READ_DATA
;
339 jerry_ee_data_cnt
= 16;
341 jerry_ee_direct_jump
= 1;
343 case EE_STATE_0_0_1_0
:
345 WriteLog("eeprom: filling eeprom with 0x%.4x\n",data
);
347 if (jerry_writes_enabled
)
349 for(int i
=0; i
<64; i
++)
350 eeprom_ram
[i
] = jerry_ee_data
;
352 EEPROMSave(); // Save it NOW!
357 WriteLog("eeprom: not writing because read only\n");
359 jerry_ee_state
= EE_STATE_BUSY
;
364 WriteLog("eeprom: erasing eeprom\n");
366 if (jerry_writes_enabled
)
367 for(int i
=0; i
<64; i
++)
368 eeprom_ram
[i
] = 0xFFFF;
370 jerry_ee_state
= EE_STATE_BUSY
;
375 WriteLog("eeprom: read/write\n");
377 jerry_writes_enabled
= 1;
378 jerry_ee_state
= EE_STATE_START
;
381 jerry_ee_rstate
= EE_STATE_1_0
;
382 jerry_ee_state
= EE_READ_ADDRESS
;
383 jerry_ee_address_cnt
= 6;
384 jerry_ee_address_data
= 0;
385 jerry_ee_direct_jump
= 1;
388 jerry_ee_rstate
= EE_STATE_1_1
;
389 jerry_ee_state
= EE_READ_DATA
;
390 jerry_ee_data_cnt
= 16;
392 jerry_ee_direct_jump
= 1;
396 WriteLog("eeprom: writing 0x%.4x at 0x%.2x\n",jerry_ee_data
,jerry_ee_address_data
);
398 if (jerry_writes_enabled
)
400 eeprom_ram
[jerry_ee_address_data
] = jerry_ee_data
;
401 EEPROMSave(); // Save it NOW!
404 jerry_ee_state
= EE_STATE_BUSY
;
407 jerry_ee_rstate
= EE_STATE_2_0
;
408 jerry_ee_state
= EE_READ_ADDRESS
;
409 jerry_ee_address_cnt
= 6;
410 jerry_ee_address_data
= 0;
411 jerry_ee_data_cnt
= 16;
415 jerry_ee_rstate
= EE_STATE_3_0
;
416 jerry_ee_state
= EE_READ_ADDRESS
;
417 jerry_ee_address_cnt
= 6;
418 jerry_ee_address_data
= 0;
419 jerry_ee_direct_jump
= 1;
423 WriteLog("eeprom: erasing 0x%.2x\n",jerry_ee_address_data
);
425 if (jerry_writes_enabled
)
426 eeprom_ram
[jerry_ee_address_data
] = 0xFFFF;
428 jerry_ee_state
= EE_STATE_BUSY
;
432 WriteLog("eeprom:\t\t\t%i bit %i\n",data
,jerry_ee_data_cnt
-1);
435 jerry_ee_data
|= data
;
438 if (!jerry_ee_data_cnt
)
440 jerry_ee_state
= jerry_ee_rstate
;
442 if (jerry_ee_direct_jump
)
447 case EE_READ_ADDRESS
:
448 jerry_ee_address_data
<<= 1;
449 jerry_ee_address_data
|= data
;
450 jerry_ee_address_cnt
--;
452 WriteLog("eeprom:\t%i bits remaining\n",jerry_ee_address_cnt
);
455 if (!jerry_ee_address_cnt
)
457 jerry_ee_state
= jerry_ee_rstate
;
459 WriteLog("eeprom:\t\tread address 0x%.2x\n",jerry_ee_address_data
);
462 if (jerry_ee_direct_jump
)
468 jerry_ee_state
= EE_STATE_OP_A
;
473 static void eeprom_set_cs(uint32_t state
)
476 WriteLog("eeprom: cs=%i\n",state
);
478 jerry_ee_state
= EE_STATE_START
;
481 jerry_ee_address_data
= 0;
482 jerry_ee_address_cnt
= 6;
484 jerry_ee_data_cnt
= 16;
485 jerry_writes_enabled
= 1;
489 static uint32_t eeprom_get_do(void)
493 switch (jerry_ee_state
)
499 jerry_ee_state
= EE_STATE_START
;
504 data
= (eeprom_ram
[jerry_ee_address_data
] >> jerry_ee_data_cnt
) & 0x01;
506 if (!jerry_ee_data_cnt
)
509 //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());
511 jerry_ee_state
= EE_STATE_START
;
517 WriteLog("eeprom: do=%i\n",data
);