1 #include "rockmacros.h"
13 #ifdef ROCKBOX_LITTLE_ENDIAN
16 #define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24))
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 }
38 static int sramblock
, iramblock
, vramblock
;
39 static int hramofs
, hiofs
, palofs
, oamofs
, wavofs
;
62 I4("spd ", &cpu
.speed
),
63 I4("halt", &cpu
.halt
),
66 I4("lcdc", &cpu
.lcdc
),
69 I1("ints", &hw
.ilines
),
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
),
80 I4("rtcL", &rtc
.latch
),
81 I4("rtcC", &rtc
.carry
),
82 I4("rtcS", &rtc
.stop
),
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
),
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... */
128 /* the following are obsolete as of 0x104 */
130 I4("hram", &hramofs
),
131 /* I4("gba ", &hw.gba), */
132 /* I4("S1sf", &snd.ch[0].swfreq), */
136 R(DIV
), R(TIMA
), R(TMA
), R(TAC
),
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
),
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
)
166 un32 (*header
)[2] = (un32 (*)[2])buf
;
168 int irl
= hw
.cgb
? 8 : 2;
169 int vrl
= hw
.cgb
? 4 : 2;
170 int srl
= mbc
.ramsize
<< 1;
173 ver
= hramofs
= hiofs
= palofs
= oamofs
= wavofs
= 0;
175 base_offset
= lseek(fd
, 0, SEEK_CUR
);
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
)
185 d
= LIL(header
[j
][1]);
186 switch (svars
[i
].len
)
189 *(byte
*)svars
[i
].ptr
= d
;
192 *(un16
*)svars
[i
].ptr
= d
;
195 *(un32
*)svars
[i
].ptr
= d
;
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
);
224 void savestate(int fd
)
228 un32 (*header
)[2] = (un32 (*)[2])buf
;
230 int irl
= hw
.cgb
? 8 : 2;
231 int vrl
= hw
.cgb
? 4 : 2;
232 int srl
= mbc
.ramsize
<< 1;
238 sramblock
= 1+irl
+vrl
;
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
)
250 d
= *(byte
*)svars
[i
].ptr
;
253 d
= *(un16
*)svars
[i
].ptr
;
256 d
= *(un32
*)svars
[i
].ptr
;
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
);
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
);