summaryrefslogtreecommitdiff
path: root/apps/plugins/rockboy/save.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/rockboy/save.c')
-rw-r--r--apps/plugins/rockboy/save.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/apps/plugins/rockboy/save.c b/apps/plugins/rockboy/save.c
new file mode 100644
index 0000000..bb9f905
--- /dev/null
+++ b/apps/plugins/rockboy/save.c
@@ -0,0 +1,286 @@
+
+
+#include "rockmacros.h"
+#include <stdio.h>
+
+#include "defs.h"
+#include "cpu.h"
+#include "cpuregs.h"
+#include "hw.h"
+#include "regs.h"
+#include "lcd.h"
+#include "rtc.h"
+#include "mem.h"
+#include "sound.h"
+
+
+
+#ifdef LITTLE_ENDIAN
+#define LIL(x) (x)
+#else
+#define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24))
+#endif
+
+#define I1(s, p) { 1, s, p }
+#define I2(s, p) { 2, s, p }
+#define I4(s, p) { 4, s, p }
+#define R(r) I1(#r, &R_##r)
+#define NOSAVE { -1, "\0\0\0\0", 0 }
+#define END { 0, "\0\0\0\0", 0 }
+
+struct svar
+{
+ int len;
+ char key[4];
+ void *ptr;
+};
+
+static int ver;
+static int sramblock, iramblock, vramblock;
+static int hramofs, hiofs, palofs, oamofs, wavofs;
+
+struct svar svars[] =
+{
+ I4("GbSs", &ver),
+
+ I2("PC ", &PC),
+ I2("SP ", &SP),
+ I2("BC ", &BC),
+ I2("DE ", &DE),
+ I2("HL ", &HL),
+ I2("AF ", &AF),
+
+ I4("IME ", &cpu.ime),
+ I4("ima ", &cpu.ima),
+ I4("spd ", &cpu.speed),
+ I4("halt", &cpu.halt),
+ I4("div ", &cpu.div),
+ I4("tim ", &cpu.tim),
+ I4("lcdc", &cpu.lcdc),
+ I4("snd ", &cpu.snd),
+
+ I1("ints", &hw.ilines),
+ I1("pad ", &hw.pad),
+ I4("cgb ", &hw.cgb),
+ I4("gba ", &hw.gba),
+
+ I4("mbcm", &mbc.model),
+ I4("romb", &mbc.rombank),
+ I4("ramb", &mbc.rambank),
+ I4("enab", &mbc.enableram),
+ I4("batt", &mbc.batt),
+
+ I4("rtcR", &rtc.sel),
+ I4("rtcL", &rtc.latch),
+ I4("rtcC", &rtc.carry),
+ I4("rtcS", &rtc.stop),
+ I4("rtcd", &rtc.d),
+ I4("rtch", &rtc.h),
+ I4("rtcm", &rtc.m),
+ I4("rtcs", &rtc.s),
+ I4("rtct", &rtc.t),
+ I1("rtR8", &rtc.regs[0]),
+ I1("rtR9", &rtc.regs[1]),
+ I1("rtRA", &rtc.regs[2]),
+ I1("rtRB", &rtc.regs[3]),
+ I1("rtRC", &rtc.regs[4]),
+
+ I4("S1on", &snd.ch[0].on),
+ I4("S1p ", &snd.ch[0].pos),
+ I4("S1c ", &snd.ch[0].cnt),
+ I4("S1ec", &snd.ch[0].encnt),
+ I4("S1sc", &snd.ch[0].swcnt),
+ I4("S1sf", &snd.ch[0].swfreq),
+
+ I4("S2on", &snd.ch[1].on),
+ I4("S2p ", &snd.ch[1].pos),
+ I4("S2c ", &snd.ch[1].cnt),
+ I4("S2ec", &snd.ch[1].encnt),
+
+ I4("S3on", &snd.ch[2].on),
+ I4("S3p ", &snd.ch[2].pos),
+ I4("S3c ", &snd.ch[2].cnt),
+
+ I4("S4on", &snd.ch[3].on),
+ I4("S4p ", &snd.ch[3].pos),
+ I4("S4c ", &snd.ch[3].cnt),
+ I4("S4ec", &snd.ch[3].encnt),
+
+ I4("hdma", &hw.hdma),
+
+ I4("sram", &sramblock),
+ I4("iram", &iramblock),
+ I4("vram", &vramblock),
+ I4("hi ", &hiofs),
+ I4("pal ", &palofs),
+ I4("oam ", &oamofs),
+ I4("wav ", &wavofs),
+
+ /* NOSAVE is a special code to prevent the rest of the table
+ * from being saved, used to support old stuff for backwards
+ * compatibility... */
+ NOSAVE,
+
+ /* the following are obsolete as of 0x104 */
+
+ I4("hram", &hramofs),
+
+ R(P1), R(SB), R(SC),
+ R(DIV), R(TIMA), R(TMA), R(TAC),
+ R(IE), R(IF),
+ R(LCDC), R(STAT), R(LY), R(LYC),
+ R(SCX), R(SCY), R(WX), R(WY),
+ R(BGP), R(OBP0), R(OBP1),
+ R(DMA),
+
+ R(VBK), R(SVBK), R(KEY1),
+ R(BCPS), R(BCPD), R(OCPS), R(OCPD),
+
+ R(NR10), R(NR11), R(NR12), R(NR13), R(NR14),
+ R(NR21), R(NR22), R(NR23), R(NR24),
+ R(NR30), R(NR31), R(NR32), R(NR33), R(NR34),
+ R(NR41), R(NR42), R(NR43), R(NR44),
+ R(NR50), R(NR51), R(NR52),
+
+ I1("DMA1", &R_HDMA1),
+ I1("DMA2", &R_HDMA2),
+ I1("DMA3", &R_HDMA3),
+ I1("DMA4", &R_HDMA4),
+ I1("DMA5", &R_HDMA5),
+
+ END
+};
+
+
+void loadstate(int fd)
+{
+ int i, j;
+ byte buf[4096];
+ un32 (*header)[2] = (un32 (*)[2])buf;
+ un32 d;
+ int irl = hw.cgb ? 8 : 2;
+ int vrl = hw.cgb ? 4 : 2;
+ int srl = mbc.ramsize << 1;
+
+ ver = hramofs = hiofs = palofs = oamofs = wavofs = 0;
+
+ read(fd,buf, 4096);
+
+ for (j = 0; header[j][0]; j++)
+ {
+ for (i = 0; svars[i].ptr; i++)
+ {
+ if (header[j][0] != *(un32 *)svars[i].key)
+ continue;
+ d = LIL(header[j][1]);
+ switch (svars[i].len)
+ {
+ case 1:
+ *(byte *)svars[i].ptr = d;
+ break;
+ case 2:
+ *(un16 *)svars[i].ptr = d;
+ break;
+ case 4:
+ *(un32 *)svars[i].ptr = d;
+ break;
+ }
+ break;
+ }
+ }
+
+ /* obsolete as of version 0x104 */
+ if (hramofs) memcpy(ram.hi+128, buf+hramofs, 127);
+
+ if (hiofs) memcpy(ram.hi, buf+hiofs, sizeof ram.hi);
+ if (palofs) memcpy(lcd.pal, buf+palofs, sizeof lcd.pal);
+ if (oamofs) memcpy(lcd.oam.mem, buf+oamofs, sizeof lcd.oam);
+
+ if (wavofs) memcpy(snd.wave, buf+wavofs, sizeof snd.wave);
+ else memcpy(snd.wave, ram.hi+0x30, 16); /* patch data from older files */
+
+ lseek(fd, iramblock<<12, SEEK_SET);
+ read(fd,ram.ibank, 4096*irl);
+
+ lseek(fd, vramblock<<12, SEEK_SET);
+ read(fd,lcd.vbank, 4096*vrl);
+
+ lseek(fd, sramblock<<12, SEEK_SET);
+ read(fd,ram.sbank, 4096*srl);
+}
+
+void savestate(int fd)
+{
+ int i;
+ byte buf[4096];
+ un32 (*header)[2] = (un32 (*)[2])buf;
+ un32 d = 0;
+ int irl = hw.cgb ? 8 : 2;
+ int vrl = hw.cgb ? 4 : 2;
+ int srl = mbc.ramsize << 1;
+
+ ver = 0x105;
+ iramblock = 1;
+ vramblock = 1+irl;
+ sramblock = 1+irl+vrl;
+ wavofs = 4096 - 784;
+ hiofs = 4096 - 768;
+ palofs = 4096 - 512;
+ oamofs = 4096 - 256;
+ memset(buf, 0, sizeof buf);
+
+ for (i = 0; svars[i].len > 0; i++)
+ {
+ header[i][0] = *(un32 *)svars[i].key;
+ switch (svars[i].len)
+ {
+ case 1:
+ d = *(byte *)svars[i].ptr;
+ break;
+ case 2:
+ d = *(un16 *)svars[i].ptr;
+ break;
+ case 4:
+ d = *(un32 *)svars[i].ptr;
+ break;
+ }
+ header[i][1] = LIL(d);
+ }
+ header[i][0] = header[i][1] = 0;
+
+ memcpy(buf+hiofs, ram.hi, sizeof ram.hi);
+ memcpy(buf+palofs, lcd.pal, sizeof lcd.pal);
+ memcpy(buf+oamofs, lcd.oam.mem, sizeof lcd.oam);
+ memcpy(buf+wavofs, snd.wave, sizeof snd.wave);
+
+ lseek(fd, 0, SEEK_SET);
+ write(fd,buf, 4096);
+
+ lseek(fd, iramblock<<12, SEEK_SET);
+ write(fd,ram.ibank, 4096*irl);
+
+ lseek(fd, vramblock<<12, SEEK_SET);
+ write(fd,lcd.vbank, 4096*vrl);
+
+ lseek(fd, sramblock<<12, SEEK_SET);
+ write(fd,ram.sbank, 4096*srl);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+