TAPE: Add tolerance when handling TPC formatted tapes which may have garbage at EOT.

If a TPC format tape image has garbage at the end of the image, but the
image contains multiple successive tape marks, then assume that logical
End Of Tape is immediately after the last successive tape marks.
This commit is contained in:
Mark Pizzolato 2016-01-04 14:55:03 -08:00
parent e1d5ab153e
commit 434a367daf

View file

@ -124,7 +124,7 @@ static const uint32 bpi [] = { /* tape density table, i
static t_stat sim_tape_ioerr (UNIT *uptr);
static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat);
static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map);
static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize);
static t_stat sim_tape_simh_check (UNIT *uptr);
static t_stat sim_tape_e11_check (UNIT *uptr);
static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map);
@ -133,7 +133,7 @@ static void sim_tape_data_trace (UNIT *uptr, const uint8 *data, size_t len, cons
struct tape_context {
DEVICE *dptr; /* Device for unit (access to debug flags) */
uint32 dbit; /* debugging bit */
uint32 dbit; /* debugging bit for trace */
uint32 auto_format; /* Format determined dynamically */
#if defined SIM_ASYNCH_IO
int asynch_io; /* Asynchronous Interrupt scheduling enabled */
@ -485,7 +485,7 @@ switch (MT_GET_FMT (uptr)) { /* case on format */
break;
case MTUF_F_TPC: /* TPC */
objc = sim_tape_tpc_map (uptr, NULL); /* get # objects */
objc = sim_tape_tpc_map (uptr, NULL, 0); /* get # objects */
if (objc == 0) { /* tape empty? */
sim_tape_detach (uptr);
return SCPE_FMT; /* yes, complain */
@ -496,7 +496,7 @@ switch (MT_GET_FMT (uptr)) { /* case on format */
return SCPE_MEM; /* no, complain */
}
uptr->hwmark = objc + 1; /* save map size */
sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf); /* fill map */
sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf, objc);/* fill map */
break;
default:
@ -2142,20 +2142,22 @@ return SCPE_OK;
/* Map a TPC format tape image */
static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map)
static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize)
{
t_addr tpos;
t_addr tpos, leot;
t_addr tape_size;
t_tpclnt bc, last_bc;
t_bool had_double_tape_mark = FALSE;
uint32 had_double_tape_mark = 0;
size_t i;
uint32 objc, sizec;
uint32 *countmap = NULL;
uint8 *recbuf = NULL;
DEVICE *dptr = find_dev_from_unit (uptr);
if ((uptr == NULL) || (uptr->fileref == NULL))
return 0;
countmap = calloc (65536, sizeof(*countmap));
recbuf = malloc (65536);
tape_size = (t_addr)sim_fsize (uptr->fileref);
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape_size: %" T_ADDR_FMT "u\n", tape_size);
for (objc = 0, sizec = 0, tpos = 0;; ) {
@ -2166,19 +2168,38 @@ for (objc = 0, sizec = 0, tpos = 0;; ) {
if (countmap[bc] == 0)
sizec++;
++countmap[bc];
if (map)
if (map && (objc < mapsize))
map[objc] = tpos;
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: %d byte count at pos: %" T_ADDR_FMT "u\n", bc, tpos);
if (bc) {
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: %d byte count at pos: %" T_ADDR_FMT "u\n", bc, tpos);
if (sim_deb && (dptr->dctrl & MTSE_DBG_STR)) {
sim_fread (recbuf, 1, bc, uptr->fileref);
sim_data_trace(dptr, uptr, ((dptr->dctrl & MTSE_DBG_DAT) ? recbuf : NULL), "", bc, "Data Record", MTSE_DBG_STR);
}
}
else
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape mark at pos: %" T_ADDR_FMT "u\n", tpos);
objc++;
tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt);
if ((bc == 0) && (last_bc == 0)) /* double tape mark? */
had_double_tape_mark |= TRUE;
if ((bc == 0) && (last_bc == 0)) { /* double tape mark? */
had_double_tape_mark = objc;
leot = tpos;
}
last_bc = bc;
}
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: objc: %d, sizec: %d\n", objc, sizec);
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: objc: %u, different record sizes: %u\n", objc, sizec);
for (i=0; i<65535; i++) {
if (countmap[i]) {
if (i == 0)
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u tape marks\n", countmap[i]);
else
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u %d byte record%s\n", countmap[i], (int)i, (countmap[i] > 1) ? "s" : "");
}
}
if (((last_bc != 0xffff) &&
(tpos > tape_size)) ||
(!had_double_tape_mark) ||
(tpos > tape_size) &&
(!had_double_tape_mark)) ||
(!had_double_tape_mark) ||
((objc == countmap[0]) &&
(countmap[0] != 2))) { /* Unreasonable format? */
if (last_bc != 0xffff)
@ -2188,13 +2209,20 @@ if (((last_bc != 0xffff) &&
if (objc == countmap[0])
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR tape cnly contains tape marks\n");
free (countmap);
free (recbuf);
return 0;
}
if ((last_bc != 0xffff) && (tpos > tape_size)) {
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: WARNING unexpected EOT byte count: %d, double tape mark before %" T_ADDR_FMT "u provides logical EOT\n", last_bc, leot);
objc = had_double_tape_mark;
tpos = leot;
}
if (map)
map[objc] = tpos;
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: OK objc: %d\n", objc);
free (countmap);
free (recbuf);
return objc;
}