Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/eeprom.cpp
2 views
1
// Meteor - A Nintendo Gameboy Advance emulator
2
// Copyright (C) 2009-2011 Philippe Daouadi
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
#include "ameteor/eeprom.hpp"
18
#include "globals.hpp"
19
#include "debug.hpp"
20
21
#include <cstring>
22
23
namespace AMeteor
24
{
25
Eeprom::Eeprom (bool big) :
26
CartMem(),
27
m_state(IDLE),
28
m_add(0),
29
m_pos(0)
30
{
31
if (big)
32
m_size = 0x2000;
33
else
34
m_size = 0x0200;
35
36
*(uint32_t*)(m_data+MAX_SIZE) = m_size;
37
}
38
39
void Eeprom::Reset ()
40
{
41
std::memset(m_data, 0, m_size);
42
}
43
44
bool Eeprom::Load (std::istream& f)
45
{
46
f.read((char*)m_data, m_size);
47
return f.good();
48
}
49
50
bool Eeprom::Save (std::ostream& f)
51
{
52
f.write((char*)m_data, m_size);
53
return f.good();
54
}
55
56
uint8_t Eeprom::Read (uint16_t MET_UNUSED(add))
57
{
58
met_abort("8 bits write to EEPROM");
59
return 0;
60
}
61
62
uint16_t Eeprom::Read ()
63
{
64
switch (m_state)
65
{
66
case READ_GARBAGE:
67
++m_pos;
68
if (m_pos == 4)
69
{
70
m_pos = 0;
71
m_state = READ_DATA;
72
}
73
return 0;
74
case READ_DATA:
75
{
76
uint16_t ret =
77
(m_data[m_add + m_pos / 8] & (0x1 << (7 - (m_pos % 8)))) ? 1 : 0;
78
++m_pos;
79
if (m_pos == 64)
80
m_state = IDLE;
81
return ret;
82
}
83
default:
84
return 1;
85
}
86
}
87
88
bool Eeprom::Write (uint16_t MET_UNUSED(add), uint8_t MET_UNUSED(val))
89
{
90
met_abort("8 bits write to EEPROM");
91
return false;
92
}
93
//XXX
94
#if 0
95
bool Eeprom::Write (uint16_t val)
96
{
97
switch (m_state)
98
{
99
case IDLE:
100
if (val & 0x1)
101
m_state = WAITING;
102
else
103
met_abort("First bit is not 1");
104
return false;
105
case WAITING:
106
m_add = 0;
107
m_pos = 0;
108
if (val & 0x1)
109
m_state = READ_ADD;
110
else
111
m_state = WRITE_ADD;
112
return false;
113
114
case READ_ADD:
115
m_add <<= 1;
116
m_add |= val & 0x1;
117
++m_pos;
118
if (m_size == 0x0200 && m_pos == 6 ||
119
m_size == 0x2000 && m_pos == 14)
120
{
121
m_state = READ_END;
122
if (m_size == 0x2000 && (m_add & 0x3C000))
123
met_abort("In large EEPROM, 4 upper address bits are not 0");
124
}
125
return false;
126
case READ_END:
127
if (val & 0x1)
128
met_abort("Last bit of EEPROM read request is not 0");
129
m_pos = 0;
130
m_state = READ_GARBAGE;
131
return false;
132
133
case WRITE_ADD:
134
m_add <<= 1;
135
m_add |= val & 0x1;
136
++m_pos;
137
if (m_size == 0x0200 && m_pos == 6 ||
138
m_size == 0x2000 && m_pos == 14)
139
{
140
m_state = WRITE_DATA;
141
m_pos = 0;
142
if (m_size == 0x2000 && (m_add & 0x3C000))
143
met_abort("In large EEPROM, 4 upper address bits are not 0");
144
}
145
return false;
146
case WRITE_DATA:
147
{
148
uint8_t& d = m_data[m_add + m_pos / 8];
149
d <<= 1;
150
d |= val & 0x1;
151
}
152
++m_pos;
153
if (m_pos == 64)
154
m_state = WRITE_END;
155
return true;
156
case WRITE_END:
157
if (val & 0x1)
158
met_abort("Last bit of EEPROM write request is not 0");
159
return false;
160
}
161
}
162
#endif
163
164
bool Eeprom::Write (uint16_t* pData, uint16_t size)
165
{
166
if (!(*pData & 0x1))
167
met_abort("Bit 1 is not 1 in EEPROM DMA");
168
++pData;
169
170
uint16_t add = 0;
171
if (*pData & 0x1) // read
172
{
173
if (size != 9 && size != 17)
174
met_abort("Invalid size for read");
175
++pData;
176
177
// read address
178
for (uint8_t i = 0, end = (m_size == 0x0200) ? 6 : 14; i < end;
179
++i, ++pData)
180
add = (add << 1) | (*pData & 0x1);
181
if (m_size == 0x2000 && (add & 0x3C00))
182
met_abort("In large EEPROM, 4 upper address bits are not 0");
183
184
//XXX
185
/*if (*pData & 0x1)
186
met_abort("Last bit of EEPROM read request is not 0");*/
187
188
m_add = add*8;
189
m_state = READ_GARBAGE;
190
m_pos = 0;
191
192
return false;
193
}
194
else // write
195
{
196
if (size != 73 && size != 81)
197
met_abort("Invalid size for write");
198
++pData;
199
200
// read address
201
for (uint8_t i = 0, end = (m_size == 0x0200) ? 6 : 14; i < end;
202
++i, ++pData)
203
add = (add << 1) | (*pData & 0x1);
204
if (m_size == 0x2000 && (add & 0x3C00))
205
met_abort("In large EEPROM, 4 upper address bits are not 0");
206
207
// read data
208
uint8_t* pMem = m_data + add*8;
209
for (uint8_t i = 0; i < 8; ++i, ++pMem)
210
{
211
for (uint8_t j = 0; j < 8; ++j, ++pData)
212
{
213
*pMem <<= 1;
214
*pMem |= (*pData & 0x1);
215
}
216
}
217
218
if (*pData & 0x1)
219
met_abort("Last bit of EEPROM write request is not 0");
220
221
m_state = IDLE;
222
223
return true;
224
}
225
}
226
227
//XXX
228
#if 0
229
void Eeprom::Read (uint16_t* pOut)
230
{
231
if (m_state != READ)
232
met_abort("Read in invalid EEPROM state");
233
234
pOut += 4; // ignore these
235
uint8_t* pData = m_data + m_add;
236
uint8_t cur;
237
for (uint8_t i = 0; i < 8; ++i, ++pData)
238
{
239
cur = *pData;
240
pOut += 7;
241
for (uint8_t j = 0; j < 8; ++j, --pOut, cur >>= 1)
242
*pOut = cur & 0x1;
243
pOut += 9;
244
}
245
246
m_state = NORMAL;
247
}
248
#endif
249
250
bool Eeprom::SaveState (std::ostream& stream)
251
{
252
//XXX TODO
253
SS_WRITE_VAR(m_size);
254
SS_WRITE_VAR(m_state);
255
SS_WRITE_VAR(m_add);
256
257
SS_WRITE_DATA(m_data, m_size);
258
259
return true;
260
}
261
262
bool Eeprom::LoadState (std::istream& stream)
263
{
264
SS_READ_VAR(m_size);
265
SS_READ_VAR(m_state);
266
SS_READ_VAR(m_add);
267
268
SS_READ_DATA(m_data, m_size);
269
270
return true;
271
}
272
}
273
274