mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-11 23:52:48 +00:00
SCP: Updated to current.
This commit is contained in:
parent
554fab9268
commit
9a63bc521e
104
scp.c
104
scp.c
@ -754,57 +754,58 @@ const struct scp_error {
|
||||
const char *code;
|
||||
const char *message;
|
||||
} scp_errors[1+SCPE_MAX_ERR-SCPE_BASE] =
|
||||
{{"NXM", "Address space exceeded"},
|
||||
{"UNATT", "Unit not attached"},
|
||||
{"IOERR", "I/O error"},
|
||||
{"CSUM", "Checksum error"},
|
||||
{"FMT", "Format error"},
|
||||
{"NOATT", "Unit not attachable"},
|
||||
{"OPENERR", "File open error"},
|
||||
{"MEM", "Memory exhausted"},
|
||||
{"ARG", "Invalid argument"},
|
||||
{"STEP", "Step expired"},
|
||||
{"UNK", "Unknown command"},
|
||||
{"RO", "Read only argument"},
|
||||
{"INCOMP", "Command not completed"},
|
||||
{"STOP", "Simulation stopped"},
|
||||
{"EXIT", "Goodbye"},
|
||||
{"TTIERR", "Console input I/O error"},
|
||||
{"TTOERR", "Console output I/O error"},
|
||||
{"EOF", "End of file"},
|
||||
{"REL", "Relocation error"},
|
||||
{"NOPARAM", "No settable parameters"},
|
||||
{"ALATT", "Unit already attached"},
|
||||
{"TIMER", "Hardware timer error"},
|
||||
{"SIGERR", "Signal handler setup error"},
|
||||
{"TTYERR", "Console terminal setup error"},
|
||||
{"SUB", "Subscript out of range"},
|
||||
{"NOFNC", "Command not allowed"},
|
||||
{"UDIS", "Unit disabled"},
|
||||
{"NORO", "Read only operation not allowed"},
|
||||
{"INVSW", "Invalid switch"},
|
||||
{"MISVAL", "Missing value"},
|
||||
{"2FARG", "Too few arguments"},
|
||||
{"2MARG", "Too many arguments"},
|
||||
{"NXDEV", "Non-existent device"},
|
||||
{"NXUN", "Non-existent unit"},
|
||||
{"NXREG", "Non-existent register"},
|
||||
{"NXPAR", "Non-existent parameter"},
|
||||
{"NEST", "Nested DO command limit exceeded"},
|
||||
{"IERR", "Internal error"},
|
||||
{"MTRLNT", "Invalid magtape record length"},
|
||||
{"LOST", "Console Telnet connection lost"},
|
||||
{"TTMO", "Console Telnet connection timed out"},
|
||||
{"STALL", "Console Telnet output stall"},
|
||||
{"AFAIL", "Assertion failed"},
|
||||
{"INVREM", "Invalid remote console command"},
|
||||
{"EXPECT", "Expect matched"},
|
||||
{"AMBREG", "Ambiguous register name"},
|
||||
{"REMOTE", "remote console command"},
|
||||
{"INVEXPR", "invalid expression"},
|
||||
{"SIGTERM", "SIGTERM received"},
|
||||
{"FSSIZE", "File System size larger than disk size"},
|
||||
{"RUNTIME", "Run time limit exhausted"},
|
||||
{{"NXM", "Address space exceeded"},
|
||||
{"UNATT", "Unit not attached"},
|
||||
{"IOERR", "I/O error"},
|
||||
{"CSUM", "Checksum error"},
|
||||
{"FMT", "Format error"},
|
||||
{"NOATT", "Unit not attachable"},
|
||||
{"OPENERR", "File open error"},
|
||||
{"MEM", "Memory exhausted"},
|
||||
{"ARG", "Invalid argument"},
|
||||
{"STEP", "Step expired"},
|
||||
{"UNK", "Unknown command"},
|
||||
{"RO", "Read only argument"},
|
||||
{"INCOMP", "Command not completed"},
|
||||
{"STOP", "Simulation stopped"},
|
||||
{"EXIT", "Goodbye"},
|
||||
{"TTIERR", "Console input I/O error"},
|
||||
{"TTOERR", "Console output I/O error"},
|
||||
{"EOF", "End of file"},
|
||||
{"REL", "Relocation error"},
|
||||
{"NOPARAM", "No settable parameters"},
|
||||
{"ALATT", "Unit already attached"},
|
||||
{"TIMER", "Hardware timer error"},
|
||||
{"SIGERR", "Signal handler setup error"},
|
||||
{"TTYERR", "Console terminal setup error"},
|
||||
{"SUB", "Subscript out of range"},
|
||||
{"NOFNC", "Command not allowed"},
|
||||
{"UDIS", "Unit disabled"},
|
||||
{"NORO", "Read only operation not allowed"},
|
||||
{"INVSW", "Invalid switch"},
|
||||
{"MISVAL", "Missing value"},
|
||||
{"2FARG", "Too few arguments"},
|
||||
{"2MARG", "Too many arguments"},
|
||||
{"NXDEV", "Non-existent device"},
|
||||
{"NXUN", "Non-existent unit"},
|
||||
{"NXREG", "Non-existent register"},
|
||||
{"NXPAR", "Non-existent parameter"},
|
||||
{"NEST", "Nested DO command limit exceeded"},
|
||||
{"IERR", "Internal error"},
|
||||
{"MTRLNT", "Invalid magtape record length"},
|
||||
{"LOST", "Console Telnet connection lost"},
|
||||
{"TTMO", "Console Telnet connection timed out"},
|
||||
{"STALL", "Console Telnet output stall"},
|
||||
{"AFAIL", "Assertion failed"},
|
||||
{"INVREM", "Invalid remote console command"},
|
||||
{"EXPECT", "Expect matched"},
|
||||
{"AMBREG", "Ambiguous register name"},
|
||||
{"REMOTE", "remote console command"},
|
||||
{"INVEXPR", "invalid expression"},
|
||||
{"SIGTERM", "SIGTERM received"},
|
||||
{"FSSIZE", "File System size larger than disk size"},
|
||||
{"RUNTIME", "Run time limit exhausted"},
|
||||
{"INCOMPVHD", "Incompatible VHD Container"},
|
||||
};
|
||||
|
||||
const size_t size_map[] = { sizeof (int8),
|
||||
@ -6089,7 +6090,6 @@ if (flag) {
|
||||
fprintf (st, "\n Time taken by msleep(1): %dms", os_ms_sleep_1);
|
||||
if (eth_version ())
|
||||
fprintf (st, "\n Ethernet packet info: %s", eth_version());
|
||||
fprintf (st, "\n Time taken by msleep(1): %dms", os_ms_sleep_1);
|
||||
#if defined(__VMS)
|
||||
if (1) {
|
||||
char *arch =
|
||||
|
||||
@ -433,8 +433,9 @@ typedef uint32 t_addr;
|
||||
#define SCPE_SIGTERM (SCPE_BASE + 48) /* SIGTERM has been received */
|
||||
#define SCPE_FSSIZE (SCPE_BASE + 49) /* File System size larger than disk size */
|
||||
#define SCPE_RUNTIME (SCPE_BASE + 50) /* Run Time Limit Exhausted */
|
||||
#define SCPE_INCOMPVHD (SCPE_BASE + 51) /* Incompatible VHD Container */
|
||||
|
||||
#define SCPE_MAX_ERR (SCPE_BASE + 50) /* Maximum SCPE Error Value */
|
||||
#define SCPE_MAX_ERR (SCPE_BASE + 51) /* Maximum SCPE Error Value */
|
||||
#define SCPE_KFLAG 0x10000000 /* tti data flag */
|
||||
#define SCPE_BREAK 0x20000000 /* tti break flag */
|
||||
#define SCPE_NOMESSAGE 0x40000000 /* message display supression flag */
|
||||
@ -675,9 +676,9 @@ struct UNIT {
|
||||
#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_S_TAPE_FMT 4 /* 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_V_TAPE_ANSI 17 /* 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)
|
||||
|
||||
|
||||
264
sim_disk.c
264
sim_disk.c
@ -53,14 +53,6 @@ Public routines:
|
||||
sim_disk_data_trace debug support
|
||||
sim_disk_test unit test routine
|
||||
|
||||
Guest-specific routines for PDP-10 which uses 1024 byte sectors and
|
||||
requires mapping functions to allow access to the underlying 512 byte
|
||||
sectors provided by the sim_disk routines
|
||||
|
||||
sim_disk_pdp10_attach attach disk unit
|
||||
sim_disk_pdp10_rdsect read PDP-10 disk sectors
|
||||
sim_disk_pdp10_wrsect write PDP-10 disk sectors
|
||||
|
||||
Internal routines:
|
||||
|
||||
sim_os_disk_open_raw platform specific open raw device
|
||||
@ -282,8 +274,8 @@ static t_offset sim_vhd_disk_size (FILE *f);
|
||||
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
||||
static t_stat sim_vhd_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects);
|
||||
static t_stat sim_vhd_disk_clearerr (UNIT *uptr);
|
||||
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype);
|
||||
static const char *sim_vhd_disk_get_dtype (FILE *f);
|
||||
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype, uint32 SectorSize, uint32 xfer_element_size);
|
||||
static const char *sim_vhd_disk_get_dtype (FILE *f, uint32 *SectorSize, uint32 *xfer_element_size);
|
||||
static t_stat sim_os_disk_implemented_raw (void);
|
||||
static FILE *sim_os_disk_open_raw (const char *rawdevicename, const char *openmode);
|
||||
static int sim_os_disk_close_raw (FILE *f);
|
||||
@ -306,11 +298,11 @@ struct sim_disk_fmt {
|
||||
};
|
||||
|
||||
static struct sim_disk_fmt fmts[] = {
|
||||
{ "AUTO", 0, DKUF_F_AUTO, NULL},
|
||||
{ "SIMH", 0, DKUF_F_STD, NULL},
|
||||
{ "RAW", 0, DKUF_F_RAW, sim_os_disk_implemented_raw},
|
||||
{ "VHD", 0, DKUF_F_VHD, sim_vhd_disk_implemented},
|
||||
{ NULL, 0, 0, NULL}
|
||||
{ "AUTO detect", 0, DKUF_F_AUTO, NULL},
|
||||
{ "SIMH", 0, DKUF_F_STD, NULL},
|
||||
{ "RAW", 0, DKUF_F_RAW, sim_os_disk_implemented_raw},
|
||||
{ "VHD", 0, DKUF_F_VHD, sim_vhd_disk_implemented},
|
||||
{ NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
/* Set disk format */
|
||||
@ -321,10 +313,10 @@ uint32 f;
|
||||
|
||||
if (uptr == NULL)
|
||||
return SCPE_IERR;
|
||||
if (cptr == NULL)
|
||||
if ((cptr == NULL) || (*cptr == '\0'))
|
||||
return SCPE_ARG;
|
||||
for (f = 0; fmts[f].name; f++) {
|
||||
if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) {
|
||||
if (fmts[f].name && (MATCH_CMD (cptr, fmts[f].name) == 0)) {
|
||||
if ((fmts[f].impl_fnc) && (fmts[f].impl_fnc() != SCPE_OK))
|
||||
return SCPE_NOFNC;
|
||||
uptr->flags = (uptr->flags & ~DKUF_FMT) |
|
||||
@ -2031,13 +2023,13 @@ for (i = 0; checks[i] != NULL; i++) {
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
|
||||
t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontchangecapac,
|
||||
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay)
|
||||
{
|
||||
return sim_disk_attach_ex (uptr, cptr, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay, NULL);
|
||||
return sim_disk_attach_ex (uptr, cptr, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay, NULL);
|
||||
}
|
||||
|
||||
t_stat sim_disk_attach_ex (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
|
||||
t_stat sim_disk_attach_ex (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontchangecapac,
|
||||
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay, const char **drivetypes)
|
||||
{
|
||||
struct disk_context *ctx;
|
||||
@ -2079,7 +2071,7 @@ if (sim_switches & SWMASK ('D')) { /* create difference dis
|
||||
vhd = sim_vhd_disk_create_diff (gbuf, cptr);
|
||||
if (vhd) {
|
||||
sim_vhd_disk_close (vhd);
|
||||
return sim_disk_attach (uptr, gbuf, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
return sim_disk_attach (uptr, gbuf, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
}
|
||||
return sim_messagef (SCPE_ARG, "Unable to create differencing VHD: %s\n", gbuf);
|
||||
}
|
||||
@ -2098,7 +2090,7 @@ if (sim_switches & SWMASK ('C')) { /* create vhd disk & cop
|
||||
sim_switches |= SWMASK ('R') | SWMASK ('E');
|
||||
sim_quiet = TRUE;
|
||||
/* First open the source of the copy operation */
|
||||
r = sim_disk_attach (uptr, cptr, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
r = sim_disk_attach (uptr, cptr, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
sim_quiet = saved_sim_quiet;
|
||||
if (r != SCPE_OK) {
|
||||
sim_switches = saved_sim_switches;
|
||||
@ -2228,7 +2220,7 @@ else
|
||||
t_stat r;
|
||||
|
||||
sim_vhd_disk_close (vhd);
|
||||
r = sim_disk_attach (uptr, Parent, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
r = sim_disk_attach (uptr, Parent, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
free (Parent);
|
||||
return r;
|
||||
}
|
||||
@ -2328,13 +2320,27 @@ else { /* normal */
|
||||
} /* end if null */
|
||||
} /* end else */
|
||||
if (DK_GET_FMT (uptr) == DKUF_F_VHD) {
|
||||
if ((created) && dtype)
|
||||
sim_vhd_disk_set_dtype (uptr->fileref, dtype);
|
||||
if (dtype && strcmp (dtype, sim_vhd_disk_get_dtype (uptr->fileref))) {
|
||||
char cmd[32];
|
||||
uint32 sector_size, xfer_element_size;
|
||||
|
||||
sprintf (cmd, "%s%d %s", dptr->name, (int)(uptr-dptr->units), sim_vhd_disk_get_dtype (uptr->fileref));
|
||||
set_cmd (0, cmd);
|
||||
if ((created) && dtype)
|
||||
sim_vhd_disk_set_dtype (uptr->fileref, dtype, ctx->sector_size, ctx->xfer_element_size);
|
||||
if (dtype && strcmp (dtype, sim_vhd_disk_get_dtype (uptr->fileref, §or_size, &xfer_element_size))) {
|
||||
char cmd[32];
|
||||
t_stat r = SCPE_OK;
|
||||
|
||||
if (((sector_size == 0) || (sector_size == ctx->sector_size)) &&
|
||||
((xfer_element_size == 0) || (xfer_element_size == ctx->xfer_element_size))) {
|
||||
sprintf (cmd, "%s%d %s", dptr->name, (int)(uptr-dptr->units), sim_vhd_disk_get_dtype (uptr->fileref, NULL, NULL));
|
||||
r = set_cmd (0, cmd);
|
||||
if (r != SCPE_OK)
|
||||
r = sim_messagef (r, "Can't set %s%d to drive type %s\n", dptr->name, (int)(uptr-dptr->units), sim_vhd_disk_get_dtype (uptr->fileref, NULL, NULL));
|
||||
}
|
||||
else
|
||||
r = sim_messagef (SCPE_INCOMPVHD, "VHD incompatible with %s simulator\n", sim_name);
|
||||
if (r != SCPE_OK) {
|
||||
sim_disk_detach (uptr); /* report error now */
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
uptr->flags = uptr->flags | UNIT_ATT;
|
||||
@ -2468,9 +2474,11 @@ filesystem_size = get_filesystem_size (uptr);
|
||||
container_size = size_function (uptr->fileref);
|
||||
current_unit_size = ((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1);
|
||||
if (container_size && (container_size != (t_offset)-1)) {
|
||||
if (dontautosize) {
|
||||
if (dontchangecapac) {
|
||||
t_addr saved_capac = uptr->capac;
|
||||
|
||||
if (filesystem_size == (t_offset)-1) /* No file system found? */
|
||||
filesystem_size = container_size; /* Assume full container */
|
||||
if (filesystem_size != (t_offset)-1) {
|
||||
const char *drive_type = NULL;
|
||||
|
||||
@ -2600,16 +2608,53 @@ return SCPE_OK;
|
||||
|
||||
t_stat sim_disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||
{
|
||||
static struct example_fields {
|
||||
const char *dname;
|
||||
const char *dtype;
|
||||
const char *dsize;
|
||||
const char *dtype2;
|
||||
const char *dsize2;
|
||||
const char *dtype3;
|
||||
const char *dsize3;
|
||||
const char *dtype4;
|
||||
const char *dsize4;
|
||||
} ex_data[] = {
|
||||
{"RQ", "RD54", "159MB", "RX50", "409KB", "RA81", "456MB", "RA92", "1505MB"},
|
||||
{"RP", "RM03", "33MW", "RM03", "33MW", "RP07", "258MW", "RM03", "15MW"},
|
||||
{"RP", "RM03", "39MW", "RM03", "39MW", "RP07", "110MW", "RM03", "15MW"},
|
||||
};
|
||||
struct example_fields *ex = &ex_data[0];
|
||||
|
||||
if (strcmp (dptr->name, "RP") == 0)
|
||||
ex = &ex_data[1];
|
||||
if (strstr (sim_name, "-10")) {
|
||||
ex = &ex_data[2];
|
||||
if (strstr (sim_name, "PDP") == NULL)
|
||||
ex->dname = "RPA";
|
||||
}
|
||||
|
||||
fprintf (st, "%s Disk Attach Help\n\n", dptr->name);
|
||||
|
||||
fprintf (st, "Disk container files can be one of 3 different types:\n\n");
|
||||
fprintf (st, " SIMH A disk is an unstructured binary file of the size appropriate\n");
|
||||
fprintf (st, " for the disk drive being simulated\n");
|
||||
fprintf (st, " VHD Virtual Disk format which is described in the \"Microsoft\n");
|
||||
fprintf (st, " Virtual Hard Disk (VHD) Image Format Specification\". The\n");
|
||||
fprintf (st, " VHD implementation includes support for 1) Fixed (Preallocated)\n");
|
||||
fprintf (st, " disks, 2) Dynamically Expanding disks, and 3) Differencing disks.\n");
|
||||
fprintf (st, " RAW platform specific access to physical disk or CDROM drives\n\n");
|
||||
fprintf (st, "Disk container files can be one of several different types:\n\n");
|
||||
if (strstr (sim_name, "-10") == NULL) {
|
||||
fprintf (st, " SIMH A disk is an unstructured binary file of the size appropriate\n");
|
||||
fprintf (st, " for the disk drive being simulated accessed by C runtime APIs\n");
|
||||
fprintf (st, " VHD Virtual Disk format which is described in the \"Microsoft\n");
|
||||
fprintf (st, " Virtual Hard Disk (VHD) Image Format Specification\". The\n");
|
||||
fprintf (st, " VHD implementation includes support for 1) Fixed (Preallocated)\n");
|
||||
fprintf (st, " disks, 2) Dynamically Expanding disks, and 3) Differencing disks.\n");
|
||||
fprintf (st, " RAW platform specific access to physical disk or CDROM drives\n\n");
|
||||
}
|
||||
else {
|
||||
fprintf (st, " SIMH A disk is an unstructured binary file of 64bit integers\n"
|
||||
" access by C runtime APIs\n");
|
||||
fprintf (st, " VHD A disk is an unstructured binary file of 64bit integers\n"
|
||||
" contained in a VHD container\n");
|
||||
fprintf (st, " RAW A disk is an unstructured binary file of 64bit integers\n"
|
||||
" accessed by direct read/write APIs\n");
|
||||
fprintf (st, " DBD9 Compatible with KLH10 is a packed big endian word\n");
|
||||
fprintf (st, " DLD9 Compatible with KLH10 is a packed little endian word\n\n");
|
||||
}
|
||||
fprintf (st, "Virtual (VHD) Disks supported conform to \"Virtual Hard Disk Image Format\n");
|
||||
fprintf (st, "Specification\", Version 1.0 October 11, 2006.\n");
|
||||
fprintf (st, "Dynamically expanding disks never change their \"Virtual Size\", but they don't\n");
|
||||
@ -2676,54 +2721,62 @@ fprintf (st, " -M Merge a Differencing VHD into its parent VHD disk\
|
||||
fprintf (st, " -O Override consistency checks when attaching differencing disks\n");
|
||||
fprintf (st, " which have unexpected parent disk GUID or timestamps\n\n");
|
||||
fprintf (st, " -U Fix inconsistencies which are overridden by the -O switch\n");
|
||||
fprintf (st, " -Y Answer Yes to prompt to overwrite last track (on disk create)\n");
|
||||
fprintf (st, " -N Answer No to prompt to overwrite last track (on disk create)\n");
|
||||
if (strstr (sim_name, "-10") == NULL) {
|
||||
fprintf (st, " -Y Answer Yes to prompt to overwrite last track (on disk create)\n");
|
||||
fprintf (st, " -N Answer No to prompt to overwrite last track (on disk create)\n");
|
||||
}
|
||||
fprintf (st, "Examples:\n");
|
||||
fprintf (st, " sim> show rq\n");
|
||||
fprintf (st, " RQ, address=20001468-2000146B*, no vector, 4 units\n");
|
||||
fprintf (st, " RQ0, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n");
|
||||
fprintf (st, " RQ1, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n");
|
||||
fprintf (st, " RQ2, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n");
|
||||
fprintf (st, " RQ3, 409KB, not attached, write enabled, RX50, autosize, SIMH format\n");
|
||||
fprintf (st, " sim> atta rq0 RA81.vhd\n");
|
||||
fprintf (st, " sim> show rq0\n");
|
||||
fprintf (st, " RQ0, 456MB, attached to RA81.vhd, write enabled, RA81, autosize, VHD format\n");
|
||||
fprintf (st, " sim> set rq2 ra92\n");
|
||||
fprintf (st, " sim> att rq2 -f vhd RA92.vhd\n");
|
||||
fprintf (st, " RQ2: creating new file\n");
|
||||
fprintf (st, " sim> sho rq2\n");
|
||||
fprintf (st, " RQ2, 1505MB, attached to RA92.vhd, write enabled, RA92, autosize, VHD format\n");
|
||||
fprintf (st, " sim> dir RA92.vhd\n");
|
||||
fprintf (st, " sim> show %s\n", ex->dname);
|
||||
fprintf (st, " %s, address=20001468-2000146B*, no vector, 4 units\n", ex->dname);
|
||||
fprintf (st, " %s0, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize, ex->dtype);
|
||||
fprintf (st, " %s1, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize, ex->dtype);
|
||||
fprintf (st, " %s2, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize, ex->dtype);
|
||||
fprintf (st, " %s3, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize2, ex->dtype2);
|
||||
fprintf (st, " sim> # attach an existing VHD and determine its size and type automatically\n");
|
||||
fprintf (st, " sim> attach %s0 %s.vhd\n", ex->dname, ex->dtype3);
|
||||
fprintf (st, " sim> show %s0\n", ex->dname);
|
||||
fprintf (st, " %s0, %s, attached to %s.vhd, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize3, ex->dtype3, ex->dtype3);
|
||||
fprintf (st, " sim> # create a new %s drive type VHD\n", ex->dtype4);
|
||||
fprintf (st, " sim> set %s2 %s\n", ex->dname, ex->dtype4);
|
||||
fprintf (st, " sim> attach %s2 -f vhd %s.vhd\n", ex->dname, ex->dtype4);
|
||||
fprintf (st, " %s2: creating new file\n", ex->dname);
|
||||
fprintf (st, " sim> show %s2\n", ex->dname);
|
||||
fprintf (st, " %s2, %s, attached to %s.vhd, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize4, ex->dtype4, ex->dtype4);
|
||||
fprintf (st, " sim> # examine the size consumed by the %s VHD file\n", ex->dsize4);
|
||||
fprintf (st, " sim> dir %s.vhd\n", ex->dtype4);
|
||||
fprintf (st, " Directory of H:\\Data\n\n");
|
||||
fprintf (st, " 04/14/2011 12:57 PM 5,120 RA92.vhd\n");
|
||||
fprintf (st, " 04/14/2011 12:57 PM 5,120 %s.vhd\n", ex->dtype4);
|
||||
fprintf (st, " 1 File(s) 5,120 bytes\n");
|
||||
fprintf (st, " sim> atta rq3 -d RA92-1-Diff.vhd RA92.vhd\n");
|
||||
fprintf (st, " sim> atta rq3 -c RA92-1.vhd RA92.vhd\n");
|
||||
fprintf (st, " RQ3: creating new virtual disk 'RA92-1.vhd'\n");
|
||||
fprintf (st, " RQ3: Copied 1505MB. 99%% complete.\n");
|
||||
fprintf (st, " RQ3: Copied 1505MB. Done.\n");
|
||||
fprintf (st, " sim> sh rq3\n");
|
||||
fprintf (st, " RQ3, 1505MB, attached to RA92-1.vhd, write enabled, RA92, autosize, VHD format\n");
|
||||
fprintf (st, " sim> dir RA92*\n");
|
||||
fprintf (st, " sim> # create a differencing vhd (%s-1-Diff.vhd) with %s.vhd as parent\n", ex->dtype4, ex->dtype4);
|
||||
fprintf (st, " sim> attach %s3 -d %s-1-Diff.vhd %s.vhd\n", ex->dname, ex->dtype4, ex->dtype4);
|
||||
fprintf (st, " sim> # create a VHD (%s-1.vhd) which is a copy of an existing disk\n", ex->dtype4);
|
||||
fprintf (st, " sim> attach %s3 -c %s-1.vhd %s.vhd\n", ex->dname, ex->dtype4, ex->dtype4);
|
||||
fprintf (st, " %s3: creating new virtual disk '%s-1.vhd'\n", ex->dname, ex->dtype4);
|
||||
fprintf (st, " %s3: Copied %s. 99%% complete.\n", ex->dname, ex->dsize4);
|
||||
fprintf (st, " %s3: Copied %s. Done.\n", ex->dname, ex->dsize4);
|
||||
fprintf (st, " sim> show %s3\n", ex->dname);
|
||||
fprintf (st, " %s3, %s, attached to %s-1.vhd, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize4, ex->dtype4, ex->dtype4);
|
||||
fprintf (st, " sim> dir %s*\n", ex->dtype4);
|
||||
fprintf (st, " Directory of H:\\Data\n\n");
|
||||
fprintf (st, " 04/14/2011 01:12 PM 5,120 RA92-1.vhd\n");
|
||||
fprintf (st, " 04/14/2011 12:58 PM 5,120 RA92.vhd\n");
|
||||
fprintf (st, " 04/14/2011 01:12 PM 5,120 %s-1.vhd\n", ex->dtype4);
|
||||
fprintf (st, " 04/14/2011 12:58 PM 5,120 %s.vhd\n", ex->dtype4);
|
||||
fprintf (st, " 2 File(s) 10,240 bytes\n");
|
||||
fprintf (st, " sim> sho rq2\n");
|
||||
fprintf (st, " RQ2, 1505MB, not attached, write enabled, RA92, autosize, VHD format\n");
|
||||
fprintf (st, " sim> set rq2 ra81\n");
|
||||
fprintf (st, " sim> set rq2 noauto\n");
|
||||
fprintf (st, " sim> sho rq2\n");
|
||||
fprintf (st, " RQ2, 456MB, not attached, write enabled, RA81, noautosize, VHD format\n");
|
||||
fprintf (st, " sim> set rq2 format=simh\n");
|
||||
fprintf (st, " sim> sho rq2\n");
|
||||
fprintf (st, " RQ2, 456MB, not attached, write enabled, RA81, noautosize, SIMH format\n");
|
||||
fprintf (st, " sim> atta rq2 -c RA81-Copy.vhd VMS055.dsk\n");
|
||||
fprintf (st, " RQ2: creating new virtual disk 'RA81-Copy.vhd'\n");
|
||||
fprintf (st, " RQ2: Copied 456MB. 99%% complete.\n");
|
||||
fprintf (st, " RQ2: Copied 456MB. Done.\n");
|
||||
fprintf (st, " sim> sho rq2\n");
|
||||
fprintf (st, " RQ2, 456MB, attached to RA81-Copy.vhd, write enabled, RA81, noautosize, VHD format\n");
|
||||
fprintf (st, " sim> show %s2\n", ex->dname);
|
||||
fprintf (st, " %s2, %s, not attached, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize4, ex->dtype4);
|
||||
fprintf (st, " sim> set %s2 %s\n", ex->dname, ex->dtype3);
|
||||
fprintf (st, " sim> set %s2 noauto\n", ex->dname);
|
||||
fprintf (st, " sim> show %s2\n", ex->dname);
|
||||
fprintf (st, " %s2, %s, not attached, write enabled, %s, noautosize, VHD format\n", ex->dname, ex->dsize3, ex->dtype3);
|
||||
fprintf (st, " sim> set %s2 format=simh\n", ex->dname);
|
||||
fprintf (st, " sim> show %s2\n", ex->dname);
|
||||
fprintf (st, " %s2, %s, not attached, write enabled, %s, noautosize, SIMH format\n", ex->dname, ex->dsize3, ex->dtype3);
|
||||
fprintf (st, " sim> # create a VHD from an existing SIMH format disk\n");
|
||||
fprintf (st, " sim> attach %s2 -c %s-Copy.vhd XYZZY.dsk\n", ex->dname, ex->dtype3);
|
||||
fprintf (st, " %s2: creating new virtual disk '%s-Copy.vhd'\n", ex->dname, ex->dtype3);
|
||||
fprintf (st, " %s2: Copied %s. 99%% complete.\n", ex->dname, ex->dsize3);
|
||||
fprintf (st, " %s2: Copied %s. Done.\n", ex->dname, ex->dsize3);
|
||||
fprintf (st, " sim> show %s2\n", ex->dname);
|
||||
fprintf (st, " %s2, %s, attached to %s-Copy.vhd, write enabled, %s, noautosize, VHD format\n", ex->dname, ex->dsize3, ex->dtype3, ex->dtype3);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -2877,37 +2930,6 @@ if (sim_deb && (dptr->dctrl & reason)) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Guest specific Disk I/O support */
|
||||
#define PDP10_SECTORS 2 /* PDP-10 sectors are 1024 bytes */
|
||||
|
||||
t_stat sim_disk_pdp10_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
|
||||
uint32 dbit, const char *dtype, int completion_delay, const char **drivetypes)
|
||||
{
|
||||
return sim_disk_attach_ex (uptr, cptr, sector_size / PDP10_SECTORS, xfer_element_size, dontautosize, dbit, dtype, 0, completion_delay, drivetypes);
|
||||
}
|
||||
|
||||
t_stat sim_disk_pdp10_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects)
|
||||
{
|
||||
t_seccnt sectors;
|
||||
t_stat r = sim_disk_rdsect (uptr, lba * PDP10_SECTORS, buf, §ors, sects * PDP10_SECTORS);
|
||||
|
||||
if (sectsread)
|
||||
*sectsread = sectors / PDP10_SECTORS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
t_stat sim_disk_pdp10_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects)
|
||||
{
|
||||
t_seccnt sectors;
|
||||
t_stat r = sim_disk_wrsect (uptr, lba * PDP10_SECTORS, buf, §ors, sects * PDP10_SECTORS);
|
||||
|
||||
if (sectswritten)
|
||||
*sectswritten = sectors / PDP10_SECTORS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* OS Specific RAW Disk I/O support */
|
||||
|
||||
#if defined _WIN32
|
||||
@ -3858,10 +3880,12 @@ typedef struct _VHD_Footer {
|
||||
name as a nul terminated string.
|
||||
*/
|
||||
uint8 DriveType[16];
|
||||
uint32 DriveSectorSize;
|
||||
uint32 DriveTransferElementSize;
|
||||
/*
|
||||
This field contains zeroes. It is 400 bytes in size.
|
||||
This field contains zeroes. It is 392 bytes in size.
|
||||
*/
|
||||
uint8 Reserved[400];
|
||||
uint8 Reserved[392];
|
||||
} VHD_Footer;
|
||||
|
||||
/*
|
||||
@ -4331,13 +4355,15 @@ static t_stat sim_vhd_disk_implemented (void)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype)
|
||||
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype, uint32 SectorSize, uint32 xfer_element_size)
|
||||
{
|
||||
VHDHANDLE hVHD = (VHDHANDLE)f;
|
||||
int Status = 0;
|
||||
|
||||
memset (hVHD->Footer.DriveType, '\0', sizeof hVHD->Footer.DriveType);
|
||||
memcpy (hVHD->Footer.DriveType, dtype, ((1+strlen (dtype)) < sizeof (hVHD->Footer.DriveType)) ? (1+strlen (dtype)) : sizeof (hVHD->Footer.DriveType));
|
||||
hVHD->Footer.DriveSectorSize = NtoHl (SectorSize);
|
||||
hVHD->Footer.DriveTransferElementSize = NtoHl (xfer_element_size);
|
||||
hVHD->Footer.Checksum = 0;
|
||||
hVHD->Footer.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Footer, sizeof(hVHD->Footer)));
|
||||
|
||||
@ -4383,10 +4409,14 @@ if (Status)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static const char *sim_vhd_disk_get_dtype (FILE *f)
|
||||
static const char *sim_vhd_disk_get_dtype (FILE *f, uint32 *SectorSize, uint32 *xfer_element_size)
|
||||
{
|
||||
VHDHANDLE hVHD = (VHDHANDLE)f;
|
||||
|
||||
if (SectorSize)
|
||||
*SectorSize = NtoHl (hVHD->Footer.DriveSectorSize);
|
||||
if (xfer_element_size)
|
||||
*xfer_element_size = NtoHl (hVHD->Footer.DriveTransferElementSize);
|
||||
return (char *)(&hVHD->Footer.DriveType[0]);
|
||||
}
|
||||
|
||||
@ -5052,6 +5082,8 @@ hVHD->Dynamic.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Dynamic, size
|
||||
hVHD->Footer.Checksum = 0;
|
||||
hVHD->Footer.DiskType = NtoHl (VHD_DT_Differencing);
|
||||
memcpy (hVHD->Footer.DriveType, ParentFooter.DriveType, sizeof (hVHD->Footer.DriveType));
|
||||
hVHD->Footer.DriveSectorSize = ParentFooter.DriveSectorSize;
|
||||
hVHD->Footer.DriveTransferElementSize = ParentFooter.DriveTransferElementSize;
|
||||
hVHD->Footer.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Footer, sizeof(hVHD->Footer)));
|
||||
|
||||
if (WriteFilePosition (hVHD->File,
|
||||
|
||||
23
sim_disk.h
23
sim_disk.h
@ -68,10 +68,25 @@ typedef void (*DISK_PCALLBACK)(UNIT *unit, t_stat status);
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
|
||||
uint32 debugbit, const char *drivetype, uint32 pdp11_tracksize, int completion_delay);
|
||||
t_stat sim_disk_attach_ex (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
|
||||
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay, const char **drivetypes);
|
||||
t_stat sim_disk_attach (UNIT *uptr,
|
||||
const char *cptr,
|
||||
size_t sector_size, size_t xfer_element_size,
|
||||
t_bool dontchangecapac,
|
||||
uint32 debugbit,
|
||||
const char *drivetype,
|
||||
uint32 pdp11_tracksize,
|
||||
int completion_delay);
|
||||
t_stat sim_disk_attach_ex (UNIT *uptr,
|
||||
const char *cptr,
|
||||
size_t sector_size,
|
||||
size_t xfer_element_size,
|
||||
t_bool dontchangecapac, /* if false just change uptr->capac as needed */
|
||||
uint32 dbit, /* debug bit */
|
||||
const char *dtype, /* drive type */
|
||||
uint32 pdp11tracksize, /* BAD144 track */
|
||||
int completion_delay, /* Minimum Delay for asynch I/O completion */
|
||||
const char **drivetypes); /* list of drive types (from smallest to largest) */
|
||||
/* to try and fit the container/file system into */
|
||||
t_stat sim_disk_detach (UNIT *uptr);
|
||||
t_stat sim_disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||
t_stat sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
||||
|
||||
308
sim_tape.c
308
sim_tape.c
@ -114,6 +114,7 @@ static struct sim_tape_fmt {
|
||||
{ "TAR", UNIT_RO, 0, 0 },
|
||||
{ "ANSI", UNIT_RO, 0, 0 },
|
||||
{ "FIXED", UNIT_RO, 0, 0 },
|
||||
{ "DOS11", UNIT_RO, 0, 0 },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@ -518,7 +519,26 @@ static void sim_tape_add_ansi_entry (const char *directory,
|
||||
const struct stat *filestat,
|
||||
void *context);
|
||||
static t_bool memory_tape_add_block (MEMORY_TAPE *tape, uint8 *block, uint32 size);
|
||||
|
||||
typedef struct DOS11_HDR {
|
||||
uint16 fname[2]; /* File name (RAD50 - 6 characters) */
|
||||
uint16 ext; /* Extension (RAD50 - 3 characters) */
|
||||
uint8 prog; /* Programmer # */
|
||||
uint8 proj; /* Project # */
|
||||
uint16 prot; /* Protection */
|
||||
uint16 date; /* (year - 1970) * 1000 + day of year */
|
||||
uint16 fname3; /* File name (RAD50 - 3 characters) */
|
||||
} DOS11_HDR;
|
||||
#define DOS11_PROT 0233
|
||||
|
||||
static void sim_tape_add_dos11_entry (const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
const struct stat *filestat,
|
||||
void *context);
|
||||
|
||||
static t_stat sim_export_tape (UNIT *uptr, const char *export_file);
|
||||
static FILE *tape_open_and_check_file(const char *filename);
|
||||
static int tape_classify_file_contents (FILE *f, size_t *max_record_size, t_bool *lf_line_endings, t_bool *crlf_line_endings);
|
||||
|
||||
|
||||
@ -659,8 +679,6 @@ else {
|
||||
if ((MT_GET_FMT (uptr) == MTUF_F_TAR) && (uptr->recsize == 0))
|
||||
uptr->recsize = TAR_DFLT_RECSIZE;
|
||||
}
|
||||
if (sim_switches & SWMASK ('X'))
|
||||
cptr = get_glyph_nc (cptr, export_file, 0); /* get spec */
|
||||
if ((MT_GET_FMT (uptr) == MTUF_F_TPC) ||
|
||||
(MT_GET_FMT (uptr) == MTUF_F_TAR) ||
|
||||
(MT_GET_FMT (uptr) >= MTUF_F_ANSI))
|
||||
@ -807,6 +825,48 @@ switch (MT_GET_FMT (uptr)) {
|
||||
}
|
||||
break;
|
||||
|
||||
case MTUF_F_DOS11:
|
||||
if (1) {
|
||||
const char *ocptr = cptr;
|
||||
int file_errors = 0;
|
||||
|
||||
uptr->recsize = 512;
|
||||
|
||||
tape = memory_create_tape();
|
||||
tape->block_size = uptr->recsize;
|
||||
uptr->fileref = (FILE *)tape;
|
||||
if (!uptr->fileref)
|
||||
return SCPE_MEM;
|
||||
|
||||
while (*cptr != 0) {
|
||||
uint32 initial_file_count = tape->file_count;
|
||||
|
||||
cptr = get_glyph_nc (cptr, gbuf, ','); /* Get filename */
|
||||
r = sim_dir_scan (gbuf, sim_tape_add_dos11_entry, tape);
|
||||
if (r != SCPE_OK)
|
||||
sim_messagef (SCPE_ARG, "file not found: %s\n", gbuf);
|
||||
if (tape->file_count == initial_file_count)
|
||||
++file_errors;
|
||||
}
|
||||
|
||||
if ((tape->file_count > 0) && (file_errors == 0)) {
|
||||
r = SCPE_OK;
|
||||
memory_tape_add_block (tape, NULL, 0); /* Tape Mark */
|
||||
memory_tape_add_block (tape, NULL, 0); /* Tape Mark */
|
||||
uptr->flags |= UNIT_ATT;
|
||||
uptr->filename = (char *)malloc (strlen (ocptr) + 1);
|
||||
strcpy (uptr->filename, ocptr);
|
||||
uptr->tape_eom = tape->record_count;
|
||||
}
|
||||
else {
|
||||
r = SCPE_ARG;
|
||||
memory_free_tape (uptr->fileref);
|
||||
uptr->fileref = NULL;
|
||||
cptr = ocptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MTUF_F_TAR:
|
||||
if (uptr->recsize == 0)
|
||||
uptr->recsize = TAR_DFLT_RECSIZE; /* Apply default block size */
|
||||
@ -820,6 +880,7 @@ if (r != SCPE_OK) { /* error? */
|
||||
case MTUF_F_ANSI:
|
||||
case MTUF_F_TAR:
|
||||
case MTUF_F_FIXED:
|
||||
case MTUF_F_DOS11:
|
||||
r = sim_messagef (r, "Error opening %s format internal tape image generated from: %s\n", _sim_tape_format_name (uptr), cptr);
|
||||
break;
|
||||
default:
|
||||
@ -975,7 +1036,8 @@ fprintf (st, " -E Must Exist (if not specified, the default behavior
|
||||
fprintf (st, " attempt to create the indicated virtual tape file).\n");
|
||||
fprintf (st, " -F Open the indicated tape container in a specific format\n");
|
||||
fprintf (st, " (default is SIMH, alternatives are E11, TPC, P7B, AWS, TAR,\n");
|
||||
fprintf (st, " ANSI-VMS, ANSI-RT11, ANSI-RSX11, ANSI-RSTS, ANSI-VAR, FIXED)\n");
|
||||
fprintf (st, " ANSI-VMS, ANSI-RT11, ANSI-RSX11, ANSI-RSTS, ANSI-VAR, FIXED,\n");
|
||||
fprintf (st, " DOS11)\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");
|
||||
@ -1000,12 +1062,23 @@ fprintf (st, " accessible directly as files on the tape.\n\n");
|
||||
fprintf (st, " FIXED format will present the contents of a file (text or binary) as\n");
|
||||
fprintf (st, " fixed sized records/blocks with ascii text data optionally converted\n");
|
||||
fprintf (st, " to EBCDIC.\n\n");
|
||||
fprintf (st, " DOS11 format will present the contents of a file preceeded by a DOS11\n");
|
||||
fprintf (st, " 14-byte header. All files will be owned by [1,1], have a default\n");
|
||||
fprintf (st, " protection of <233> and a date in the range 1972 - 1999 with the\n");
|
||||
fprintf (st, " month/day layout as the current year. The file name on the tape\n");
|
||||
fprintf (st, " will be sanitized to contain only alphanumeric characters from the\n");
|
||||
fprintf (st, " original source file name. Characters 7 - 9 of the file name will be\n");
|
||||
fprintf (st, " placed in an otherwise unused word in the header which some DEC\n");
|
||||
fprintf (st, " operating systems will be able to process. If the resulting\n");
|
||||
fprintf (st, " filename is NULL, a filename in the range 000000 - 999999 will be\n");
|
||||
fprintf (st, " generated based of the file position on the tape.\n\n");
|
||||
fprintf (st, "Examples:\n\n");
|
||||
fprintf (st, " sim> ATTACH %s -F ANSI-VMS Hobbyist-USE-ONLY-VA.TXT\n", dptr->name);
|
||||
fprintf (st, " sim> ATTACH %s -F ANSI-RSX11 *.TXT,*.ini,*.exe\n", dptr->name);
|
||||
fprintf (st, " sim> ATTACH %s -FX ANSI-RSTS RSTS.tap *.TXT,*.SAV\n", dptr->name);
|
||||
fprintf (st, " sim> ATTACH %s -F ANSI-RT11 *.TXT,*.TSK\n", dptr->name);
|
||||
fprintf (st, " sim> ATTACH %s -FB FIXED 80 SOMEFILE.TXT\n\n", dptr->name);
|
||||
fprintf (st, " sim> ATTACH %s -FB FIXED 80 SOMEFILE.TXT\n", dptr->name);
|
||||
fprintf (st, " sim> ATTACH %s -F DOS11 *.LDA,*.TXT\n\n", dptr->name);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -1422,6 +1495,7 @@ switch (f) { /* otherwise the read method
|
||||
|
||||
case MTUF_F_ANSI:
|
||||
case MTUF_F_FIXED:
|
||||
case MTUF_F_DOS11:
|
||||
if (1) {
|
||||
MEMORY_TAPE *tape = (MEMORY_TAPE *)uptr->fileref;
|
||||
|
||||
@ -1757,6 +1831,7 @@ switch (f) { /* otherwise the read me
|
||||
|
||||
case MTUF_F_ANSI:
|
||||
case MTUF_F_FIXED:
|
||||
case MTUF_F_DOS11:
|
||||
if (1) {
|
||||
MEMORY_TAPE *tape = (MEMORY_TAPE *)uptr->fileref;
|
||||
|
||||
@ -4340,6 +4415,203 @@ tape->ansi_type = -1;
|
||||
return tape;
|
||||
}
|
||||
|
||||
static const char rad50[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ%.%0123456789";
|
||||
|
||||
static uint16 dos11_ascR50(char *inbuf)
|
||||
{
|
||||
uint16 value;
|
||||
|
||||
value = (strchr (rad50, *inbuf++) - rad50) * 03100;
|
||||
value += (strchr (rad50, *inbuf++) - rad50) * 050;
|
||||
value += (strchr (rad50, *inbuf++) - rad50);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanitize a filename to generate a DOS-11 compatible version. Ignore
|
||||
* non-alphanumerics, upper case lower case characters and terminate on '.'
|
||||
*/
|
||||
static void dos11_sanitize(char *buf, int len, const char *inbuf)
|
||||
{
|
||||
while ((len != 0) && (*inbuf != '\0') && (*inbuf !='.')) {
|
||||
char ch = toupper (*inbuf++);
|
||||
|
||||
if (isalnum(ch)) {
|
||||
*buf++ = ch;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int dos11_copy_ascii_file(FILE *f, MEMORY_TAPE *tape, char *buf, size_t bufSize)
|
||||
{
|
||||
char ch, tmp[512];
|
||||
t_bool crlast = FALSE;
|
||||
int error = 0;
|
||||
size_t i, data_read, offset = 0;
|
||||
|
||||
memset (buf, 0, bufSize);
|
||||
|
||||
while (!feof (f) && !error) {
|
||||
data_read = fread (tmp, 1, sizeof (tmp), f);
|
||||
if (data_read > 0)
|
||||
for (i = 0; i < data_read; i++) {
|
||||
ch = tmp[i];
|
||||
if (ch == '\n') {
|
||||
if (!crlast) {
|
||||
buf[offset++] = '\r';
|
||||
if (offset == bufSize) {
|
||||
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
|
||||
offset = 0;
|
||||
memset (buf, 0, bufSize);
|
||||
}
|
||||
}
|
||||
buf[offset++] = ch;
|
||||
if (offset == bufSize) {
|
||||
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
|
||||
offset = 0;
|
||||
memset (buf, 0, bufSize);
|
||||
}
|
||||
crlast = FALSE;
|
||||
}
|
||||
else {
|
||||
crlast = ch == '\r';
|
||||
|
||||
buf[offset++] = ch;
|
||||
if (offset == bufSize) {
|
||||
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
|
||||
offset = 0;
|
||||
memset (buf, 0, bufSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (offset != 0)
|
||||
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void sim_tape_add_dos11_entry (const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
const struct stat *filestat,
|
||||
void *context)
|
||||
{
|
||||
MEMORY_TAPE *tape = (MEMORY_TAPE *)context;
|
||||
char FullPath[PATH_MAX + 1];
|
||||
FILE *f;
|
||||
size_t max_record_size;
|
||||
t_bool lf_line_endings;
|
||||
t_bool crlf_line_endings;
|
||||
uint8 *block = NULL;
|
||||
int error = 0;
|
||||
DOS11_HDR hdr;
|
||||
char fname[9], ext[3];
|
||||
const char *ptr;
|
||||
struct tm *tm;
|
||||
time_t now = time (NULL);
|
||||
uint16 today;
|
||||
int year;
|
||||
|
||||
/*
|
||||
* Compute a suitable year for file creation date. This year will have the
|
||||
* same calendar as the current year but will be in the 20th century so that
|
||||
* DOS/BATCH-11 will be able to interpret it correctly.
|
||||
*/
|
||||
tm = localtime (&now);
|
||||
year = tm->tm_year + 1900;
|
||||
while (year >= 2000)
|
||||
year -= 28;
|
||||
|
||||
today = ((year - 70) * 1000) + tm->tm_yday + 1;
|
||||
|
||||
sprintf (FullPath, "%s%s", directory, filename);
|
||||
f = tape_open_and_check_file(FullPath);
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
|
||||
|
||||
memset (&hdr, 0, sizeof (hdr));
|
||||
memset (fname, ' ', sizeof (fname));
|
||||
memset (ext, ' ', sizeof (ext));
|
||||
|
||||
dos11_sanitize (fname, sizeof (fname), filename);
|
||||
ptr = strchr (filename, '.');
|
||||
if (ptr != NULL)
|
||||
dos11_sanitize (ext, sizeof (ext), ++ptr);
|
||||
|
||||
/*
|
||||
* If we were unable to generate a valid DOS11 filename, generate one based
|
||||
* on the file number on the tape (000000 - 999999).
|
||||
*/
|
||||
if (fname[0] == ' ') {
|
||||
char temp[10];
|
||||
|
||||
sprintf(temp, "%06u ", tape->file_count % 100000);
|
||||
memcpy(fname, temp, sizeof(fname));
|
||||
}
|
||||
|
||||
hdr.fname[0] = dos11_ascR50 (&fname[0]);
|
||||
hdr.fname[1] = dos11_ascR50 (&fname[3]);
|
||||
hdr.ext = dos11_ascR50 (&ext[0]);
|
||||
hdr.prog = 1;
|
||||
hdr.proj = 1;
|
||||
hdr.prot = DOS11_PROT;
|
||||
hdr.date = today;
|
||||
hdr.fname3 = dos11_ascR50 (&fname[6]);
|
||||
|
||||
memory_tape_add_block (tape, (uint8 *)&hdr, sizeof (hdr));
|
||||
|
||||
rewind (f);
|
||||
block = (uint8 *)calloc (tape->block_size, 1);
|
||||
|
||||
if (lf_line_endings || crlf_line_endings)
|
||||
error = dos11_copy_ascii_file (f, tape, (char *)block, tape->block_size);
|
||||
else {
|
||||
size_t data_read;
|
||||
|
||||
while (!feof (f) && !error) {
|
||||
data_read = fread (block, 1, tape->block_size, f);
|
||||
if (data_read > 0)
|
||||
error = memory_tape_add_block (tape, block, data_read);
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
free (block);
|
||||
memory_tape_add_block (tape, NULL, 0);
|
||||
++tape->file_count;
|
||||
}
|
||||
|
||||
static FILE *tape_open_and_check_file(const char *filename)
|
||||
{
|
||||
FILE *file = fopen(filename, "rb");
|
||||
|
||||
if (file != NULL) {
|
||||
struct stat statb;
|
||||
|
||||
memset (&statb, 0, sizeof (statb));
|
||||
if (fstat (fileno (file), &statb) == 0) {
|
||||
if (((S_IFDIR | S_IFREG) & statb.st_mode) == S_IFREG)
|
||||
return file;
|
||||
|
||||
sim_printf ("Can't put a %s on tape: %s\n",
|
||||
statb.st_mode & S_IFREG ? "directory" : "non regular file",
|
||||
filename);
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
sim_printf ("Can't stat: %s\n", filename);
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
sim_printf ("Can't open: %s - %s\n", filename, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int tape_classify_file_contents (FILE *f, size_t *max_record_size, t_bool *lf_line_endings, t_bool *crlf_line_endings)
|
||||
{
|
||||
long pos = -1;
|
||||
@ -4412,7 +4684,6 @@ return tape;
|
||||
static int ansi_add_file_to_tape (MEMORY_TAPE *tape, const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
struct stat statb;
|
||||
struct ansi_tape_parameters *ansi = &ansi_args[tape->ansi_type];
|
||||
uint8 *block = NULL;
|
||||
size_t max_record_size;
|
||||
@ -4427,27 +4698,10 @@ HDR2 hdr2;
|
||||
HDR3 hdr3;
|
||||
HDR4 hdr4;
|
||||
|
||||
f = fopen (filename, "rb");
|
||||
if (f == NULL) {
|
||||
sim_printf ("Can't open: %s - %s\n", filename, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
memset (&statb, 0, sizeof (statb));
|
||||
if (fstat (fileno (f), &statb)) {
|
||||
sim_printf ("Can't stat: %s\n", filename);
|
||||
fclose (f);
|
||||
return -1;
|
||||
}
|
||||
if (S_IFDIR & statb.st_mode) {
|
||||
sim_printf ("Can't put a directory on tape: %s\n", filename);
|
||||
fclose (f);
|
||||
return -1;
|
||||
}
|
||||
if (!(S_IFREG & statb.st_mode)) {
|
||||
sim_printf ("Can't put a non regular file on tape: %s\n", filename);
|
||||
fclose (f);
|
||||
return -1;
|
||||
}
|
||||
f = tape_open_and_check_file(filename);
|
||||
if (f == NULL)
|
||||
return TRUE;
|
||||
|
||||
tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
|
||||
ansi_make_HDR1 (&hdr1, &tape->vol1, &hdr4, filename, tape->ansi_type);
|
||||
sprintf (file_sequence, "%04d", 1 + tape->file_count);
|
||||
@ -4580,4 +4834,4 @@ free (buf);
|
||||
fclose (f);
|
||||
uptr->pos = saved_pos;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,6 +100,7 @@ typedef struct {
|
||||
#define MTUF_F_TAR 5 /* TAR format */
|
||||
#define MTUF_F_ANSI 6 /* ANSI format */
|
||||
#define MTUF_F_FIXED 7 /* FIXED format */
|
||||
#define MTUF_F_DOS11 8 /* DOS11 format */
|
||||
|
||||
#define MTAT_F_VMS 0 /* VMS ANSI type */
|
||||
#define MTAT_F_RSX11 1 /* RSX-11 ANSI type */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user