ref: 46168ec503ec75926366a8f4ab505fd44ef271b7
parent: 4b0467ce442ad6a4eef0caf44391f7b924186a1b
author: aiju <devnull@localhost>
date: Fri Mar 21 06:53:33 EDT 2014
games/snes: added state saving
--- a/sys/src/games/snes/dat.h
+++ b/sys/src/games/snes/dat.h
@@ -1,10 +1,9 @@
typedef signed char s8int;
typedef signed short s16int;
-extern u16int pc;
-extern u32int rPB, curpc;
-extern u8int dma, nmi, irq;
-extern u32int hdma;
+extern u8int rP, dma, nmi, irq, emu, wai;
+extern u16int rA, rX, rY, rS, rD, pc;
+extern u32int rPB, rDB, curpc, hdma;
extern int trace;
extern int memcyc;
@@ -11,8 +10,8 @@
extern uchar *prg, *sram;
extern int nprg, nsram, hirom;
extern u32int keys, keylatch, lastkeys;
-extern u8int reg[32768], spcmem[65536], vram[65536], oam[544];
-extern u16int cgram[256];
+extern u8int reg[32768], mem[131072], spcmem[65536], vram[65536], oam[544];
+extern u16int cgram[256], vramlatch;
extern int ppux, ppuy, rx;
extern u16int vtime, htime, subcolor, oamaddr;
@@ -19,8 +18,13 @@
extern u16int hofs[5], vofs[5];
extern s16int m7[6];
-extern u8int spcmem[65536];
+extern u8int spcmem[65536], spctimer[4], dsp[256];
+extern u8int sA, sX, sY, sP, sS;
+extern u16int spc;
+extern u8int dspstate;
+extern u16int dspcounter, noise;
+extern int ppuclock, spcclock, dspclock, stimerclock;
extern int battery, saveclock, scale, mouse;
enum {
--- a/sys/src/games/snes/dsp.c
+++ b/sys/src/games/snes/dsp.c
@@ -4,8 +4,8 @@
#include "dat.h"
#include "fns.h"
-static u8int dsp[256], dspstate;
-static u16int counter, noise;
+u8int dsp[256], dspstate;
+u16int dspcounter, noise;
static s16int samp[2], echoin[2];
enum {
@@ -134,9 +134,9 @@
if(r >= 30){
if(r == 31)
return 1;
- return (counter & 1) == 0;
+ return (dspcounter & 1) == 0;
}
- c = counter;
+ c = dspcounter;
switch(r % 3){
case 0: c += 536; break;
case 2: c += 1040; break;
@@ -515,8 +515,8 @@
dsp[INT|KOFF] = dsp[KOFF];
dsp[INT|KON] = dsp[NEWKON];
}
- if(counter-- == 0)
- counter = 0x77ff;
+ if(dspcounter-- == 0)
+ dspcounter = 0x77ff;
break;
case 31: voice(0, 4); voice(2, 1); break;
}
--- a/sys/src/games/snes/fns.h
+++ b/sys/src/games/snes/fns.h
@@ -17,3 +17,6 @@
void dspreset(void);
void audioinit(void);
int audioout(void);
+void flushram(void);
+void loadstate(char *);
+void savestate(char *);
--- a/sys/src/games/snes/mkfile
+++ b/sys/src/games/snes/mkfile
@@ -9,6 +9,7 @@
ppu.$O\
spc.$O\
dsp.$O\
+ state.$O\
HFILES=dat.h fns.h
--- a/sys/src/games/snes/ppu.c
+++ b/sys/src/games/snes/ppu.c
@@ -7,7 +7,7 @@
int ppux, ppuy, rx;
static u8int mode, bright, pixelpri[2];
static u32int pixelcol[2];
-u16int vtime = 0x1ff, htime = 0x1ff, subcolor, mosatop;
+u16int vtime = 0x1ff, htime = 0x1ff, subcolor;
uchar pic[256*239*2*9];
u16int hofs[5], vofs[5];
s16int m7[6];
--- a/sys/src/games/snes/snes.c
+++ b/sys/src/games/snes/snes.c
@@ -15,7 +15,7 @@
Mousectl *mc;
QLock pauselock;
u32int keys;
-int savefd, scale, profile, mouse;
+int savefd, scale, profile, mouse, loadreq, savereq;
Rectangle picr;
Image *tmp, *bg;
@@ -126,6 +126,10 @@
if(read(fd, buf, sizeof(buf) - 1) <= 0)
sysfatal("read /dev/kbd: %r");
if(buf[0] == 'c'){
+ if(utfrune(buf, KF|5))
+ savereq = 1;
+ if(utfrune(buf, KF|6))
+ loadreq = 1;
if(utfrune(buf, Kdel)){
close(fd);
threadexitsall(nil);
@@ -251,6 +255,14 @@
spcreset();
dspreset();
for(;;){
+ if(savereq){
+ savestate("snes.save");
+ savereq = 0;
+ }
+ if(loadreq){
+ loadstate("snes.save");
+ loadreq = 0;
+ }
if(paused){
qlock(&pauselock);
qunlock(&pauselock);
--- /dev/null
+++ b/sys/src/games/snes/state.c
@@ -1,0 +1,184 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <bio.h>
+#include "dat.h"
+#include "fns.h"
+
+static Biobuf *bp;
+
+void
+put8(u8int i)
+{
+ Bputc(bp, i);
+}
+
+void
+put16(u16int i)
+{
+ put8(i);
+ put8(i >> 8);
+}
+
+void
+put32(u32int i)
+{
+ put8(i);
+ put8(i >> 8);
+ put8(i >> 16);
+ put8(i >> 24);
+}
+
+void
+put16s(u16int *p, int n)
+{
+ while(n--)
+ put16(*p++);
+}
+
+int
+get8(void)
+{
+ return Bgetc(bp);
+}
+
+int
+get16(void)
+{
+ int i;
+
+ i = get8();
+ i |= get8() << 8;
+ return i;
+}
+
+int
+get32(void)
+{
+ int i;
+
+ i = get8();
+ i |= get8() << 8;
+ i |= get8() << 16;
+ i |= get8() << 24;
+ return i;
+}
+
+void
+get16s(u16int *p, int n)
+{
+ while(n--)
+ *p++ = get16();
+}
+
+void
+loadstate(char *file)
+{
+ bp = Bopen(file, OREAD);
+ if(bp == nil){
+ message("open: %r");
+ return;
+ }
+ Bread(bp, reg, sizeof(reg));
+ Bread(bp, mem, sizeof(mem));
+ Bread(bp, vram, sizeof(vram));
+ Bread(bp, oam, sizeof(oam));
+ Bread(bp, spcmem, sizeof(spcmem));
+ Bread(bp, dsp, sizeof(dsp));
+ get16s(cgram, nelem(cgram));
+ ppuclock = get32();
+ spcclock = get32();
+ dspclock = get32();
+ stimerclock = get32();
+ rA = get16();
+ rX = get16();
+ rY = get16();
+ rS = get16();
+ rP = get8();
+ rD = get16();
+ rDB = get8()<<16;
+ pc = get16();
+ rPB = get8()<<16;
+ emu = get8();
+ irq = get8();
+ nmi = get8();
+ dma = get8();
+ hdma = get32();
+ wai = get8();
+ oamaddr = get16();
+ vramlatch = get16();
+ keylatch = get32();
+ ppux = get16();
+ ppuy = get16();
+ htime = reg[0x4207] | reg[0x4208] << 8 & 0x100;
+ vtime = reg[0x4209] | reg[0x420a] << 8 & 0x100;
+ subcolor = get16();
+ get16s(hofs, nelem(hofs));
+ get16s(vofs, nelem(vofs));
+ get16s((u16int*) m7, nelem(m7));
+ sA = get8();
+ sX = get8();
+ sY = get8();
+ sS = get8();
+ sP = get8();
+ dspstate = get8();
+ dspcounter = get16();
+ noise = get16();
+ Bterm(bp);
+}
+
+void
+savestate(char *file)
+{
+ flushram();
+ bp = Bopen(file, OWRITE);
+ if(bp == nil){
+ message("open: %r");
+ return;
+ }
+ Bwrite(bp, reg, sizeof(reg));
+ Bwrite(bp, mem, sizeof(mem));
+ Bwrite(bp, vram, sizeof(vram));
+ Bwrite(bp, oam, sizeof(oam));
+ Bwrite(bp, spcmem, sizeof(spcmem));
+ Bwrite(bp, dsp, sizeof(dsp));
+ put16s(cgram, nelem(cgram));
+ put32(ppuclock);
+ put32(spcclock);
+ put32(dspclock);
+ put32(stimerclock);
+ put16(rA);
+ put16(rX);
+ put16(rY);
+ put16(rS);
+ put8(rP);
+ put16(rD);
+ put8(rDB>>16);
+ put16(pc);
+ put8(rPB>>16);
+ put8(emu);
+ put8(irq);
+ put8(nmi);
+ put8(dma);
+ put32(hdma);
+ put8(wai);
+ put16(oamaddr);
+ put16(vramlatch);
+ put32(keylatch);
+ put16(ppux);
+ put16(ppuy);
+ put16(subcolor);
+ put16s(hofs, nelem(hofs));
+ put16s(vofs, nelem(vofs));
+ put16s((u16int*) m7, nelem(m7));
+ put8(sA);
+ put8(sX);
+ put8(sY);
+ put8(sS);
+ put8(sP);
+ put8(dspstate);
+ put16(dspcounter);
+ put16(noise);
+ Bterm(bp);
+}