Renamed button description layer to 'Text'.
[kugel-rb.git] / apps / plugins / rockboy / save.c
blob817973bcb23535ad96a0abc4e869d820594197d1
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 union
31 char key_[4];
32 un32 key;
33 } k;
34 void *ptr;
37 static int ver;
38 static int sramblock, iramblock, vramblock;
39 static int hramofs, hiofs, palofs, oamofs, wavofs;
41 struct svar svars[] =
43 I4("GbSs", &ver),
45 I2("PC ", &PC),
46 I2("SP ", &SP),
47 I2("HL ", &HL),
48 #ifdef DYNAREC
49 I1("A ", &A),
50 I1("B ", &A),
51 I1("C ", &A),
52 I1("D ", &A),
53 I1("E ", &A),
54 I1("F ", &A),
55 #else
56 I2("BC ", &BC),
57 I2("DE ", &DE),
58 I2("AF ", &AF),
59 #endif
60 I4("IME ", &cpu.ime),
61 I4("ima ", &cpu.ima),
62 I4("spd ", &cpu.speed),
63 I4("halt", &cpu.halt),
64 I4("div ", &cpu.div),
65 I4("tim ", &cpu.tim),
66 I4("lcdc", &cpu.lcdc),
67 I4("snd ", &cpu.snd),
69 I1("ints", &hw.ilines),
70 I1("pad ", &hw.pad),
71 I4("cgb ", &hw.cgb),
73 I4("mbcm", &mbc.model),
74 I4("romb", &mbc.rombank),
75 I4("ramb", &mbc.rambank),
76 I4("enab", &mbc.enableram),
77 I4("batt", &mbc.batt),
79 I4("rtcR", &rtc.sel),
80 I4("rtcL", &rtc.latch),
81 I4("rtcC", &rtc.carry),
82 I4("rtcS", &rtc.stop),
83 I4("rtcd", &rtc.d),
84 I4("rtch", &rtc.h),
85 I4("rtcm", &rtc.m),
86 I4("rtcs", &rtc.s),
87 I4("rtct", &rtc.t),
88 I1("rtR8", &rtc.regs[0]),
89 I1("rtR9", &rtc.regs[1]),
90 I1("rtRA", &rtc.regs[2]),
91 I1("rtRB", &rtc.regs[3]),
92 I1("rtRC", &rtc.regs[4]),
94 I4("S1on", &snd.ch[0].on),
95 I4("S1p ", &snd.ch[0].pos),
96 I4("S1c ", &snd.ch[0].len),
97 I4("S1ec", &snd.ch[0].enlen),
98 I4("S1sc", &snd.ch[0].swlen),
100 I4("S2on", &snd.ch[1].on),
101 I4("S2p ", &snd.ch[1].pos),
102 I4("S2c ", &snd.ch[1].len),
103 I4("S2ec", &snd.ch[1].enlen),
105 I4("S3on", &snd.ch[2].on),
106 I4("S3p ", &snd.ch[2].pos),
107 I4("S3c ", &snd.ch[2].len),
109 I4("S4on", &snd.ch[3].on),
110 I4("S4p ", &snd.ch[3].pos),
111 I4("S4c ", &snd.ch[3].len),
112 I4("S4ec", &snd.ch[3].enlen),
114 I4("hdma", &hw.hdma),
116 I4("sram", &sramblock),
117 I4("iram", &iramblock),
118 I4("vram", &vramblock),
119 I4("hi ", &hiofs),
120 I4("pal ", &palofs),
121 I4("oam ", &oamofs),
123 /* NOSAVE is a special code to prevent the rest of the table
124 * from being saved, used to support old stuff for backwards
125 * compatibility... */
126 NOSAVE,
128 /* the following are obsolete as of 0x104 */
130 I4("hram", &hramofs),
131 /* I4("gba ", &hw.gba), */
132 /* I4("S1sf", &snd.ch[0].swfreq), */
133 I4("wav ", &wavofs),
135 R(P1), R(SB), R(SC),
136 R(DIV), R(TIMA), R(TMA), R(TAC),
137 R(IE), R(IF),
138 R(LCDC), R(STAT), R(LY), R(LYC),
139 R(SCX), R(SCY), R(WX), R(WY),
140 R(BGP), R(OBP0), R(OBP1),
141 R(DMA),
143 R(VBK), R(SVBK), R(KEY1),
144 R(BCPS), R(BCPD), R(OCPS), R(OCPD),
146 R(NR10), R(NR11), R(NR12), R(NR13), R(NR14),
147 R(NR21), R(NR22), R(NR23), R(NR24),
148 R(NR30), R(NR31), R(NR32), R(NR33), R(NR34),
149 R(NR41), R(NR42), R(NR43), R(NR44),
150 R(NR50), R(NR51), R(NR52),
152 I1("DMA1", &R_HDMA1),
153 I1("DMA2", &R_HDMA2),
154 I1("DMA3", &R_HDMA3),
155 I1("DMA4", &R_HDMA4),
156 I1("DMA5", &R_HDMA5),
162 void loadstate(int fd)
164 int i, j;
165 byte buf[4096];
166 un32 (*header)[2] = (un32 (*)[2])buf;
167 un32 d;
168 int irl = hw.cgb ? 8 : 2;
169 int vrl = hw.cgb ? 4 : 2;
170 int srl = mbc.ramsize << 1;
171 size_t base_offset;
173 ver = hramofs = hiofs = palofs = oamofs = wavofs = 0;
175 base_offset = lseek(fd, 0, SEEK_CUR);
177 read(fd,buf, 4096);
179 for (j = 0; header[j][0]; j++)
181 for (i = 0; svars[i].ptr; i++)
183 if (header[j][0] != svars[i].k.key)
184 continue;
185 d = LIL(header[j][1]);
186 switch (svars[i].len)
188 case 1:
189 *(byte *)svars[i].ptr = d;
190 break;
191 case 2:
192 *(un16 *)svars[i].ptr = d;
193 break;
194 case 4:
195 *(un32 *)svars[i].ptr = d;
196 break;
198 break;
202 /* obsolete as of version 0x104 */
203 if (hramofs) memcpy(ram.hi+128, buf+hramofs, 127);
204 if (wavofs) memcpy(ram.hi+48, buf+wavofs, 16);
206 if (hiofs) memcpy(ram.hi, buf+hiofs, sizeof ram.hi);
207 if (palofs) memcpy(lcd.pal, buf+palofs, sizeof lcd.pal);
208 if (oamofs) memcpy(lcd.oam.mem, buf+oamofs, sizeof lcd.oam);
210 lseek(fd, base_offset + (iramblock << 12), SEEK_SET);
211 read(fd,ram.ibank, 4096*irl);
213 lseek(fd, base_offset + (vramblock << 12), SEEK_SET);
214 read(fd,lcd.vbank, 4096*vrl);
216 lseek(fd, base_offset + (sramblock << 12), SEEK_SET);
217 read(fd,ram.sbank, 4096*srl);
218 vram_dirty();
219 pal_dirty();
220 sound_dirty();
221 mem_updatemap();
224 void savestate(int fd)
226 int i;
227 byte buf[4096];
228 un32 (*header)[2] = (un32 (*)[2])buf;
229 un32 d = 0;
230 int irl = hw.cgb ? 8 : 2;
231 int vrl = hw.cgb ? 4 : 2;
232 int srl = mbc.ramsize << 1;
233 size_t base_offset;
235 ver = 0x104;
236 iramblock = 1;
237 vramblock = 1+irl;
238 sramblock = 1+irl+vrl;
239 hiofs = 4096 - 768;
240 palofs = 4096 - 512;
241 oamofs = 4096 - 256;
242 memset(buf, 0, sizeof buf);
244 for (i = 0; svars[i].len > 0; i++)
246 header[i][0] = svars[i].k.key;
247 switch (svars[i].len)
249 case 1:
250 d = *(byte *)svars[i].ptr;
251 break;
252 case 2:
253 d = *(un16 *)svars[i].ptr;
254 break;
255 case 4:
256 d = *(un32 *)svars[i].ptr;
257 break;
259 header[i][1] = LIL(d);
261 header[i][0] = header[i][1] = 0;
263 memcpy(buf+hiofs, ram.hi, sizeof ram.hi);
264 memcpy(buf+palofs, lcd.pal, sizeof lcd.pal);
265 memcpy(buf+oamofs, lcd.oam.mem, sizeof lcd.oam);
267 /* calculate base offset for output file */
268 /* (we'll seek relative to that from now on) */
269 base_offset = lseek(fd, 0, SEEK_CUR);
270 write(fd,buf, 4096);
272 lseek(fd, base_offset + (iramblock << 12), SEEK_SET);
273 write(fd,ram.ibank, 4096*irl);
275 lseek(fd, base_offset + (vramblock << 12), SEEK_SET);
276 write(fd,lcd.vbank, 4096*vrl);
278 lseek(fd, base_offset + (sramblock << 12), SEEK_SET);
279 write(fd,ram.sbank, 4096*srl);