Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx32/core/cart_hw/eeprom_i2c.c
2 views
1
/****************************************************************************
2
* Genesis Plus
3
* I2C Serial EEPROM (24Cxx) support
4
*
5
* Copyright (C) 2007-2013 Eke-Eke (Genesis Plus GX)
6
*
7
* Redistribution and use of this code or any derivative works are permitted
8
* provided that the following conditions are met:
9
*
10
* - Redistributions may not be sold, nor may they be used in a commercial
11
* product or activity.
12
*
13
* - Redistributions that are modified from the original source must include the
14
* complete source code, including the source code for all components used by a
15
* binary built from the modified sources. However, as a special exception, the
16
* source code distributed need not include anything that is normally distributed
17
* (in either source or binary form) with the major components (compiler, kernel,
18
* and so on) of the operating system on which the executable runs, unless that
19
* component itself accompanies the executable.
20
*
21
* - Redistributions must reproduce the above copyright notice, this list of
22
* conditions and the following disclaimer in the documentation and/or other
23
* materials provided with the distribution.
24
*
25
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
* POSSIBILITY OF SUCH DAMAGE.
36
*
37
****************************************************************************************/
38
39
#include "shared.h"
40
#include "eeprom_i2c.h"
41
42
#define GAME_CNT 28
43
44
/* this defines the type of EEPROM inside the game cartridge as Backup RAM
45
*
46
* Here are some notes from 8BitWizard (http://www.spritesmind.net/_GenDev/forum):
47
*
48
* Mode 1 (7-bit) - the chip takes a single byte with a 7-bit memory address and a R/W bit (24C01)
49
* Mode 2 (8-bit) - the chip takes a 7-bit device address and R/W bit followed by an 8-bit memory address;
50
* the device address may contain up to three more memory address bits (24C01 - 24C16).
51
* You can also string eight 24C01, four 24C02, two 24C08, or various combinations, set their address config lines correctly,
52
* and the result appears exactly the same as a 24C16
53
* Mode 3 (16-bit) - the chip takes a 7-bit device address and R/W bit followed by a 16-bit memory address (24C32 and larger)
54
*
55
* Also, while most 24Cxx are addressed at 200000-2FFFFF, I have found two different ways of mapping the control lines.
56
* EA uses SDA on D7 (read/write) and SCL on D6 (write only), and I have found boards using different mapping (I think Accolade)
57
* which uses D1-read=SDA, D0-write=SDA, D1-write=SCL. Accolade also has a custom-chip mapper which may even use a third method.
58
*/
59
60
typedef struct
61
{
62
char game_id[16];
63
uint16 chk;
64
T_CONFIG_I2C config;
65
} T_GAME_ENTRY;
66
67
static const T_GAME_ENTRY database[GAME_CNT] =
68
{
69
/* ACCLAIM mappers */
70
/* 24C02 (old mapper) */
71
{{"T-081326" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (UE) */
72
{{"T-81033" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (J) */
73
/* 24C02 */
74
{{"T-081276" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club */
75
/* 24C04 */
76
{{"T-81406" }, 0, {8, 0x1FF, 0x1FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NBA Jam TE */
77
/* 24C16 */
78
{{"T-081586" }, 0, {8, 0x7FF, 0x7FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club '96 */
79
/* 24C65 */
80
{{"T-81576" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* College Slam */
81
{{"T-81476" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* Frank Thomas Big Hurt Baseball */
82
83
/* EA mapper (X24C01 only) */
84
{{"T-50176" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* Rings of Power */
85
{{"T-50396" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* NHLPA Hockey 93 */
86
{{"T-50446" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* John Madden Football 93 */
87
{{"T-50516" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* John Madden Football 93 (Championship Ed.) */
88
{{"T-50606" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* Bill Walsh College Football */
89
90
/* SEGA mapper (X24C01 only) */
91
{{"T-12046" }, 0xAD23, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Megaman - The Wily Wars */
92
{{"T-12053" }, 0xEA80, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Rockman Mega World [Alt] */
93
{{"MK-1215" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Evander 'Real Deal' Holyfield's Boxing */
94
{{"MK-1228" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (U) */
95
{{"G-5538" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (J) */
96
{{"PR-1993" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (E) */
97
{{"G-4060" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Wonderboy in Monster World */
98
{{"00001211-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Sports Talk Baseball */
99
{{"00004076-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Honoo no Toukyuuji Dodge Danpei */
100
{{"G-4524" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Ninja Burai Densetsu */
101
{{"00054503-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Game Toshokan */
102
103
/* CODEMASTERS mapper */
104
/* 24C08 */
105
{{"T-120106" }, 0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Brian Lara Cricket */
106
{{"00000000-00"}, 0xCEE0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military */
107
/* 24C16 */
108
{{"T-120096" }, 0, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines 2 - Turbo Tournament */
109
{{"00000000-00"}, 0x2C41, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 */
110
/* 24C65 */
111
{{"T-120146-50"}, 0, {16, 0x1FFF, 0x1FFF, 0x300000, 0x380001, 0x300000, 0, 7, 1}} /* Brian Lara Cricket 96, Shane Warne Cricket */
112
};
113
114
T_EEPROM_I2C eeprom_i2c;
115
116
static unsigned int eeprom_i2c_read_byte(unsigned int address);
117
static unsigned int eeprom_i2c_read_word(unsigned int address);
118
static void eeprom_i2c_write_byte(unsigned int address, unsigned int data);
119
static void eeprom_i2c_write_word(unsigned int address, unsigned int data);
120
121
void eeprom_i2c_init()
122
{
123
int i = 0;
124
125
/* initialize eeprom */
126
memset(&eeprom_i2c, 0, sizeof(T_EEPROM_I2C));
127
eeprom_i2c.sda = eeprom_i2c.old_sda = 1;
128
eeprom_i2c.scl = eeprom_i2c.old_scl = 1;
129
eeprom_i2c.state = STAND_BY;
130
131
/* no eeprom by default */
132
sram.custom = 0;
133
134
/* look into game database */
135
while (i<GAME_CNT)
136
{
137
if (strstr(rominfo.product,database[i].game_id) != NULL)
138
{
139
/* additional check (Micro Machines, Rockman Mega World) */
140
if ((database[i].chk == 0x0000) || (database[i].chk == rominfo.realchecksum))
141
{
142
sram.custom = 1;
143
sram.on = 1;
144
memcpy(&eeprom_i2c.config, &database[i].config, sizeof(T_CONFIG_I2C));
145
i = GAME_CNT;
146
}
147
}
148
i++;
149
}
150
151
/* Game not found in database but ROM header indicates it uses serial EEPROM */
152
if (!sram.custom && sram.detected)
153
{
154
if ((READ_BYTE(cart.rom,0x1b2) == 0xe8) || ((sram.end - sram.start) < 2))
155
{
156
/* set SEGA mapper as default */
157
sram.custom = 1;
158
memcpy(&eeprom_i2c.config, &database[9].config, sizeof(T_CONFIG_I2C));
159
}
160
}
161
162
/* initialize m68k bus handlers */
163
if (sram.custom)
164
{
165
m68k.memory_map[eeprom_i2c.config.sda_out_adr >> 16].read8 = eeprom_i2c_read_byte;
166
m68k.memory_map[eeprom_i2c.config.sda_out_adr >> 16].read16 = eeprom_i2c_read_word;
167
m68k.memory_map[eeprom_i2c.config.sda_in_adr >> 16].read8 = eeprom_i2c_read_byte;
168
m68k.memory_map[eeprom_i2c.config.sda_in_adr >> 16].read16 = eeprom_i2c_read_word;
169
m68k.memory_map[eeprom_i2c.config.scl_adr >> 16].write8 = eeprom_i2c_write_byte;
170
m68k.memory_map[eeprom_i2c.config.scl_adr >> 16].write16 = eeprom_i2c_write_word;
171
zbank_memory_map[eeprom_i2c.config.sda_out_adr >> 16].read = eeprom_i2c_read_byte;
172
zbank_memory_map[eeprom_i2c.config.sda_in_adr >> 16].read = eeprom_i2c_read_byte;
173
zbank_memory_map[eeprom_i2c.config.scl_adr >> 16].write = eeprom_i2c_write_byte;
174
}
175
}
176
177
INLINE void Detect_START()
178
{
179
if (eeprom_i2c.old_scl && eeprom_i2c.scl)
180
{
181
if (eeprom_i2c.old_sda && !eeprom_i2c.sda)
182
{
183
eeprom_i2c.cycles = 0;
184
eeprom_i2c.slave_mask = 0;
185
if (eeprom_i2c.config.address_bits == 7)
186
{
187
eeprom_i2c.word_address = 0;
188
eeprom_i2c.state = GET_WORD_ADR_7BITS;
189
}
190
else eeprom_i2c.state = GET_SLAVE_ADR;
191
}
192
}
193
}
194
195
INLINE void Detect_STOP()
196
{
197
if (eeprom_i2c.old_scl && eeprom_i2c.scl)
198
{
199
if (!eeprom_i2c.old_sda && eeprom_i2c.sda)
200
{
201
eeprom_i2c.state = STAND_BY;
202
}
203
}
204
}
205
206
static void eeprom_i2c_update(void)
207
{
208
/* EEPROM current state */
209
switch (eeprom_i2c.state)
210
{
211
/* Standby Mode */
212
case STAND_BY:
213
{
214
Detect_START();
215
Detect_STOP();
216
break;
217
}
218
219
/* Suspended Mode */
220
case WAIT_STOP:
221
{
222
Detect_STOP();
223
break;
224
}
225
226
/* Get Word Address 7 bits: MODE-1 only (24C01)
227
* and R/W bit
228
*/
229
case GET_WORD_ADR_7BITS:
230
{
231
Detect_START();
232
Detect_STOP();
233
234
/* look for SCL LOW to HIGH transition */
235
if (!eeprom_i2c.old_scl && eeprom_i2c.scl)
236
{
237
if (eeprom_i2c.cycles == 0) eeprom_i2c.cycles ++;
238
}
239
240
241
/* look for SCL HIGH to LOW transition */
242
if (eeprom_i2c.old_scl && !eeprom_i2c.scl && (eeprom_i2c.cycles > 0))
243
{
244
if (eeprom_i2c.cycles < 8)
245
{
246
eeprom_i2c.word_address |= (eeprom_i2c.old_sda << (7 - eeprom_i2c.cycles));
247
}
248
else if (eeprom_i2c.cycles == 8)
249
{
250
eeprom_i2c.rw = eeprom_i2c.old_sda;
251
}
252
else
253
{ /* ACK CYCLE */
254
eeprom_i2c.cycles = 0;
255
eeprom_i2c.word_address &= eeprom_i2c.config.size_mask;
256
eeprom_i2c.state = eeprom_i2c.rw ? READ_DATA : WRITE_DATA;
257
}
258
259
eeprom_i2c.cycles ++;
260
}
261
break;
262
}
263
264
/* Get Slave Address (3bits) : MODE-2 & MODE-3 only (24C01 - 24C512) (0-3bits, depending on the array size)
265
* or/and Word Address MSB: MODE-2 only (24C04 - 24C16) (0-3bits, depending on the array size)
266
* and R/W bit
267
*/
268
case GET_SLAVE_ADR:
269
{
270
Detect_START();
271
Detect_STOP();
272
273
/* look for SCL LOW to HIGH transition */
274
if (!eeprom_i2c.old_scl && eeprom_i2c.scl)
275
{
276
if (eeprom_i2c.cycles == 0) eeprom_i2c.cycles ++;
277
}
278
279
/* look for SCL HIGH to LOW transition */
280
if (eeprom_i2c.old_scl && !eeprom_i2c.scl && (eeprom_i2c.cycles > 0))
281
{
282
if ((eeprom_i2c.cycles > 4) && (eeprom_i2c.cycles <8))
283
{
284
if ((eeprom_i2c.config.address_bits == 16) ||
285
(eeprom_i2c.config.size_mask < (1 << (15 - eeprom_i2c.cycles))))
286
{
287
/* this is a SLAVE ADDRESS bit */
288
eeprom_i2c.slave_mask |= (eeprom_i2c.old_sda << (7 - eeprom_i2c.cycles));
289
}
290
else
291
{
292
/* this is a WORD ADDRESS high bit */
293
if (eeprom_i2c.old_sda) eeprom_i2c.word_address |= (1 << (15 - eeprom_i2c.cycles));
294
else eeprom_i2c.word_address &= ~(1 << (15 - eeprom_i2c.cycles));
295
}
296
}
297
else if (eeprom_i2c.cycles == 8) eeprom_i2c.rw = eeprom_i2c.old_sda;
298
else if (eeprom_i2c.cycles > 8)
299
{
300
/* ACK CYCLE */
301
eeprom_i2c.cycles = 0;
302
if (eeprom_i2c.config.address_bits == 16)
303
{
304
/* two ADDRESS bytes */
305
eeprom_i2c.state = eeprom_i2c.rw ? READ_DATA : GET_WORD_ADR_HIGH;
306
eeprom_i2c.slave_mask <<= 16;
307
}
308
else
309
{
310
/* one ADDRESS byte */
311
eeprom_i2c.state = eeprom_i2c.rw ? READ_DATA : GET_WORD_ADR_LOW;
312
eeprom_i2c.slave_mask <<= 8;
313
}
314
}
315
316
eeprom_i2c.cycles ++;
317
}
318
break;
319
}
320
321
/* Get Word Address MSB (4-8bits depending on the array size)
322
* MODE-3 only (24C32 - 24C512)
323
*/
324
case GET_WORD_ADR_HIGH:
325
{
326
Detect_START();
327
Detect_STOP();
328
329
/* look for SCL HIGH to LOW transition */
330
if (eeprom_i2c.old_scl && !eeprom_i2c.scl)
331
{
332
if (eeprom_i2c.cycles < 9)
333
{
334
if ((eeprom_i2c.config.size_mask + 1) < (1 << (17 - eeprom_i2c.cycles)))
335
{
336
/* ignored bit: slave mask should be right-shifted by one */
337
eeprom_i2c.slave_mask >>= 1;
338
}
339
else
340
{
341
/* this is a WORD ADDRESS high bit */
342
if (eeprom_i2c.old_sda) eeprom_i2c.word_address |= (1 << (16 - eeprom_i2c.cycles));
343
else eeprom_i2c.word_address &= ~(1 << (16 - eeprom_i2c.cycles));
344
}
345
346
eeprom_i2c.cycles ++;
347
}
348
else
349
{
350
/* ACK CYCLE */
351
eeprom_i2c.cycles = 1;
352
eeprom_i2c.state = GET_WORD_ADR_LOW;
353
}
354
}
355
break;
356
}
357
358
/* Get Word Address LSB: 7bits (24C01) or 8bits (24C02-24C512)
359
* MODE-2 and MODE-3 only (24C01 - 24C512)
360
*/
361
case GET_WORD_ADR_LOW:
362
{
363
Detect_START();
364
Detect_STOP();
365
366
/* look for SCL HIGH to LOW transition */
367
if (eeprom_i2c.old_scl && !eeprom_i2c.scl)
368
{
369
if (eeprom_i2c.cycles < 9)
370
{
371
if ((eeprom_i2c.config.size_mask + 1) < (1 << (9 - eeprom_i2c.cycles)))
372
{
373
/* ignored bit (X24C01): slave mask should be right-shifted by one */
374
eeprom_i2c.slave_mask >>= 1;
375
}
376
else
377
{
378
/* this is a WORD ADDRESS high bit */
379
if (eeprom_i2c.old_sda) eeprom_i2c.word_address |= (1 << (8 - eeprom_i2c.cycles));
380
else eeprom_i2c.word_address &= ~(1 << (8 - eeprom_i2c.cycles));
381
}
382
383
eeprom_i2c.cycles ++;
384
}
385
else
386
{
387
/* ACK CYCLE */
388
eeprom_i2c.cycles = 1;
389
eeprom_i2c.word_address &= eeprom_i2c.config.size_mask;
390
eeprom_i2c.state = WRITE_DATA;
391
}
392
}
393
break;
394
}
395
396
/*
397
* Read Cycle
398
*/
399
case READ_DATA:
400
{
401
Detect_START();
402
Detect_STOP();
403
404
/* look for SCL HIGH to LOW transition */
405
if (eeprom_i2c.old_scl && !eeprom_i2c.scl)
406
{
407
if (eeprom_i2c.cycles < 9) eeprom_i2c.cycles ++;
408
else
409
{
410
eeprom_i2c.cycles = 1;
411
412
/* ACK not received */
413
if (eeprom_i2c.old_sda) eeprom_i2c.state = WAIT_STOP;
414
}
415
}
416
break;
417
}
418
419
/*
420
* Write Cycle
421
*/
422
case WRITE_DATA:
423
{
424
Detect_START();
425
Detect_STOP();
426
427
/* look for SCL HIGH to LOW transition */
428
if (eeprom_i2c.old_scl && !eeprom_i2c.scl)
429
{
430
if (eeprom_i2c.cycles < 9)
431
{
432
/* Write DATA bits (max 64kBytes) */
433
uint16 sram_address = (eeprom_i2c.slave_mask | eeprom_i2c.word_address) & 0xFFFF;
434
if (eeprom_i2c.old_sda) sram.sram[sram_address] |= (1 << (8 - eeprom_i2c.cycles));
435
else sram.sram[sram_address] &= ~(1 << (8 - eeprom_i2c.cycles));
436
437
if (eeprom_i2c.cycles == 8)
438
{
439
/* WORD ADDRESS is incremented (roll up at maximum pagesize) */
440
eeprom_i2c.word_address = (eeprom_i2c.word_address & (0xFFFF - eeprom_i2c.config.pagewrite_mask)) |
441
((eeprom_i2c.word_address + 1) & eeprom_i2c.config.pagewrite_mask);
442
}
443
444
eeprom_i2c.cycles ++;
445
}
446
else eeprom_i2c.cycles = 1; /* ACK cycle */
447
}
448
break;
449
}
450
}
451
452
eeprom_i2c.old_scl = eeprom_i2c.scl;
453
eeprom_i2c.old_sda = eeprom_i2c.sda;
454
}
455
456
static unsigned char eeprom_i2c_out(void)
457
{
458
uint8 sda_out = eeprom_i2c.sda;
459
460
/* EEPROM state */
461
switch (eeprom_i2c.state)
462
{
463
case READ_DATA:
464
{
465
if (eeprom_i2c.cycles < 9)
466
{
467
/* Return DATA bits (max 64kBytes) */
468
uint16 sram_address = (eeprom_i2c.slave_mask | eeprom_i2c.word_address) & 0xffff;
469
sda_out = (sram.sram[sram_address] >> (8 - eeprom_i2c.cycles)) & 1;
470
471
if (eeprom_i2c.cycles == 8)
472
{
473
/* WORD ADDRESS is incremented (roll up at maximum array size) */
474
eeprom_i2c.word_address ++;
475
eeprom_i2c.word_address &= eeprom_i2c.config.size_mask;
476
}
477
}
478
break;
479
}
480
481
case GET_WORD_ADR_7BITS:
482
case GET_SLAVE_ADR:
483
case GET_WORD_ADR_HIGH:
484
case GET_WORD_ADR_LOW:
485
case WRITE_DATA:
486
{
487
if (eeprom_i2c.cycles == 9) sda_out = 0;
488
break;
489
}
490
491
default:
492
{
493
break;
494
}
495
}
496
497
return (sda_out << eeprom_i2c.config.sda_out_bit);
498
}
499
500
static unsigned int eeprom_i2c_read_byte(unsigned int address)
501
{
502
if (address == eeprom_i2c.config.sda_out_adr)
503
{
504
return eeprom_i2c_out();
505
}
506
507
return READ_BYTE(cart.rom, address);
508
}
509
510
static unsigned int eeprom_i2c_read_word(unsigned int address)
511
{
512
if (address == eeprom_i2c.config.sda_out_adr)
513
{
514
return (eeprom_i2c_out() << 8);
515
}
516
517
if (address == (eeprom_i2c.config.sda_out_adr ^ 1))
518
{
519
return eeprom_i2c_out();
520
}
521
522
return *(uint16 *)(cart.rom + address);
523
}
524
525
static void eeprom_i2c_write_byte(unsigned int address, unsigned int data)
526
{
527
int do_update = 0;
528
529
if (address == eeprom_i2c.config.sda_in_adr)
530
{
531
eeprom_i2c.sda = (data >> eeprom_i2c.config.sda_in_bit) & 1;
532
do_update = 1;
533
}
534
535
if (address == eeprom_i2c.config.scl_adr)
536
{
537
eeprom_i2c.scl = (data >> eeprom_i2c.config.scl_bit) & 1;
538
do_update = 1;
539
}
540
541
if (do_update)
542
{
543
eeprom_i2c_update();
544
return;
545
}
546
547
m68k_unused_8_w(address, data);
548
}
549
550
static void eeprom_i2c_write_word(unsigned int address, unsigned int data)
551
{
552
int do_update = 0;
553
554
if (address == eeprom_i2c.config.sda_in_adr)
555
{
556
eeprom_i2c.sda = (data >> (8 + eeprom_i2c.config.sda_in_bit)) & 1;
557
do_update = 1;
558
}
559
else if (address == (eeprom_i2c.config.sda_in_adr ^1))
560
{
561
eeprom_i2c.sda = (data >> eeprom_i2c.config.sda_in_bit) & 1;
562
do_update = 1;
563
}
564
565
if (address == eeprom_i2c.config.scl_adr)
566
{
567
eeprom_i2c.scl = (data >> (8 + eeprom_i2c.config.scl_bit)) & 1;
568
do_update = 1;
569
}
570
else if (address == (eeprom_i2c.config.scl_adr ^1))
571
{
572
eeprom_i2c.scl = (data >> eeprom_i2c.config.scl_bit) & 1;
573
do_update = 1;
574
}
575
576
if (do_update)
577
{
578
eeprom_i2c_update();
579
return;
580
}
581
582
m68k_unused_16_w(address, data);
583
}
584
585