From 434a367daf11f22163e65a9c27d12f82fdd033ef Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 4 Jan 2016 14:55:03 -0800 Subject: [PATCH] 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. --- sim_tape.c | 56 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/sim_tape.c b/sim_tape.c index b347d7b8..6728971b 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -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; }