Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/flash.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/flash.hpp"
18
#include "globals.hpp"
19
#include <cstring>
20
#include <fstream>
21
22
namespace AMeteor
23
{
24
Flash::Flash (bool big) :
25
CartMem(),
26
m_state(NORMAL)
27
{
28
if (big)
29
{
30
m_device_id = 0x13;
31
m_manufacturer_id = 0x62;
32
m_size = 128*1024;
33
}
34
else
35
{
36
m_device_id = 0x1B;
37
m_manufacturer_id = 0x32;
38
m_size = 64*1024;
39
}
40
41
*(uint32_t*)(m_data+MAX_SIZE) = m_size;
42
}
43
44
void Flash::Reset ()
45
{
46
std::memset(m_data, 0, m_size);
47
}
48
49
bool Flash::Load (std::istream& f)
50
{
51
f.read((char*)m_data, m_size);
52
return f.good();
53
}
54
55
bool Flash::Save (std::ostream& f)
56
{
57
f.write((char*)m_data, m_size);
58
return f.good();
59
}
60
61
uint8_t Flash::Read (uint16_t add)
62
{
63
switch (m_state)
64
{
65
case NORMAL:
66
return m_data[add];
67
case ID:
68
switch (add)
69
{
70
case 0: return m_manufacturer_id;
71
case 1: return m_device_id;
72
default: return 0;
73
}
74
// FIXME vba returns 0xff after an erase regardless of the read address
75
default:
76
return 0;
77
}
78
}
79
80
bool Flash::Write (uint16_t add, uint8_t val)
81
{
82
switch (m_state)
83
{
84
case ID:
85
case NORMAL:
86
if (add == 0x5555 && val == 0xAA)
87
m_state = CMD1;
88
else
89
m_state = NORMAL; // for case ID
90
break;
91
case CMD1:
92
if (add == 0x2AAA && val == 0x55)
93
m_state = CMD2;
94
else
95
m_state = NORMAL;
96
break;
97
case CMD2:
98
if (add == 0x5555)
99
switch (val)
100
{
101
case 0x80: // erase mode
102
m_state = ERASE1;
103
break;
104
case 0x90: // id mode
105
m_state = ID;
106
break;
107
case 0xA0: // write byte
108
m_state = WRITE;
109
break;
110
case 0xF0:
111
m_state = NORMAL;
112
break;
113
default:
114
m_state = NORMAL;
115
break;
116
}
117
else
118
m_state = NORMAL;
119
break;
120
case ERASE1:
121
if (add == 0x5555 && val == 0xAA)
122
m_state = ERASE2;
123
else
124
m_state = NORMAL;
125
break;
126
case ERASE2:
127
if (add == 0x2AAA && val == 0x55)
128
m_state = ERASE3;
129
else
130
m_state = NORMAL;
131
break;
132
case ERASE3:
133
// according to vba, after a whole erase command we can juste repeat the
134
// last byte of the command to execute another erase command
135
switch (val)
136
{
137
case 0x10: // erase entire chip
138
if (add == 0x5555)
139
memset(m_data, 0xFF, m_size);
140
m_state = NORMAL;
141
break;
142
case 0x30: // erase sector
143
if (!(add & 0x0FFF))
144
memset(m_data+add, 0xFF, 0x1000);
145
m_state = NORMAL;
146
break;
147
default:
148
m_state = NORMAL;
149
break;
150
}
151
break;
152
case WRITE:
153
// I think this is how it works
154
m_data[add] &= val;
155
m_state = NORMAL;
156
return true;
157
}
158
return false;
159
}
160
161
bool Flash::SaveState (std::ostream& stream)
162
{
163
SS_WRITE_VAR(m_state);
164
165
SS_WRITE_DATA(m_data, m_size);
166
167
return true;
168
}
169
170
bool Flash::LoadState (std::istream& stream)
171
{
172
SS_READ_VAR(m_state);
173
174
SS_READ_DATA(m_data, m_size);
175
176
return true;
177
}
178
}
179
180