TAPE: Add ability to copy a tape to a SIMH format tape image
This is an implicit tape conversion tool from any supported format to SIMH format.
This commit is contained in:
parent
dd715e609e
commit
e49617cd0c
1 changed files with 81 additions and 22 deletions
103
sim_tape.c
103
sim_tape.c
|
@ -515,6 +515,7 @@ static void sim_tape_add_ansi_entry (const char *directory,
|
||||||
const struct stat *filestat,
|
const struct stat *filestat,
|
||||||
void *context);
|
void *context);
|
||||||
static t_bool ansi_tape_add_block (ANSI_TAPE *tape, uint8 *block, uint32 size);
|
static t_bool ansi_tape_add_block (ANSI_TAPE *tape, uint8 *block, uint32 size);
|
||||||
|
static t_stat sim_export_tape (UNIT *uptr, const char *export_file);
|
||||||
|
|
||||||
|
|
||||||
/* Enable asynchronous operation */
|
/* Enable asynchronous operation */
|
||||||
|
@ -610,6 +611,7 @@ struct tape_context *ctx;
|
||||||
uint32 objc;
|
uint32 objc;
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
|
char export_file[CBUFSIZE] = "";
|
||||||
uint32 recsize = 0;
|
uint32 recsize = 0;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
t_bool auto_format = FALSE;
|
t_bool auto_format = FALSE;
|
||||||
|
@ -646,6 +648,8 @@ if ((MT_GET_FMT (uptr) == MTUF_F_TPC) ||
|
||||||
(MT_GET_FMT (uptr) == MTUF_F_TAR) ||
|
(MT_GET_FMT (uptr) == MTUF_F_TAR) ||
|
||||||
(MT_GET_FMT (uptr) == MTUF_F_ANSI))
|
(MT_GET_FMT (uptr) == MTUF_F_ANSI))
|
||||||
sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC, TAR and ANSI tapes */
|
sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC, TAR and ANSI tapes */
|
||||||
|
if (sim_switches & SWMASK ('X'))
|
||||||
|
cptr = get_glyph_nc (cptr, export_file, 0); /* get export file spec */
|
||||||
if (MT_GET_FMT (uptr) == MTUF_F_ANSI) {
|
if (MT_GET_FMT (uptr) == MTUF_F_ANSI) {
|
||||||
const char *ocptr = cptr;
|
const char *ocptr = cptr;
|
||||||
char label[CBUFSIZE] = "simh";
|
char label[CBUFSIZE] = "simh";
|
||||||
|
@ -667,15 +671,15 @@ if (MT_GET_FMT (uptr) == MTUF_F_ANSI) {
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
while (*cptr != 0) { /* do all mods */
|
while (*cptr != 0) { /* do all mods */
|
||||||
cptr = get_glyph_nc (cptr, gbuf, ','); /* get filename */
|
cptr = get_glyph_nc (cptr, gbuf, ','); /* get filename */
|
||||||
sim_dir_scan (gbuf, sim_tape_add_ansi_entry, uptr->fileref);
|
sim_dir_scan (gbuf, sim_tape_add_ansi_entry, tape);
|
||||||
}
|
}
|
||||||
if (((ANSI_TAPE *)uptr->fileref)->file_count > 0) {
|
if (tape->file_count > 0) {
|
||||||
r = SCPE_OK;
|
r = SCPE_OK;
|
||||||
ansi_tape_add_block ((ANSI_TAPE *)uptr->fileref, NULL, 0); /* Tape Mark */
|
ansi_tape_add_block (tape, NULL, 0); /* Tape Mark */
|
||||||
uptr->flags |= UNIT_ATT;
|
uptr->flags |= UNIT_ATT;
|
||||||
uptr->filename = (char *)malloc (strlen (ocptr) + 1);
|
uptr->filename = (char *)malloc (strlen (ocptr) + 1);
|
||||||
strcpy (uptr->filename, ocptr);
|
strcpy (uptr->filename, ocptr);
|
||||||
uptr->tape_eom = ((ANSI_TAPE *)uptr->fileref)->record_count;
|
uptr->tape_eom = tape->record_count;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = SCPE_ARG;
|
r = SCPE_ARG;
|
||||||
|
@ -743,6 +747,8 @@ if ((sim_switches & SWMASK ('D')) && !had_debug)
|
||||||
sim_set_deboff (0, "");
|
sim_set_deboff (0, "");
|
||||||
if (sim_switches & SWMASK ('D'))
|
if (sim_switches & SWMASK ('D'))
|
||||||
uptr->dctrl = starting_dctrl;
|
uptr->dctrl = starting_dctrl;
|
||||||
|
if ((r == SCPE_OK) && (sim_switches & SWMASK ('X')))
|
||||||
|
r = sim_export_tape (uptr, export_file);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,16 +844,18 @@ fprintf (st, " -L Display detailed record size counts observed durin
|
||||||
fprintf (st, " validation pass\n");
|
fprintf (st, " validation pass\n");
|
||||||
fprintf (st, " contained in the tape image scan performed when it is attached.\n");
|
fprintf (st, " contained in the tape image scan performed when it is attached.\n");
|
||||||
fprintf (st, " -D Causes the internal tape structure information to be displayed\n");
|
fprintf (st, " -D Causes the internal tape structure information to be displayed\n");
|
||||||
fprintf (st, " while the tape image is scanned.\n\n");
|
fprintf (st, " while the tape image is scanned.\n");
|
||||||
|
fprintf (st, " -X Extract a copy of the attached tape and convert it to a SIMH\n");
|
||||||
|
fprintf (st, " format tape image.\n\n");
|
||||||
fprintf (st, "Notes: ANSI-VMS, ANSI-RT11, ANSI-RSTS, ANSI-RSX11 formats allows one or several\n");
|
fprintf (st, "Notes: ANSI-VMS, ANSI-RT11, ANSI-RSTS, ANSI-RSX11 formats allows one or several\n");
|
||||||
fprintf (st, " files to be presented to as a read only ANSI Level 3 labeled tape with\n");
|
fprintf (st, " files to be presented to as a read only ANSI Level 3 labeled tape with\n");
|
||||||
fprintf (st, " file labels that make each individual file accessible directly as files\n");
|
fprintf (st, " file labels that make each individual file accessible directly as files\n");
|
||||||
fprintf (st, " on the tape.\n\n");
|
fprintf (st, " on the tape.\n\n");
|
||||||
fprintf (st, "Examples:\n\n");
|
fprintf (st, "Examples:\n\n");
|
||||||
fprintf (st, " sim> ATTACH -F %s ANSI-VMS Hobbyist-USE-ONLY-VA.TXT\n\n", dptr->name);
|
fprintf (st, " sim> ATTACH %s -F ANSI-VMS Hobbyist-USE-ONLY-VA.TXT\n", dptr->name);
|
||||||
fprintf (st, " sim> ATTACH -F %s ANSI-RSX11 *.TXT,*.ini,*.exe\n", dptr->name);
|
fprintf (st, " sim> ATTACH %s -F ANSI-RSX11 *.TXT,*.ini,*.exe\n", dptr->name);
|
||||||
fprintf (st, " sim> ATTACH -F %s ANSI-RSTS *.TXT,*.SAV\n", dptr->name);
|
fprintf (st, " sim> ATTACH %s -FX ANSI-RSTS RSTS.tap *.TXT,*.SAV\n", dptr->name);
|
||||||
fprintf (st, " sim> ATTACH -F %s ANSI-RT11 *.TXT,*.TSK\n", dptr->name);
|
fprintf (st, " sim> ATTACH %s -F ANSI-RT11 *.TXT,*.TSK\n\n", dptr->name);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3330,29 +3338,25 @@ if ((!stop_cpu) &&
|
||||||
((uint32)(sim_tape_size (uptr) - (t_offset)uptr->pos) > fmts[MT_GET_FMT (uptr)].eom_remnant) ||
|
((uint32)(sim_tape_size (uptr) - (t_offset)uptr->pos) > fmts[MT_GET_FMT (uptr)].eom_remnant) ||
|
||||||
(unique_record_sizes > 2 * tapemark_total))) {
|
(unique_record_sizes > 2 * tapemark_total))) {
|
||||||
remaining_data = (uint32)(sim_tape_size (uptr) - (t_offset)uptr->tape_eom);
|
remaining_data = (uint32)(sim_tape_size (uptr) - (t_offset)uptr->tape_eom);
|
||||||
sim_printf ("Tape Image %s'%s' scanned as %s format.\n", ((MT_GET_FMT (uptr) == MTUF_F_ANSI) ? "made from " : ""), uptr->filename, (MT_GET_FMT (uptr) == MTUF_F_ANSI) ? ansi_args[MT_GET_ANSI_TYP (uptr)].name : fmts[MT_GET_FMT (uptr)].name);
|
sim_messagef (SCPE_OK, "Tape Image %s'%s' scanned as %s format.\n", ((MT_GET_FMT (uptr) == MTUF_F_ANSI) ? "made from " : ""), uptr->filename, (MT_GET_FMT (uptr) == MTUF_F_ANSI) ? ansi_args[MT_GET_ANSI_TYP (uptr)].name : fmts[MT_GET_FMT (uptr)].name);
|
||||||
if (r != MTSE_EOM)
|
sim_messagef (SCPE_OK, "%s %u bytes of tape data (%u records, %u tapemarks)\n",
|
||||||
sim_printf ("After processing ");
|
(r != MTSE_EOM) ? "After processing" : "contains", data_total, record_total, tapemark_total);
|
||||||
else
|
|
||||||
sim_printf ("contains ");
|
|
||||||
sim_printf ("%u bytes of tape data (%u records, %u tapemarks)\n",
|
|
||||||
data_total, record_total, tapemark_total);
|
|
||||||
if ((record_total > 0) && (sim_switches & SWMASK ('L'))) {
|
if ((record_total > 0) && (sim_switches & SWMASK ('L'))) {
|
||||||
sim_printf ("Comprising %d different sized records (in record size order):\n", unique_record_sizes);
|
sim_messagef (SCPE_OK, "Comprising %d different sized records (in record size order):\n", unique_record_sizes);
|
||||||
for (bc = 0; bc <= max; bc++) {
|
for (bc = 0; bc <= max; bc++) {
|
||||||
if (rec_sizes[bc])
|
if (rec_sizes[bc])
|
||||||
sim_printf ("%8u %u byte records\n", rec_sizes[bc], (uint32)bc);
|
sim_messagef (SCPE_OK, "%8u %u byte records\n", rec_sizes[bc], (uint32)bc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r != MTSE_EOM)
|
if (r != MTSE_EOM)
|
||||||
sim_printf ("Read Tape Record Returned Unexpected Status: %s\n", sim_tape_error_text (r));
|
sim_messagef (SCPE_OK, "Read Tape Record Returned Unexpected Status: %s\n", sim_tape_error_text (r));
|
||||||
if (remaining_data > fmts[MT_GET_FMT (uptr)].eom_remnant)
|
if (remaining_data > fmts[MT_GET_FMT (uptr)].eom_remnant)
|
||||||
sim_printf ("%u bytes of unexamined data remain in the tape image file\n", remaining_data);
|
sim_messagef (SCPE_OK, "%u bytes of unexamined data remain in the tape image file\n", remaining_data);
|
||||||
}
|
}
|
||||||
if ((!stop_cpu) &&
|
if ((!stop_cpu) &&
|
||||||
(unique_record_sizes > 2 * tapemark_total)) {
|
(unique_record_sizes > 2 * tapemark_total)) {
|
||||||
sim_printf ("A potentially unreasonable number of record sizes(%u) vs tape marks (%u) have been found\n", unique_record_sizes, tapemark_total);
|
sim_messagef (SCPE_OK, "A potentially unreasonable number of record sizes(%u) vs tape marks (%u) have been found\n", unique_record_sizes, tapemark_total);
|
||||||
sim_printf ("The tape format (%s) might not be correct for the '%s' tape image\n", fmts[MT_GET_FMT (uptr)].name, uptr->filename);
|
sim_messagef (SCPE_OK, "The tape format (%s) might not be correct for the '%s' tape image\n", fmts[MT_GET_FMT (uptr)].name, uptr->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (buf_f);
|
free (buf_f);
|
||||||
|
@ -4298,3 +4302,58 @@ sprintf (FullPath, "%s%s", directory, filename);
|
||||||
|
|
||||||
(void)ansi_add_file_to_tape (tape, FullPath);
|
(void)ansi_add_file_to_tape (tape, FullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* export an existing tape to a SIMH tape image */
|
||||||
|
static t_stat sim_export_tape (UNIT *uptr, const char *export_file)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
FILE *f;
|
||||||
|
t_addr saved_pos = uptr->pos;
|
||||||
|
uint8 *buf = NULL;
|
||||||
|
t_mtrlnt bc, sbc;
|
||||||
|
t_mtrlnt max = MTR_MAXLEN;
|
||||||
|
|
||||||
|
if ((export_file == NULL) || (*export_file == '\0'))
|
||||||
|
return sim_messagef (SCPE_ARG, "Missing tape export file specification\n");
|
||||||
|
f = fopen (export_file, "wb");
|
||||||
|
if (f == NULL)
|
||||||
|
return sim_messagef (SCPE_OPENERR, "Can't open SIMH tape image file: %s - %s\n", export_file, strerror (errno));
|
||||||
|
|
||||||
|
buf = (uint8 *)calloc (max, 1);
|
||||||
|
if (buf == NULL) {
|
||||||
|
fclose (f);
|
||||||
|
return SCPE_MEM;
|
||||||
|
}
|
||||||
|
r = sim_tape_rewind (uptr);
|
||||||
|
while (r == SCPE_OK) {
|
||||||
|
r = sim_tape_rdrecf (uptr, buf, &bc, max);
|
||||||
|
switch (r) {
|
||||||
|
case MTSE_OK:
|
||||||
|
sbc = ((bc + 1) & ~1); /* word alignment for SIMH format data */
|
||||||
|
if ((1 != sim_fwrite (&bc, sizeof (bc), 1, f)) ||
|
||||||
|
(sbc != sim_fwrite (buf, 1, sbc, f)) ||
|
||||||
|
(1 != sim_fwrite (&bc, sizeof (bc), 1, f)))
|
||||||
|
r = sim_messagef (SCPE_IOERR, "Error writing file: %s - %s\n", export_file, strerror (errno));
|
||||||
|
else
|
||||||
|
r = SCPE_OK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MTSE_TMK:
|
||||||
|
bc = 0;
|
||||||
|
if (1 != sim_fwrite (&bc, sizeof (bc), 1, f))
|
||||||
|
r = sim_messagef (SCPE_IOERR, "Error writing file: %s - %s\n", export_file, strerror (errno));
|
||||||
|
else
|
||||||
|
r = SCPE_OK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r == MTSE_EOM)
|
||||||
|
r = SCPE_OK;
|
||||||
|
free (buf);
|
||||||
|
fclose (f);
|
||||||
|
uptr->pos = saved_pos;
|
||||||
|
return r;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue