1 #include "rockmacros.h"
14 #ifdef ROCKBOX_LITTLE_ENDIAN
17 #define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24))
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 }
39 static int sramblock
, iramblock
, vramblock
;
40 static int hramofs
, hiofs
, palofs
, oamofs
, wavofs
;
63 I4("spd ", &cpu
.speed
),
64 I4("halt", &cpu
.halt
),
67 I4("lcdc", &cpu
.lcdc
),
70 I1("ints", &hw
.ilines
),
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
),
81 I4("rtcL", &rtc
.latch
),
82 I4("rtcC", &rtc
.carry
),
83 I4("rtcS", &rtc
.stop
),
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
),
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... */
129 /* the following are obsolete as of 0x104 */
131 I4("hram", &hramofs
),
132 /* I4("gba ", &hw.gba), */
133 /* I4("S1sf", &snd.ch[0].swfreq), */
137 R(DIV
), R(TIMA
), R(TMA
), R(TAC
),
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
),
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
)
167 un32 (*header
)[2] = (un32 (*)[2])buf
;
169 int irl
= hw
.cgb
? 8 : 2;
170 int vrl
= hw
.cgb
? 4 : 2;
171 int srl
= mbc
.ramsize
<< 1;
174 ver
= hramofs
= hiofs
= palofs
= oamofs
= wavofs
= 0;
176 base_offset
= lseek(fd
, 0, SEEK_CUR
);
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
)
186 d
= LIL(header
[j
][1]);
187 switch (svars
[i
].len
)
190 *(byte
*)svars
[i
].ptr
= d
;
193 *(un16
*)svars
[i
].ptr
= d
;
196 *(un32
*)svars
[i
].ptr
= d
;
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
);
225 void savestate(int fd
)
229 un32 (*header
)[2] = (un32 (*)[2])buf
;
231 int irl
= hw
.cgb
? 8 : 2;
232 int vrl
= hw
.cgb
? 4 : 2;
233 int srl
= mbc
.ramsize
<< 1;
239 sramblock
= 1+irl
+vrl
;
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
)
251 d
= *(byte
*)svars
[i
].ptr
;
254 d
= *(un16
*)svars
[i
].ptr
;
257 d
= *(un32
*)svars
[i
].ptr
;
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
);
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
);