Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/ameteor.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.hpp"
18
#include "debug.hpp"
19
#include "globals.hpp"
20
#include <cstring>
21
#include <sstream>
22
23
// TODO add version
24
#define SS_MAGIC_STRING ("AMeteor SaveState")
25
#define SS_MS_SIZE (sizeof(SS_MAGIC_STRING)-1)
26
27
namespace AMeteor
28
{
29
namespace
30
{
31
class AMeteor
32
{
33
public :
34
AMeteor ()
35
{
36
Audio::InitNoise();
37
}
38
} __ameteor;
39
}
40
41
// the clock must be initialized first since there are devices like
42
// lcd which needs to set the timer
43
Clock _clock;
44
Io _io;
45
// the interpreter (which is in the cpu) takes io addresses, thus the
46
// cpu must be initialized after io
47
Interpreter _cpu;
48
Memory _memory;
49
Dma _dma;
50
// the lcd must be initialized after the memory since it takes
51
// pointers from it
52
Lcd _lcd;
53
// the sound must be initialized after the io since it takes references
54
// from it
55
Sound _sound;
56
// the keypad needs to take the vblank event from lcd, so it must be
57
// initialized after lcd
58
// it must also be initialized after io since it takes the keyinput
59
// reference
60
Keypad _keypad;
61
Timer _timer3(3, NULL);
62
Timer _timer2(2, &_timer3);
63
Timer _timer1(1, &_timer2);
64
Timer _timer0(0, &_timer1);
65
66
void Reset (uint32_t units)
67
{
68
#define RESET(u, e) \
69
if (units & UNIT_##e) \
70
_##u.Reset();
71
RESET(clock, CLOCK);
72
RESET(io, IO);
73
RESET(cpu, CPU);
74
RESET(dma, DMA);
75
RESET(lcd, LCD);
76
RESET(sound, SOUND);
77
RESET(keypad, KEYPAD);
78
RESET(timer0, TIMER0);
79
RESET(timer1, TIMER1);
80
RESET(timer2, TIMER2);
81
RESET(timer3, TIMER3);
82
#undef RESET
83
if (units & UNIT_MEMORY)
84
_memory.Reset(units);
85
}
86
87
bool SaveState (const char* filename)
88
{
89
if (_cpu.IsRunning())
90
return false;
91
92
std::ostringstream ss;
93
94
if (!SaveState(ss))
95
return false;
96
97
std::ofstream file(filename);
98
99
if (!file)
100
return false;
101
102
std::string buf = ss.str();
103
if (!file.write(buf.c_str(), buf.length()))
104
return false;
105
106
file.close();
107
if (file.bad())
108
return false;
109
110
return true;
111
}
112
113
bool LoadState (const char* filename)
114
{
115
if (_cpu.IsRunning())
116
return false;
117
118
std::istringstream ss;
119
{
120
std::ifstream file(filename);
121
if (!file)
122
return false;
123
124
// 1Mo
125
std::vector<uint8_t> buf(0x100000);
126
if (file.read((char*)&buf[0], 0x100000).bad())
127
return false;
128
int nread = file.gcount();
129
130
file.close();
131
if (file.bad())
132
return false;
133
134
ss.str(std::string((char*)&buf[0], nread));
135
}
136
137
return LoadState(ss);
138
}
139
140
bool SaveState (std::ostream& stream)
141
{
142
if (_cpu.IsRunning())
143
return false;
144
145
SS_WRITE_DATA(SS_MAGIC_STRING, SS_MS_SIZE);
146
147
#define SAVE(dev) \
148
if (!dev.SaveState(stream)) \
149
return false
150
SAVE(_clock);
151
SAVE(_io);
152
SAVE(_cpu);
153
SAVE(_memory);
154
SAVE(_dma);
155
SAVE(_lcd);
156
SAVE(_sound);
157
//SAVE(_keypad);
158
SAVE(_timer0);
159
SAVE(_timer1);
160
SAVE(_timer2);
161
SAVE(_timer3);
162
#undef SAVE
163
164
return true;
165
}
166
167
bool LoadState (std::istream& stream)
168
{
169
if (_cpu.IsRunning())
170
return false;
171
172
{
173
char buf[SS_MS_SIZE];
174
SS_READ_DATA(buf, SS_MS_SIZE);
175
if (std::memcmp(buf, SS_MAGIC_STRING, SS_MS_SIZE))
176
return false;
177
}
178
179
180
#define LOAD(dev) \
181
if (!dev.LoadState(stream)) \
182
return false
183
LOAD(_clock);
184
LOAD(_io);
185
LOAD(_cpu);
186
LOAD(_memory);
187
LOAD(_dma);
188
LOAD(_lcd);
189
LOAD(_sound);
190
//LOAD(_keypad);
191
LOAD(_timer0);
192
LOAD(_timer1);
193
LOAD(_timer2);
194
LOAD(_timer3);
195
#undef LOAD
196
197
uint8_t xxx;
198
// if there is garbage at end of file
199
if (stream.read((char*)&xxx, 1))
200
return false;
201
202
return true;
203
}
204
}
205
206