Commit Diff


commit - 5e4364907c5751cad3217f76d1cebf1ba2a1154b
commit + 099e4c576c83e653f3220c05a8a471417a4de660
blob - f142c392765c47cc9b0a063b4f08d8643fb03fa0
blob + 966431d7270ad444dff4709625e9d61ac3c004d8
--- hackem.c
+++ hackem.c
@@ -26,6 +26,7 @@ struct device {
 struct tape {
 	struct device dev;
 	FILE *stream;
+	long busy;
 };
 
 /* I/O update routines */
@@ -34,12 +35,13 @@ void r_itape(struct device *, uint16_t *, uint16_t);
 void w_itape(struct device *, uint16_t *, uint16_t);
 void r_otape(struct device *, uint16_t *, uint16_t);
 void w_otape(struct device *, uint16_t *, uint16_t);
+void t_tape(struct device *, uint16_t *);
 
 /* device structures */
 struct device dev_dummy	= {NULL, w_dummy};	/* writes are no-ops */
-struct tape dev_itape	= {{r_itape, w_itape}, stdin};
-struct tape dev_otape	= {{r_otape, w_otape}, stdout};
-struct tape dev_printer	= {{r_otape, w_otape}, stderr};
+struct tape dev_itape	= {{r_itape, w_itape, t_tape}, stdin};
+struct tape dev_otape	= {{r_otape, w_otape, t_tape}, stdout};
+struct tape dev_printer	= {{r_otape, w_otape, t_tape}, stderr};
 
 /* instruction and data memories */
 uint16_t ram[32 * 1024];			/* includes I/O space */
@@ -331,6 +333,10 @@ main(int argc, char *argv[])
 
 	/* print header line to trace file, if applicable */
 	tracehdr();
+
+	/* disable stdout buffering unless running at max speed */
+	if (sfactor > 0.0)
+		setbuf(stdout, NULL);
 
 	/* compute the desired duration of one clock tick */
 	dur.tv_nsec = 1000000000L * modf(sfactor / cpufreq, &d);
@@ -423,7 +429,16 @@ w_itape(struct device *dev, uint16_t *mem, uint16_t of
 	// XXX input tape advance/seek
 }
 
+void
+t_tape(struct device *dev, uint16_t *mem)
+{
+	struct tape *tp = (struct tape *)dev;
 
+	if (tp->busy > 0)
+		tp->busy--;
+}
+
+
 /*
  * The tape punch provides two addresses.
  *
@@ -447,13 +462,24 @@ w_itape(struct device *dev, uint16_t *mem, uint16_t of
 void
 r_otape(struct device *dev, uint16_t *mem, uint16_t offset)
 {
+	struct tape *tp = (struct tape *)dev;
+	uint16_t w = 0;
+
 	if (offset & 1) {			/* offset 1 */
 		/* bit 15: tape position */
+		if (!tp->busy)
+			w |= 0x8000u;
+
 		/* bit 14: tape presence */
-		mem[offset] = 0x8000;
+		if (feof(tp->stream))
+			w |= 0x4000u;
 	} else {				/* offset 0 */
 		/* bit 15: tape presence */
+		if (feof(tp->stream))
+			w |= 0x8000u;
 	}
+
+	mem[offset] = w;
 }
 
 void
@@ -463,9 +489,16 @@ w_otape(struct device *dev, uint16_t *mem, uint16_t of
 
 	if (offset & 1) {			/* offset 1 */
 		/* no effect */
-		return;
 	} else {				/* offset 0 */
-		// XXX no/ill effect if tape not ready
+		/* no effect if tape not ready */
+		if (tp->busy)
+			return;
+
+		/* NB: no effect if stream at EOF */
 		fputc((unsigned char) mem[offset], tp->stream);
+
+		/* set tape busy for 150 ms */
+		tp->busy = cpufreq * 150 / 1000;
+		assert(tp->busy >= 0);
 	}
 }