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:
parent
e1d5ab153e
commit
434a367daf
1 changed files with 42 additions and 14 deletions
56
sim_tape.c
56
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue