games/gba: add state saving
This commit is contained in:
parent
99e004c72e
commit
040166493d
|
@ -50,6 +50,16 @@ chan sndch[4] = {
|
|||
}
|
||||
};
|
||||
|
||||
Var apuvars[] = {
|
||||
ARR(snddma), VAR(envctr), VAR(envrel), VAR(envmod), VAR(sweepen),
|
||||
VAR(sweepctr), VAR(sweepfreq), ARR(wave), VAR(wpos), VAR(wbank), VAR(lfsr),
|
||||
VAR(sndch[0].ectr), VAR(sndch[0].len), VAR(sndch[0].fctr), VAR(sndch[0].fthr), VAR(sndch[0].finc), VAR(sndch[0].vol),
|
||||
VAR(sndch[1].ectr), VAR(sndch[1].len), VAR(sndch[1].fctr), VAR(sndch[1].fthr), VAR(sndch[1].finc), VAR(sndch[1].vol),
|
||||
VAR(sndch[2].ectr), VAR(sndch[2].len), VAR(sndch[2].fctr), VAR(sndch[2].fthr), VAR(sndch[2].finc), VAR(sndch[2].vol),
|
||||
VAR(sndch[3].ectr), VAR(sndch[3].len), VAR(sndch[3].fctr), VAR(sndch[3].fthr), VAR(sndch[3].finc), VAR(sndch[3].vol),
|
||||
{nil, 0, 0},
|
||||
};
|
||||
|
||||
void
|
||||
rate(int i, u16int v)
|
||||
{
|
||||
|
|
|
@ -36,6 +36,12 @@ int irq;
|
|||
u32int instr0, instr1, pipel = -1;
|
||||
int cyc, trace;
|
||||
|
||||
Var cpuvars[] = {
|
||||
ARR(r), VAR(cpsr), VAR(spsr), ARR(saver), VAR(irq),
|
||||
VAR(instr0), VAR(instr1), VAR(pipel),
|
||||
{nil, 0, 0},
|
||||
};
|
||||
|
||||
#define pipeflush() {io(); pipel = -1;}
|
||||
#define io() cyc++
|
||||
|
||||
|
@ -1267,3 +1273,12 @@ reset(void)
|
|||
r[15] = 0;
|
||||
pipel = -1;
|
||||
}
|
||||
|
||||
void
|
||||
cpuload(void)
|
||||
{
|
||||
if((cpsr & FLAGT) != 0)
|
||||
step = stepthumb;
|
||||
else
|
||||
step = steparm;
|
||||
}
|
||||
|
|
|
@ -142,3 +142,13 @@ enum {
|
|||
BACKTYPELEN = 64,
|
||||
HZ = 16777216,
|
||||
};
|
||||
|
||||
typedef struct Var Var;
|
||||
|
||||
struct Var {
|
||||
void *a;
|
||||
int s, n;
|
||||
};
|
||||
#define VAR(a) {&a, sizeof(a), 1}
|
||||
#define ARR(a) {a, sizeof(*a), nelem(a)}
|
||||
enum { NEVENT = 6 };
|
||||
|
|
|
@ -22,6 +22,19 @@ fifo sndfifo[2];
|
|||
Event *elist;
|
||||
Timer timers[4];
|
||||
Event evhblank;
|
||||
extern Event evsamp;
|
||||
Event *events[NEVENT] = {&timers[0].Event, &timers[1].Event, &timers[2].Event, &timers[3].Event, &evhblank, &evsamp};
|
||||
|
||||
Var evvars[] = {
|
||||
VAR(clock),
|
||||
ARR(sndfifo[0].d), VAR(sndfifo[0].head), VAR(sndfifo[0].level), VAR(sndfifo[0].headpos),
|
||||
ARR(sndfifo[1].d), VAR(sndfifo[1].head), VAR(sndfifo[1].level), VAR(sndfifo[1].headpos),
|
||||
VAR(timers[0].val), VAR(timers[0].clock), VAR(timers[0].sh), VAR(timers[0].snd),
|
||||
VAR(timers[1].val), VAR(timers[1].clock), VAR(timers[1].sh), VAR(timers[1].snd),
|
||||
VAR(timers[2].val), VAR(timers[2].clock), VAR(timers[2].sh), VAR(timers[2].snd),
|
||||
VAR(timers[3].val), VAR(timers[3].clock), VAR(timers[3].sh), VAR(timers[3].snd),
|
||||
{nil, 0, 0},
|
||||
};
|
||||
|
||||
void
|
||||
addevent(Event *ev, int time)
|
||||
|
|
|
@ -23,3 +23,6 @@ void soundbias(u16int);
|
|||
void audioinit(void);
|
||||
int audioout(void);
|
||||
void sndwrite(u16int, u16int);
|
||||
void loadstate(char *);
|
||||
void savestate(char *);
|
||||
void cpuload(void);
|
||||
|
|
|
@ -16,6 +16,7 @@ int keys, paused, framestep, backup;
|
|||
QLock pauselock;
|
||||
int savefd, saveframes;
|
||||
int clock;
|
||||
int savereq, loadreq;
|
||||
|
||||
char *biosfile = "/sys/games/lib/gbabios.bin";
|
||||
|
||||
|
@ -237,10 +238,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))
|
||||
if(utfrune(buf, KF|5))
|
||||
savereq = 1;
|
||||
if(utfrune(buf, KF|6))
|
||||
loadreq = 1;*/
|
||||
loadreq = 1;
|
||||
if(utfrune(buf, Kdel)){
|
||||
close(fd);
|
||||
threadexitsall(nil);
|
||||
|
@ -424,6 +425,14 @@ threadmain(int argc, char **argv)
|
|||
memreset();
|
||||
reset();
|
||||
for(;;){
|
||||
if(savereq){
|
||||
savestate("gba.save");
|
||||
savereq = 0;
|
||||
}
|
||||
if(loadreq){
|
||||
loadstate("gba.save");
|
||||
loadreq = 0;
|
||||
}
|
||||
if(paused){
|
||||
qlock(&pauselock);
|
||||
qunlock(&pauselock);
|
||||
|
|
|
@ -20,6 +20,12 @@ u32int dmar[16];
|
|||
u8int waitst[16] = {5, 5, 5, 5, 3, 5, 5, 9, 8, 10, 10, 14};
|
||||
u32int eepstart;
|
||||
|
||||
Var memvars[] = {
|
||||
ARR(wram0), ARR(wram1), ARR(vram), ARR(pram), ARR(oam), ARR(reg),
|
||||
VAR(dmaact), ARR(dmar), ARR(waitst),
|
||||
{nil, 0, 0},
|
||||
};
|
||||
|
||||
extern int cyc;
|
||||
|
||||
static int eepromread(void);
|
||||
|
|
|
@ -9,6 +9,7 @@ OFILES=\
|
|||
ppu.$O\
|
||||
ev.$O\
|
||||
apu.$O\
|
||||
state.$O\
|
||||
|
||||
HFILES=dat.h fns.h
|
||||
|
||||
|
|
|
@ -27,6 +27,13 @@ struct bg {
|
|||
};
|
||||
static bg bgst[4] = {{.n = 0}, {.n = 1}, {.n = 2}, {.n = 3}};
|
||||
|
||||
Var ppuvars[] = {
|
||||
VAR(hblank), VAR(ppuy), VAR(hblclock),
|
||||
VAR(bldy), VAR(blda), VAR(bldb), VAR(objalpha),
|
||||
VAR(bgst[2].rpx0), VAR(bgst[2].rpy0), VAR(bgst[3].rpx0), VAR(bgst[3].rpy0),
|
||||
{nil, 0, 0},
|
||||
};
|
||||
|
||||
typedef struct sprite sprite;
|
||||
struct sprite {
|
||||
uchar w, wb, h;
|
||||
|
|
165
sys/src/games/gba/state.c
Normal file
165
sys/src/games/gba/state.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <draw.h>
|
||||
#include <bio.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
extern Var cpuvars[], ppuvars[], memvars[], apuvars[], evvars[];
|
||||
extern Event *events[NEVENT], *elist;
|
||||
|
||||
static void
|
||||
putevents(Biobuf *bp)
|
||||
{
|
||||
int i, j;
|
||||
Event *e;
|
||||
|
||||
for(i = 0; i < NEVENT; i++)
|
||||
if(elist == events[i])
|
||||
break;
|
||||
if(i == NEVENT && elist != nil)
|
||||
print("unknown event %p in chain\n", elist);
|
||||
Bputc(bp, i);
|
||||
for(i = 0; i < NEVENT; i++){
|
||||
e = events[i];
|
||||
Bputc(bp, e->time);
|
||||
Bputc(bp, e->time >> 8);
|
||||
Bputc(bp, e->time >> 16);
|
||||
Bputc(bp, e->time >> 24);
|
||||
for(j = 0; j < NEVENT; j++)
|
||||
if(e->next == events[j])
|
||||
break;
|
||||
if(j == NEVENT && e->next != nil)
|
||||
print("unknown event %p in chain\n", e->next);
|
||||
Bputc(bp, j);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
getevents(Biobuf *bp)
|
||||
{
|
||||
int i, j;
|
||||
Event *e;
|
||||
|
||||
i = Bgetc(bp);
|
||||
elist = i >= NEVENT ? nil : events[i];
|
||||
for(i = 0; i < NEVENT; i++){
|
||||
e = events[i];
|
||||
e->time = Bgetc(bp);
|
||||
e->time |= Bgetc(bp) << 8;
|
||||
e->time |= Bgetc(bp) << 16;
|
||||
e->time |= Bgetc(bp) << 24;
|
||||
j = Bgetc(bp);
|
||||
e->next = j >= NEVENT ? nil : events[j];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
getvars(Biobuf *bp, Var *v)
|
||||
{
|
||||
int n;
|
||||
u16int *p, w;
|
||||
u32int *q, l;
|
||||
|
||||
for(; v->a != nil; v++)
|
||||
switch(v->s){
|
||||
case 1:
|
||||
Bread(bp, v->a, v->n);
|
||||
break;
|
||||
case 2:
|
||||
n = v->n;
|
||||
p = v->a;
|
||||
while(n--){
|
||||
w = Bgetc(bp);
|
||||
*p++ = w | Bgetc(bp) << 8;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
n = v->n;
|
||||
q = v->a;
|
||||
while(n--){
|
||||
l = Bgetc(bp);
|
||||
l |= Bgetc(bp) << 8;
|
||||
l |= Bgetc(bp) << 16;
|
||||
*q++ = l | Bgetc(bp) << 24;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
putvars(Biobuf *bp, Var *v)
|
||||
{
|
||||
int n;
|
||||
u16int *p;
|
||||
u32int *q;
|
||||
|
||||
for(; v->a != nil; v++)
|
||||
switch(v->s){
|
||||
case 1:
|
||||
Bwrite(bp, v->a, v->n);
|
||||
break;
|
||||
case 2:
|
||||
n = v->n;
|
||||
p = v->a;
|
||||
while(n--){
|
||||
Bputc(bp, *p & 0xff);
|
||||
Bputc(bp, *p++ >> 8);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
n = v->n;
|
||||
q = v->a;
|
||||
while(n--){
|
||||
Bputc(bp, *q);
|
||||
Bputc(bp, *q >> 8);
|
||||
Bputc(bp, *q >> 16);
|
||||
Bputc(bp, *q++ >> 24);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
savestate(char *file)
|
||||
{
|
||||
Biobuf *bp;
|
||||
|
||||
flushback();
|
||||
bp = Bopen(file, OWRITE);
|
||||
if(bp == nil){
|
||||
print("open: %r\n");
|
||||
return;
|
||||
}
|
||||
putvars(bp, cpuvars);
|
||||
putvars(bp, ppuvars);
|
||||
putvars(bp, memvars);
|
||||
putvars(bp, apuvars);
|
||||
putvars(bp, evvars);
|
||||
putevents(bp);
|
||||
Bterm(bp);
|
||||
}
|
||||
|
||||
void
|
||||
loadstate(char *file)
|
||||
{
|
||||
Biobuf *bp;
|
||||
extern u32int r[16];
|
||||
|
||||
bp = Bopen(file, OREAD);
|
||||
if(bp == nil){
|
||||
print("open: %r\n");
|
||||
return;
|
||||
}
|
||||
getvars(bp, cpuvars);
|
||||
getvars(bp, ppuvars);
|
||||
getvars(bp, memvars);
|
||||
getvars(bp, apuvars);
|
||||
getvars(bp, evvars);
|
||||
getevents(bp);
|
||||
cpuload();
|
||||
Bterm(bp);
|
||||
}
|
Loading…
Reference in a new issue