shithub: riscv

Download patch

ref: 838163670c27c9962f33f0cea680aba0f777dc59
parent: e30fc1fbdf2eaac19eac54e9e656c0db7fc5a108
author: aiju <devnull@localhost>
date: Sun Jun 15 11:52:29 EDT 2014

games/md: add save game support, fix cpu bug

--- a/sys/src/games/md/cpu.c
+++ b/sys/src/games/md/cpu.c
@@ -509,7 +509,7 @@
 	int n, m, d;
 	static int cnt;
 
-	if(0 && pc == 0x23000000){
+	if(0 && pc == 0x59500){
 		trace++;
 		print("%x\n", curpc);
 	}
@@ -552,7 +552,7 @@
 			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 @@
 			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 */
--- a/sys/src/games/md/dat.h
+++ b/sys/src/games/md/dat.h
@@ -14,6 +14,9 @@
 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 @@
 	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,
 };
--- a/sys/src/games/md/md.c
+++ b/sys/src/games/md/md.c
@@ -11,10 +11,13 @@
 
 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 @@
 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 @@
 		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
@@ -194,6 +243,13 @@
 		while(ymclock >= YMDIV){
 			ymstep();
 			ymclock -= YMDIV;
+		}
+		if(saveclock > 0){
+			saveclock -= t;
+			if(saveclock <= 0){
+				saveclock = 0;
+				flushram();
+			}
 		}
 	}
 }
--- a/sys/src/games/md/mem.c
+++ b/sys/src/games/md/mem.c
@@ -37,7 +37,7 @@
 		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 @@
 		}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 @@
 	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 @@
 	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: