From 838163670c27c9962f33f0cea680aba0f777dc59 Mon Sep 17 00:00:00 2001 From: aiju Date: Sun, 15 Jun 2014 15:52:29 +0200 Subject: [PATCH] games/md: add save game support, fix cpu bug --- sys/src/games/md/cpu.c | 6 ++--- sys/src/games/md/dat.h | 14 ++++++++++ sys/src/games/md/md.c | 58 +++++++++++++++++++++++++++++++++++++++++- sys/src/games/md/mem.c | 36 ++++++++++++++++++++++++-- 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: