16 #define I1(s, p) { 1, s, p }
17 #define I2(s, p) { 2, s, p }
18 #define I4(s, p) { 4, s, p }
19 #define R(r) I1(#r, &R_##r)
20 #define NOSAVE { -1, "\0\0\0\0", 0 }
21 #define END { 0, "\0\0\0\0", 0 }
31 static int sramblock
, iramblock
, vramblock
;
32 static int hramofs
, hiofs
, palofs
, oamofs
, wavofs
;
47 I4("spd ", &cpu
.speed
),
48 I4("halt", &cpu
.halt
),
51 I4("lcdc", &cpu
.lcdc
),
54 I1("ints", &hw
.ilines
),
59 I4("mbcm", &mbc
.model
),
60 I4("romb", &mbc
.rombank
),
61 I4("ramb", &mbc
.rambank
),
62 I4("enab", &mbc
.enableram
),
63 I4("batt", &mbc
.batt
),
66 I4("rtcL", &rtc
.latch
),
67 I4("rtcC", &rtc
.carry
),
68 I4("rtcS", &rtc
.stop
),
74 I1("rtR8", &rtc
.regs
[0]),
75 I1("rtR9", &rtc
.regs
[1]),
76 I1("rtRA", &rtc
.regs
[2]),
77 I1("rtRB", &rtc
.regs
[3]),
78 I1("rtRC", &rtc
.regs
[4]),
80 I4("S1on", &snd
.ch
[0].on
),
81 I4("S1p ", &snd
.ch
[0].pos
),
82 I4("S1c ", &snd
.ch
[0].cnt
),
83 I4("S1ec", &snd
.ch
[0].encnt
),
84 I4("S1sc", &snd
.ch
[0].swcnt
),
85 I4("S1sf", &snd
.ch
[0].swfreq
),
87 I4("S2on", &snd
.ch
[1].on
),
88 I4("S2p ", &snd
.ch
[1].pos
),
89 I4("S2c ", &snd
.ch
[1].cnt
),
90 I4("S2ec", &snd
.ch
[1].encnt
),
92 I4("S3on", &snd
.ch
[2].on
),
93 I4("S3p ", &snd
.ch
[2].pos
),
94 I4("S3c ", &snd
.ch
[2].cnt
),
96 I4("S4on", &snd
.ch
[3].on
),
97 I4("S4p ", &snd
.ch
[3].pos
),
98 I4("S4c ", &snd
.ch
[3].cnt
),
99 I4("S4ec", &snd
.ch
[3].encnt
),
101 I4("hdma", &hw
.hdma
),
103 I4("sram", &sramblock
),
104 I4("iram", &iramblock
),
105 I4("vram", &vramblock
),
111 /* NOSAVE is a special code to prevent the rest of the table
112 * from being saved, used to support old stuff for backwards
113 * compatibility... */
116 /* the following are obsolete as of 0x104 */
118 I4("hram", &hramofs
),
121 R(DIV
), R(TIMA
), R(TMA
), R(TAC
),
123 R(LCDC
), R(STAT
), R(LY
), R(LYC
),
124 R(SCX
), R(SCY
), R(WX
), R(WY
),
125 R(BGP
), R(OBP0
), R(OBP1
),
128 R(VBK
), R(SVBK
), R(KEY1
),
129 R(BCPS
), R(BCPD
), R(OCPS
), R(OCPD
),
131 R(NR10
), R(NR11
), R(NR12
), R(NR13
), R(NR14
),
132 R(NR21
), R(NR22
), R(NR23
), R(NR24
),
133 R(NR30
), R(NR31
), R(NR32
), R(NR33
), R(NR34
),
134 R(NR41
), R(NR42
), R(NR43
), R(NR44
),
135 R(NR50
), R(NR51
), R(NR52
),
137 I1("DMA1", &R_HDMA1
),
138 I1("DMA2", &R_HDMA2
),
139 I1("DMA3", &R_HDMA3
),
140 I1("DMA4", &R_HDMA4
),
141 I1("DMA5", &R_HDMA5
),
147 void loadstate(FILE *f
)
151 un32 (*header
)[2] = (un32 (*)[2])buf
;
153 int irl
= hw
.cgb
? 8 : 2;
154 int vrl
= hw
.cgb
? 4 : 2;
155 int srl
= mbc
.ramsize
<< 1;
157 ver
= hramofs
= hiofs
= palofs
= oamofs
= wavofs
= 0;
159 fseek(f
, 0, SEEK_SET
);
160 fread(buf
, 4096, 1, f
);
162 for (j
= 0; header
[j
][0]; j
++)
164 for (i
= 0; svars
[i
].ptr
; i
++)
166 if (memcmp(&header
[j
][0], svars
[i
].key
, 4))
168 d
= LIL(header
[j
][1]);
169 switch (svars
[i
].len
)
172 *(byte
*)svars
[i
].ptr
= d
;
175 *(un16
*)svars
[i
].ptr
= d
;
178 *(un32
*)svars
[i
].ptr
= d
;
185 /* obsolete as of version 0x104 */
186 if (hramofs
) memcpy(ram
.hi
+128, buf
+hramofs
, 127);
188 if (hiofs
) memcpy(ram
.hi
, buf
+hiofs
, sizeof ram
.hi
);
189 if (palofs
) memcpy(lcd
.pal
, buf
+palofs
, sizeof lcd
.pal
);
190 if (oamofs
) memcpy(lcd
.oam
.mem
, buf
+oamofs
, sizeof lcd
.oam
);
192 if (wavofs
) memcpy(snd
.wave
, buf
+wavofs
, sizeof snd
.wave
);
193 else memcpy(snd
.wave
, ram
.hi
+0x30, 16); /* patch data from older files */
195 fseek(f
, iramblock
<<12, SEEK_SET
);
196 fread(ram
.ibank
, 4096, irl
, f
);
198 fseek(f
, vramblock
<<12, SEEK_SET
);
199 fread(lcd
.vbank
, 4096, vrl
, f
);
201 fseek(f
, sramblock
<<12, SEEK_SET
);
202 fread(ram
.sbank
, 4096, srl
, f
);
205 void savestate(FILE *f
)
209 un32 (*header
)[2] = (un32 (*)[2])buf
;
211 int irl
= hw
.cgb
? 8 : 2;
212 int vrl
= hw
.cgb
? 4 : 2;
213 int srl
= mbc
.ramsize
<< 1;
218 sramblock
= 1+irl
+vrl
;
223 memset(buf
, 0, sizeof buf
);
225 for (i
= 0; svars
[i
].len
> 0; i
++)
227 memcpy(&header
[i
][0], svars
[i
].key
, 4);
228 switch (svars
[i
].len
)
231 d
= *(byte
*)svars
[i
].ptr
;
234 d
= *(un16
*)svars
[i
].ptr
;
237 d
= *(un32
*)svars
[i
].ptr
;
240 header
[i
][1] = LIL(d
);
242 header
[i
][0] = header
[i
][1] = 0;
244 memcpy(buf
+hiofs
, ram
.hi
, sizeof ram
.hi
);
245 memcpy(buf
+palofs
, lcd
.pal
, sizeof lcd
.pal
);
246 memcpy(buf
+oamofs
, lcd
.oam
.mem
, sizeof lcd
.oam
);
247 memcpy(buf
+wavofs
, snd
.wave
, sizeof snd
.wave
);
249 fseek(f
, 0, SEEK_SET
);
250 fwrite(buf
, 4096, 1, f
);
252 fseek(f
, iramblock
<<12, SEEK_SET
);
253 fwrite(ram
.ibank
, 4096, irl
, f
);
255 fseek(f
, vramblock
<<12, SEEK_SET
);
256 fwrite(lcd
.vbank
, 4096, vrl
, f
);
258 fseek(f
, sramblock
<<12, SEEK_SET
);
259 fwrite(ram
.sbank
, 4096, srl
, f
);