TAPE: Add system specific ANSI tape formats VMS, RSX, RSTS and RT11

These formats are named ANSI-VMS, ANSI-RSX11, ANSI-RSTS and ANSI-RT11
This commit is contained in:
Mark Pizzolato 2019-05-14 01:04:18 -07:00
parent c9b0e2b00f
commit db26349bd7
6 changed files with 274 additions and 157 deletions

View file

@ -231,7 +231,7 @@ Host platforms which have libSDL available can leverage this functionality.
#### Tape Extensions
AWS format tape support
TAR format tape support
ANSIFILES format tape support
ANSI-VMS, ANSI-RSX11, ANSI-RSTS, ANSI-RT11 format tape support
#### Embedded ROM support
Simulators which have boot commands which load constant files as part of

Binary file not shown.

Binary file not shown.

View file

@ -652,10 +652,17 @@ struct UNIT {
#define UNIT_TM_POLL 0000002 /* TMXR Polling unit */
#define UNIT_NO_FIO 0000004 /* fileref is NOT a FILE * */
#define UNIT_DISK_CHK 0000010 /* disk data debug checking (sim_disk) */
#define UNIT_TMR_UNIT 0000020 /* Unit registered as a calibrated timer */
#define UNIT_TAPE_MRK 0000040 /* Tape Unit AWS Tapemark */
#define UNIT_V_DF_TAPE 7 /* Bit offset for Tape Density reservation */
#define UNIT_TMR_UNIT 0000200 /* Unit registered as a calibrated timer */
#define UNIT_TAPE_MRK 0000400 /* Tape Unit AWS Tapemark */
#define UNIT_TAPE_PNU 0001000 /* Tape Unit Position Not Updated */
#define UNIT_V_DF_TAPE 10 /* Bit offset for Tape Density reservation */
#define UNIT_S_DF_TAPE 3 /* Bits Reserved for Tape Density */
#define UNIT_V_TAPE_FMT 13 /* Bit offset for Tape Format */
#define UNIT_S_TAPE_FMT 3 /* Bits Reserved for Tape Format */
#define UNIT_M_TAPE_FMT (((1 << UNIT_S_TAPE_FMT) - 1) << UNIT_V_TAPE_FMT)
#define UNIT_V_TAPE_ANSI 16 /* Bit offset for ANSI Tape Type */
#define UNIT_S_TAPE_ANSI 4 /* Bits Reserved for ANSI Tape Type */
#define UNIT_M_TAPE_ANSI (((1 << UNIT_S_TAPE_ANSI) - 1) << UNIT_V_TAPE_ANSI)
struct BITFIELD {
const char *name; /* field name */

View file

@ -100,21 +100,19 @@
#include <pthread.h>
#endif
struct sim_tape_fmt {
static struct sim_tape_fmt {
const char *name; /* name */
int32 uflags; /* unit flags */
t_addr bot; /* bot test */
t_addr eom_remnant; /* potentially unprocessed data */
};
static struct sim_tape_fmt fmts[MTUF_N_FMT] = {
} fmts[] = {
{ "SIMH", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
{ "E11", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
{ "TPC", UNIT_RO, sizeof (t_tpclnt) - 1, sizeof (t_tpclnt) },
{ "P7B", 0, 0, 0 },
{ "AWS", 0, 0, 0 },
{ "TAR", 0, 0, 0 },
{ "ANSIFILES", 0, 0, 0 },
{ "TAR", UNIT_RO, 0, 0 },
{ "ANSI", UNIT_RO, 0, 0 },
{ NULL, 0, 0, 0 }
};
@ -411,7 +409,9 @@ typedef struct HDR2 { /* Also EOF2, EOV2 */
char record_format; /* F(fixed)|D(variable)|S(spanned) */
char block_length[5]; /* label ident */
char record_length[5]; /* */
char reserved_os[35]; /* */
char reserved_os1[21]; /* */
char carriage_control; /* A - Fortran CC, M - Record contained CC, space - CR/LF to be added */
char reserved_os2[13]; /* */
char buffer_offset[2]; /* */
char reserved_std[28]; /* */
} HDR2;
@ -442,15 +442,68 @@ typedef struct TAPE_RECORD {
} TAPE_RECORD;
typedef struct ANSI_TAPE {
uint32 file_count;
uint32 record_count;
uint32 array_size;
uint32 block_size;
uint32 ansi_type; /* ANSI-VMS, ANSI-RT11, ANSI-RSTS, ANSI-RSX11 */
uint32 file_count; /* number of labeled files */
uint32 record_count; /* number of entries in the record array */
uint32 array_size; /* allocated size of records array */
uint32 block_size; /* tape block size */
TAPE_RECORD **records;
VOL1 vol1;
} ANSI_TAPE;
static ANSI_TAPE *ansi_create_tape (const char *label, uint32 block_size);
const char HDR3_RMS_STREAM[] = "HDR3020002040000"
"0000000100000000"
"0000000002000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_STMLF[] = "HDR3020002050000"
"0000000100000000"
"0000000002000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_VAR[] = "HDR3005C02020000"
"0000000100000000"
"0000000000000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_FIXED[] = "HDR3020000010000"
"0000000100000000"
"0000000002000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_VARRSX[] = "HDR300000A020000"
"0000000100000000"
"0000000000000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_FIXRSX[] = "HDR3020008010000"
"0000000100000000"
"0000000000000000"
"0000000000000000"
"0000 ";
static struct ansi_tape_parameters {
const char *name; /* operating system */
const char *system_code; /* */
t_bool nohdr2; /* no HDR2 records */
t_bool nohdr3; /* no HDR2 records */
t_bool fixed_text; /* */
char vol1_standard; /* 3 or 4 */
const char *hdr3_fixed; /* HDR3 template for Fixed format files */
const char *hdr3_lf_line_endings; /* HDR3 template for text with LF line ending files */
const char *hdr3_crlf_line_endings;/* HDR3 template for text with CRLF line ending files */
int skip_lf_line_endings;
int skip_crlf_line_endings;
} ansi_args[] = { /* code nohdr2 nohdr3 fixed_text lvl hdr3 fir fuxed hdr3 fir lf hdr3 for crlf */
{"ANSI-VMS" , "DECFILE11A", FALSE, FALSE, FALSE, '3', HDR3_RMS_FIXED, HDR3_RMS_STMLF, HDR3_RMS_STREAM, 0, 0},
{"ANSI-RSX11" , "DECFILE11A", FALSE, FALSE, FALSE, '4', HDR3_RMS_FIXRSX, HDR3_RMS_VARRSX, HDR3_RMS_VARRSX, 1, 2},
{"ANSI-RT11" , "DECRT11A", TRUE, TRUE, TRUE, '3', NULL, NULL, NULL, 0, 0},
{"ANSI-RSTS" , "DECRSTS/E", FALSE, TRUE, TRUE, '3', NULL, NULL, NULL, 0, 0},
{NULL}
};
static ANSI_TAPE *ansi_create_tape (const char *label, uint32 block_size, uint32 ansi_type);
static int ansi_free_tape (void *vtape);
static void sim_tape_add_ansi_entry (const char *directory,
const char *filename,
@ -532,7 +585,7 @@ sim_tape_clr_async (uptr);
if (sim_asynch_enabled)
sim_tape_set_async (uptr, ctx->asynch_io_latency);
#endif
if (MT_GET_FMT (uptr) != MTUF_F_ANSI)
if (MT_GET_FMT (uptr) < MTUF_F_ANSI)
fflush (uptr->fileref);
}
@ -553,6 +606,7 @@ struct tape_context *ctx;
uint32 objc;
DEVICE *dptr;
char gbuf[CBUFSIZE];
uint32 recsize = 0;
t_stat r;
t_bool auto_format = FALSE;
t_bool had_debug = (sim_deb != NULL);
@ -564,16 +618,13 @@ 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 sim_messagef (SCPE_2FARG, "Missing Format specifier and filename to attach\n");
return sim_messagef (SCPE_2FARG, "Missing Format specifier and/or 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_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");
@ -583,18 +634,27 @@ if (MT_GET_FMT (uptr) == MTUF_F_TAR) {
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) ||
(MT_GET_FMT (uptr) == MTUF_F_ANSI))
sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC, TAR and ANSIFILES tapes */
sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC, TAR and ANSI tapes */
if (MT_GET_FMT (uptr) == MTUF_F_ANSI) {
const char *ocptr = cptr;
char label[CBUFSIZE] = "simh";
ANSI_TAPE *tape;
uptr->fileref = (FILE *)ansi_create_tape (label, 2048);
if ((MT_GET_ANSI_TYP (uptr) == MTAT_F_RT11) ||
(MT_GET_ANSI_TYP (uptr) == MTAT_F_RSX11) ||
(MT_GET_ANSI_TYP (uptr) == MTAT_F_RSTS))
uptr->recsize = 512;
if (uptr->recsize == 0)
uptr->recsize = 2048;
else {
if ((uptr->recsize < 512) || (uptr->recsize % 512))
return sim_messagef (SCPE_ARG, "Block size of %u is below or not a multiple of the required minimum ANSI size of 512.\n", uptr->recsize);
}
tape = ansi_create_tape (label, uptr->recsize, MT_GET_ANSI_TYP (uptr));
uptr->fileref = (FILE *)tape;
if (!uptr->fileref)
return SCPE_MEM;
while (*cptr != 0) { /* do all mods */
@ -603,7 +663,7 @@ if (MT_GET_FMT (uptr) == MTUF_F_ANSI) {
}
if (((ANSI_TAPE *)uptr->fileref)->file_count > 0) {
r = SCPE_OK;
ansi_tape_add_block ((ANSI_TAPE *)uptr->fileref, NULL, 0);
ansi_tape_add_block ((ANSI_TAPE *)uptr->fileref, NULL, 0); /* Tape Mark */
uptr->flags |= UNIT_ATT;
uptr->filename = (char *)malloc (strlen (ocptr) + 1);
strcpy (uptr->filename, ocptr);
@ -757,7 +817,8 @@ 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, P7B, AWS, TAR and ANSIFILES)\n");
fprintf (st, " is SIMH, alternatives are E11, TPC, P7B, AWS, TAR, ANSI-VMS,\n");
fprintf (st, " ANSI-RT11, ANSI-RSX11 or ANSI-RSTS)\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");
@ -769,12 +830,15 @@ fprintf (st, " validation pass\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, " while the tape image is scanned.\n\n");
fprintf (st, "Notes: ANSIFILES format allows one or several files to be presented to as a\n");
fprintf (st, " read only ANSI Level 3 labeled tape with file labels that make each\n");
fprintf (st, " individual file accessible directly as files on the tape.\n\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, " file labels that make each individual file accessible directly as files\n");
fprintf (st, " on the tape.\n\n");
fprintf (st, "Examples:\n\n");
fprintf (st, " sim> ATTACH -F %s ANSIFILES Hobbyist-USE-ONLY-VA.TXT\n\n", dptr->name);
fprintf (st, " sim> ATTACH -F %s ANSIFILES *.TXT,*.ini,*.exe\n", dptr->name);
fprintf (st, " sim> ATTACH -F %s ANSI-VMS Hobbyist-USE-ONLY-VA.TXT\n\n", dptr->name);
fprintf (st, " sim> ATTACH -F %s 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 -F %s ANSI-RT11 *.TXT,*.TSK\n", dptr->name);
return SCPE_OK;
}
@ -790,14 +854,14 @@ if (sim_deb && ((uptr->dctrl | ctx->dptr->dctrl) & reason))
static int sim_tape_seek (UNIT *uptr, t_addr pos)
{
if (MT_GET_FMT (uptr) != MTUF_F_ANSI)
if (MT_GET_FMT (uptr) < MTUF_F_ANSI)
return sim_fseek (uptr->fileref, pos, SEEK_SET);
return 0;
}
static t_offset sim_tape_size (UNIT *uptr)
{
if (MT_GET_FMT (uptr) != MTUF_F_ANSI)
if (MT_GET_FMT (uptr) < MTUF_F_ANSI)
return sim_fsize_ex (uptr->fileref);
return uptr->tape_eom;
}
@ -1603,7 +1667,7 @@ if (rbc > max) { /* rec out of range? */
uptr->pos = opos;
return MTSE_INVRL;
}
if (f != MTUF_F_ANSI) {
if (f < MTUF_F_ANSI) {
i = (t_mtrlnt) sim_fread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
if (ferror (uptr->fileref)) { /* error? */
MT_SET_PNU (uptr);
@ -1676,7 +1740,7 @@ if (st != MTSE_OK) {
*bc = rbc = MTR_L (tbc); /* strip error flag */
if (rbc > max) /* rec out of range? */
return MTSE_INVRL;
if (f != MTUF_F_ANSI) {
if (f < MTUF_F_ANSI) {
i = (t_mtrlnt) sim_fread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
if (ferror (uptr->fileref)) /* error? */
return sim_tape_ioerr (uptr);
@ -2989,14 +3053,27 @@ if (uptr->flags & UNIT_ATT)
return SCPE_ALATT;
if (cptr == NULL)
return SCPE_ARG;
for (f = 0; f < MTUF_N_FMT; f++) {
if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) {
uptr->flags = (uptr->flags & ~MTUF_FMT) |
(f << MTUF_V_FMT) | fmts[f].uflags;
for (f = 0; fmts[f].name; f++) {
if (MATCH_CMD(fmts[f].name, cptr) == 0) {
uint32 a = 0;
if (f == MTUF_F_ANSI) {
for (a = 0; ansi_args[a].name; a++)
if (MATCH_CMD(ansi_args[a].name, cptr) == 0)
break;
if (ansi_args[a].name == NULL)
return sim_messagef (SCPE_ARG, "Unknown ANSI tape format: %s\n", cptr);
}
uptr->flags &= ~UNIT_RO;
uptr->flags |= fmts[f].uflags;
uptr->dynflags &= ~UNIT_M_TAPE_FMT;
uptr->dynflags |= (f << UNIT_V_TAPE_FMT);
uptr->dynflags &= ~UNIT_M_TAPE_ANSI;
uptr->dynflags |= (a << UNIT_V_TAPE_ANSI);
return SCPE_OK;
}
}
return SCPE_ARG;
return sim_messagef (SCPE_ARG, "Unknown tape format: %s\n", cptr);
}
/* Show tape format */
@ -3005,9 +3082,10 @@ t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
int32 f = MT_GET_FMT (uptr);
if (fmts[f].name)
if (f == MTUF_F_ANSI)
fprintf (st, "%s format", ansi_args[MT_GET_ANSI_TYP (uptr)].name);
else
fprintf (st, "%s format", fmts[f].name);
else fprintf (st, "invalid format");
return SCPE_OK;
}
@ -3233,7 +3311,7 @@ if ((!stop_cpu) &&
((uint32)(sim_tape_size (uptr) - (t_offset)uptr->pos) > fmts[MT_GET_FMT (uptr)].eom_remnant) ||
(unique_record_sizes > 2 * tapemark_total))) {
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, fmts[MT_GET_FMT (uptr)].name);
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);
if (r != MTSE_EOM)
sim_printf ("After processing ");
else
@ -3762,27 +3840,6 @@ SIM_TEST(sim_tape_test_remove_tape_files (dptr->units, "TapeTestFile1"));
return SCPE_OK;
}
const char HDR3_RMS_STREAM[] = "HDR3020002040000"
"0000000100000000"
"0000000002000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_STMLF[] = "HDR3020002050000"
"0000000100000000"
"0000000002000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_VAR[] = "HDR3005C02020000"
"0000000100000000"
"0000000000000000"
"0000000000000000"
"0000 ";
const char HDR3_RMS_FIXED[] = "HDR3020000010000"
"0000000100000000"
"0000000002000000"
"0000000000000000"
"0000 ";
static void ansi_date (time_t datetime, char date[6])
{
struct tm *lt;
@ -3795,6 +3852,11 @@ static void ansi_date (time_t datetime, char date[6])
memcpy (date, buf, 6);
}
/*
* This isn't quite ANSI 'a' since several ANSI allowed characters
* are either illegal file names on many DEC systems or are confusing
* to OS file name parsers.
*/
static void to_ansi_a (char *out, const char *in, size_t size)
{
memset (out, ' ', size);
@ -3809,7 +3871,7 @@ static void to_ansi_a (char *out, const char *in, size_t size)
++in;
}
else {
if (strchr ("-.$_", *in))
if (strchr ("-.$_/", *in))
*(out++) = *in++;
else
++in;
@ -3818,16 +3880,16 @@ static void to_ansi_a (char *out, const char *in, size_t size)
}
}
static void ansi_make_VOL1 (VOL1 *vol, const char *ident)
static void ansi_make_VOL1 (VOL1 *vol, const char *ident, uint32 ansi_type)
{
memset (vol, ' ', sizeof (*vol));
memcpy (vol->type, "VOL", 3);
vol->num = '1';
vol->standard = '3';
to_ansi_a (vol->ident, ident, sizeof (vol->ident));
vol->standard = ansi_args[ansi_type].vol1_standard;
}
static void ansi_make_HDR1 (HDR1 *hdr1, VOL1 *vol, HDR4 *hdr4, const char *filename)
static void ansi_make_HDR1 (HDR1 *hdr1, VOL1 *vol, HDR4 *hdr4, const char *filename, uint32 ansi_type)
{
const char *fn;
struct stat statb;
@ -3867,11 +3929,11 @@ static void ansi_make_HDR1 (HDR1 *hdr1, VOL1 *vol, HDR4 *hdr4, const char *filen
ansi_date (statb.st_mtime, hdr1->creation_date);
memcpy (hdr1->expiration_date, " 00000", 6);
memcpy (hdr1->block_count, "000000", 6);
to_ansi_a (hdr1->system_code, "DECFILE11A", sizeof (hdr1->system_code));
to_ansi_a (hdr1->system_code, ansi_args[ansi_type].system_code, sizeof (hdr1->system_code));
free (fn_cpy);
}
static void ansi_make_HDR2 (HDR2 *hdr, t_bool fixed_record, size_t block_size, size_t record_size)
static void ansi_make_HDR2 (HDR2 *hdr, t_bool fixed_record, size_t block_size, size_t record_size, uint32 ansi_type)
{
char size[12];
@ -3883,31 +3945,68 @@ static void ansi_make_HDR2 (HDR2 *hdr, t_bool fixed_record, size_t block_size, s
memcpy (hdr->block_length, size, sizeof (hdr->block_length));
sprintf (size, "%05d", (int)record_size);
memcpy (hdr->record_length, size, sizeof (hdr->record_length));
hdr->carriage_control = fixed_record ? 'M' : ' ';
memcpy (hdr->buffer_offset, "00", 2);
if (ansi_type == MTAT_F_RSTS) {
hdr->record_format = 'U';
memcpy (hdr->record_length, "00000", sizeof (hdr->record_length));
hdr->carriage_control = 'M';
}
}
static void ansi_fill_text_buffer (FILE *f, char *buf, size_t bufsize)
static void ansi_fill_text_buffer (FILE *f, char *buf, size_t buf_size, size_t record_skip_ending, t_bool fixed_text)
{
long start;
char *tmp = (char *)calloc (1 + bufsize, sizeof (*buf));
char *tmp = (char *)calloc (2 + buf_size, sizeof (*buf));
size_t offset = 0;
while (1) {
int rec_size;
size_t rec_size;
char rec_size_str[16];
start = ftell (f);
if (!fgets (tmp, bufsize, f))
if (!fgets (tmp, buf_size, f))
break;
rec_size = strlen (tmp);
if ((rec_size + 4) > (int)(bufsize - offset)) { /* room for record? */
if (!fixed_text) {
if (rec_size >= record_skip_ending)
rec_size -= record_skip_ending;
if ((rec_size + 4) > (int)(buf_size - offset)) { /* room for record? */
fseek (f, start, SEEK_SET);
break;
}
sprintf (buf + offset, "%04d%*.*s", rec_size + 4, rec_size, rec_size, tmp);
sprintf (rec_size_str, "%04u", (int)(rec_size + 4));
memcpy (buf + offset, rec_size_str, 4);
memcpy (buf + offset + 4, tmp, rec_size);
offset += 4 + rec_size;
}
if (bufsize > offset)
memset (buf + offset, '^', bufsize - offset);
else {
size_t move_size;
if ((tmp[rec_size - 2] != '\r') &&
(tmp[rec_size - 1] == '\n')) {
memcpy (&tmp[rec_size - 1], "\r\n", 3);
rec_size += 1;
}
if (offset + rec_size < buf_size)
move_size = rec_size;
else
move_size = buf_size - offset;
/* We've got a line that stradles a block boundary */
memcpy (buf + offset, tmp, move_size);
offset += move_size;
if (offset == buf_size) {
fseek (f, start + move_size, SEEK_SET);
break;
}
}
}
if (buf_size > offset) {
if (fixed_text)
memset (buf + offset, 0, buf_size - offset);
else
memset (buf + offset, '^', buf_size - offset);
}
free (tmp);
}
@ -3947,12 +4046,15 @@ free (tape);
return 0;
}
ANSI_TAPE *ansi_create_tape (const char *label, uint32 block_size)
ANSI_TAPE *ansi_create_tape (const char *label, uint32 block_size, uint32 ansi_type)
{
ANSI_TAPE *tape = (ANSI_TAPE *)calloc (1, sizeof (*tape));
if (NULL == tape)
return tape;
tape->block_size = block_size;
ansi_make_VOL1 (&tape->vol1, label);
tape->ansi_type = ansi_type;
ansi_make_VOL1 (&tape->vol1, label, ansi_type);
ansi_tape_add_block (tape, (uint8 *)&tape->vol1, sizeof (tape->vol1));
return tape;
}
@ -3974,7 +4076,7 @@ long crlf_lines = 0;
rewind (f);
while (EOF != (chr = fgetc (f))) {
++pos;
if (!isprint (chr) && (!(chr == '\r')) && (!(chr == '\n')))
if (!isprint (chr) && (!(chr == '\r')) && (!(chr == '\n')) && (!(chr == '\t')))
++non_print_chars;
if (chr == '\r')
last_cr = pos;
@ -4016,6 +4118,7 @@ return 0;
static int ansi_add_file_to_tape (ANSI_TAPE *tape, const char *filename)
{
FILE *f;
struct ansi_tape_parameters *ansi = &ansi_args[tape->ansi_type];
uint8 *block = NULL;
size_t max_record_size;
t_bool lf_line_endings;
@ -4035,30 +4138,40 @@ if (f == NULL) {
return errno;
}
ansi_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
ansi_make_HDR1 (&hdr1, &tape->vol1, &hdr4, filename);
ansi_make_HDR1 (&hdr1, &tape->vol1, &hdr4, filename, tape->ansi_type);
sprintf (file_sequence, "%04d", 1 + tape->file_count);
memcpy (hdr1.file_sequence, file_sequence, sizeof (hdr1.file_sequence));
ansi_make_HDR2 (&hdr2, !lf_line_endings && !crlf_line_endings, tape->block_size, max_record_size);
if (!lf_line_endings && !crlf_line_endings)
memcpy (&hdr3, HDR3_RMS_FIXED, sizeof (hdr3));
else {
if (lf_line_endings)
memcpy (&hdr3, HDR3_RMS_STMLF, sizeof (hdr3));
if (ansi->fixed_text)
max_record_size = 512;
ansi_make_HDR2 (&hdr2, !lf_line_endings && !crlf_line_endings, tape->block_size, (tape->ansi_type > MTUF_F_ANSI) ? 512 : max_record_size, tape->ansi_type);
if (!ansi->nohdr3) { /* Need HDR3? */
if (!lf_line_endings && !crlf_line_endings) /* Binary File? */
memcpy (&hdr3, ansi->hdr3_fixed, sizeof (hdr3));
else { /* Text file */
if ((lf_line_endings) && !(ansi->fixed_text))
memcpy (&hdr3, ansi->hdr3_lf_line_endings, sizeof (hdr3));
else
memcpy (&hdr3, HDR3_RMS_STREAM, sizeof (hdr3));
memcpy (&hdr3, ansi->hdr3_crlf_line_endings, sizeof (hdr3));
}
}
ansi_tape_add_block (tape, (uint8 *)&hdr1, sizeof (hdr1));
if (!ansi->nohdr2)
ansi_tape_add_block (tape, (uint8 *)&hdr2, sizeof (hdr2));
if (!ansi->nohdr3)
ansi_tape_add_block (tape, (uint8 *)&hdr3, sizeof (hdr3));
if ((0 != memcmp (hdr4.extra_name_used, "00", 2)) && !ansi->nohdr3 && !ansi->nohdr2)
ansi_tape_add_block (tape, (uint8 *)&hdr4, sizeof (hdr4));
ansi_tape_add_block (tape, NULL, 0);
ansi_tape_add_block (tape, NULL, 0); /* Tape Mark */
rewind (f);
block = (uint8 *)malloc (tape->block_size);
block = (uint8 *)calloc (tape->block_size, 1);
while (!feof(f) && !error) {
size_t data_read = tape->block_size;
if (lf_line_endings || crlf_line_endings)
ansi_fill_text_buffer (f, (char *)block, tape->block_size);
if (lf_line_endings || crlf_line_endings) /* text file? */
ansi_fill_text_buffer (f, (char *)block, tape->block_size,
crlf_line_endings ? ansi->skip_crlf_line_endings : ansi->skip_lf_line_endings,
ansi->fixed_text);
else
data_read = fread (block, 1, tape->block_size, f);
if (data_read > 0)
@ -4068,7 +4181,7 @@ while (!feof(f) && !error) {
}
fclose (f);
free (block);
ansi_tape_add_block (tape, NULL, 0);
ansi_tape_add_block (tape, NULL, 0); /* Tape Mark */
memcpy (hdr1.type, "EOF", sizeof (hdr1.type));
memcpy (hdr2.type, "EOF", sizeof (hdr2.type));
memcpy (hdr3.type, "EOF", sizeof (hdr3.type));
@ -4076,10 +4189,13 @@ memcpy (hdr4.type, "EOF", sizeof (hdr4.type));
sprintf (block_count_string, "%06d", block_count);
memcpy (hdr1.block_count, block_count_string, sizeof (hdr1.block_count));
ansi_tape_add_block (tape, (uint8 *)&hdr1, sizeof (hdr1));
if (!ansi->nohdr2)
ansi_tape_add_block (tape, (uint8 *)&hdr2, sizeof (hdr2));
if (!ansi->nohdr3)
ansi_tape_add_block (tape, (uint8 *)&hdr3, sizeof (hdr3));
if ((0 != memcmp (hdr4.extra_name_used, "00", 2)) && !ansi->nohdr3 && !ansi->nohdr2)
ansi_tape_add_block (tape, (uint8 *)&hdr4, sizeof (hdr4));
ansi_tape_add_block (tape, NULL, 0);
ansi_tape_add_block (tape, NULL, 0); /* Tape Mark */
if (sim_switches & SWMASK ('V'))
sim_messagef (SCPE_OK, "%17.17s%62.62s\n\t%d blocks of data\n", hdr1.file_ident, hdr4.extra_name, block_count);
++tape->file_count;

View file

@ -90,39 +90,33 @@ typedef struct {
/* Unit flags */
#define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */
#define MTUF_V_WLK (UNIT_V_UF + 1) /* write locked */
#define MTUF_V_WLK (UNIT_V_UF + 0) /* write locked */
#define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */
#define MTUF_W_FMT 3 /* 3b of formats */
#define MTUF_N_FMT (1u << MTUF_W_FMT) /* number of formats */
#define MTUF_M_FMT ((1u << MTUF_W_FMT) - 1)
#define MTUF_F_STD 0 /* SIMH format */
#define MTUF_F_E11 1 /* E11 format */
#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_F_ANSI 6 /* ANSIFILES format */
#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT)
#define MTUF_PNU (1u << MTUF_V_PNU)
#define MTUF_F_ANSI 6 /* ANSI format */
#define MTAT_F_VMS 0 /* VMS ANSI type */
#define MTAT_F_RSX11 1 /* RSX-11 ANSI type */
#define MTAT_F_RSTS 2 /* RSTS ANSI type */
#define MTAT_F_RT11 3 /* RT-11 ANSI type */
#define MTUF_V_UF (MTUF_V_WLK + 1)
#define MTUF_WLK (1u << MTUF_V_WLK)
#define MTUF_FMT (MTUF_M_FMT << MTUF_V_FMT)
#define MTUF_WRP (MTUF_WLK | UNIT_RO)
#define MT_F_STD (MTUF_F_STD << MTUF_V_FMT)
#define MT_F_E11 (MTUF_F_E11 << MTUF_V_FMT)
#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
#define MT_TST_PNU(u) ((u)->flags & MTUF_PNU)
#define MT_SET_PNU(u) (u)->dynflags |= UNIT_TAPE_PNU
#define MT_CLR_PNU(u) (u)->dynflags &= ~UNIT_TAPE_PNU
#define MT_TST_PNU(u) ((u)->dynflags & UNIT_TAPE_PNU)
#define MT_SET_INMRK(u) (u)->dynflags = (u)->dynflags | UNIT_TAPE_MRK
#define MT_CLR_INMRK(u) (u)->dynflags = (u)->dynflags & ~UNIT_TAPE_MRK
#define MT_TST_INMRK(u) ((u)->dynflags & UNIT_TAPE_MRK)
#define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT)
#define MT_GET_FMT(u) (((u)->dynflags >> UNIT_V_TAPE_FMT) & ((1 << UNIT_S_TAPE_FMT) - 1))
#define MT_GET_ANSI_TYP(u) (((u)->dynflags >> UNIT_V_TAPE_ANSI) & ((1 << UNIT_S_TAPE_ANSI) - 1))
/* sim_tape_position Position Flags */
#define MTPOS_V_REW 3