fix FS#8187 - charging breaks sleep timer. Now if the timer goes off and the player...
[Rockbox.git] / apps / plugins / rockboy / save.c
blob4211ceb77fcad18dd09037a1fe70f4c6ba3d314e
1 #include "rockmacros.h"
3 #include "defs.h"
4 #include "cpu-gb.h"
5 #include "cpuregs.h"
6 #include "hw.h"
7 #include "regs.h"
8 #include "lcd-gb.h"
9 #include "rtc-gb.h"
10 #include "mem.h"
11 #include "sound.h"
13 #ifdef ROCKBOX_LITTLE_ENDIAN
14 #define LIL(x) (x)
15 #else
16 #define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24))
17 #endif
19 #define I1(s, p) { 1, s, p }
20 #define I2(s, p) { 2, s, p }
21 #define I4(s, p) { 4, s, p }
22 #define R(r) I1(#r, &R_##r)
23 #define NOSAVE { -1, "\0\0\0\0", 0 }
24 #define END { 0, "\0\0\0\0", 0 }
26 struct svar
28 int len;
29 char key[4];
30 void *ptr;
33 static int ver;
34 static int sramblock, iramblock, vramblock;
35 static int hramofs, hiofs, palofs, oamofs, wavofs;
37 struct svar svars[] =
39 I4("GbSs", &ver),
41 I2("PC ", &PC),
42 I2("SP ", &SP),
43 I2("HL ", &HL),
44 #ifdef DYNAREC
45 I1("A ", &A),
46 I1("B ", &A),
47 I1("C ", &A),
48 I1("D ", &A),
49 I1("E ", &A),
50 I1("F ", &A),
51 #else
52 I2("BC ", &BC),
53 I2("DE ", &DE),
54 I2("AF ", &AF),
55 #endif
56 I4("IME ", &cpu.ime),
57 I4("ima ", &cpu.ima),
58 I4("spd ", &cpu.speed),
59 I4("halt", &cpu.halt),
60 I4("div ", &cpu.div),
61 I4("tim ", &cpu.tim),
62 I4("lcdc", &cpu.lcdc),
63 I4("snd ", &cpu.snd),
65 I1("ints", &hw.ilines),
66 I1("pad ", &hw.pad),
67 I4("cgb ", &hw.cgb),
69 I4("mbcm", &mbc.model),
70 I4("romb", &mbc.rombank),
71 I4("ramb", &mbc.rambank),
72 I4("enab", &mbc.enableram),
73 I4("batt", &mbc.batt),
75 I4("rtcR", &rtc.sel),
76 I4("rtcL", &rtc.latch),
77 I4("rtcC", &rtc.carry),
78 I4("rtcS", &rtc.stop),
79 I4("rtcd", &rtc.d),
80 I4("rtch", &rtc.h),
81 I4("rtcm", &rtc.m),
82 I4("rtcs", &rtc.s),
83 I4("rtct", &rtc.t),
84 I1("rtR8", &rtc.regs[0]),
85 I1("rtR9", &rtc.regs[1]),
86 I1("rtRA", &rtc.regs[2]),
87 I1("rtRB", &rtc.regs[3]),
88 I1("rtRC", &rtc.regs[4]),
90 I4("S1on", &snd.ch[0].on),
91 I4("S1p ", &snd.ch[0].pos),
92 I4("S1c ", &snd.ch[0].len),
93 I4("S1ec", &snd.ch[0].enlen),
94 I4("S1sc", &snd.ch[0].swlen),
96 I4("S2on", &snd.ch[1].on),
97 I4("S2p ", &snd.ch[1].pos),
98 I4("S2c ", &snd.ch[1].len),
99 I4("S2ec", &snd.ch[1].enlen),
101 I4("S3on", &snd.ch[2].on),
102 I4("S3p ", &snd.ch[2].pos),
103 I4("S3c ", &snd.ch[2].len),
105 I4("S4on", &snd.ch[3].on),
106 I4("S4p ", &snd.ch[3].pos),
107 I4("S4c ", &snd.ch[3].len),
108 I4("S4ec", &snd.ch[3].enlen),
110 I4("hdma", &hw.hdma),
112 I4("sram", &sramblock),
113 I4("iram", &iramblock),
114 I4("vram", &vramblock),
115 I4("hi ", &hiofs),
116 I4("pal ", &palofs),
117 I4("oam ", &oamofs),
119 /* NOSAVE is a special code to prevent the rest of the table
120 * from being saved, used to support old stuff for backwards
121 * compatibility... */
122 NOSAVE,
124 /* the following are obsolete as of 0x104 */
126 I4("hram", &hramofs),
127 /* I4("gba ", &hw.gba), */
128 /* I4("S1sf", &snd.ch[0].swfreq), */
129 I4("wav ", &wavofs),
131 R(P1), R(SB), R(SC),
132 R(DIV), R(TIMA), R(TMA), R(TAC),
133 R(IE), R(IF),
134 R(LCDC), R(STAT), R(LY), R(LYC),
135 R(SCX), R(SCY), R(WX), R(WY),
136 R(BGP), R(OBP0), R(OBP1),
137 R(DMA),
139 R(VBK), R(SVBK), R(KEY1),
140 R(BCPS), R(BCPD), R(OCPS), R(OCPD),
142 R(NR10), R(NR11), R(NR12), R(NR13), R(NR14),
143 R(NR21), R(NR22), R(NR23), R(NR24),
144 R(NR30), R(NR31), R(NR32), R(NR33), R(NR34),
145 R(NR41), R(NR42), R(NR43), R(NR44),
146 R(NR50), R(NR51), R(NR52),
148 I1("DMA1", &R_HDMA1),
149 I1("DMA2", &R_HDMA2),
150 I1("DMA3", &R_HDMA3),
151 I1("DMA4", &R_HDMA4),
152 I1("DMA5", &R_HDMA5),
158 void loadstate(int fd)
160 int i, j;
161 byte buf[4096];
162 un32 (*header)[2] = (un32 (*)[2])buf;
163 un32 d;
164 int irl = hw.cgb ? 8 : 2;
165 int vrl = hw.cgb ? 4 : 2;
166 int srl = mbc.ramsize << 1;
167 size_t base_offset;
169 ver = hramofs = hiofs = palofs = oamofs = wavofs = 0;
171 base_offset = lseek(fd, 0, SEEK_CUR);
173 read(fd,buf, 4096);
175 for (j = 0; header[j][0]; j++)
177 for (i = 0; svars[i].ptr; i++)
179 if (header[j][0] != *(un32 *)svars[i].key)
180 continue;
181 d = LIL(header[j][1]);
182 switch (svars[i].len)
184 case 1:
185 *(byte *)svars[i].ptr = d;
186 break;
187 case 2:
188 *(un16 *)svars[i].ptr = d;
189 break;
190 case 4:
191 *(un32 *)svars[i].ptr = d;
192 break;
194 break;
198 /* obsolete as of version 0x104 */
199 if (hramofs) memcpy(ram.hi+128, buf+hramofs, 127);
200 if (wavofs) memcpy(ram.hi+48, buf+wavofs, 16);
202 if (hiofs) memcpy(ram.hi, buf+hiofs, sizeof ram.hi);
203 if (palofs) memcpy(lcd.pal, buf+palofs, sizeof lcd.pal);
204 if (oamofs) memcpy(lcd.oam.mem, buf+oamofs, sizeof lcd.oam);
206 lseek(fd, base_offset + (iramblock << 12), SEEK_SET);
207 read(fd,ram.ibank, 4096*irl);
209 lseek(fd, base_offset + (vramblock << 12), SEEK_SET);
210 read(fd,lcd.vbank, 4096*vrl);
212 lseek(fd, base_offset + (sramblock << 12), SEEK_SET);
213 read(fd,ram.sbank, 4096*srl);
214 vram_dirty();
215 pal_dirty();
216 sound_dirty();
217 mem_updatemap();
220 void savestate(int fd)
222 int i;
223 byte buf[4096];
224 un32 (*header)[2] = (un32 (*)[2])buf;
225 un32 d = 0;
226 int irl = hw.cgb ? 8 : 2;
227 int vrl = hw.cgb ? 4 : 2;
228 int srl = mbc.ramsize << 1;
229 size_t base_offset;
231 ver = 0x104;
232 iramblock = 1;
233 vramblock = 1+irl;
234 sramblock = 1+irl+vrl;
235 hiofs = 4096 - 768;
236 palofs = 4096 - 512;
237 oamofs = 4096 - 256;
238 memset(buf, 0, sizeof buf);
240 for (i = 0; svars[i].len > 0; i++)
242 header[i][0] = *(un32 *)svars[i].key;
243 switch (svars[i].len)
245 case 1:
246 d = *(byte *)svars[i].ptr;
247 break;
248 case 2:
249 d = *(un16 *)svars[i].ptr;
250 break;
251 case 4:
252 d = *(un32 *)svars[i].ptr;
253 break;
255 header[i][1] = LIL(d);
257 header[i][0] = header[i][1] = 0;
259 memcpy(buf+hiofs, ram.hi, sizeof ram.hi);
260 memcpy(buf+palofs, lcd.pal, sizeof lcd.pal);
261 memcpy(buf+oamofs, lcd.oam.mem, sizeof lcd.oam);
263 /* calculate base offset for output file */
264 /* (we'll seek relative to that from now on) */
265 base_offset = lseek(fd, 0, SEEK_CUR);
266 write(fd,buf, 4096);
268 lseek(fd, base_offset + (iramblock << 12), SEEK_SET);
269 write(fd,ram.ibank, 4096*irl);
271 lseek(fd, base_offset + (vramblock << 12), SEEK_SET);
272 write(fd,lcd.vbank, 4096*vrl);
274 lseek(fd, base_offset + (sramblock << 12), SEEK_SET);
275 write(fd,ram.sbank, 4096*srl);