SIM_CARD: cleaned up handling of binary cards.

Handling of first character ~ to simulate End of File, now only
is treated as End of File if it appears on a line by itself.
This commit is contained in:
Richard Cornwell 2017-01-30 20:49:32 -05:00
parent d14243c858
commit 057120e0b3
3 changed files with 211 additions and 125 deletions

View file

@ -38,7 +38,7 @@
/* For Card reader, when set returns end of file at end of deck. */ /* For Card reader, when set returns end of file at end of deck. */
/* Reset after sent to system */ /* Reset after sent to system */
#define MODE_EOF (0x40 << UNIT_V_MODE) #define MODE_EOF (0x40 << UNIT_V_CARD_MODE)

View file

@ -1,4 +1,4 @@
/* Card read/punch routines for 7000 simulators. /* Generic Card read/punch routines for simulators.
Copyright (c) 2005, Richard Cornwell Copyright (c) 2005, Richard Cornwell
@ -61,9 +61,9 @@
The card module uses up7 to hold a buffer for the card being translated The card module uses up7 to hold a buffer for the card being translated
and the backward translation table. Which is generated from the table. and the backward translation table. Which is generated from the table.
*/ */
#if defined(USE_SIM_CARD)
#if defined(USE_SIM_CARD)
#include <ctype.h> #include <ctype.h>
#include "sim_defs.h" #include "sim_defs.h"
#include "sim_card.h" #include "sim_card.h"
@ -344,6 +344,7 @@ static struct card_formats fmts[] = {
{MODE_BCD, "BCD"}, {MODE_BCD, "BCD"},
{MODE_CBN, "CBN"}, {MODE_CBN, "CBN"},
{MODE_EBCDIC,"EBCDIC"}, {MODE_EBCDIC,"EBCDIC"},
{MODE_OCTAL, "OCTAL"},
{0, 0}, {0, 0},
}; };
@ -476,7 +477,7 @@ static int cmpcard(const char *p, const char *s) {
t_stat t_stat
sim_read_card(UNIT * uptr) sim_read_card(UNIT * uptr)
{ {
int i, j; int i;
char c; char c;
uint16 temp; uint16 temp;
int mode; int mode;
@ -499,11 +500,11 @@ sim_read_card(UNIT * uptr)
int ptr = data->ptr; int ptr = data->ptr;
int start = 0; int start = 0;
while (ptr < sizeof(data->cbuff)) while (ptr < data->len)
(data->cbuff)[start++] = (data->cbuff)[ptr++]; (data->cbuff)[start++] = (data->cbuff)[ptr++];
data->len -= data->ptr; data->len -= data->ptr;
/* On eof, just return */ /* On eof, just return */
if (!feof(uptr->fileref)) if (!feof(uptr->fileref) && data->len < 512)
len = sim_fread(&data->cbuff[start], 1, len = sim_fread(&data->cbuff[start], 1,
sizeof(data->cbuff) - start, uptr->fileref); sizeof(data->cbuff) - start, uptr->fileref);
else else
@ -534,7 +535,7 @@ sim_read_card(UNIT * uptr)
/* Clear image buffer */ /* Clear image buffer */
for (col = 0; col < 80; data->image[col++] = 0); for (col = 0; col < 80; data->image[col++] = 0);
if ((uptr->flags & UNIT_MODE) == MODE_AUTO) { if ((uptr->flags & UNIT_CARD_MODE) == MODE_AUTO) {
mode = MODE_TEXT; /* Default is text */ mode = MODE_TEXT; /* Default is text */
/* Check buffer to see if binary card in it. */ /* Check buffer to see if binary card in it. */
@ -571,18 +572,42 @@ sim_read_card(UNIT * uptr)
} }
/* Check if modes match */ /* Check if modes match */
if ((uptr->flags & UNIT_MODE) != MODE_AUTO && if ((uptr->flags & UNIT_CARD_MODE) != MODE_AUTO &&
(uptr->flags & UNIT_MODE) != mode) { (uptr->flags & UNIT_CARD_MODE) != mode) {
sim_debug(DEBUG_CARD, dptr, "invalid mode\n\r"); sim_debug(DEBUG_CARD, dptr, "invalid mode\n");
return SCPE_IOERR; return SCPE_IOERR;
} }
} else } else
mode = uptr->flags & UNIT_MODE; mode = uptr->flags & UNIT_CARD_MODE;
switch(mode) { switch(mode) {
case MODE_TEXT: case MODE_TEXT:
sim_debug(DEBUG_CARD, dptr, "text: ["); sim_debug(DEBUG_CARD, dptr, "text: [");
/* Check for special codes */ /* Check for special codes */
if (data->cbuff[0] == '~') {
int f = 1;
for(col = i = 1; col < 80 && f; i++) {
c = data->cbuff[i];
switch (c) {
case '\n':
case '\0':
case '\r':
col = 80;
case ' ':
break; /* Ignore these */
case '\t':
col = (col | 7) + 1; /* Mult of 8 */
break;
default:
f = 0;
break;
}
}
if (f) {
r = SCPE_EOF;
goto end_card;
}
}
if (cmpcard(&data->cbuff[0], "raw")) { if (cmpcard(&data->cbuff[0], "raw")) {
int j = 0; int j = 0;
for(col = 0, i = 4; col < 80; i++) { for(col = 0, i = 4; col < 80; i++) {
@ -624,12 +649,8 @@ sim_read_card(UNIT * uptr)
break; break;
case '\n': case '\n':
col = 80; col = 80;
i--;
break; break;
case '~': /* End of file mark */
if (col == 0) {
r = SCPE_EOF;
break;
}
default: default:
sim_debug(DEBUG_CARD, dptr, "%c", c); sim_debug(DEBUG_CARD, dptr, "%c", c);
if ((uptr->flags & MODE_LOWER) == 0) if ((uptr->flags & MODE_LOWER) == 0)
@ -649,31 +670,33 @@ sim_read_card(UNIT * uptr)
if (temp & 0xf000) if (temp & 0xf000)
r = SCPE_IOERR; r = SCPE_IOERR;
data->image[col++] = temp & 0xfff; data->image[col++] = temp & 0xfff;
/* Eat cr if line exactly 80 columns */ }
if (col == 80) { }
if (data->cbuff[i + 1] == '\n') }
end_card:
sim_debug(DEBUG_CARD, dptr, "-%d-", i);
/* Scan to end of line, ignore anything after last column */
while (data->cbuff[i] != '\n' && data->cbuff[i] != '\r' && i < data->len) {
i++; i++;
} }
}
}
}
if (data->cbuff[i] == '\n')
i++;
if (data->cbuff[i] == '\r') if (data->cbuff[i] == '\r')
i++; i++;
sim_debug(DEBUG_CARD, dptr, "]\r\n"); if (data->cbuff[i] == '\n')
i++;
sim_debug(DEBUG_CARD, dptr, "]\n");
break; break;
case MODE_BIN: case MODE_BIN:
temp = 0; temp = 0;
sim_debug(DEBUG_CARD, dptr, "bin\r\n"); sim_debug(DEBUG_CARD, dptr, "bin\n");
if (size < 160) if (size < 160)
return SCPE_IOERR; return SCPE_IOERR;
/* Move data to buffer */ /* Move data to buffer */
for (j = i = 0; i < 160;) { for (col = i = 0; i < 160;) {
temp |= data->cbuff[i]; temp |= data->cbuff[i];
data->image[j] = (data->cbuff[i++] >> 4) & 0xF; data->image[col] = (data->cbuff[i++] >> 4) & 0xF;
data->image[j++] |= ((uint16)data->cbuff[i++]) << 4; data->image[col++] |= ((uint16)data->cbuff[i++]) << 4;
} }
/* Check if format error */ /* Check if format error */
if (temp & 0xF) if (temp & 0xF)
@ -682,7 +705,7 @@ sim_read_card(UNIT * uptr)
break; break;
case MODE_CBN: case MODE_CBN:
sim_debug(DEBUG_CARD, dptr, "cbn\r\n"); sim_debug(DEBUG_CARD, dptr, "cbn\n");
/* Check if first character is a tape mark */ /* Check if first character is a tape mark */
if (size == 1 && ((uint8)data->cbuff[0]) == 0217) { if (size == 1 && ((uint8)data->cbuff[0]) == 0217) {
r = SCPE_EOF; r = SCPE_EOF;
@ -693,7 +716,7 @@ sim_read_card(UNIT * uptr)
data->cbuff[0] &= 0x7f; data->cbuff[0] &= 0x7f;
/* Convert card and check for errors */ /* Convert card and check for errors */
for (j = i = 0; i < size;) { for (col = i = 0; i < data->len && col < 80;) {
uint8 c; uint8 c;
if (data->cbuff[i] & 0x80) if (data->cbuff[i] & 0x80)
@ -701,19 +724,24 @@ sim_read_card(UNIT * uptr)
c = data->cbuff[i] & 077; c = data->cbuff[i] & 077;
if (sim_parity_table[(int)c] == (data->cbuff[i++] & 0100)) if (sim_parity_table[(int)c] == (data->cbuff[i++] & 0100))
r = SCPE_IOERR; r = SCPE_IOERR;
data->image[j] = ((uint16)c) << 6; data->image[col] = ((uint16)c) << 6;
if (data->cbuff[i] & 0x80) if (data->cbuff[i] & 0x80)
break; break;
c = data->cbuff[i] & 077; c = data->cbuff[i] & 077;
if (sim_parity_table[(int)c] == (data->cbuff[i++] & 0100)) if (sim_parity_table[(int)c] == (data->cbuff[i++] & 0100))
r = SCPE_IOERR; r = SCPE_IOERR;
data->image[j++] |= c; data->image[col++] |= c;
} }
/* If not full record, return error */ if (col >= 80 && (data->cbuff[i] & 0x80) == 0) {
if (size != 160) {
r = SCPE_IOERR; r = SCPE_IOERR;
} }
/* Record over length of card, skip until next */
while ((data->cbuff[i] & 0x80) == 0) {
if (i > data->len)
break;
i++;
}
break; break;
case MODE_BCD: case MODE_BCD:
@ -728,7 +756,7 @@ sim_read_card(UNIT * uptr)
data->cbuff[0] &= 0x7f; data->cbuff[0] &= 0x7f;
/* Convert text line into card image */ /* Convert text line into card image */
for (col = 0, i = 0; col < 80 && i < size; i++) { for (col = 0, i = 0; col < 80 && i < data->len; i++) {
if (data->cbuff[i] & 0x80) if (data->cbuff[i] & 0x80)
break; break;
c = data->cbuff[i] & 077; c = data->cbuff[i] & 077;
@ -738,7 +766,19 @@ sim_read_card(UNIT * uptr)
/* Convert to top column */ /* Convert to top column */
data->image[col++] = sim_bcd_to_hol(c); data->image[col++] = sim_bcd_to_hol(c);
} }
sim_debug(DEBUG_CARD, dptr, "]\r\n");
if (col >= 80 && (data->cbuff[i] & 0x80) == 0) {
r = SCPE_IOERR;
}
/* Record over length of card, skip until next */
while ((data->cbuff[i] & 0x80) == 0) {
if (i > data->len)
break;
i++;
}
sim_debug(DEBUG_CARD, dptr, "]\n");
break; break;
case MODE_EBCDIC: case MODE_EBCDIC:
@ -799,10 +839,11 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr)
/* Else if binary or not convertable, dump as image */ /* Else if binary or not convertable, dump as image */
/* Try to convert to text */ /* Try to convert to text */
uint8 out[160]; uint8 out[512];
int i; int i;
int outp;
FILE *fo = uptr->fileref; FILE *fo = uptr->fileref;
int mode = uptr->flags & UNIT_MODE; int mode = uptr->flags & UNIT_CARD_MODE;
int ok = 1; int ok = 1;
struct _card_data *data; struct _card_data *data;
DEVICE *dptr; DEVICE *dptr;
@ -810,14 +851,15 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr)
if ((uptr->flags & UNIT_ATT) == 0) { if ((uptr->flags & UNIT_ATT) == 0) {
if (stkuptr != NULL && stkuptr->flags & UNIT_ATT) { if (stkuptr != NULL && stkuptr->flags & UNIT_ATT) {
fo = stkuptr->fileref; fo = stkuptr->fileref;
if ((stkuptr->flags & UNIT_MODE) != MODE_AUTO) if ((stkuptr->flags & UNIT_CARD_MODE) != MODE_AUTO)
mode = stkuptr->flags & UNIT_MODE; mode = stkuptr->flags & UNIT_CARD_MODE;
} else } else
return SCPE_UNATT; /* attached? */ return SCPE_UNATT; /* attached? */
} }
data = (struct _card_data *)uptr->up7; data = (struct _card_data *)uptr->up7;
dptr = find_dev_from_unit(uptr); dptr = find_dev_from_unit(uptr);
outp = 0;
/* Fix mode if in auto mode */ /* Fix mode if in auto mode */
if (mode == MODE_AUTO) { if (mode == MODE_AUTO) {
@ -828,7 +870,7 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr)
ok = 0; ok = 0;
} }
} }
mode = ok?MODE_TEXT:MODE_BIN; mode = ok?MODE_TEXT:MODE_OCTAL;
} }
switch(mode) { switch(mode) {
@ -836,71 +878,115 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr)
case MODE_TEXT: case MODE_TEXT:
/* Scan each column */ /* Scan each column */
sim_debug(DEBUG_CARD, dptr, "text: ["); sim_debug(DEBUG_CARD, dptr, "text: [");
for (i = 0; i < 80; i++) { for (i = 0; i < 80; i++, outp++) {
out[i] = data->hol_to_ascii[data->image[i]]; out[outp] = data->hol_to_ascii[data->image[i]];
if (out[i] == 0xff) if (out[outp] == 0xff) {
out[i] = '?'; out[outp] = '?';
sim_debug(DEBUG_CARD, dptr, "%c", out[i]);
} }
sim_debug(DEBUG_CARD, dptr, "]\r\n"); sim_debug(DEBUG_CARD, dptr, "%c", out[outp]);
}
sim_debug(DEBUG_CARD, dptr, "]\n");
/* Trim off trailing spaces */ /* Trim off trailing spaces */
while (i > 0 && out[--i] == ' ') ; while (outp > 0 && out[--outp] == ' ') ;
out[++i] = '\n'; out[++outp] = '\n';
out[++i] = '\0'; out[++outp] = '\0';
break; break;
case MODE_BIN:
sim_debug(DEBUG_CARD, dptr, "bin\r\n"); case MODE_OCTAL:
sim_debug(DEBUG_CARD, dptr, "octal: [");
out[outp++] = '~';
for (i = 80; i > 0; i--) {
if (data->image[i] != 0)
break;
}
/* Check if special card */
if (i == 0) {
out[outp++] = 'e';
out[outp++] = 'o';
if (data->image[0] == 07) {
out[outp++] = 'r';
out[outp++] = '\n';
sim_debug(DEBUG_CARD, dptr, "eor\n");
break;
}
if (data->image[0] == 015) {
out[outp++] = 'f';
out[outp++] = '\n';
sim_debug(DEBUG_CARD, dptr, "eof\n");
break;
}
if (data->image[0] == 017) {
out[outp++] = 'f';
out[outp++] = '\n';
sim_debug(DEBUG_CARD, dptr, "eoi\n");
break;
}
}
out[outp++] = 'r';
out[outp++] = 'a';
out[outp++] = 'w';
for (i = 0; i < 80; i++) { for (i = 0; i < 80; i++) {
uint16 col = data->image[i]; uint16 col = data->image[i];
out[i*2] = (col & 0x00f) << 4; out[outp++] = ((col >> 9) & 07) + '0';
out[i*2+1] = (col & 0xff0) >> 4; out[outp++] = ((col >> 6) & 07) + '0';
out[outp++] = ((col >> 3) & 07) + '0';
out[outp++] = (col & 07) + '0';
}
out[outp++] = '\n';
sim_debug(DEBUG_CARD, dptr, "%s", &out[4]);
break;
case MODE_BIN:
sim_debug(DEBUG_CARD, dptr, "bin\n");
for (i = 0; i < 80; i++) {
uint16 col = data->image[i];
out[outp++] = (col & 0x00f) << 4;
out[outp++] = (col & 0xff0) >> 4;
} }
i = 160;
break; break;
case MODE_CBN: case MODE_CBN:
sim_debug(DEBUG_CARD, dptr, "cbn\r\n"); sim_debug(DEBUG_CARD, dptr, "cbn\n");
/* Fill buffer */ /* Fill buffer */
for (i = 0; i < 80; i++) { for (i = 0; i < 80; i++) {
uint16 col = data->image[i]; uint16 col = data->image[i];
out[i*2] = (col >> 6) & 077; out[outp++] = (col >> 6) & 077;
out[i*2+1] = col & 077; out[outp++] = col & 077;
} }
/* Now set parity */ /* Now set parity */
for (i = 0; i < 160; i++) for (i = 0; i < 160; i++)
out[i] |= 0100 ^ sim_parity_table[(int)out[i]]; out[i] |= 0100 ^ sim_parity_table[(int)out[i]];
out[0] |= 0x80; /* Set record mark */ out[0] |= 0x80; /* Set record mark */
i = 160;
break; break;
case MODE_BCD: case MODE_BCD:
sim_debug(DEBUG_CARD, dptr, "bcd ["); sim_debug(DEBUG_CARD, dptr, "bcd [");
for (i = 0; i < 80; i++) { for (i = 0; i < 80; i++, outp++) {
out[i] = sim_hol_to_bcd(data->image[i]); out[outp] = sim_hol_to_bcd(data->image[i]);
if (out[i] != 0x7f) if (out[outp] != 0x7f)
out[i] |= sim_parity_table[(int)out[i]]; out[outp] |= sim_parity_table[(int)out[outp]];
else else
out[i] = 077; out[outp] = 077;
sim_debug(DEBUG_CARD, dptr, "%c", sim_debug(DEBUG_CARD, dptr, "%c",
sim_six_to_ascii[(int)out[i]]); sim_six_to_ascii[(int)out[outp]]);
} }
sim_debug(DEBUG_CARD, dptr, "]\r\n"); sim_debug(DEBUG_CARD, dptr, "]\n");
out[0] |= 0x80; /* Set record mark */ out[0] |= 0x80; /* Set record mark */
while (i > 0 && out[--i] == 0); while (outp > 0 && out[--outp] == 0);
i++; outp++;
break; break;
case MODE_EBCDIC: case MODE_EBCDIC:
sim_debug(DEBUG_CARD, dptr, "ebcdic\r\n"); sim_debug(DEBUG_CARD, dptr, "ebcdic\n");
/* Fill buffer */ /* Fill buffer */
for (i = 0; i < 80; i++) { for (i = 0; i < 80; i++, outp++) {
uint16 col = data->image[i]; uint16 col = data->image[i];
out[i] = 0xff & hol_to_ebcdic[col]; out[outp] = 0xff & hol_to_ebcdic[col];
} }
i = 80;
break; break;
} }
sim_fwrite(out, 1, i, fo); sim_fwrite(out, 1, outp, fo);
memset(&data->image[0], 0, sizeof(data->image)); memset(&data->image[0], 0, sizeof(data->image));
return SCPE_OK; return SCPE_OK;
} }
@ -914,7 +1000,7 @@ t_stat sim_card_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
if (cptr == NULL) return SCPE_ARG; if (cptr == NULL) return SCPE_ARG;
for (f = 0; fmts[f].name != 0; f++) { for (f = 0; fmts[f].name != 0; f++) {
if (strcmp (cptr, fmts[f].name) == 0) { if (strcmp (cptr, fmts[f].name) == 0) {
uptr->flags = (uptr->flags & ~UNIT_MODE) | fmts[f].mode; uptr->flags = (uptr->flags & ~UNIT_CARD_MODE) | fmts[f].mode;
return SCPE_OK; return SCPE_OK;
} }
} }
@ -928,7 +1014,7 @@ t_stat sim_card_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
int f; int f;
for (f = 0; fmts[f].name != 0; f++) { for (f = 0; fmts[f].name != 0; f++) {
if ((uptr->flags & UNIT_MODE) == fmts[f].mode) { if ((uptr->flags & UNIT_CARD_MODE) == fmts[f].mode) {
fprintf (st, "%s format", fmts[f].name); fprintf (st, "%s format", fmts[f].name);
return SCPE_OK; return SCPE_OK;
} }
@ -965,6 +1051,7 @@ sim_card_attach(UNIT * uptr, CONST char *cptr)
} else { } else {
data = (struct _card_data *)uptr->up7; data = (struct _card_data *)uptr->up7;
} }
memset(data, 0, sizeof(struct _card_data));
for (i = 0; i < 4096; i++) for (i = 0; i < 4096; i++)
hol_to_ebcdic[i] = 0x100; hol_to_ebcdic[i] = 0x100;
@ -996,7 +1083,6 @@ sim_card_attach(UNIT * uptr, CONST char *cptr)
} }
} }
memset(data, 0, sizeof(struct _card_data));
data->ptr = 0; /* Set for initial read */ data->ptr = 0; /* Set for initial read */
data->len = 0; data->len = 0;
return SCPE_OK; return SCPE_OK;
@ -1035,5 +1121,4 @@ t_stat sim_card_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, cons
return SCPE_OK; return SCPE_OK;
} }
#endif /* USE_SIM_CARD */ #endif /* USE_SIM_CARD */

View file

@ -1,4 +1,4 @@
/* Card read/punch routines for 7000 simulators. /* Generic Card read/punch routines for simulators.
Copyright (c) 2005, Richard Cornwell Copyright (c) 2005, Richard Cornwell
@ -69,19 +69,20 @@ extern "C" {
#define DEBUG_CARD 0x0000010 /* Show details */ #define DEBUG_CARD 0x0000010 /* Show details */
/* Flags for punch and reader. */ /* Flags for punch and reader. */
#define UNIT_V_MODE (UNIT_V_UF + 0) #define UNIT_V_CARD_MODE (UNIT_V_UF + 0)
#define UNIT_MODE (7 << UNIT_V_MODE) #define UNIT_CARD_MODE (7 << UNIT_V_CARD_MODE)
#define MODE_AUTO (0 << UNIT_V_MODE) #define MODE_AUTO (0 << UNIT_V_CARD_MODE)
#define MODE_BIN (1 << UNIT_V_MODE) #define MODE_BIN (1 << UNIT_V_CARD_MODE)
#define MODE_TEXT (2 << UNIT_V_MODE) #define MODE_TEXT (2 << UNIT_V_CARD_MODE)
#define MODE_BCD (3 << UNIT_V_MODE) #define MODE_BCD (3 << UNIT_V_CARD_MODE)
#define MODE_CBN (4 << UNIT_V_MODE) #define MODE_CBN (4 << UNIT_V_CARD_MODE)
#define MODE_EBCDIC (5 << UNIT_V_MODE) #define MODE_EBCDIC (5 << UNIT_V_CARD_MODE)
#define MODE_OCTAL (6 << UNIT_V_CARD_MODE)
/* Allow lower case letters */ /* Allow lower case letters */
#define MODE_LOWER (8 << UNIT_V_MODE) #define MODE_LOWER (8 << UNIT_V_CARD_MODE)
#define MODE_026 (0x10 << UNIT_V_MODE) #define MODE_026 (0x10 << UNIT_V_CARD_MODE)
#define MODE_029 (0x20 << UNIT_V_MODE) #define MODE_029 (0x20 << UNIT_V_CARD_MODE)
#define MODE_CHAR (0x30 << UNIT_V_MODE) #define MODE_CHAR (0x30 << UNIT_V_CARD_MODE)
struct _card_data struct _card_data
@ -104,7 +105,7 @@ t_stat sim_card_detach(UNIT *uptr);
uint16 sim_bcd_to_hol(uint8 bcd); uint16 sim_bcd_to_hol(uint8 bcd);
uint16 sim_ebcdic_to_hol(uint8 ebcdic); uint16 sim_ebcdic_to_hol(uint8 ebcdic);
uint8 sim_hol_to_bcd(uint16 hol); uint8 sim_hol_to_bcd(uint16 hol);
uint8 sim_hol_to_ebbcd(uint16 hol); uint16 sim_hol_to_ebcdic(uint16 hol);
/* Format control routines. */ /* Format control routines. */
t_stat sim_card_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_card_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc);