summaryrefslogtreecommitdiff
path: root/sys/src/games
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2014-06-15 15:52:29 +0200
committeraiju <devnull@localhost>2014-06-15 15:52:29 +0200
commit838163670c27c9962f33f0cea680aba0f777dc59 (patch)
tree5222345c1ef9c43bed812a27c1922279c42bb20a /sys/src/games
parente30fc1fbdf2eaac19eac54e9e656c0db7fc5a108 (diff)
games/md: add save game support, fix cpu bug
Diffstat (limited to 'sys/src/games')
-rw-r--r--sys/src/games/md/cpu.c6
-rw-r--r--sys/src/games/md/dat.h14
-rw-r--r--sys/src/games/md/md.c58
-rw-r--r--sys/src/games/md/mem.c36
4 files changed, 108 insertions, 6 deletions
diff --git a/sys/src/games/md/cpu.c b/sys/src/games/md/cpu.c
index fd05c980b..3a097a5ff 100644
--- a/sys/src/games/md/cpu.c
+++ b/sys/src/games/md/cpu.c
@@ -509,7 +509,7 @@ step(void)
int n, m, d;
static int cnt;
- if(0 && pc == 0x23000000){
+ if(0 && pc == 0x59500){
trace++;
print("%x\n", curpc);
}
@@ -552,7 +552,7 @@ step(void)
tim += 20;
break;
}
- if((op & 0x13f) == 0x108){ /* MOVEP */
+ if((op & 0x138) == 0x108){ /* MOVEP */
a = ra[op & 7] + (s16int)fetch16();
switch(s){
case 0:
@@ -829,7 +829,7 @@ step(void)
v = op >> 4 & 0xf;
n = op & 7;
if(v == 4){ /* TRAP */
- trap(op & 0xf, curpc);
+ trap(0x20 | op & 0xf, pc);
break;
}else if(v == 5){
if((op & 8) == 0){ /* LINK */
diff --git a/sys/src/games/md/dat.h b/sys/src/games/md/dat.h
index 33467024e..2fa68a530 100644
--- a/sys/src/games/md/dat.h
+++ b/sys/src/games/md/dat.h
@@ -14,6 +14,9 @@ extern u16int spc, scurpc;
extern u16int ram[32768];
extern u16int *prg;
extern int nprg;
+extern u8int *sram;
+extern u32int sramctl, sram0, sram1;
+extern int savefd, saveclock;
extern int keys, scale;
@@ -77,6 +80,17 @@ enum {
Z80DIV = 15,
RATE = 44100,
SAMPDIV = FREQ / RATE,
+ SAVEFREQ = FREQ / 4,
MILLION = 1000 * 1000,
BILLION = 1000 * 1000 * 1000,
};
+
+enum {
+ SRAM = 0x01,
+ BATTERY = 0x02,
+ ADDRMASK = 0x0c,
+ ADDRBOTH = 0x00,
+ ADDREVEN = 0x08,
+ ADDRODD = 0x0c,
+ SRAMEN = 0x10,
+};
diff --git a/sys/src/games/md/md.c b/sys/src/games/md/md.c
index 12d95dcd9..0a53e414c 100644
--- a/sys/src/games/md/md.c
+++ b/sys/src/games/md/md.c
@@ -11,10 +11,13 @@ int debug;
u16int *prg;
int nprg;
+u8int *sram;
+u32int sramctl, nsram, sram0, sram1;
+int savefd = -1;
int keys;
-int dmaclock, vdpclock, z80clock, audioclock, ymclock;
+int dmaclock, vdpclock, z80clock, audioclock, ymclock, saveclock;
int scale, paused;
QLock pauselock;
@@ -23,6 +26,30 @@ Rectangle picr;
Image *tmp, *bg;
void
+flushram(void)
+{
+ if(savefd >= 0)
+ pwrite(savefd, sram, nsram, 0);
+ saveclock = 0;
+}
+
+static void
+loadbat(char *file)
+{
+ static char buf[512];
+
+ strncpy(buf, file, sizeof buf - 5);
+ strcat(buf, ".sav");
+ savefd = create(buf, ORDWR | OEXCL, 0666);
+ if(savefd < 0)
+ savefd = open(buf, ORDWR);
+ if(savefd < 0)
+ print("open: %r\n");
+ else
+ readn(savefd, sram, nsram);
+}
+
+static void
loadrom(char *file)
{
static uchar hdr[512], buf[4096];
@@ -61,6 +88,28 @@ loadrom(char *file)
v -= rc;
}
close(fd);
+ if(hdr[0x1b0] == 0x52 && hdr[0x1b1] == 0x41){
+ sramctl = SRAM | hdr[0x1b2] >> 1 & ADDRMASK;
+ if((hdr[0x1b2] & 0x40) != 0)
+ sramctl |= BATTERY;
+ sram0 = hdr[0x1b4] << 24 | hdr[0x1b5] << 16 | hdr[0x1b6] << 8 | hdr[0x1b7] & 0xfe;
+ sram1 = hdr[0x1b8] << 24 | hdr[0x1b9] << 16 | hdr[0x1ba] << 8 | hdr[0x1bb] | 1;
+ if(sram1 <= sram0){
+ print("SRAM of size <= 0?\n");
+ sramctl = 0;
+ }else{
+ nsram = sram1 - sram0;
+ if((sramctl & ADDRMASK) != ADDRBOTH)
+ nsram >>= 1;
+ sram = malloc(nsram);
+ if(sram == nil)
+ sysfatal("malloc: %r");
+ if((sramctl & BATTERY) != 0){
+ loadbat(file);
+ atexit(flushram);
+ }
+ }
+ }
}
void
@@ -195,6 +244,13 @@ threadmain(int argc, char **argv)
ymstep();
ymclock -= YMDIV;
}
+ if(saveclock > 0){
+ saveclock -= t;
+ if(saveclock <= 0){
+ saveclock = 0;
+ flushram();
+ }
+ }
}
}
diff --git a/sys/src/games/md/mem.c b/sys/src/games/md/mem.c
index a1474934e..48139101c 100644
--- a/sys/src/games/md/mem.c
+++ b/sys/src/games/md/mem.c
@@ -37,7 +37,7 @@ regread(u16int a)
return ctl[0] & 0xc0 | v & 0x3f;
case 0x0005:
case 0x0007:
- return ctl[1] & 0xc0 | 0x3f;
+ return ctl[a-3>>1] & 0xc0 | 0x3f;
case 0x0009: case 0x000b: case 0x000d:
return ctl[a-3>>1];
case 0x1101:
@@ -65,6 +65,14 @@ regwrite(u16int a, u16int v)
}else
z80bus &= ~RESET;
return;
+ case 0x30f1:
+ if((v & 1) != 0)
+ sramctl |= SRAMEN;
+ else
+ sramctl &= ~SRAMEN;
+ return;
+ case 0x30f3: case 0x30f5: case 0x30f7: case 0x30f9: case 0x30fb:
+ return;
}
sysfatal("write to 0xa1%.4x (pc=%#.6ux)", a, curpc);
}
@@ -112,7 +120,14 @@ memread(u32int a)
u16int v;
switch(a >> 21 & 7){
- case 0: case 1: return prg[(a % nprg) / 2];
+ case 0: case 1:
+ if((sramctl & SRAMEN) != 0 && a >= sram0 && a <= sram1)
+ switch(sramctl & ADDRMASK){
+ case ADDREVEN: return sram[(a - sram0) >> 1] << 8;
+ case ADDRODD: return sram[(a - sram0) >> 1];
+ case ADDRBOTH: return sram[a - sram0] << 8 | sram[a - sram0 + 1];
+ }
+ return prg[(a % nprg) / 2];
case 5:
switch(a >> 16 & 0xff){
case 0xa0:
@@ -186,6 +201,23 @@ memwrite(u32int a, u16int v, u16int m)
if(0 && (a & 0xe0fffe) == 0xe0df46)
print("%x %x %x\n", curpc, v, m);
switch((a >> 21) & 7){
+ case 0: case 1:
+ if((sramctl & SRAMEN) != 0 && a >= sram0 && a <= sram1){
+ switch(sramctl & ADDRMASK){
+ case ADDREVEN: sram[(a - sram0) >> 1] = v >> 8; break;
+ case ADDRODD: sram[(a - sram0) >> 1] = v; break;
+ case ADDRBOTH:
+ if((m & 0xff00) == 0xff00)
+ sram[a - sram0] = v >> 8;
+ if((m & 0xff) == 0xff)
+ sram[a + 1 - sram0] = v;
+ break;
+ }
+ if(saveclock == 0)
+ saveclock = SAVEFREQ;
+ return;
+ }
+ goto invalid;
case 5:
switch(a >> 16 & 0xff){
case 0xa0: