]> Shamusworld >> Repos - virtualjaguar/blob - src/eeprom.cpp
Initial changeset to experimental branch
[virtualjaguar] / src / eeprom.cpp
1 //
2 // Jaguar EEPROM handler
3 //
4 // by Cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups/enhancements by James L. Hammons
7 // (C) 2010 Underground Software
8 //
9 // JLH = James L. Hammons <jlhamm@acm.org>
10 //
11 // Who  When        What
12 // ---  ----------  -------------------------------------------------------------
13 // JLH  01/16/2010  Created this log ;-)
14 //
15
16 #include "eeprom.h"
17
18 #include <stdlib.h>
19 #include <string.h>                                                             // For memset
20 #include "jaguar.h"
21 #include "log.h"
22 #include "settings.h"
23
24 #define eeprom_LOG
25
26 static uint16 eeprom_ram[64];
27
28 //
29 // Private function prototypes
30 //
31
32 static void EEPROMSave(void);
33 static void eeprom_set_di(uint32 state);
34 static void eeprom_set_cs(uint32 state);
35 static uint32 eeprom_get_do(void);
36
37 enum { EE_STATE_START = 1, EE_STATE_OP_A, EE_STATE_OP_B, EE_STATE_0, EE_STATE_1,
38         EE_STATE_2, EE_STATE_3, EE_STATE_0_0, EE_READ_ADDRESS, EE_STATE_0_0_0,
39         EE_STATE_0_0_1, EE_STATE_0_0_2, EE_STATE_0_0_3, EE_STATE_0_0_1_0, EE_READ_DATA,
40         EE_STATE_BUSY, EE_STATE_1_0, EE_STATE_1_1, EE_STATE_2_0, EE_STATE_3_0 };
41
42 // Local global variables
43
44 static uint16 jerry_ee_state = EE_STATE_START;
45 static uint16 jerry_ee_op = 0;
46 static uint16 jerry_ee_rstate = 0;
47 static uint16 jerry_ee_address_data = 0;
48 static uint16 jerry_ee_address_cnt = 6;
49 static uint16 jerry_ee_data = 0;
50 static uint16 jerry_ee_data_cnt = 16;
51 static uint16 jerry_writes_enabled = 0;
52 static uint16 jerry_ee_direct_jump = 0;
53 static char eeprom_filename[MAX_PATH];
54 static bool foundEEPROM = false;
55
56 void EepromInit(void)
57 {
58         sprintf(eeprom_filename, "%s%08X.eep", vjs.EEPROMPath, (unsigned int)jaguarMainROMCRC32);
59         FILE * fp = fopen(eeprom_filename, "rb");
60
61         if (fp)
62         {
63                 fread(eeprom_ram, 1, 128, fp);
64                 fclose(fp);
65                 WriteLog("EEPROM: Loaded from %s\n", eeprom_filename);
66                 foundEEPROM = true;
67         }
68         else
69                 WriteLog("EEPROM: Could not open file \"%s\"!\n", eeprom_filename);
70 }
71
72 void EepromReset(void)
73 {
74         if (!foundEEPROM)
75                 memset(eeprom_ram, 0xFF, 64 * sizeof(uint16));
76 }
77
78 void EepromDone(void)
79 {
80         WriteLog("EEPROM: Done.\n");
81 }
82
83 static void EEPROMSave(void)
84 {
85         FILE * fp = fopen(eeprom_filename, "wb");
86
87         if (fp == NULL)
88         {
89                 WriteLog("EEPROM: Could not create file \"%s!\"\n", eeprom_filename);
90                 return;
91         }
92
93         fwrite(eeprom_ram, 1, 128, fp);
94         fclose(fp);
95 }
96
97 uint8 EepromReadByte(uint32 offset)
98 {
99         switch (offset)
100         {
101         case 0xF14001:
102                 return eeprom_get_do();
103         case 0xF14801:
104                 break;
105         case 0xF15001:
106                 eeprom_set_cs(1);
107                 break;
108 //      default: WriteLog("EEPROM: unmapped 0x%.8x\n", offset); break;
109         }
110
111         return 0x00;
112 }
113
114 uint16 EepromReadWord(uint32 offset)
115 {
116         return ((uint16)EepromReadByte(offset + 0) << 8) | EepromReadByte(offset + 1);
117 }
118
119 void EepromWriteByte(uint32 offset, uint8 data)
120 {
121         switch (offset)
122         {
123         case 0xF14001:
124                 break;
125         case 0xF14801:
126                 eeprom_set_di(data & 0x01);
127                 break;
128         case 0xF15001:
129                 eeprom_set_cs(1);
130                 break;
131 //      default: WriteLog("eeprom: unmapped 0x%.8x\n",offset); break;
132         }
133 }
134
135 void EepromWriteWord(uint32 offset, uint16 data)
136 {
137         EepromWriteByte(offset + 0, (data >> 8) & 0xFF);
138         EepromWriteByte(offset + 1, data & 0xFF);
139 }
140
141 static void eeprom_set_di(uint32 data)
142 {
143 //      WriteLog("eeprom: di=%i\n",data);
144 //      WriteLog("eeprom: state %i\n",jerry_ee_state);
145         switch (jerry_ee_state)
146         {
147         case EE_STATE_START:
148                 jerry_ee_state = EE_STATE_OP_A;
149                 break;
150         case EE_STATE_OP_A:
151                 jerry_ee_op = (data << 1);
152                 jerry_ee_state = EE_STATE_OP_B;
153                 break;
154         case EE_STATE_OP_B:
155                 jerry_ee_op |= data;
156                 jerry_ee_direct_jump = 0;
157 //              WriteLog("eeprom: opcode %i\n",jerry_ee_op);
158                 switch (jerry_ee_op)
159                 {
160                 case 0: jerry_ee_state = EE_STATE_0; break;
161                 case 1: jerry_ee_state = EE_STATE_1; break;
162                 case 2: jerry_ee_state = EE_STATE_2; break;
163                 case 3: jerry_ee_state = EE_STATE_3; break;
164                 }
165                 eeprom_set_di(data);
166                 break;
167         case EE_STATE_0:
168                 jerry_ee_rstate = EE_STATE_0_0;
169                 jerry_ee_state = EE_READ_ADDRESS;
170                 jerry_ee_direct_jump = 1;
171                 jerry_ee_address_cnt = 6;
172                 jerry_ee_address_data = 0;
173                 break;
174         case EE_STATE_0_0:
175                 switch ((jerry_ee_address_data >> 4) & 0x03)
176                 {
177                 case 0: jerry_ee_state=EE_STATE_0_0_0; break;
178                 case 1: jerry_ee_state=EE_STATE_0_0_1; break;
179                 case 2: jerry_ee_state=EE_STATE_0_0_2; break;
180                 case 3: jerry_ee_state=EE_STATE_0_0_3; break;
181                 }
182                 eeprom_set_di(data);
183                 break;
184         case EE_STATE_0_0_0:
185                 // writes disable
186                 // WriteLog("eeprom: read only\n");
187                 jerry_writes_enabled = 0;
188                 jerry_ee_state = EE_STATE_START;
189                 break;
190         case EE_STATE_0_0_1:
191                 // writes all
192                 jerry_ee_rstate = EE_STATE_0_0_1_0;
193                 jerry_ee_state = EE_READ_DATA;
194                 jerry_ee_data_cnt = 16;
195                 jerry_ee_data = 0;
196                 jerry_ee_direct_jump = 1;
197                 break;
198         case EE_STATE_0_0_1_0:
199                 // WriteLog("eeprom: filling eeprom with 0x%.4x\n",data);
200                 if (jerry_writes_enabled)
201                         for(int i=0; i<64; i++)
202                                 eeprom_ram[i] = jerry_ee_data;
203                 EEPROMSave();                                                           // Save it NOW!
204                 //else
205                 //      WriteLog("eeprom: not writing because read only\n");
206                 jerry_ee_state = EE_STATE_BUSY;
207                 break;
208         case EE_STATE_0_0_2:
209                 // erase all
210                 //WriteLog("eeprom: erasing eeprom\n");
211                 if (jerry_writes_enabled)
212                         for(int i=0; i<64; i++)
213                                 eeprom_ram[i] = 0xFFFF;
214
215                 jerry_ee_state = EE_STATE_BUSY;
216                 break;
217         case EE_STATE_0_0_3:
218                 // writes enable
219                 //WriteLog("eeprom: read/write\n");
220                 jerry_writes_enabled = 1;
221                 jerry_ee_state = EE_STATE_START;
222                 break;
223         case EE_STATE_1:
224                 jerry_ee_rstate = EE_STATE_1_0;
225                 jerry_ee_state = EE_READ_ADDRESS;
226                 jerry_ee_address_cnt = 6;
227                 jerry_ee_address_data = 0;
228                 jerry_ee_direct_jump = 1;
229                 break;
230         case EE_STATE_1_0:
231                 jerry_ee_rstate = EE_STATE_1_1;
232                 jerry_ee_state = EE_READ_DATA;
233                 jerry_ee_data_cnt = 16;
234                 jerry_ee_data = 0;
235                 jerry_ee_direct_jump = 1;
236                 break;
237         case EE_STATE_1_1:
238                 //WriteLog("eeprom: writing 0x%.4x at 0x%.2x\n",jerry_ee_data,jerry_ee_address_data);
239                 if (jerry_writes_enabled)
240                         eeprom_ram[jerry_ee_address_data] = jerry_ee_data;
241                 EEPROMSave();                                                           // Save it NOW!
242                 jerry_ee_state = EE_STATE_BUSY;
243                 break;
244         case EE_STATE_2:
245                 jerry_ee_rstate = EE_STATE_2_0;
246                 jerry_ee_state = EE_READ_ADDRESS;
247                 jerry_ee_address_cnt = 6;
248                 jerry_ee_address_data = 0;
249                 jerry_ee_data_cnt = 16;
250                 jerry_ee_data = 0;
251                 break;
252         case EE_STATE_3:
253                 jerry_ee_rstate = EE_STATE_3_0;
254                 jerry_ee_state = EE_READ_ADDRESS;
255                 jerry_ee_address_cnt = 6;
256                 jerry_ee_address_data = 0;
257                 jerry_ee_direct_jump = 1;
258                 break;
259         case EE_STATE_3_0:
260                 //WriteLog("eeprom: erasing 0x%.2x\n",jerry_ee_address_data);
261                 if (jerry_writes_enabled)
262                         eeprom_ram[jerry_ee_address_data] = 0xFFFF;
263                 jerry_ee_state = EE_STATE_BUSY;
264                 break;
265         case EE_READ_DATA:
266                 //WriteLog("eeprom:\t\t\t%i bit %i\n",data,jerry_ee_data_cnt-1);
267                 jerry_ee_data <<= 1;
268                 jerry_ee_data |= data;
269                 jerry_ee_data_cnt--;
270                 if (!jerry_ee_data_cnt)
271                 {
272                         jerry_ee_state = jerry_ee_rstate;
273                         if (jerry_ee_direct_jump)
274                                 eeprom_set_di(data);
275                 }
276                 break;
277         case EE_READ_ADDRESS:
278                 jerry_ee_address_data <<= 1;
279                 jerry_ee_address_data |= data;
280                 jerry_ee_address_cnt--;
281 //              WriteLog("eeprom:\t%i bits remaining\n",jerry_ee_address_cnt);
282                 if (!jerry_ee_address_cnt)
283                 {
284                         jerry_ee_state = jerry_ee_rstate;
285                         //WriteLog("eeprom:\t\tread address 0x%.2x\n",jerry_ee_address_data);
286                         if (jerry_ee_direct_jump)
287                                 eeprom_set_di(data);
288                 }
289                 break;
290         default:
291                 jerry_ee_state = EE_STATE_OP_A;
292         }
293 }
294
295 static void eeprom_set_cs(uint32 state)
296 {
297 //      WriteLog("eeprom: cs=%i\n",state);
298         jerry_ee_state = EE_STATE_START;
299         jerry_ee_op = 0;
300         jerry_ee_rstate = 0;
301         jerry_ee_address_data = 0;
302         jerry_ee_address_cnt = 6;
303         jerry_ee_data = 0;
304         jerry_ee_data_cnt = 16;
305         jerry_writes_enabled = 1;
306 }
307
308 static uint32 eeprom_get_do(void)
309 {
310         uint16 data = 1;
311
312         switch (jerry_ee_state)
313         {
314         case EE_STATE_START:
315                 data = 1;
316                 break;
317         case EE_STATE_BUSY:
318                 jerry_ee_state = EE_STATE_START;
319                 data = 0;
320                 break;
321         case EE_STATE_2_0:
322                 jerry_ee_data_cnt--;
323                 data = (eeprom_ram[jerry_ee_address_data] & (1 << jerry_ee_data_cnt)) >> jerry_ee_data_cnt;
324                 if (!jerry_ee_data_cnt)
325                 {
326                         //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());
327                         jerry_ee_state = EE_STATE_START;
328                 }
329                 break;
330         }
331
332 //      WriteLog("eeprom: do=%i\n",data);
333         return data;
334 }