Bump version numbers for 3.13
[maemo-rb.git] / apps / plugins / rockboy / save.c
blobd0dd3dd2b9577234f2f34be74d77c48e21fbb6ee
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"
12 #include "save.h"
14 #ifdef ROCKBOX_LITTLE_ENDIAN
15 #define LIL(x) (x)
16 #else
17 #define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24))
18 #endif
20 #define I1(s, p) { 1, { s }, p }
21 #define I2(s, p) { 2, { s }, p }
22 #define I4(s, p) { 4, { s }, p }
23 #define R(r) I1(#r, &R_##r)
24 #define NOSAVE { -1, { "\0\0\0\0" }, 0 }
25 #define END { 0, { "\0\0\0\0" }, 0 }
27 struct svar
29 int len;
30 union
32 char key_[4];
33 un32 key;
34 } k;
35 void *ptr;
38 static int ver;
39 static int sramblock, iramblock, vramblock;
40 static int hramofs, hiofs, palofs, oamofs, wavofs;
42 struct svar svars[] =
44 I4("GbSs", &ver),
46 I2("PC ", &PC),
47 I2("SP ", &SP),
48 I2("HL ", &HL),
49 #ifdef DYNAREC
50 I1("A ", &A),
51 I1("B ", &A),
52 I1("C ", &A),
53 I1("D ", &A),
54 I1("E ", &A),
55 I1("F ", &A),
56 #else
57 I2("BC ", &BC),
58 I2("DE ", &DE),
59 I2("AF ", &AF),
60 #endif
61 I4("IME ", &cpu.ime),
62 I4("ima ", &cpu.ima),
63 I4("spd ", &cpu.speed),
64 I4("halt", &cpu.halt),
65 I4("div ", &cpu.div),
66 I4("tim ", &cpu.tim),
67 I4("lcdc", &cpu.lcdc),
68 I4("snd ", &cpu.snd),
70 I1("ints", &hw.ilines),
71 I1("pad ", &hw.pad),
72 I4("cgb ", &hw.cgb),
74 I4("mbcm", &mbc.model),
75 I4("romb", &mbc.rombank),
76 I4("ramb", &mbc.rambank),
77 I4("enab", &mbc.enableram),
78 I4("batt", &mbc.batt),
80 I4("rtcR", &rtc.sel),
81 I4("rtcL", &rtc.latch),
82 I4("rtcC", &rtc.carry),
83 I4("rtcS", &rtc.stop),
84 I4("rtcd", &rtc.d),
85 I4("rtch", &rtc.h),
86 I4("rtcm", &rtc.m),
87 I4("rtcs", &rtc.s),
88 I4("rtct", &rtc.t),
89 I1("rtR8", &rtc.regs[0]),
90 I1("rtR9", &rtc.regs[1]),
91 I1("rtRA", &rtc.regs[2]),
92 I1("rtRB", &rtc.regs[3]),
93 I1("rtRC", &rtc.regs[4]),
95 I4("S1on", &snd.ch[0].on),
96 I4("S1p ", &snd.ch[0].pos),
97 I4("S1c ", &snd.ch[0].len),
98 I4("S1ec", &snd.ch[0].enlen),
99 I4("S1sc", &snd.ch[0].swlen),
101 I4("S2on", &snd.ch[1].on),
102 I4("S2p ", &snd.ch[1].pos),
103 I4("S2c ", &snd.ch[1].len),
104 I4("S2ec", &snd.ch[1].enlen),
106 I4("S3on", &snd.ch[2].on),
107 I4("S3p ", &snd.ch[2].pos),
108 I4("S3c ", &snd.ch[2].len),
110 I4("S4on", &snd.ch[3].on),
111 I4("S4p ", &snd.ch[3].pos),
112 I4("S4c ", &snd.ch[3].len),
113 I4("S4ec", &snd.ch[3].enlen),
115 I4("hdma", &hw.hdma),
117 I4("sram", &sramblock),
118 I4("iram", &iramblock),
119 I4("vram", &vramblock),
120 I4("hi ", &hiofs),
121 I4("pal ", &palofs),
122 I4("oam ", &oamofs),
124 /* NOSAVE is a special code to prevent the rest of the table
125 * from being saved, used to support old stuff for backwards
126 * compatibility... */
127 NOSAVE,
129 /* the following are obsolete as of 0x104 */
131 I4("hram", &hramofs),
132 /* I4("gba ", &hw.gba), */
133 /* I4("S1sf", &snd.ch[0].swfreq), */
134 I4("wav ", &wavofs),
136 R(P1), R(SB), R(SC),
137 R(DIV), R(TIMA), R(TMA), R(TAC),
138 R(IE), R(IF),
139 R(LCDC), R(STAT), R(LY), R(LYC),
140 R(SCX), R(SCY), R(WX), R(WY),
141 R(BGP), R(OBP0), R(OBP1),
142 R(DMA),
144 R(VBK), R(SVBK), R(KEY1),
145 R(BCPS), R(BCPD), R(OCPS), R(OCPD),
147 R(NR10), R(NR11), R(NR12), R(NR13), R(NR14),
148 R(NR21), R(NR22), R(NR23), R(NR24),
149 R(NR30), R(NR31), R(NR32), R(NR33), R(NR34),
150 R(NR41), R(NR42), R(NR43), R(NR44),
151 R(NR50), R(NR51), R(NR52),
153 I1("DMA1", &R_HDMA1),
154 I1("DMA2", &R_HDMA2),
155 I1("DMA3", &R_HDMA3),
156 I1("DMA4", &R_HDMA4),
157 I1("DMA5", &R_HDMA5),
163 void loadstate(int fd)
165 int i, j;
166 byte buf[4096];
167 un32 (*header)[2] = (un32 (*)[2])buf;
168 un32 d;
169 int irl = hw.cgb ? 8 : 2;
170 int vrl = hw.cgb ? 4 : 2;
171 int srl = mbc.ramsize << 1;
172 size_t base_offset;
174 ver = hramofs = hiofs = palofs = oamofs = wavofs = 0;
176 base_offset = lseek(fd, 0, SEEK_CUR);
178 read(fd,buf, 4096);
180 for (j = 0; header[j][0]; j++)
182 for (i = 0; svars[i].ptr; i++)
184 if (header[j][0] != svars[i].k.key)
185 continue;
186 d = LIL(header[j][1]);
187 switch (svars[i].len)
189 case 1:
190 *(byte *)svars[i].ptr = d;
191 break;
192 case 2:
193 *(un16 *)svars[i].ptr = d;
194 break;
195 case 4:
196 *(un32 *)svars[i].ptr = d;
197 break;
199 break;
203 /* obsolete as of version 0x104 */
204 if (hramofs) memcpy(ram.hi+128, buf+hramofs, 127);
205 if (wavofs) memcpy(ram.hi+48, buf+wavofs, 16);
207 if (hiofs) memcpy(ram.hi, buf+hiofs, sizeof ram.hi);
208 if (palofs) memcpy(lcd.pal, buf+palofs, sizeof lcd.pal);
209 if (oamofs) memcpy(lcd.oam.mem, buf+oamofs, sizeof lcd.oam);
211 lseek(fd, base_offset + (iramblock << 12), SEEK_SET);
212 read(fd,ram.ibank, 4096*irl);
214 lseek(fd, base_offset + (vramblock << 12), SEEK_SET);
215 read(fd,lcd.vbank, 4096*vrl);
217 lseek(fd, base_offset + (sramblock << 12), SEEK_SET);
218 read(fd,ram.sbank, 4096*srl);
219 vram_dirty();
220 pal_dirty();
221 sound_dirty();
222 mem_updatemap();
225 void savestate(int fd)
227 int i;
228 byte buf[4096];
229 un32 (*header)[2] = (un32 (*)[2])buf;
230 un32 d = 0;
231 int irl = hw.cgb ? 8 : 2;
232 int vrl = hw.cgb ? 4 : 2;
233 int srl = mbc.ramsize << 1;
234 size_t base_offset;
236 ver = 0x104;
237 iramblock = 1;
238 vramblock = 1+irl;
239 sramblock = 1+irl+vrl;
240 hiofs = 4096 - 768;
241 palofs = 4096 - 512;
242 oamofs = 4096 - 256;
243 memset(buf, 0, sizeof buf);
245 for (i = 0; svars[i].len > 0; i++)
247 header[i][0] = svars[i].k.key;
248 switch (svars[i].len)
250 case 1:
251 d = *(byte *)svars[i].ptr;
252 break;
253 case 2:
254 d = *(un16 *)svars[i].ptr;
255 break;
256 case 4:
257 d = *(un32 *)svars[i].ptr;
258 break;
260 header[i][1] = LIL(d);
262 header[i][0] = header[i][1] = 0;
264 memcpy(buf+hiofs, ram.hi, sizeof ram.hi);
265 memcpy(buf+palofs, lcd.pal, sizeof lcd.pal);
266 memcpy(buf+oamofs, lcd.oam.mem, sizeof lcd.oam);
268 /* calculate base offset for output file */
269 /* (we'll seek relative to that from now on) */
270 base_offset = lseek(fd, 0, SEEK_CUR);
271 write(fd,buf, 4096);
273 lseek(fd, base_offset + (iramblock << 12), SEEK_SET);
274 write(fd,ram.ibank, 4096*irl);
276 lseek(fd, base_offset + (vramblock << 12), SEEK_SET);
277 write(fd,lcd.vbank, 4096*vrl);
279 lseek(fd, base_offset + (sramblock << 12), SEEK_SET);
280 write(fd,ram.sbank, 4096*srl);