add load and save function
This commit is contained in:
parent
c8c2a4fc19
commit
4661fc35bb
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@
|
|||||||
*.ko
|
*.ko
|
||||||
*.obj
|
*.obj
|
||||||
*.elf
|
*.elf
|
||||||
|
.*.swp
|
||||||
|
|
||||||
# Linker output
|
# Linker output
|
||||||
*.ilk
|
*.ilk
|
||||||
|
|||||||
3
cpu.c
3
cpu.c
@ -30,6 +30,9 @@ u8 r[8], ime;
|
|||||||
u16 pc, sp, curpc;
|
u16 pc, sp, curpc;
|
||||||
int halt;
|
int halt;
|
||||||
|
|
||||||
|
Var cpuvars[] = {ARR(r), VAR(ime), VAR(pc), VAR(curpc), VAR(sp), VAR(halt),
|
||||||
|
{nil, 0, 0}};
|
||||||
|
|
||||||
void
|
void
|
||||||
state(void)
|
state(void)
|
||||||
{
|
{
|
||||||
|
|||||||
3
ev.c
3
ev.c
@ -1,8 +1,11 @@
|
|||||||
#include "gb.h"
|
#include "gb.h"
|
||||||
|
|
||||||
Event evhblank, evjoypad;
|
Event evhblank, evjoypad;
|
||||||
|
Event *events[NEVENT] = {&evhblank, &evjoypad, nil};
|
||||||
Event* elist;
|
Event* elist;
|
||||||
|
|
||||||
|
Var evvars[] = {{nil, 0, 0}};
|
||||||
|
|
||||||
void
|
void
|
||||||
addevent(Event* ev, int time)
|
addevent(Event* ev, int time)
|
||||||
{
|
{
|
||||||
|
|||||||
1
gb.c
1
gb.c
@ -5,7 +5,6 @@
|
|||||||
int cpuhalt;
|
int cpuhalt;
|
||||||
int backup;
|
int backup;
|
||||||
int savefd = -1;
|
int savefd = -1;
|
||||||
u64 clock;
|
|
||||||
u8 mbc, feat, mode;
|
u8 mbc, feat, mode;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
22
gb.h
22
gb.h
@ -1,5 +1,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define nelem(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
|
||||||
|
#define VAR(a) {&a, sizeof(a), 1}
|
||||||
|
#define ARR(a) {a, sizeof(*a), nelem(a)}
|
||||||
#define nil ((void*)0)
|
#define nil ((void*)0)
|
||||||
#define JOYPAD_CYCLE (30)
|
#define JOYPAD_CYCLE (30)
|
||||||
|
|
||||||
@ -128,6 +132,8 @@ enum
|
|||||||
GB_KEY_START = 0x80
|
GB_KEY_START = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum { NEVENT = 2 + 1};
|
||||||
|
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
typedef int8_t i8;
|
typedef int8_t i8;
|
||||||
@ -136,6 +142,7 @@ typedef int32_t i32;
|
|||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
typedef int64_t i64;
|
typedef int64_t i64;
|
||||||
typedef struct Event Event;
|
typedef struct Event Event;
|
||||||
|
typedef struct Var Var;
|
||||||
|
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
@ -145,6 +152,15 @@ struct Event
|
|||||||
void* aux;
|
void* aux;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Var
|
||||||
|
{
|
||||||
|
void *a;
|
||||||
|
int s, n;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VAR(a) {&a, sizeof(a), 1}
|
||||||
|
#define ARR(a) {a, sizeof(*a), nelem(a)}
|
||||||
|
|
||||||
extern u8 *rom, *back, reg[256], oam[256];
|
extern u8 *rom, *back, reg[256], oam[256];
|
||||||
extern u8 vram[16384];
|
extern u8 vram[16384];
|
||||||
extern int nrom, nback, nbackbank;
|
extern int nrom, nback, nbackbank;
|
||||||
@ -163,6 +179,7 @@ extern u32 moncols[4];
|
|||||||
extern u32 white;
|
extern u32 white;
|
||||||
extern u8* pic;
|
extern u8* pic;
|
||||||
extern int (*mapper)(int, int);
|
extern int (*mapper)(int, int);
|
||||||
|
extern Event *events[NEVENT];
|
||||||
|
|
||||||
/* joypad */
|
/* joypad */
|
||||||
void
|
void
|
||||||
@ -206,6 +223,11 @@ flush();
|
|||||||
void
|
void
|
||||||
initwindow(int scale);
|
initwindow(int scale);
|
||||||
|
|
||||||
|
/* save */
|
||||||
|
void
|
||||||
|
putvars(Var *v);
|
||||||
|
void
|
||||||
|
getvars(Var *v);
|
||||||
/* error */
|
/* error */
|
||||||
void
|
void
|
||||||
error(const char*, ...);
|
error(const char*, ...);
|
||||||
|
|||||||
19
mem.c
19
mem.c
@ -9,17 +9,18 @@ u8* rom;
|
|||||||
u8 *romb, *vramb, *wramb, *eramb;
|
u8 *romb, *vramb, *wramb, *eramb;
|
||||||
u8 wram[32768], vram[16384], oam[256], reg[256];
|
u8 wram[32768], vram[16384], oam[256], reg[256];
|
||||||
u8* back;
|
u8* back;
|
||||||
u8 palm[128];
|
|
||||||
u32 pal[64];
|
u32 pal[64];
|
||||||
int nrom, nback, nbackbank;
|
int nrom, nback, nbackbank;
|
||||||
|
u64 clock;
|
||||||
u32 divclock;
|
u32 divclock;
|
||||||
int prish;
|
int prish;
|
||||||
u8 dma;
|
|
||||||
u32 moncols[4];
|
u32 moncols[4];
|
||||||
u32 white;
|
u32 white;
|
||||||
int (*mappers[])(int, int) = { mbc0, mbc1 };
|
int (*mappers[])(int, int) = { mbc0, mbc1 };
|
||||||
int (*mapper)(int, int);
|
int (*mapper)(int, int);
|
||||||
|
|
||||||
|
Var memvars[] = {ARR(wram), ARR(vram), ARR(oam), ARR(reg), VAR(clock), VAR(divclock), {nil, 0, 0}};
|
||||||
|
|
||||||
static u8
|
static u8
|
||||||
regread(u16 a)
|
regread(u16 a)
|
||||||
{
|
{
|
||||||
@ -198,29 +199,29 @@ static int
|
|||||||
mbc1(int a, int v)
|
mbc1(int a, int v)
|
||||||
{
|
{
|
||||||
static u8 ramen, b0, b1, romram;
|
static u8 ramen, b0, b1, romram;
|
||||||
|
static Var mbc1vars[] = {VAR(ramen), VAR(b0), VAR(b1), VAR(romram),
|
||||||
|
{nil, 0,0}};
|
||||||
u16 b;
|
u16 b;
|
||||||
|
|
||||||
if (a < 0) {
|
if (a < 0) {
|
||||||
switch(a) {
|
switch(a) {
|
||||||
case INIT: return 0;
|
case INIT: return 0;
|
||||||
case SAVE:
|
case SAVE: putvars(mbc1vars); break;
|
||||||
case RSTR:
|
case RSTR: getvars(mbc1vars); break;
|
||||||
break;
|
case READ: return -1;
|
||||||
case READ:
|
|
||||||
return -1;
|
|
||||||
default: panic("MBC1 does not have function of %d", a);
|
default: panic("MBC1 does not have function of %d", a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (a >> 13) {
|
switch (a >> 13) {
|
||||||
case 0: ramen = (v & 0xF) == 0xA; break;
|
case 0: ramen = (v & 0xF) == 0xA; break;
|
||||||
case 1: v &= 0x1F; b0 = v != 0 ? v : 1; break;
|
case 1: v &= 0x1F; b0 = v != 0 ? v : 1; break;
|
||||||
case 2: b1 = v & 3; b1 % nbackbank; break;
|
case 2: b1 = v & 3; b1 %= nbackbank; break;
|
||||||
case 3: romram = v & 1; break;
|
case 3: romram = v & 1; break;
|
||||||
}
|
}
|
||||||
b = b0;
|
b = b0;
|
||||||
if (romram == 0)
|
if (romram == 0)
|
||||||
b |= b1 << 5;
|
b |= b1 << 5;
|
||||||
b %= nrom >> 14; /* 32KB => 2bank */
|
b %= nrom >> 14;
|
||||||
romb = rom + (b << 14);
|
romb = rom + (b << 14);
|
||||||
if (ramen) {
|
if (ramen) {
|
||||||
if (romram)
|
if (romram)
|
||||||
|
|||||||
3
ppu.c
3
ppu.c
@ -36,6 +36,9 @@ u64 hblclock, rendclock;
|
|||||||
static int cyc, ppux, ppux0;
|
static int cyc, ppux, ppux0;
|
||||||
sprite spr[10], *sprm;
|
sprite spr[10], *sprm;
|
||||||
|
|
||||||
|
Var ppuvars[] = {VAR(ppustate), VAR(ppuy), VAR(hblclock), VAR(rendclock),
|
||||||
|
{nil, 0, 0}};
|
||||||
|
|
||||||
void
|
void
|
||||||
pputask(void* _)
|
pputask(void* _)
|
||||||
{
|
{
|
||||||
|
|||||||
165
save.c
Normal file
165
save.c
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
#include "gb.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern Var cpuvars[], ppuvars[], memvars[], evvars[];
|
||||||
|
static FILE *fp;
|
||||||
|
|
||||||
|
void
|
||||||
|
putevents(void)
|
||||||
|
{
|
||||||
|
u8 i, j;
|
||||||
|
Event *e;
|
||||||
|
|
||||||
|
for(i = 0; i < NEVENT; ++i)
|
||||||
|
if(elist == events[i]) /* find head */
|
||||||
|
break;
|
||||||
|
if(i == NEVENT && elist != nil)
|
||||||
|
error("Unkown event in chain [%p]", e->next);
|
||||||
|
fputc(i, fp);
|
||||||
|
for(i = 0; i < NEVENT; ++i){
|
||||||
|
e = events[i];
|
||||||
|
fputc(e->time & 0x000000ff, fp);
|
||||||
|
fputc(e->time & 0x0000ff00, fp);
|
||||||
|
fputc(e->time & 0x00ff0000, fp);
|
||||||
|
fputc(e->time & 0xff000000, fp);
|
||||||
|
for(j = 0; j < NEVENT; ++j)
|
||||||
|
if(e->next == events[j]) /* find next */
|
||||||
|
break;
|
||||||
|
if(j == NEVENT && e->next != nil)
|
||||||
|
error("Unkown event in chain [%p]", e->next);
|
||||||
|
fputc(j, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
putvars(Var *v)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
u16 *p;
|
||||||
|
u32 *q;
|
||||||
|
|
||||||
|
for(; v->a != nil; v++){
|
||||||
|
switch(v->s){
|
||||||
|
case 1:
|
||||||
|
fwrite(v->a, 1, v->n, fp);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
n = v->n;
|
||||||
|
p = v->a;
|
||||||
|
while(n--){
|
||||||
|
fputc(*p & 0xff, fp);
|
||||||
|
fputc(*p++ >> 8, fp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
n = v->n;
|
||||||
|
q = v->a;
|
||||||
|
while(n--){
|
||||||
|
fputc(*q, fp);
|
||||||
|
fputc(*q >> 8, fp);
|
||||||
|
fputc(*q >> 16, fp);
|
||||||
|
fputc(*q >> 24, fp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getvars(Var *v)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
u16 *p, w;
|
||||||
|
u32 *q, l;
|
||||||
|
|
||||||
|
for(; v->a != nil; v++){
|
||||||
|
switch(v->s){
|
||||||
|
case 1: fread(v->a, v->n, 1, fp); break;
|
||||||
|
case 2:
|
||||||
|
n = v->n;
|
||||||
|
p = v->a;
|
||||||
|
while(n--){
|
||||||
|
w = fgetc(fp);
|
||||||
|
w |= fgetc(fp) << 8;
|
||||||
|
*p++ = w;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
n = v->n;
|
||||||
|
q = v->a;
|
||||||
|
while(n--){
|
||||||
|
l |= fgetc(fp);
|
||||||
|
l |= fgetc(fp) << 8;
|
||||||
|
l |= fgetc(fp) << 16;
|
||||||
|
l |= fgetc(fp) << 24;
|
||||||
|
*q++ = l;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
savestate(const char *fname)
|
||||||
|
{
|
||||||
|
fp = fopen(fname, "w");
|
||||||
|
if(fp == 0){
|
||||||
|
error("Can't open '%s'", fname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
putvars(cpuvars);
|
||||||
|
putvars(ppuvars);
|
||||||
|
putvars(memvars);
|
||||||
|
putvars(evvars);
|
||||||
|
putevents();
|
||||||
|
mapper(SAVE, 0);
|
||||||
|
fclose(fp);
|
||||||
|
fp = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
getevents(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
Event *e;
|
||||||
|
|
||||||
|
i = fgetc(fp);
|
||||||
|
if(i > NEVENT){
|
||||||
|
error("Unkown event index [%d]", i);
|
||||||
|
elist = nil;
|
||||||
|
}
|
||||||
|
for(i = 0; i < NEVENT; ++i){
|
||||||
|
e = events[i];
|
||||||
|
e->time = fgetc(fp);
|
||||||
|
e->time |= fgetc(fp) << 8;
|
||||||
|
e->time |= fgetc(fp) << 16;
|
||||||
|
e->time |= fgetc(fp) << 24;
|
||||||
|
j = fgetc(fp);
|
||||||
|
if(j >= NEVENT){
|
||||||
|
error("Unkown event index [%d]", j);
|
||||||
|
e->next = nil;
|
||||||
|
}else{
|
||||||
|
e->next = events[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
loadstate(const char *fname)
|
||||||
|
{
|
||||||
|
fp = fopen(fname, "r");
|
||||||
|
if(fp == 0){
|
||||||
|
error("Can't load '%s'", fname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
getvars(cpuvars);
|
||||||
|
getvars(ppuvars);
|
||||||
|
getvars(memvars);
|
||||||
|
getvars(evvars);
|
||||||
|
getevents();
|
||||||
|
mapper(RSTR, 0);
|
||||||
|
fclose(fp);
|
||||||
|
fp = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user