17 #ifdef IS_LITTLE_ENDIAN
20 #define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24))
23 #define I1(s, p) { 1, s, p }
24 #define I2(s, p) { 2, s, p }
25 #define I4(s, p) { 4, s, p }
26 #define R(r) I1(#r, &R_##r)
27 #define NOSAVE { -1, "\0\0\0\0", 0 }
28 #define END { 0, "\0\0\0\0", 0 }
38 static int sramblock
, iramblock
, vramblock
;
39 static int hramofs
, hiofs
, palofs
, oamofs
, wavofs
;
54 I4("spd ", &cpu
.speed
),
55 I4("halt", &cpu
.halt
),
58 I4("lcdc", &cpu
.lcdc
),
61 I1("ints", &hw
.ilines
),
66 I4("mbcm", &mbc
.model
),
67 I4("romb", &mbc
.rombank
),
68 I4("ramb", &mbc
.rambank
),
69 I4("enab", &mbc
.enableram
),
70 I4("batt", &mbc
.batt
),
73 I4("rtcL", &rtc
.latch
),
74 I4("rtcC", &rtc
.carry
),
75 I4("rtcS", &rtc
.stop
),
81 I1("rtR8", &rtc
.regs
[0]),
82 I1("rtR9", &rtc
.regs
[1]),
83 I1("rtRA", &rtc
.regs
[2]),
84 I1("rtRB", &rtc
.regs
[3]),
85 I1("rtRC", &rtc
.regs
[4]),
87 I4("S1on", &snd
.ch
[0].on
),
88 I4("S1p ", &snd
.ch
[0].pos
),
89 I4("S1c ", &snd
.ch
[0].cnt
),
90 I4("S1ec", &snd
.ch
[0].encnt
),
91 I4("S1sc", &snd
.ch
[0].swcnt
),
92 I4("S1sf", &snd
.ch
[0].swfreq
),
94 I4("S2on", &snd
.ch
[1].on
),
95 I4("S2p ", &snd
.ch
[1].pos
),
96 I4("S2c ", &snd
.ch
[1].cnt
),
97 I4("S2ec", &snd
.ch
[1].encnt
),
99 I4("S3on", &snd
.ch
[2].on
),
100 I4("S3p ", &snd
.ch
[2].pos
),
101 I4("S3c ", &snd
.ch
[2].cnt
),
103 I4("S4on", &snd
.ch
[3].on
),
104 I4("S4p ", &snd
.ch
[3].pos
),
105 I4("S4c ", &snd
.ch
[3].cnt
),
106 I4("S4ec", &snd
.ch
[3].encnt
),
108 I4("hdma", &hw
.hdma
),
110 I4("sram", &sramblock
),
111 I4("iram", &iramblock
),
112 I4("vram", &vramblock
),
118 /* NOSAVE is a special code to prevent the rest of the table
119 * from being saved, used to support old stuff for backwards
120 * compatibility... */
123 /* the following are obsolete as of 0x104 */
125 I4("hram", &hramofs
),
128 R(DIV
), R(TIMA
), R(TMA
), R(TAC
),
130 R(LCDC
), R(STAT
), R(LY
), R(LYC
),
131 R(SCX
), R(SCY
), R(WX
), R(WY
),
132 R(BGP
), R(OBP0
), R(OBP1
),
135 R(VBK
), R(SVBK
), R(KEY1
),
136 R(BCPS
), R(BCPD
), R(OCPS
), R(OCPD
),
138 R(NR10
), R(NR11
), R(NR12
), R(NR13
), R(NR14
),
139 R(NR21
), R(NR22
), R(NR23
), R(NR24
),
140 R(NR30
), R(NR31
), R(NR32
), R(NR33
), R(NR34
),
141 R(NR41
), R(NR42
), R(NR43
), R(NR44
),
142 R(NR50
), R(NR51
), R(NR52
),
144 I1("DMA1", &R_HDMA1
),
145 I1("DMA2", &R_HDMA2
),
146 I1("DMA3", &R_HDMA3
),
147 I1("DMA4", &R_HDMA4
),
148 I1("DMA5", &R_HDMA5
),
154 void loadstate(FILE *f
)
158 un32 (*header
)[2] = (un32 (*)[2])buf
;
160 int irl
= hw
.cgb
? 8 : 2;
161 int vrl
= hw
.cgb
? 4 : 2;
162 int srl
= mbc
.ramsize
<< 1;
164 ver
= hramofs
= hiofs
= palofs
= oamofs
= wavofs
= 0;
166 fseek(f
, 0, SEEK_SET
);
167 fread(buf
, 4096, 1, f
);
169 for (j
= 0; header
[j
][0]; j
++)
171 for (i
= 0; svars
[i
].ptr
; i
++)
173 if (memcmp(&header
[j
][0], svars
[i
].key
, 4))
175 d
= LIL(header
[j
][1]);
176 switch (svars
[i
].len
)
179 *(byte
*)svars
[i
].ptr
= d
;
182 *(un16
*)svars
[i
].ptr
= d
;
185 *(un32
*)svars
[i
].ptr
= d
;
192 /* obsolete as of version 0x104 */
193 if (hramofs
) memcpy(ram
.hi
+128, buf
+hramofs
, 127);
195 if (hiofs
) memcpy(ram
.hi
, buf
+hiofs
, sizeof ram
.hi
);
196 if (palofs
) memcpy(lcd
.pal
, buf
+palofs
, sizeof lcd
.pal
);
197 if (oamofs
) memcpy(lcd
.oam
.mem
, buf
+oamofs
, sizeof lcd
.oam
);
199 if (wavofs
) memcpy(snd
.wave
, buf
+wavofs
, sizeof snd
.wave
);
200 else memcpy(snd
.wave
, ram
.hi
+0x30, 16); /* patch data from older files */
202 fseek(f
, iramblock
<<12, SEEK_SET
);
203 fread(ram
.ibank
, 4096, irl
, f
);
205 fseek(f
, vramblock
<<12, SEEK_SET
);
206 fread(lcd
.vbank
, 4096, vrl
, f
);
208 fseek(f
, sramblock
<<12, SEEK_SET
);
209 fread(ram
.sbank
, 4096, srl
, f
);
212 void savestate(FILE *f
)
216 un32 (*header
)[2] = (un32 (*)[2])buf
;
218 int irl
= hw
.cgb
? 8 : 2;
219 int vrl
= hw
.cgb
? 4 : 2;
220 int srl
= mbc
.ramsize
<< 1;
225 sramblock
= 1+irl
+vrl
;
230 memset(buf
, 0, sizeof buf
);
232 for (i
= 0; svars
[i
].len
> 0; i
++)
234 memcpy(&header
[i
][0], svars
[i
].key
, 4);
235 switch (svars
[i
].len
)
238 d
= *(byte
*)svars
[i
].ptr
;
241 d
= *(un16
*)svars
[i
].ptr
;
244 d
= *(un32
*)svars
[i
].ptr
;
247 header
[i
][1] = LIL(d
);
249 header
[i
][0] = header
[i
][1] = 0;
251 memcpy(buf
+hiofs
, ram
.hi
, sizeof ram
.hi
);
252 memcpy(buf
+palofs
, lcd
.pal
, sizeof lcd
.pal
);
253 memcpy(buf
+oamofs
, lcd
.oam
.mem
, sizeof lcd
.oam
);
254 memcpy(buf
+wavofs
, snd
.wave
, sizeof snd
.wave
);
256 fseek(f
, 0, SEEK_SET
);
257 fwrite(buf
, 4096, 1, f
);
259 fseek(f
, iramblock
<<12, SEEK_SET
);
260 fwrite(ram
.ibank
, 4096, irl
, f
);
262 fseek(f
, vramblock
<<12, SEEK_SET
);
263 fwrite(lcd
.vbank
, 4096, vrl
, f
);
265 fseek(f
, sramblock
<<12, SEEK_SET
);
266 fwrite(ram
.sbank
, 4096, srl
, f
);