diff --git a/sys/src/games/snes/dat.h b/sys/src/games/snes/dat.h index ebc92dd9d..8489b9f9b 100644 --- a/sys/src/games/snes/dat.h +++ b/sys/src/games/snes/dat.h @@ -1,26 +1,30 @@ 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; 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; 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 { diff --git a/sys/src/games/snes/dsp.c b/sys/src/games/snes/dsp.c index 019b93cd4..0351d1c01 100644 --- 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 @@ envyes(int r) 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 @@ dspstep(void) 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; } diff --git a/sys/src/games/snes/fns.h b/sys/src/games/snes/fns.h index d554e3b70..f4904c73c 100644 --- a/sys/src/games/snes/fns.h +++ b/sys/src/games/snes/fns.h @@ -17,3 +17,6 @@ void dspwrite(u8int, u8int); void dspreset(void); void audioinit(void); int audioout(void); +void flushram(void); +void loadstate(char *); +void savestate(char *); diff --git a/sys/src/games/snes/mkfile b/sys/src/games/snes/mkfile index 5a74ccf00..6171c70ac 100644 --- a/sys/src/games/snes/mkfile +++ b/sys/src/games/snes/mkfile @@ -9,6 +9,7 @@ OFILES=\ ppu.$O\ spc.$O\ dsp.$O\ + state.$O\ HFILES=dat.h fns.h diff --git a/sys/src/games/snes/ppu.c b/sys/src/games/snes/ppu.c index 1d5ef7cdf..b905fc34a 100644 --- 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]; diff --git a/sys/src/games/snes/snes.c b/sys/src/games/snes/snes.c index 939397ec4..3ce5faca4 100644 --- a/sys/src/games/snes/snes.c +++ b/sys/src/games/snes/snes.c @@ -15,7 +15,7 @@ int ppuclock, spcclock, dspclock, stimerclock, saveclock, msgclock, paused, perf 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 @@ keyproc(void *) 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 @@ usage: spcreset(); dspreset(); for(;;){ + if(savereq){ + savestate("snes.save"); + savereq = 0; + } + if(loadreq){ + loadstate("snes.save"); + loadreq = 0; + } if(paused){ qlock(&pauselock); qunlock(&pauselock); diff --git a/sys/src/games/snes/state.c b/sys/src/games/snes/state.c new file mode 100644 index 000000000..a206cf340 --- /dev/null +++ b/sys/src/games/snes/state.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#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); +}