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:
parent
c9b0e2b00f
commit
db26349bd7
6 changed files with 274 additions and 157 deletions
|
@ -231,7 +231,7 @@ Host platforms which have libSDL available can leverage this functionality.
|
||||||
#### Tape Extensions
|
#### Tape Extensions
|
||||||
AWS format tape support
|
AWS format tape support
|
||||||
TAR 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
|
#### Embedded ROM support
|
||||||
Simulators which have boot commands which load constant files as part of
|
Simulators which have boot commands which load constant files as part of
|
||||||
|
|
BIN
doc/simh_doc.doc
BIN
doc/simh_doc.doc
Binary file not shown.
BIN
doc/simh_faq.doc
BIN
doc/simh_faq.doc
Binary file not shown.
23
sim_defs.h
23
sim_defs.h
|
@ -648,14 +648,21 @@ struct UNIT {
|
||||||
|
|
||||||
/* These flags are only set dynamically */
|
/* These flags are only set dynamically */
|
||||||
|
|
||||||
#define UNIT_ATTMULT 0000001 /* Allow multiple attach commands */
|
#define UNIT_ATTMULT 0000001 /* Allow multiple attach commands */
|
||||||
#define UNIT_TM_POLL 0000002 /* TMXR Polling unit */
|
#define UNIT_TM_POLL 0000002 /* TMXR Polling unit */
|
||||||
#define UNIT_NO_FIO 0000004 /* fileref is NOT a FILE * */
|
#define UNIT_NO_FIO 0000004 /* fileref is NOT a FILE * */
|
||||||
#define UNIT_DISK_CHK 0000010 /* disk data debug checking (sim_disk) */
|
#define UNIT_DISK_CHK 0000010 /* disk data debug checking (sim_disk) */
|
||||||
#define UNIT_TMR_UNIT 0000020 /* Unit registered as a calibrated timer */
|
#define UNIT_TMR_UNIT 0000200 /* Unit registered as a calibrated timer */
|
||||||
#define UNIT_TAPE_MRK 0000040 /* Tape Unit AWS Tapemark */
|
#define UNIT_TAPE_MRK 0000400 /* Tape Unit AWS Tapemark */
|
||||||
#define UNIT_V_DF_TAPE 7 /* Bit offset for Tape Density reservation */
|
#define UNIT_TAPE_PNU 0001000 /* Tape Unit Position Not Updated */
|
||||||
#define UNIT_S_DF_TAPE 3 /* Bits Reserved for Tape Density */
|
#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 {
|
struct BITFIELD {
|
||||||
const char *name; /* field name */
|
const char *name; /* field name */
|
||||||
|
|
360
sim_tape.c
360
sim_tape.c
|
@ -100,22 +100,20 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sim_tape_fmt {
|
static struct sim_tape_fmt {
|
||||||
const char *name; /* name */
|
const char *name; /* name */
|
||||||
int32 uflags; /* unit flags */
|
int32 uflags; /* unit flags */
|
||||||
t_addr bot; /* bot test */
|
t_addr bot; /* bot test */
|
||||||
t_addr eom_remnant; /* potentially unprocessed data */
|
t_addr eom_remnant; /* potentially unprocessed data */
|
||||||
};
|
} fmts[] = {
|
||||||
|
{ "SIMH", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
|
||||||
static struct sim_tape_fmt fmts[MTUF_N_FMT] = {
|
{ "E11", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
|
||||||
{ "SIMH", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
|
{ "TPC", UNIT_RO, sizeof (t_tpclnt) - 1, sizeof (t_tpclnt) },
|
||||||
{ "E11", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
|
{ "P7B", 0, 0, 0 },
|
||||||
{ "TPC", UNIT_RO, sizeof (t_tpclnt) - 1, sizeof (t_tpclnt) },
|
{ "AWS", 0, 0, 0 },
|
||||||
{ "P7B", 0, 0, 0 },
|
{ "TAR", UNIT_RO, 0, 0 },
|
||||||
{ "AWS", 0, 0, 0 },
|
{ "ANSI", UNIT_RO, 0, 0 },
|
||||||
{ "TAR", 0, 0, 0 },
|
{ NULL, 0, 0, 0 }
|
||||||
{ "ANSIFILES", 0, 0, 0 },
|
|
||||||
{ NULL, 0, 0, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32 bpi [] = { /* tape density table, indexed by MT_DENS constants */
|
static const uint32 bpi [] = { /* tape density table, indexed by MT_DENS constants */
|
||||||
|
@ -411,7 +409,9 @@ typedef struct HDR2 { /* Also EOF2, EOV2 */
|
||||||
char record_format; /* F(fixed)|D(variable)|S(spanned) */
|
char record_format; /* F(fixed)|D(variable)|S(spanned) */
|
||||||
char block_length[5]; /* label ident */
|
char block_length[5]; /* label ident */
|
||||||
char record_length[5]; /* */
|
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 buffer_offset[2]; /* */
|
||||||
char reserved_std[28]; /* */
|
char reserved_std[28]; /* */
|
||||||
} HDR2;
|
} HDR2;
|
||||||
|
@ -442,15 +442,68 @@ typedef struct TAPE_RECORD {
|
||||||
} TAPE_RECORD;
|
} TAPE_RECORD;
|
||||||
|
|
||||||
typedef struct ANSI_TAPE {
|
typedef struct ANSI_TAPE {
|
||||||
uint32 file_count;
|
uint32 ansi_type; /* ANSI-VMS, ANSI-RT11, ANSI-RSTS, ANSI-RSX11 */
|
||||||
uint32 record_count;
|
uint32 file_count; /* number of labeled files */
|
||||||
uint32 array_size;
|
uint32 record_count; /* number of entries in the record array */
|
||||||
uint32 block_size;
|
uint32 array_size; /* allocated size of records array */
|
||||||
|
uint32 block_size; /* tape block size */
|
||||||
TAPE_RECORD **records;
|
TAPE_RECORD **records;
|
||||||
VOL1 vol1;
|
VOL1 vol1;
|
||||||
} ANSI_TAPE;
|
} 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 int ansi_free_tape (void *vtape);
|
||||||
static void sim_tape_add_ansi_entry (const char *directory,
|
static void sim_tape_add_ansi_entry (const char *directory,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
@ -532,7 +585,7 @@ sim_tape_clr_async (uptr);
|
||||||
if (sim_asynch_enabled)
|
if (sim_asynch_enabled)
|
||||||
sim_tape_set_async (uptr, ctx->asynch_io_latency);
|
sim_tape_set_async (uptr, ctx->asynch_io_latency);
|
||||||
#endif
|
#endif
|
||||||
if (MT_GET_FMT (uptr) != MTUF_F_ANSI)
|
if (MT_GET_FMT (uptr) < MTUF_F_ANSI)
|
||||||
fflush (uptr->fileref);
|
fflush (uptr->fileref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,6 +606,7 @@ struct tape_context *ctx;
|
||||||
uint32 objc;
|
uint32 objc;
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
|
uint32 recsize = 0;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
t_bool auto_format = FALSE;
|
t_bool auto_format = FALSE;
|
||||||
t_bool had_debug = (sim_deb != NULL);
|
t_bool had_debug = (sim_deb != NULL);
|
||||||
|
@ -564,37 +618,43 @@ if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
||||||
if (sim_switches & SWMASK ('F')) { /* format spec? */
|
if (sim_switches & SWMASK ('F')) { /* format spec? */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get spec */
|
cptr = get_glyph (cptr, gbuf, 0); /* get spec */
|
||||||
if (*cptr == 0) /* must be more */
|
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)
|
if (sim_tape_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK)
|
||||||
return sim_messagef (SCPE_ARG, "Invalid Tape Format: %s\n", gbuf);
|
return sim_messagef (SCPE_ARG, "Invalid Tape Format: %s\n", gbuf);
|
||||||
sim_switches = sim_switches & ~(SWMASK ('F')); /* Record Format specifier already processed */
|
sim_switches = sim_switches & ~(SWMASK ('F')); /* Record Format specifier already processed */
|
||||||
auto_format = TRUE;
|
auto_format = TRUE;
|
||||||
}
|
}
|
||||||
if (MT_GET_FMT (uptr) == MTUF_F_TAR) {
|
if (sim_switches & SWMASK ('B')) { /* Record Size (blocking factor)? */
|
||||||
if (sim_switches & SWMASK ('B')) { /* Record Size (blocking factor)? */
|
cptr = get_glyph (cptr, gbuf, 0); /* get spec */
|
||||||
uint32 recsize;
|
if (*cptr == 0) /* must be more */
|
||||||
|
return sim_messagef (SCPE_2FARG, "Missing Record Size and filename to attach\n");
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get spec */
|
recsize = (uint32) get_uint (gbuf, 10, 65536, &r);
|
||||||
if (*cptr == 0) /* must be more */
|
if ((r != SCPE_OK) || (recsize == 0))
|
||||||
return sim_messagef (SCPE_2FARG, "Missing Record Size and filename to attach\n");
|
return sim_messagef (SCPE_ARG, "Invalid Tape Record Size: %s\n", gbuf);
|
||||||
recsize = (uint32) get_uint (gbuf, 10, 65536, &r);
|
uptr->recsize = recsize;
|
||||||
if ((r != SCPE_OK) || (recsize == 0))
|
sim_switches = sim_switches & ~(SWMASK ('B')); /* Record Blocking Factor */
|
||||||
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) ||
|
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 ANSIFILES tapes */
|
sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC, TAR and ANSI tapes */
|
||||||
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";
|
||||||
|
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)
|
if (!uptr->fileref)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
while (*cptr != 0) { /* do all mods */
|
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) {
|
if (((ANSI_TAPE *)uptr->fileref)->file_count > 0) {
|
||||||
r = SCPE_OK;
|
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->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);
|
||||||
|
@ -757,9 +817,10 @@ fprintf (st, " -R Attach Read Only.\n");
|
||||||
fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\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, " virtual tape will be attempted).\n");
|
||||||
fprintf (st, " -F Open the indicated tape container in a specific format (default\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, " -B For TAR format tapes, the record size for data read from the\n");
|
fprintf (st, " ANSI-RT11, ANSI-RSX11 or ANSI-RSTS)\n");
|
||||||
fprintf (st, " specified file. This record size will be used for all but\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, " possibly the last record which will be what remains unread.\n");
|
||||||
fprintf (st, " The default TAR record size is 10240.\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, " -V Display some summary information about the record structure\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, " 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\n");
|
||||||
fprintf (st, "Notes: ANSIFILES format allows one or several files to be presented to as a\n");
|
fprintf (st, "Notes: ANSI-VMS, ANSI-RT11, ANSI-RSTS, ANSI-RSX11 formats allows one or several\n");
|
||||||
fprintf (st, " read only ANSI Level 3 labeled tape with file labels that make each\n");
|
fprintf (st, " files to be presented to as a read only ANSI Level 3 labeled tape with\n");
|
||||||
fprintf (st, " individual file accessible directly as files on the tape.\n\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, "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 ANSI-VMS 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-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;
|
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)
|
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 sim_fseek (uptr->fileref, pos, SEEK_SET);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_offset sim_tape_size (UNIT *uptr)
|
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 sim_fsize_ex (uptr->fileref);
|
||||||
return uptr->tape_eom;
|
return uptr->tape_eom;
|
||||||
}
|
}
|
||||||
|
@ -1524,7 +1588,7 @@ else switch (f) { /* otherwise the read me
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTUF_F_ANSI:
|
case MTUF_F_ANSI:
|
||||||
if (1) {
|
if (1) {
|
||||||
ANSI_TAPE *tape = (ANSI_TAPE *)uptr->fileref;
|
ANSI_TAPE *tape = (ANSI_TAPE *)uptr->fileref;
|
||||||
|
|
||||||
|
@ -1603,7 +1667,7 @@ if (rbc > max) { /* rec out of range? */
|
||||||
uptr->pos = opos;
|
uptr->pos = opos;
|
||||||
return MTSE_INVRL;
|
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 */
|
i = (t_mtrlnt) sim_fread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
MT_SET_PNU (uptr);
|
MT_SET_PNU (uptr);
|
||||||
|
@ -1676,7 +1740,7 @@ if (st != MTSE_OK) {
|
||||||
*bc = rbc = MTR_L (tbc); /* strip error flag */
|
*bc = rbc = MTR_L (tbc); /* strip error flag */
|
||||||
if (rbc > max) /* rec out of range? */
|
if (rbc > max) /* rec out of range? */
|
||||||
return MTSE_INVRL;
|
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 */
|
i = (t_mtrlnt) sim_fread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
|
||||||
if (ferror (uptr->fileref)) /* error? */
|
if (ferror (uptr->fileref)) /* error? */
|
||||||
return sim_tape_ioerr (uptr);
|
return sim_tape_ioerr (uptr);
|
||||||
|
@ -2989,14 +3053,27 @@ if (uptr->flags & UNIT_ATT)
|
||||||
return SCPE_ALATT;
|
return SCPE_ALATT;
|
||||||
if (cptr == NULL)
|
if (cptr == NULL)
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
for (f = 0; f < MTUF_N_FMT; f++) {
|
for (f = 0; fmts[f].name; f++) {
|
||||||
if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) {
|
if (MATCH_CMD(fmts[f].name, cptr) == 0) {
|
||||||
uptr->flags = (uptr->flags & ~MTUF_FMT) |
|
uint32 a = 0;
|
||||||
(f << MTUF_V_FMT) | fmts[f].uflags;
|
|
||||||
|
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_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SCPE_ARG;
|
return sim_messagef (SCPE_ARG, "Unknown tape format: %s\n", cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show tape format */
|
/* 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);
|
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);
|
fprintf (st, "%s format", fmts[f].name);
|
||||||
else fprintf (st, "invalid format");
|
|
||||||
return SCPE_OK;
|
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) ||
|
((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, 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)
|
if (r != MTSE_EOM)
|
||||||
sim_printf ("After processing ");
|
sim_printf ("After processing ");
|
||||||
else
|
else
|
||||||
|
@ -3762,27 +3840,6 @@ SIM_TEST(sim_tape_test_remove_tape_files (dptr->units, "TapeTestFile1"));
|
||||||
return SCPE_OK;
|
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])
|
static void ansi_date (time_t datetime, char date[6])
|
||||||
{
|
{
|
||||||
struct tm *lt;
|
struct tm *lt;
|
||||||
|
@ -3795,6 +3852,11 @@ static void ansi_date (time_t datetime, char date[6])
|
||||||
memcpy (date, buf, 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)
|
static void to_ansi_a (char *out, const char *in, size_t size)
|
||||||
{
|
{
|
||||||
memset (out, ' ', size);
|
memset (out, ' ', size);
|
||||||
|
@ -3809,7 +3871,7 @@ static void to_ansi_a (char *out, const char *in, size_t size)
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (strchr ("-.$_", *in))
|
if (strchr ("-.$_/", *in))
|
||||||
*(out++) = *in++;
|
*(out++) = *in++;
|
||||||
else
|
else
|
||||||
++in;
|
++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));
|
memset (vol, ' ', sizeof (*vol));
|
||||||
memcpy (vol->type, "VOL", 3);
|
memcpy (vol->type, "VOL", 3);
|
||||||
vol->num = '1';
|
vol->num = '1';
|
||||||
vol->standard = '3';
|
|
||||||
to_ansi_a (vol->ident, ident, sizeof (vol->ident));
|
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;
|
const char *fn;
|
||||||
struct stat statb;
|
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);
|
ansi_date (statb.st_mtime, hdr1->creation_date);
|
||||||
memcpy (hdr1->expiration_date, " 00000", 6);
|
memcpy (hdr1->expiration_date, " 00000", 6);
|
||||||
memcpy (hdr1->block_count, "000000", 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);
|
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];
|
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));
|
memcpy (hdr->block_length, size, sizeof (hdr->block_length));
|
||||||
sprintf (size, "%05d", (int)record_size);
|
sprintf (size, "%05d", (int)record_size);
|
||||||
memcpy (hdr->record_length, size, sizeof (hdr->record_length));
|
memcpy (hdr->record_length, size, sizeof (hdr->record_length));
|
||||||
|
hdr->carriage_control = fixed_record ? 'M' : ' ';
|
||||||
memcpy (hdr->buffer_offset, "00", 2);
|
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;
|
long start;
|
||||||
char *tmp = (char *)calloc (1 + bufsize, sizeof (*buf));
|
char *tmp = (char *)calloc (2 + buf_size, sizeof (*buf));
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int rec_size;
|
size_t rec_size;
|
||||||
|
char rec_size_str[16];
|
||||||
|
|
||||||
start = ftell (f);
|
start = ftell (f);
|
||||||
if (!fgets (tmp, bufsize, f))
|
if (!fgets (tmp, buf_size, f))
|
||||||
break;
|
break;
|
||||||
rec_size = strlen (tmp);
|
rec_size = strlen (tmp);
|
||||||
if ((rec_size + 4) > (int)(bufsize - offset)) { /* room for record? */
|
if (!fixed_text) {
|
||||||
fseek (f, start, SEEK_SET);
|
if (rec_size >= record_skip_ending)
|
||||||
break;
|
rec_size -= record_skip_ending;
|
||||||
|
if ((rec_size + 4) > (int)(buf_size - offset)) { /* room for record? */
|
||||||
|
fseek (f, start, SEEK_SET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sprintf (buf + offset, "%04d%*.*s", rec_size + 4, rec_size, rec_size, tmp);
|
|
||||||
offset += 4 + rec_size;
|
|
||||||
}
|
}
|
||||||
if (bufsize > offset)
|
if (buf_size > offset) {
|
||||||
memset (buf + offset, '^', bufsize - offset);
|
if (fixed_text)
|
||||||
|
memset (buf + offset, 0, buf_size - offset);
|
||||||
|
else
|
||||||
|
memset (buf + offset, '^', buf_size - offset);
|
||||||
|
}
|
||||||
free (tmp);
|
free (tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3947,12 +4046,15 @@ free (tape);
|
||||||
return 0;
|
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));
|
ANSI_TAPE *tape = (ANSI_TAPE *)calloc (1, sizeof (*tape));
|
||||||
|
|
||||||
|
if (NULL == tape)
|
||||||
|
return tape;
|
||||||
tape->block_size = block_size;
|
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));
|
ansi_tape_add_block (tape, (uint8 *)&tape->vol1, sizeof (tape->vol1));
|
||||||
return tape;
|
return tape;
|
||||||
}
|
}
|
||||||
|
@ -3974,7 +4076,7 @@ long crlf_lines = 0;
|
||||||
rewind (f);
|
rewind (f);
|
||||||
while (EOF != (chr = fgetc (f))) {
|
while (EOF != (chr = fgetc (f))) {
|
||||||
++pos;
|
++pos;
|
||||||
if (!isprint (chr) && (!(chr == '\r')) && (!(chr == '\n')))
|
if (!isprint (chr) && (!(chr == '\r')) && (!(chr == '\n')) && (!(chr == '\t')))
|
||||||
++non_print_chars;
|
++non_print_chars;
|
||||||
if (chr == '\r')
|
if (chr == '\r')
|
||||||
last_cr = pos;
|
last_cr = pos;
|
||||||
|
@ -4016,6 +4118,7 @@ return 0;
|
||||||
static int ansi_add_file_to_tape (ANSI_TAPE *tape, const char *filename)
|
static int ansi_add_file_to_tape (ANSI_TAPE *tape, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
struct ansi_tape_parameters *ansi = &ansi_args[tape->ansi_type];
|
||||||
uint8 *block = NULL;
|
uint8 *block = NULL;
|
||||||
size_t max_record_size;
|
size_t max_record_size;
|
||||||
t_bool lf_line_endings;
|
t_bool lf_line_endings;
|
||||||
|
@ -4035,30 +4138,40 @@ if (f == NULL) {
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
ansi_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
|
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);
|
sprintf (file_sequence, "%04d", 1 + tape->file_count);
|
||||||
memcpy (hdr1.file_sequence, file_sequence, sizeof (hdr1.file_sequence));
|
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 (ansi->fixed_text)
|
||||||
if (!lf_line_endings && !crlf_line_endings)
|
max_record_size = 512;
|
||||||
memcpy (&hdr3, HDR3_RMS_FIXED, sizeof (hdr3));
|
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);
|
||||||
else {
|
|
||||||
if (lf_line_endings)
|
if (!ansi->nohdr3) { /* Need HDR3? */
|
||||||
memcpy (&hdr3, HDR3_RMS_STMLF, sizeof (hdr3));
|
if (!lf_line_endings && !crlf_line_endings) /* Binary File? */
|
||||||
else
|
memcpy (&hdr3, ansi->hdr3_fixed, sizeof (hdr3));
|
||||||
memcpy (&hdr3, HDR3_RMS_STREAM, sizeof (hdr3));
|
else { /* Text file */
|
||||||
|
if ((lf_line_endings) && !(ansi->fixed_text))
|
||||||
|
memcpy (&hdr3, ansi->hdr3_lf_line_endings, sizeof (hdr3));
|
||||||
|
else
|
||||||
|
memcpy (&hdr3, ansi->hdr3_crlf_line_endings, sizeof (hdr3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr1, sizeof (hdr1));
|
ansi_tape_add_block (tape, (uint8 *)&hdr1, sizeof (hdr1));
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr2, sizeof (hdr2));
|
if (!ansi->nohdr2)
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr3, sizeof (hdr3));
|
ansi_tape_add_block (tape, (uint8 *)&hdr2, sizeof (hdr2));
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr4, sizeof (hdr4));
|
if (!ansi->nohdr3)
|
||||||
ansi_tape_add_block (tape, NULL, 0);
|
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); /* Tape Mark */
|
||||||
rewind (f);
|
rewind (f);
|
||||||
block = (uint8 *)malloc (tape->block_size);
|
block = (uint8 *)calloc (tape->block_size, 1);
|
||||||
while (!feof(f) && !error) {
|
while (!feof(f) && !error) {
|
||||||
size_t data_read = tape->block_size;
|
size_t data_read = tape->block_size;
|
||||||
|
|
||||||
if (lf_line_endings || crlf_line_endings)
|
if (lf_line_endings || crlf_line_endings) /* text file? */
|
||||||
ansi_fill_text_buffer (f, (char *)block, tape->block_size);
|
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
|
else
|
||||||
data_read = fread (block, 1, tape->block_size, f);
|
data_read = fread (block, 1, tape->block_size, f);
|
||||||
if (data_read > 0)
|
if (data_read > 0)
|
||||||
|
@ -4068,7 +4181,7 @@ while (!feof(f) && !error) {
|
||||||
}
|
}
|
||||||
fclose (f);
|
fclose (f);
|
||||||
free (block);
|
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 (hdr1.type, "EOF", sizeof (hdr1.type));
|
||||||
memcpy (hdr2.type, "EOF", sizeof (hdr2.type));
|
memcpy (hdr2.type, "EOF", sizeof (hdr2.type));
|
||||||
memcpy (hdr3.type, "EOF", sizeof (hdr3.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);
|
sprintf (block_count_string, "%06d", block_count);
|
||||||
memcpy (hdr1.block_count, block_count_string, sizeof (hdr1.block_count));
|
memcpy (hdr1.block_count, block_count_string, sizeof (hdr1.block_count));
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr1, sizeof (hdr1));
|
ansi_tape_add_block (tape, (uint8 *)&hdr1, sizeof (hdr1));
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr2, sizeof (hdr2));
|
if (!ansi->nohdr2)
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr3, sizeof (hdr3));
|
ansi_tape_add_block (tape, (uint8 *)&hdr2, sizeof (hdr2));
|
||||||
ansi_tape_add_block (tape, (uint8 *)&hdr4, sizeof (hdr4));
|
if (!ansi->nohdr3)
|
||||||
ansi_tape_add_block (tape, NULL, 0);
|
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); /* Tape Mark */
|
||||||
if (sim_switches & SWMASK ('V'))
|
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);
|
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;
|
++tape->file_count;
|
||||||
|
|
46
sim_tape.h
46
sim_tape.h
|
@ -90,39 +90,33 @@ typedef struct {
|
||||||
|
|
||||||
/* Unit flags */
|
/* Unit flags */
|
||||||
|
|
||||||
#define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */
|
#define MTUF_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||||
#define MTUF_V_WLK (UNIT_V_UF + 1) /* write locked */
|
|
||||||
#define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */
|
#define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */
|
||||||
#define MTUF_W_FMT 3 /* 3b of formats */
|
#define MTUF_F_STD 0 /* SIMH format */
|
||||||
#define MTUF_N_FMT (1u << MTUF_W_FMT) /* number of formats */
|
#define MTUF_F_E11 1 /* E11 format */
|
||||||
#define MTUF_M_FMT ((1u << MTUF_W_FMT) - 1)
|
#define MTUF_F_TPC 2 /* TPC format */
|
||||||
#define MTUF_F_STD 0 /* SIMH format */
|
#define MTUF_F_P7B 3 /* P7B format */
|
||||||
#define MTUF_F_E11 1 /* E11 format */
|
#define MTUF_F_AWS 4 /* AWS format */
|
||||||
#define MTUF_F_TPC 2 /* TPC format */
|
#define MTUF_F_TAR 5 /* TAR format */
|
||||||
#define MTUF_F_P7B 3 /* P7B format */
|
#define MTUF_F_ANSI 6 /* ANSI format */
|
||||||
#define MTUF_F_AWS 4 /* AWS format */
|
|
||||||
#define MTUF_F_TAR 5 /* TAR format */
|
#define MTAT_F_VMS 0 /* VMS ANSI type */
|
||||||
#define MTUF_F_ANSI 6 /* ANSIFILES format */
|
#define MTAT_F_RSX11 1 /* RSX-11 ANSI type */
|
||||||
#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT)
|
#define MTAT_F_RSTS 2 /* RSTS ANSI type */
|
||||||
#define MTUF_PNU (1u << MTUF_V_PNU)
|
#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_WLK (1u << MTUF_V_WLK)
|
||||||
#define MTUF_FMT (MTUF_M_FMT << MTUF_V_FMT)
|
|
||||||
#define MTUF_WRP (MTUF_WLK | UNIT_RO)
|
#define MTUF_WRP (MTUF_WLK | UNIT_RO)
|
||||||
|
|
||||||
#define MT_F_STD (MTUF_F_STD << MTUF_V_FMT)
|
#define MT_SET_PNU(u) (u)->dynflags |= UNIT_TAPE_PNU
|
||||||
#define MT_F_E11 (MTUF_F_E11 << MTUF_V_FMT)
|
#define MT_CLR_PNU(u) (u)->dynflags &= ~UNIT_TAPE_PNU
|
||||||
#define MT_F_TPC (MTUF_F_TPC << MTUF_V_FMT)
|
#define MT_TST_PNU(u) ((u)->dynflags & UNIT_TAPE_PNU)
|
||||||
#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_INMRK(u) (u)->dynflags = (u)->dynflags | UNIT_TAPE_MRK
|
#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_CLR_INMRK(u) (u)->dynflags = (u)->dynflags & ~UNIT_TAPE_MRK
|
||||||
#define MT_TST_INMRK(u) ((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 */
|
/* sim_tape_position Position Flags */
|
||||||
#define MTPOS_V_REW 3
|
#define MTPOS_V_REW 3
|
||||||
|
|
Loading…
Add table
Reference in a new issue