commit - 5e4364907c5751cad3217f76d1cebf1ba2a1154b
commit + 099e4c576c83e653f3220c05a8a471417a4de660
blob - f142c392765c47cc9b0a063b4f08d8643fb03fa0
blob + 966431d7270ad444dff4709625e9d61ac3c004d8
--- hackem.c
+++ hackem.c
struct tape {
struct device dev;
FILE *stream;
+ long busy;
};
/* I/O update routines */
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 */
/* 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);
// 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.
*
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
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);
}
}