diff --git a/README.md b/README.md index b03c5576..1b22e1ac 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,7 @@ Host platforms which have libSDL available can leverage this functionality. #### Tape Extensions AWS format tape support + TAR format tape support #### Embedded ROM support Simulators which have boot commands which load constant files as part of diff --git a/doc/simh_doc.doc b/doc/simh_doc.doc index 5fc390a6..611dca55 100644 Binary files a/doc/simh_doc.doc and b/doc/simh_doc.doc differ diff --git a/scp.c b/scp.c index 67296e67..09d5d96d 100644 --- a/scp.c +++ b/scp.c @@ -7280,6 +7280,7 @@ for (i = 0; i < (device_count + sim_internal_device_count); i++) {/* loop thru d WRITE_I (uptr->dynflags); WRITE_I (uptr->wait); WRITE_I (uptr->buf); + WRITE_I (uptr->recsize); WRITE_I (uptr->capac); /* [V3.5] capacity */ fprintf (sfile, "%.0f\n", uptr->usecs_remaining);/* [V4.0] remaining wait */ WRITE_I (uptr->pos); @@ -7530,6 +7531,7 @@ for ( ;; ) { /* device loop */ READ_I (uptr->dynflags); READ_I (uptr->wait); READ_I (uptr->buf); + READ_I (uptr->recsize); } old_capac = uptr->capac; /* save current capacity */ if (v35) { /* [V3.5+] capacity */ diff --git a/sim_defs.h b/sim_defs.h index ce77bf74..f6e085d4 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -591,6 +591,7 @@ struct UNIT { uint16 us9; /* device specific */ uint16 us10; /* device specific */ void *tmxr; /* TMXR linkage */ + uint32 recsize; /* Tape info */ t_bool (*cancel)(UNIT *); double usecs_remaining; /* time balance for long delays */ char *uname; /* Unit name */ diff --git a/sim_tape.c b/sim_tape.c index 77a6899a..5c1253ee 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -113,7 +113,7 @@ static struct sim_tape_fmt fmts[MTUF_N_FMT] = { { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1, sizeof (t_tpclnt) }, { "P7B", 0, 0, 0 }, { "AWS", 0, 0, 0 }, -/* { "TPF", UNIT_RO, 0 }, */ + { "TAR", 0, 0, 0 }, { NULL, 0, 0 } }; @@ -479,14 +479,31 @@ if ((dptr = find_dev_from_unit (uptr)) == NULL) if (sim_switches & SWMASK ('F')) { /* format spec? */ cptr = get_glyph (cptr, gbuf, 0); /* get spec */ if (*cptr == 0) /* must be more */ - return SCPE_2FARG; + return sim_messagef (SCPE_2FARG, "Missing Format specifier and filename to attach\n"); if (sim_tape_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK) return sim_messagef (SCPE_ARG, "Invalid Tape Format: %s\n", gbuf); sim_switches = sim_switches & ~(SWMASK ('F')); /* Record Format specifier already processed */ auto_format = TRUE; } -if (MT_GET_FMT (uptr) == MTUF_F_TPC) - sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC tapes */ +if (MT_GET_FMT (uptr) == MTUF_F_TAR) { + if (sim_switches & SWMASK ('B')) { /* Record Size (blocking factor)? */ + uint32 recsize; + + cptr = get_glyph (cptr, gbuf, 0); /* get spec */ + if (*cptr == 0) /* must be more */ + return sim_messagef (SCPE_2FARG, "Missing Record Size and filename to attach\n"); + recsize = (uint32) get_uint (gbuf, 10, 65536, &r); + if ((r != SCPE_OK) || (recsize == 0)) + return sim_messagef (SCPE_ARG, "Invalid Tape Record Size: %s\n", gbuf); + uptr->recsize = recsize; + sim_switches = sim_switches & ~(SWMASK ('B')); /* Record Blocking Factor */ + } + if (uptr->recsize == 0) + uptr->recsize = TAR_DFLT_RECSIZE; + } +if ((MT_GET_FMT (uptr) == MTUF_F_TPC) || + (MT_GET_FMT (uptr) == MTUF_F_TAR)) + sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC and TAR tapes */ r = attach_unit (uptr, (CONST char *)cptr); /* attach unit */ if (r != SCPE_OK) /* error? */ return sim_messagef (r, "Can't open tape image: %s\n", cptr); @@ -522,6 +539,10 @@ switch (MT_GET_FMT (uptr)) { /* case on format */ sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf, objc);/* fill map */ break; + case MTUF_F_TAR: /* TAR */ + uptr->hwmark = (t_addr)sim_fsize (uptr->fileref); + break; + default: break; } @@ -568,7 +589,7 @@ if (ctx) sim_tape_clr_async (uptr); -MT_CLR_INMRK (uptr); /* Not within an AWS tapemark */ +MT_CLR_INMRK (uptr); /* Not within an AWS or TAR tapemark */ r = detach_unit (uptr); /* detach unit */ if (r != SCPE_OK) return r; @@ -578,12 +599,13 @@ switch (f) { /* case on format */ if (uptr->filebuf) /* free map */ free (uptr->filebuf); uptr->filebuf = NULL; - uptr->hwmark = 0; break; default: break; } +uptr->hwmark = 0; +uptr->recsize = 0; sim_tape_rewind (uptr); free (uptr->tape_ctx); @@ -615,7 +637,11 @@ fprintf (st, " -R Attach Read Only.\n"); fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n"); fprintf (st, " virtual tape will be attempted).\n"); fprintf (st, " -F Open the indicated tape container in a specific format (default\n"); -fprintf (st, " is SIMH, alternatives are E11, TPC and P7B)\n"); +fprintf (st, " is SIMH, alternatives are E11, TPC, P7B, AWS and TAR)\n"); +fprintf (st, " -B For TAR format tapes, the record size for data read from the\n"); +fprintf (st, " specified file. This record size will be used for all but\n"); +fprintf (st, " possibly the last record which will be what remains unread.\n"); +fprintf (st, " The default TAR record size is 10240.\n"); fprintf (st, " -V Display some summary information about the record structure\n"); fprintf (st, " contained in the tape structure.\n"); fprintf (st, " -D Causes the internal tape structure information to be displayed\n"); @@ -738,6 +764,7 @@ int32 runaway_counter, sizeof_gap; /* bytes remaining befor t_stat status = MTSE_OK; MT_CLR_PNU (uptr); /* clear the position-not-updated flag */ +*bc = 0; if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */ return MTSE_UNATT; /* then quit with an error */ @@ -955,7 +982,6 @@ else switch (f) { /* otherwise the read me MT_CLR_INMRK (uptr); /* Not within an AWS tapemark */ memset (&awshdr, 0, sizeof (awshdr)); rdcnt = sim_fread (&awshdr, sizeof (t_awslnt), 3, uptr->fileref); - *bc = 0; if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); /* pos not upd */ @@ -999,6 +1025,26 @@ else switch (f) { /* otherwise the read me } break; + case MTUF_F_TAR: + if (uptr->pos < uptr->hwmark) { + if ((uptr->hwmark - uptr->pos) >= uptr->recsize) + *bc = uptr->recsize; /* TAR record size */ + else + *bc = uptr->hwmark - uptr->pos; /* TAR remnant last record */ + (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); + uptr->pos += *bc; + MT_CLR_INMRK (uptr); + } + else { + if (MT_TST_INMRK (uptr)) + status = MTSE_EOM; + else { + status = MTSE_TMK; + MT_SET_INMRK (uptr); + } + } + break; + default: status = MTSE_FMT; } @@ -1075,6 +1121,7 @@ int32 runaway_counter, sizeof_gap; /* bytes remaining befor t_stat status = MTSE_OK; MT_CLR_PNU (uptr); /* clear the position-not-updated flag */ +*bc = 0; if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */ return MTSE_UNATT; /* then quit with an error */ @@ -1297,7 +1344,28 @@ else switch (f) { /* otherwise the read me } break; - default: + case MTUF_F_TAR: + if (uptr->pos == uptr->hwmark) { + if (MT_TST_INMRK (uptr)) { + status = MTSE_TMK; + MT_CLR_INMRK (uptr); + } + else { + if (uptr->hwmark % uptr->recsize) + *bc = uptr->hwmark % uptr->recsize; + else + *bc = uptr->recsize; + } + } + else + *bc = uptr->recsize; + if (*bc) { + uptr->pos -= *bc; + (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); + } + break; + + default: status = MTSE_FMT; } @@ -2585,6 +2653,7 @@ if (uptr->flags & UNIT_ATT) { } uptr->pos = 0; MT_CLR_PNU (uptr); +MT_CLR_INMRK (uptr); /* Not within an AWS or TAR tapemark */ return MTSE_OK; } @@ -3198,6 +3267,8 @@ FILE *fE11 = NULL; FILE *fTPC = NULL; FILE *fP7B = NULL; FILE *fAWS = NULL; +FILE *fTAR = NULL; +FILE *fTAR2 = NULL; int i, j, k; t_tpclnt tpclnt; t_mtrlnt mtrlnt; @@ -3245,6 +3316,14 @@ sprintf (name, "%s.p7b", filename); fP7B = fopen (name, "wb"); if (fP7B == NULL) goto Done_Files; +sprintf (name, "%s.tar", filename); +fTAR = fopen (name, "wb"); +if (fTAR == NULL) + goto Done_Files; +sprintf (name, "%s.2.tar", filename); +fTAR2 = fopen (name, "wb"); +if (fTAR2 == NULL) + goto Done_Files; sprintf (name, "%s.aws", filename); fAWS = fopen (name, "wb"); if (fAWS == NULL) @@ -3323,6 +3402,13 @@ tpclnt = 0xffff; (void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11); (void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC); (void)sim_fwrite (buf, 1, 1, fP7B); +for (j=0; junits, "TapeTestFile1")); SIM_TEST(sim_tape_test_create_tape_files (dptr->units, "TapeTestFile1", 2, 5, 4096)); +sim_switches = saved_switches; +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "tar")); + +sim_switches = saved_switches; +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1.2", "tar")); + sim_switches = saved_switches; SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "aws")); diff --git a/sim_tape.h b/sim_tape.h index 37be7242..8a676c1a 100644 --- a/sim_tape.h +++ b/sim_tape.h @@ -85,6 +85,9 @@ typedef struct { #define AWS_REC 0x00A0 } t_awshdr; +/* TAR tape format */ +#define TAR_DFLT_RECSIZE 10240 /* Default Fixed record size */ + /* Unit flags */ #define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */ @@ -98,6 +101,7 @@ typedef struct { #define MTUF_F_TPC 2 /* TPC format */ #define MTUF_F_P7B 3 /* P7B format */ #define MTUF_F_AWS 4 /* AWS format */ +#define MTUF_F_TAR 5 /* TAR format */ #define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT) #define MTUF_PNU (1u << MTUF_V_PNU) #define MTUF_WLK (1u << MTUF_V_WLK) @@ -109,6 +113,7 @@ typedef struct { #define MT_F_TPC (MTUF_F_TPC << MTUF_V_FMT) #define MT_F_P7B (MTUF_F_P7B << MTUF_V_FMT) #define MT_F_AWS (MTUF_F_AWS << MTUF_V_FMT) +#define MT_F_TAR (MTUF_F_TAR << MTUF_V_FMT) #define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU #define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU