diff --git a/sim_card.c b/sim_card.c index 7806b658..9bfd34ba 100644 --- a/sim_card.c +++ b/sim_card.c @@ -62,12 +62,29 @@ and the backward translation table. Which is generated from the table. */ -#if defined(USE_SIM_CARD) #include #include "sim_defs.h" #include "sim_card.h" +#if defined(USE_SIM_CARD) + +#define card_ctx up8 + +#define CARD_EOF 0x1000 /* This card is end of file card. */ +#define CARD_ERR 0x2000 /* Return error for this card */ +#define DECK_SIZE 1000 /* Number of cards to allocate at a time */ + + +struct card_context +{ + t_addr punch_count; /* Number of cards punched */ + char cbuff[1024]; /* Read in buffer for cards */ + uint8 hol_to_ascii[4096]; /* Back conversion table */ + t_addr hopper_size; /* Size of hopper */ + t_addr hopper_cards; /* Number of cards in hopper */ + uint16 (*images)[1][80]; +}; /* Character conversion tables */ @@ -265,7 +282,7 @@ static uint16 ebcdic_to_hol[256] = { /* 098 0918 0928 0938 0948 0958 0968 0978 */ 0x203, 0x303, 0x283, 0x243, 0x223, 0x213, 0x20B, 0x207, /* TE0918 91 92 93 94 95 96 97 0x3x */ - 0xF03, 0x101, 0x081, 0x041, 0x021, 0x011, 0x009, 0x005, + 0xF03, 0x101, 0x081, 0x041, 0x021, 0x011, 0x009, 0x005, /* 98 918 928 938 948 958 968 978 */ 0x003, 0x103, 0x083, 0x043, 0x023, 0x013, 0x00B, 0x007, /* T091 T092 T093 T094 T095 T096 T097 0x4x */ @@ -339,12 +356,12 @@ struct card_formats { static struct card_formats fmts[] = { {MODE_AUTO, "AUTO"}, - {MODE_BIN, "BIN"}, - {MODE_TEXT, "TEXT"}, - {MODE_BCD, "BCD"}, - {MODE_CBN, "CBN"}, - {MODE_EBCDIC,"EBCDIC"}, - {MODE_OCTAL, "OCTAL"}, + {MODE_BIN, "BIN"}, + {MODE_TEXT, "TEXT"}, + {MODE_BCD, "BCD"}, + {MODE_CBN, "CBN"}, + {MODE_EBCDIC,"EBCDIC"}, + {MODE_OCTAL, "OCTAL"}, {0, 0}, }; @@ -358,7 +375,7 @@ sim_bcd_to_hol(uint8 bcd) { /* Handle space correctly */ if (bcd == 0) /* 0 to 82 punch */ - return 0x82; + return 0x82; if (bcd == 020) /* 20 no punch */ return 0; @@ -441,7 +458,7 @@ sim_hol_to_bcd(uint16 hol) { } /* Any more columns punched? */ - if ((hol & 0x1ff) != 0) + if ((hol & 0x1ff) != 0) return 0x7f; return bcd; } @@ -462,9 +479,134 @@ sim_hol_to_ebcdic(uint16 hol) { -static int cmpcard(const char *p, const char *s) { +t_addr +sim_hopper_size(UNIT * uptr) { + struct card_context *data = (struct card_context *)uptr->card_ctx; + if (data == NULL) + return 0; + return data->hopper_cards; +} + +t_addr +sim_punch_count(UNIT * uptr) { + struct card_context *data = (struct card_context *)uptr->card_ctx; + if (data == NULL) + return 0; + return data->punch_count; +} + +t_addr +sim_card_input_hopper_count(UNIT *uptr) { + struct card_context *data = (struct card_context *)uptr->card_ctx; + uint16 col; + + if (data == NULL || data->images == NULL) + return 0; /* attached? */ + + if (uptr->pos >= data->hopper_cards) + return 0; + + col = (*data->images)[data->hopper_cards-1][0]; + + return (int)((data->hopper_cards - uptr->pos) - ((col & CARD_EOF) ? 1 : 0)); +} + +t_addr +sim_card_output_hopper_count(UNIT *uptr) { + struct card_context *data = (struct card_context *)uptr->card_ctx; + + if (data == NULL) + return 0; /* attached? */ + + return (int)data->punch_count; +} + + +t_cdstat +sim_read_card(UNIT * uptr, uint16 image[80]) +{ + int i; + struct card_context *data = (struct card_context *)uptr->card_ctx; + DEVICE *dptr; + uint16 (*img)[80]; + t_stat r = CDSE_OK; + + if (data == NULL || (uptr->flags & UNIT_ATT) == 0) + return CDSE_EMPTY; /* attached? */ + if (data->hopper_cards == 0 || uptr->pos >= data->hopper_cards) + return CDSE_EMPTY; + + dptr = find_dev_from_unit( uptr); + img = &(*data->images)[uptr->pos]; + if (sim_deb && dptr && ((dptr)->dctrl & DEBUG_CARD)) { + if (image[0] & CARD_EOF) { + sim_debug(DEBUG_CARD, dptr, "Read hopper EOF\n"); + } else if (image[0] & CARD_ERR) { + sim_debug(DEBUG_CARD, dptr, "Read hopper ERR\n"); + } else { + uint8 out[81]; + int ok = 1; + for (i = 0; i < 80; i++) { + out[i] = data->hol_to_ascii[(int)(*img)[i]]; + if (out[i] == 0xff) { + ok = 0; + } + } + if (ok) { + sim_debug(DEBUG_CARD, dptr, "Read hopper: ["); + for (i = 0; i < 80; i++) { + sim_debug(DEBUG_CARD, dptr, "%c", out[i]); + } + sim_debug(DEBUG_CARD, dptr, "]\n"); + } else { + sim_debug(DEBUG_CARD, dptr, "Read hopper binary\n"); + } + } + } + if ((*img)[0] & CARD_EOF) + r = CDSE_EOF; + else if ((*img)[0] & CARD_ERR) + r = CDSE_ERROR; + uptr->pos++; + data->punch_count++; + memcpy(image, img, 80 * sizeof(uint16)); + image[0] &= 0xfff; /* Remove any CARD_EOF and CARD_ERR Flags */ + return r; +} + +/* + * Check if reader is at last card. + */ +int +sim_card_eof(UNIT *uptr) +{ + struct card_context *data = (struct card_context *)uptr->card_ctx; + uint16 col; + + if (data == NULL || data->images == NULL) + return SCPE_UNATT; /* attached? */ + + if (uptr->pos >= data->hopper_cards) + return SCPE_UNATT; + + col = (*data->images)[uptr->pos][0]; + + if (col & CARD_EOF) + return 1; + return 0; +} + + + +struct _card_buffer { + char buffer[8192+500]; /* Buffer data */ + int len; /* Amount of data in buffer */ + int size; /* Size of last card read */ +}; + +static int _cmpcard(const char *p, const char *s) { int i; - if (p[0] != '~') + if (p[0] != '~') return 0; for(i = 0; i < 3; i++) { if (tolower(p[i+1]) != s[i]) @@ -473,87 +615,34 @@ static int cmpcard(const char *p, const char *s) { return 1; } - t_stat -sim_read_card(UNIT * uptr) -{ - int i; - char c; - uint16 temp; - int mode; - int len; - int size; - int col; - struct _card_data *data; - DEVICE *dptr; - t_stat r = SCPE_OK; +_sim_parse_card(UNIT *uptr, DEVICE *dptr, struct _card_buffer *buf, uint16 (*image)[80]) { + int mode; + uint16 temp; + int i; + char c; + int col; - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; /* attached? */ - - dptr = find_dev_from_unit( uptr); - data = (struct _card_data *)uptr->up7; sim_debug(DEBUG_CARD, dptr, "Read card "); - -/* Move data to start at begining of buffer */ - if (data->ptr > 0) { - int ptr = data->ptr; - int start = 0; - - while (ptr < data->len) - (data->cbuff)[start++] = (data->cbuff)[ptr++]; - data->len -= data->ptr; - /* On eof, just return */ - if (!feof(uptr->fileref) && data->len < 512) - len = sim_fread(&data->cbuff[start], 1, - sizeof(data->cbuff) - start, uptr->fileref); - else - len = 0; - data->len += len; - size = data->len; - } else { - /* Load rest of buffer */ - if (!feof(uptr->fileref)) { - len = sim_fread(&data->cbuff[0], 1, sizeof(data->cbuff), uptr->fileref); - size = len; - } else - len = size = 0; - data->len = size; - } - - if ((len < 0 || size == 0) && feof(uptr->fileref)) { - sim_debug(DEBUG_CARD, dptr, "EOF\n"); - return SCPE_EOF; - } - - if (ferror(uptr->fileref)) { /* error? */ - sim_perror("Card reader I/O error"); - clearerr(uptr->fileref); - return SCPE_IOERR; - } - - /* Clear image buffer */ - for (col = 0; col < 80; data->image[col++] = 0); - if ((uptr->flags & UNIT_CARD_MODE) == MODE_AUTO) { mode = MODE_TEXT; /* Default is text */ /* Check buffer to see if binary card in it. */ - for (i = 0, temp = 0; i < 160; i+=2) - temp |= data->cbuff[i]; + for (i = 0, temp = 0; i < 160 && i len; i+=2) + temp |= buf->buffer[i]; /* Check if every other char < 16 & full buffer */ - if (size == 160 && (temp & 0x0f) == 0) + if ((temp & 0x0f) == 0 && i == 160) mode = MODE_BIN; /* Probably binary */ /* Check if maybe BCD or CBN */ - if (data->cbuff[0] & 0x80) { + if (buf->buffer[0] & 0x80) { int odd = 0; int even = 0; - + /* Clear record mark */ - data->cbuff[0] &= 0x7f; + buf->buffer[0] &= 0x7f; /* Check all chars for correct parity */ - for(i = 0, temp = 0; i < size; i++) { - uint8 ch = data->cbuff[i]; + for(i = 0, temp = 0; i < buf->len; i++) { + uint8 ch = buf->buffer[i]; /* Stop at EOR */ if (ch & 0x80) break; @@ -564,8 +653,8 @@ sim_read_card(UNIT * uptr) odd++; } /* Restore it */ - data->cbuff[0] |= 0x80; - if (i == 160 && odd == i) + buf->buffer[0] |= 0x80; + if (i == 160 && odd == i) mode = MODE_CBN; else if (i < 80 && even == i) mode = MODE_BCD; @@ -574,10 +663,11 @@ sim_read_card(UNIT * uptr) /* Check if modes match */ if ((uptr->flags & UNIT_CARD_MODE) != MODE_AUTO && (uptr->flags & UNIT_CARD_MODE) != mode) { + (*image)[0] = CARD_ERR; sim_debug(DEBUG_CARD, dptr, "invalid mode\n"); - return SCPE_IOERR; + return SCPE_OPENERR; } - } else + } else mode = uptr->flags & UNIT_CARD_MODE; switch(mode) { @@ -585,10 +675,10 @@ sim_read_card(UNIT * uptr) case MODE_TEXT: sim_debug(DEBUG_CARD, dptr, "text: ["); /* Check for special codes */ - if (data->cbuff[0] == '~') { + if (buf->buffer[0] == '~') { int f = 1; - for(col = i = 1; col < 80 && f; i++) { - c = data->cbuff[i]; + for(col = i = 1; col < 80 && f && i < buf->len; i++) { + c = buf->buffer[i]; switch (c) { case '\n': case '\0': @@ -605,23 +695,21 @@ sim_read_card(UNIT * uptr) } } if (f) { - r = SCPE_EOF; + (*image)[0] |= CARD_EOF; goto end_card; } } - if (cmpcard(&data->cbuff[0], "raw")) { + if (_cmpcard(&buf->buffer[0], "raw")) { int j = 0; sim_debug(DEBUG_CARD, dptr, "-octal-"); - for(col = 0, i = 4; col < 80; i++) { - if (data->cbuff[i] >= '0' && data->cbuff[i] <= '7') { - data->image[col] = (data->image[col] << 3) | - (data->cbuff[i] - '0'); + for(col = 0, i = 4; col < 80 && i < buf->len; i++) { + if (buf->buffer[i] >= '0' && buf->buffer[i] <= '7') { + (*image)[col] = ((*image)[col] << 3) | (buf->buffer[i] - '0'); j++; - } else if (data->cbuff[i] == '\n' || - data->cbuff[i] == '\r') { + } else if (buf->buffer[i] == '\n' || buf->buffer[i] == '\r') { break; } else { - r = SCPE_IOERR; + (*image)[0] = CARD_ERR; break; } if (j == 4) { @@ -629,22 +717,22 @@ sim_read_card(UNIT * uptr) j = 0; } } - } else if (cmpcard(&data->cbuff[0], "eor")) { + } else if (_cmpcard(&buf->buffer[0], "eor")) { sim_debug(DEBUG_CARD, dptr, "-eor-"); - data->image[0] = 07; /* 7/8/9 punch */ + (*image)[0] = 07; /* 7/8/9 punch */ i = 4; - } else if (cmpcard(&data->cbuff[0], "eof")) { + } else if (_cmpcard(&buf->buffer[0], "eof")) { sim_debug(DEBUG_CARD, dptr, "-eof-"); - data->image[0] = 015; /* 6/7/9 punch */ + (*image)[0] = 015; /* 6/7/9 punch */ i = 4; - } else if (cmpcard(&data->cbuff[0], "eoi")) { + } else if (_cmpcard(&buf->buffer[0], "eoi")) { sim_debug(DEBUG_CARD, dptr, "-eoi-"); - data->image[0] = 017; /* 6/7/8/9 punch */ + (*image)[0] = 017; /* 6/7/8/9 punch */ i = 4; } else { /* Convert text line into card image */ - for (col = 0, i = 0; col < 80 && i < size; i++) { - c = data->cbuff[i]; + for (col = 0, i = 0; col < 80 && i < buf->len; i++) { + c = buf->buffer[i]; switch (c) { case '\0': case '\r': @@ -673,8 +761,8 @@ sim_read_card(UNIT * uptr) break; } if (temp & 0xf000) - r = SCPE_IOERR; - data->image[col++] = temp & 0xfff; + (*image)[0] |= CARD_ERR; + (*image)[col++] = temp & 0xfff; } } } @@ -682,12 +770,12 @@ sim_read_card(UNIT * uptr) 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) { + while (buf->buffer[i] != '\n' && buf->buffer[i] != '\r' && i < buf->len) { i++; } - if (data->cbuff[i] == '\r') + if (buf->buffer[i] == '\r') i++; - if (data->cbuff[i] == '\n') + if (buf->buffer[i] == '\n') i++; sim_debug(DEBUG_CARD, dptr, "]\n"); break; @@ -695,57 +783,59 @@ sim_read_card(UNIT * uptr) case MODE_BIN: temp = 0; sim_debug(DEBUG_CARD, dptr, "bin\n"); - if (size < 160) - return SCPE_IOERR; + if (buf->len < 160) { + (*image)[0] = CARD_ERR; + return SCPE_OPENERR; + } /* Move data to buffer */ for (col = i = 0; i < 160;) { - temp |= data->cbuff[i]; - data->image[col] = (data->cbuff[i++] >> 4) & 0xF; - data->image[col++] |= ((uint16)data->cbuff[i++]) << 4; + temp |= buf->buffer[i]; + (*image)[col] = (buf->buffer[i++] >> 4) & 0xF; + (*image)[col++] |= ((uint16)buf->buffer[i++]) << 4; } /* Check if format error */ - if (temp & 0xF) - r = SCPE_IOERR; + if (temp & 0xF) + (*image)[0] |= CARD_ERR; break; case MODE_CBN: sim_debug(DEBUG_CARD, dptr, "cbn\n"); /* Check if first character is a tape mark */ - if (((uint8)data->cbuff[0]) == 0217 && - (size == 1 || (((uint8)data->cbuff[1]) & 0200) != 0)) { + if (((uint8)buf->buffer[0]) == 0217 && + (buf->len == 1 || (((uint8)buf->buffer[1]) & 0200) != 0)) { i = 1; - r = SCPE_EOF; + (*image)[0] |= CARD_EOF; break; } /* Clear record mark */ - data->cbuff[0] &= 0x7f; - + buf->buffer[0] &= 0x7f; + /* Convert card and check for errors */ - for (col = i = 0; i < data->len && col < 80;) { + for (col = i = 0; i < buf->len && col < 80;) { uint8 c; - if (data->cbuff[i] & 0x80) + if (buf->buffer[i] & 0x80) break; - c = data->cbuff[i] & 077; - if (sim_parity_table[(int)c] == (data->cbuff[i++] & 0100)) - r = SCPE_IOERR; - data->image[col] = ((uint16)c) << 6; - if (data->cbuff[i] & 0x80) + c = buf->buffer[i] & 077; + if (sim_parity_table[(int)c] == (buf->buffer[i++] & 0100)) + (*image)[0] |= CARD_ERR; + (*image)[col] = ((uint16)c) << 6; + if (buf->buffer[i] & 0x80) break; - c = data->cbuff[i] & 077; - if (sim_parity_table[(int)c] == (data->cbuff[i++] & 0100)) - r = SCPE_IOERR; - data->image[col++] |= c; + c = buf->buffer[i] & 077; + if (sim_parity_table[(int)c] == (buf->buffer[i++] & 0100)) + (*image)[0] |= CARD_ERR; + (*image)[col++] |= c; } - if (i < data->len && col >= 80 && (data->cbuff[i] & 0x80) == 0) { - r = SCPE_IOERR; + if (i < buf->len && col >= 80 && (buf->buffer[i] & 0x80) == 0) { + (*image)[0] |= CARD_ERR; } /* Record over length of card, skip until next */ - while ((data->cbuff[i] & 0x80) == 0) { - if (i > data->len) + while ((buf->buffer[i] & 0x80) == 0) { + if (i > buf->len) break; i++; } @@ -754,35 +844,34 @@ sim_read_card(UNIT * uptr) case MODE_BCD: sim_debug(DEBUG_CARD, dptr, "bcd ["); /* Check if first character is a tape mark */ - if (((uint8)data->cbuff[0]) == 0217 && - (size == 1 || (((uint8)data->cbuff[1]) & 0200) != 0)) { + if (((uint8)buf->buffer[0]) == 0217 && (((uint8)buf->buffer[1]) & 0200) != 0) { i = 1; - r = SCPE_EOF; + (*image)[0] |= CARD_EOF; break; } /* Clear record mark */ - data->cbuff[0] &= 0x7f; - + buf->buffer[0] &= 0x7f; + /* Convert text line into card image */ - for (col = 0, i = 0; col < 80 && i < data->len; i++) { - if (data->cbuff[i] & 0x80) + for (col = 0, i = 0; col < 80 && i < buf->len; i++) { + if (buf->buffer[i] & 0x80) break; - c = data->cbuff[i] & 077; - if (sim_parity_table[(int)c] != (data->cbuff[i] & 0100)) - r = SCPE_IOERR; + c = buf->buffer[i] & 077; + if (sim_parity_table[(int)c] != (buf->buffer[i] & 0100)) + (*image)[0] |= CARD_ERR; sim_debug(DEBUG_CARD, dptr, "%c", sim_six_to_ascii[(int)c]); /* Convert to top column */ - data->image[col++] = sim_bcd_to_hol(c); + (*image)[col++] = sim_bcd_to_hol(c); } - if (i < data->len && col >= 80 && (data->cbuff[i] & 0x80) == 0) { - r = SCPE_IOERR; + if (i < buf->len && col >= 80 && (buf->buffer[i] & 0x80) == 0) { + (*image)[0] |= CARD_ERR; } /* Record over length of card, skip until next */ - while ((data->cbuff[i] & 0x80) == 0) { - if (i > data->len) + while ((buf->buffer[i] & 0x80) == 0) { + if (i > buf->len) break; i++; } @@ -792,44 +881,98 @@ sim_read_card(UNIT * uptr) case MODE_EBCDIC: sim_debug(DEBUG_CARD, dptr, "ebcdic\n"); - if (size < 80) - return SCPE_IOERR; + if (buf->len < 80) + (*image)[0] |= CARD_ERR; /* Move data to buffer */ - for (i = 0; i < 80; i++) { - temp = data->cbuff[i]; - data->image[i] = ebcdic_to_hol[temp]; + for (i = 0; i < 80 && i < buf->len; i++) { + temp = buf->buffer[i] & 0xFF; + (*image)[i] = ebcdic_to_hol[temp]; } break; } - if (i < size) - data->ptr = i; - else - data->ptr = 0; - return r; + buf->size = i; + return SCPE_OK; } -/* Check if reader is at last card. - * - */ -int -sim_card_eof(UNIT *uptr) +t_stat +_sim_read_deck(UNIT * uptr, int eof) { - struct _card_data *data; + struct _card_buffer buf; + struct card_context *data; + DEVICE *dptr; + int i; + int j; + int l; + int cards = 0; + t_stat r = SCPE_OK; if ((uptr->flags & UNIT_ATT) == 0) - return 1; /* attached? */ + return SCPE_UNATT; /* attached? */ - data = (struct _card_data *)uptr->up7; - - if (data->ptr > 0) { - if ((data->ptr - data->len) == 0 && feof(uptr->fileref)) - return 1; - } else { - if (feof(uptr->fileref)) - return 1; + dptr = find_dev_from_unit( uptr); + data = (struct card_context *)uptr->card_ctx; + + buf.len = 0; + buf.size = 0; + buf.buffer[0] = 0; /* Initialize bufer to empty */ + + /* Slurp up current file */ + do { + if (buf.len < 500 && !feof(uptr->fileref)) { + l = sim_fread(&buf.buffer[buf.len], 1, 8192, uptr->fileref); + if (l < 0) + r = SCPE_OPENERR; + else + buf.len += l; + } + + /* Allocate space for some more cards if needed */ + if (data->hopper_cards >= data->hopper_size) { + data->hopper_size += DECK_SIZE; + data->images = (uint16 (*)[1][80])realloc(data->images, + data->hopper_size * sizeof(*(data->images))); + memset(&data->images[data->hopper_cards], 0, + (data->hopper_size - data->hopper_cards) * + sizeof(*(data->images))); + } + + /* Process one card */ + cards++; + if (_sim_parse_card(uptr, dptr, &buf, &(*data->images)[data->hopper_cards]) + != SCPE_OK) { + r = sim_messagef(SCPE_OPENERR, "%s: %s Error (%s) in card %d\n", + sim_uname(uptr), uptr->filename, sim_error_text(r), cards); + } + data->hopper_cards++; + /* Move data to start at begining of buffer */ + /* Data is moved down to simplify the decoding of one card */ + l = buf.len - buf.size; + j = buf.size; + for(i = 0; i < l; i++, j++) + buf.buffer[i] = buf.buffer[j]; + buf.len -= buf.size; + } while (buf.len > 0 && r == SCPE_OK); + + /* If there is an error, free just read deck */ + if (r == SCPE_OK) { + if (eof) { + /* Allocate space for some more cards if needed */ + if (data->hopper_cards >= data->hopper_size) { + data->hopper_size += DECK_SIZE; + data->images = (uint16 (*)[1][80])realloc(data->images, + data->hopper_size * sizeof(*(data->images))); + memset(&data->images[data->hopper_cards], 0, + (data->hopper_size - data->hopper_cards) * + sizeof(*(data->images))); + } + + /* Create empty card */ + (*data->images)[data->hopper_cards][0] = CARD_EOF; + data->hopper_cards++; + } } - return 0; + return r; } @@ -839,8 +982,9 @@ sim_card_eof(UNIT *uptr) C modifier is recognized (column binary is implemented) */ + t_stat -sim_punch_card(UNIT * uptr, UNIT *stkuptr) +sim_punch_card(UNIT * uptr, uint16 image[80]) { /* Convert word record into column image */ /* Check output type, if auto or text, try and convert record to bcd first */ @@ -848,33 +992,25 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) /* Else if binary or not convertable, dump as image */ /* Try to convert to text */ - uint8 out[512]; - int i; - int outp; - FILE *fo = uptr->fileref; - int mode = uptr->flags & UNIT_CARD_MODE; - int ok = 1; - struct _card_data *data; + uint8 out[512]; + int i; + int outp = 0; + int mode = uptr->flags & UNIT_CARD_MODE; + int ok = 1; + struct card_context *data; DEVICE *dptr; - if ((uptr->flags & UNIT_ATT) == 0) { - if (stkuptr != NULL && stkuptr->flags & UNIT_ATT) { - fo = stkuptr->fileref; - if ((stkuptr->flags & UNIT_CARD_MODE) != MODE_AUTO) - mode = stkuptr->flags & UNIT_CARD_MODE; - } else - return SCPE_UNATT; /* attached? */ - } - - data = (struct _card_data *)uptr->up7; dptr = find_dev_from_unit(uptr); - outp = 0; + data = (struct card_context *)uptr->card_ctx; + + if (data == NULL || (uptr->flags & UNIT_ATT) == 0) + return CDSE_EMPTY; /* attached? */ /* Fix mode if in auto mode */ if (mode == MODE_AUTO) { /* Try to convert each column to ascii */ for (i = 0; i < 80; i++) { - out[i] = data->hol_to_ascii[data->image[i]]; + out[i] = data->hol_to_ascii[image[i]]; if (out[i] == 0xff) { ok = 0; } @@ -888,7 +1024,7 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) /* Scan each column */ sim_debug(DEBUG_CARD, dptr, "text: ["); for (i = 0; i < 80; i++, outp++) { - out[outp] = data->hol_to_ascii[data->image[i]]; + out[outp] = data->hol_to_ascii[image[i]]; if (out[outp] == 0xff) { out[outp] = '?'; } @@ -905,26 +1041,26 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) sim_debug(DEBUG_CARD, dptr, "octal: ["); out[outp++] = '~'; for (i = 79; i >= 0; i--) { - if (data->image[i] != 0) + if (image[i] != 0) break; } /* Check if special card */ if (i == 0) { out[outp++] = 'e'; out[outp++] = 'o'; - if (data->image[0] == 07) { + if (image[0] == 07) { out[outp++] = 'r'; out[outp++] = '\n'; sim_debug(DEBUG_CARD, dptr, "eor\n"); break; } - if (data->image[0] == 015) { + if (image[0] == 015) { out[outp++] = 'f'; out[outp++] = '\n'; sim_debug(DEBUG_CARD, dptr, "eof\n"); break; } - if (data->image[0] == 017) { + if (image[0] == 017) { out[outp++] = 'f'; out[outp++] = '\n'; sim_debug(DEBUG_CARD, dptr, "eoi\n"); @@ -935,7 +1071,7 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) out[outp++] = 'a'; out[outp++] = 'w'; for (i = 0; i < 80; i++) { - uint16 col = data->image[i]; + uint16 col = image[i]; out[outp++] = ((col >> 9) & 07) + '0'; out[outp++] = ((col >> 6) & 07) + '0'; out[outp++] = ((col >> 3) & 07) + '0'; @@ -944,12 +1080,12 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) 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]; + uint16 col = image[i]; out[outp++] = (col & 0x00f) << 4; out[outp++] = (col & 0xff0) >> 4; } @@ -959,12 +1095,12 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) sim_debug(DEBUG_CARD, dptr, "cbn\n"); /* Fill buffer */ for (i = 0; i < 80; i++) { - uint16 col = data->image[i]; + uint16 col = image[i]; out[outp++] = (col >> 6) & 077; out[outp++] = col & 077; } /* 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[0] |= 0x80; /* Set record mark */ break; @@ -972,7 +1108,7 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) case MODE_BCD: sim_debug(DEBUG_CARD, dptr, "bcd ["); for (i = 0; i < 80; i++, outp++) { - out[outp] = sim_hol_to_bcd(data->image[i]); + out[outp] = sim_hol_to_bcd(image[i]); if (out[outp] != 0x7f) out[outp] |= sim_parity_table[(int)out[outp]]; else @@ -990,14 +1126,17 @@ sim_punch_card(UNIT * uptr, UNIT *stkuptr) sim_debug(DEBUG_CARD, dptr, "ebcdic\n"); /* Fill buffer */ for (i = 0; i < 80; i++, outp++) { - uint16 col = data->image[i]; + uint16 col = image[i]; out[outp] = 0xff & hol_to_ebcdic[col]; } break; } - sim_fwrite(out, 1, outp, fo); - memset(&data->image[0], 0, sizeof(data->image)); - return SCPE_OK; + data->punch_count++; + sim_fwrite(out, 1, outp, uptr->fileref); + uptr->pos = ftell (uptr->fileref); + /* Clear image buffer */ + for (i = 0; i < 80; image[i++] = 0); + return CDSE_OK; } /* Set card format */ @@ -1036,11 +1175,40 @@ t_stat sim_card_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc) t_stat sim_card_attach(UNIT * uptr, CONST char *cptr) { - t_stat r; - struct _card_data *data; - char gbuf[30]; - int i; + t_stat r = SCPE_OK; + int eof = 0; + struct card_context *data; + char gbuf[30]; + int i; + char *saved_filename; + t_bool was_attached = (uptr->flags & UNIT_ATT); + t_addr saved_pos; + static int ebcdic_init = 0; + if ((uptr->flags & UNIT_RO) && /* Attaching a Reader */ + strchr (cptr, ',')) { /* Restoring Attach list of files? */ + char tbuf[10*CBUFSIZE]; + char *tptr = tbuf; + int32 saved_switches = sim_switches; + + strlcpy (tbuf, cptr, sizeof(tbuf)); + tptr = strtok (tptr, ","); + while (tptr) { + cptr = tptr; + while (isspace(*cptr)) + ++cptr; + r = sim_card_attach (uptr, cptr); + if (r != SCPE_OK) + return r; + tptr = strtok (NULL, ","); + sim_switches = saved_switches & ~SWMASK('F'); + sim_switches |= SWMASK('S'); + } + sim_switches = saved_switches; + return SCPE_OK; + } + + cptr = get_sim_sw (cptr); /* Pickup optional format specifier during RESTORE */ if (sim_switches & SWMASK ('F')) { /* format spec? */ cptr = get_glyph (cptr, gbuf, 0); /* get spec */ if (*cptr == 0) return SCPE_2FARG; /* must be more */ @@ -1048,30 +1216,43 @@ sim_card_attach(UNIT * uptr, CONST char *cptr) return SCPE_ARG; } - if ((r = attach_unit(uptr, cptr)) != SCPE_OK) + if (sim_switches & SWMASK ('E')) + eof = 1; + + saved_filename = uptr->filename; + uptr->filename = NULL; + saved_pos = uptr->pos; + if ((r = attach_unit(uptr, cptr)) != SCPE_OK) { + uptr->filename = saved_filename; + uptr->pos = saved_pos; return r; + } + /* Initialize reverse mapping if not initialized */ /* Set all to invalid */ /* Allocate a buffer if one does not exist */ - if (uptr->up7 == 0) { - uptr->up7 = malloc(sizeof(struct _card_data)); - data = (struct _card_data *)uptr->up7; + if (uptr->card_ctx == 0) { + uptr->card_ctx = malloc(sizeof(struct card_context)); + data = (struct card_context *)uptr->card_ctx; + memset(data, 0, sizeof(struct card_context)); } else { - data = (struct _card_data *)uptr->up7; + data = (struct card_context *)uptr->card_ctx; } - memset(data, 0, sizeof(struct _card_data)); - for (i = 0; i < 4096; i++) - hol_to_ebcdic[i] = 0x100; - for (i = 0; i < 256; i++) { - uint16 temp = ebcdic_to_hol[i]; - if (hol_to_ebcdic[temp] != 0x100) { - fprintf(stderr, "Translation error %02x is %03x and %03x\n", - i, temp, hol_to_ebcdic[temp]); - } else { - hol_to_ebcdic[temp] = i; + if (!ebcdic_init) { + for (i = 0; i < 4096; i++) + hol_to_ebcdic[i] = 0x100; + for (i = 0; i < 256; i++) { + uint16 temp = ebcdic_to_hol[i]; + if (hol_to_ebcdic[temp] != 0x100) { + fprintf(stderr, "Translation error %02x is %03x and %03x\n", + i, temp, hol_to_ebcdic[temp]); + } else { + hol_to_ebcdic[temp] = i; + } } + ebcdic_init = 1; } memset(&data->hol_to_ascii[0], 0xff, 4096); @@ -1092,29 +1273,91 @@ sim_card_attach(UNIT * uptr, CONST char *cptr) } } - data->ptr = 0; /* Set for initial read */ - data->len = 0; - return SCPE_OK; + if (uptr->flags & UNIT_RO) { /* Card Reader? */ + t_addr previous_cards = data->hopper_cards; + + /* Check if we should append to end of existing */ + if ((sim_switches & SWMASK ('S')) == 0) { + previous_cards = 0; + data->hopper_cards = 0; + data->hopper_size = 0; + data->punch_count = 0; + free(data->images); + data->images = NULL; + free(saved_filename); + saved_filename = NULL; + saved_pos = 0; + } + + /* Go read the deck */ + r = _sim_read_deck(uptr, eof); + uptr->pos = saved_pos; + detach_unit(uptr); + if (was_attached) { + uptr->flags |= UNIT_ATT; + uptr->filename = saved_filename; + } + if (r == SCPE_OK) { + const char *fmt = "AUTO"; + int mode = uptr->flags & UNIT_CARD_MODE; + for (i = 0; fmts[i].name != 0; i++) { + if (fmts[i].mode == mode) { + fmt = fmts[i].name; + break; + } + } + uptr->flags |= UNIT_ATT; + uptr->dynflags |= UNIT_ATTMULT; + if (saved_filename) { + uptr->filename = (char *)malloc (32 + strlen (cptr) + strlen (saved_filename)); + sprintf (uptr->filename, "%s, %s-F %s %s", saved_filename, + (eof)? "-E ": "", fmt, cptr); + free(saved_filename); + } else { + uptr->filename = (char *)malloc (32 + strlen (cptr)); + sprintf (uptr->filename, "%s-F %s %s", (eof)?"-E ": "", fmt, cptr); + } + r = sim_messagef(SCPE_OK, "%s: %d card Deck Loaded from %s\n", + sim_uname(uptr), data->hopper_cards - previous_cards, cptr); + } else { + if (uptr->dynflags & UNIT_ATTMULT) + uptr->flags |= UNIT_ATT; + detach_unit(uptr); + return r; + } + } + + return r; } t_stat sim_card_detach(UNIT * uptr) { /* Free buffer if one allocated */ - if (uptr->up7 != 0) { - free((void *)uptr->up7); - uptr->up7 = 0; + if (uptr->card_ctx != 0) { + struct card_context * data = (struct card_context *)uptr->card_ctx; + /* No clear any existing decks on stack */ + free(data->images); + free(uptr->card_ctx); + uptr->card_ctx = 0; + } + if (uptr->flags & UNIT_RO) { /* Card Reader? */ + free(uptr->filename); + uptr->filename = NULL; + uptr->flags &= ~UNIT_ATT; + uptr->dynflags &= ~UNIT_ATTMULT; + return SCPE_OK; /* Already detached */ } return detach_unit(uptr); } t_stat sim_card_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { - fprintf (st, "%s Card Attach Help\n\n", dptr->name); + fprintf (st, "%s Card %sAttach Help\n\n", dptr->name, (uptr->flags & UNIT_RO) ? "Reader " : "Punch "); if (0 == (uptr-dptr->units)) { if (dptr->numunits > 1) { uint32 i; - + for (i=0; i < dptr->numunits; ++i) if (dptr->units[i].flags & UNIT_ATTABLE) fprintf (st, " sim> ATTACH {switches} %s%d carddeck\n\n", dptr->name, i); @@ -1130,7 +1373,17 @@ t_stat sim_card_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, cons if ((uptr->flags & UNIT_RO) == 0) { fprintf (st, " -N Create a new punch output file (default is to append to\n"); fprintf (st, " an existing file if it exists)\n"); - } + } else { + fprintf (st, " -E Return EOF after deck read\n"); + fprintf (st, " -S Append deck to cards currently waiting to be read\n"); + } + return SCPE_OK; +} + +#else + +t_stat sim_card_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ return SCPE_OK; } diff --git a/sim_card.h b/sim_card.h index 8cdd5a7c..05af7add 100644 --- a/sim_card.h +++ b/sim_card.h @@ -31,7 +31,7 @@ Binary Card format: Each record 160 characters. First character 21012345 - 111 + 111 Second characters 6789---- Top 4 bits of second character are 0. It is unlikely that ascii text or BCD format @@ -66,6 +66,8 @@ extern "C" { #endif +#define SIM_CARD_API 2 /* API Version */ + #define DEBUG_CARD 0x0000010 /* Show details */ /* Flags for punch and reader. */ @@ -82,22 +84,31 @@ extern "C" { #define MODE_LOWER (8 << UNIT_V_CARD_MODE) #define MODE_026 (0x10 << UNIT_V_CARD_MODE) #define MODE_029 (0x20 << UNIT_V_CARD_MODE) -#define MODE_CHAR (0x30 << UNIT_V_CARD_MODE) +#define MODE_CHAR (0x70 << UNIT_V_CARD_MODE) -struct _card_data -{ - int ptr; /* Pointer in buffer */ - int len; /* Length of buffer */ - char cbuff[1024]; /* Read in buffer for cards */ - uint16 image[80]; /* Image */ - uint8 hol_to_ascii[4096]; /* Back conversion table */ -}; +/* Card Reader Return Status code */ +typedef int t_cdstat; +#define CDSE_OK 0 /* Good */ +#define CDSE_EOF 1 /* End of File */ +#define CDSE_EMPTY 2 /* Input Hopper Empty */ +#define CDSE_ERROR 3 /* Error Card Read */ /* Generic routines. */ -t_stat sim_read_card(UNIT * uptr); + + /* Read next card into image row 12,11,10,1-9 */ + /* Return SCPE_EOF if end file detected. */ +t_cdstat sim_read_card(UNIT * uptr, uint16 image[80]); + /* Punch card from image row 12,11,10,1-9 */ +t_cdstat sim_punch_card(UNIT * uptr, uint16 image[80]); + /* Check if next card to be read is EOF */ int sim_card_eof(UNIT * uptr); -t_stat sim_punch_card(UNIT * uptr, UNIT *stkptr); + /* Return number of cards yet to read */ +t_addr sim_hopper_size(UNIT * uptr); + /* Return number of cards punched */ +t_addr sim_punch_count(UNIT * uptr); +t_addr sim_card_input_hopper_count(UNIT *uptr); +t_addr sim_card_output_hopper_count(UNIT *uptr); t_stat sim_card_attach(UNIT * uptr, CONST char *file); t_stat sim_card_detach(UNIT *uptr); @@ -108,16 +119,16 @@ uint8 sim_hol_to_bcd(uint16 hol); uint16 sim_hol_to_ebcdic(uint16 hol); /* Format control routines. */ -t_stat sim_card_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat sim_card_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat sim_card_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat sim_card_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc); /* Help information */ -t_stat sim_card_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +t_stat sim_card_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); /* Translation tables */ -extern const char sim_six_to_ascii[64]; -extern const char sim_ascii_to_six[128]; -extern const uint8 sim_parity_table[64]; +extern CONST char sim_six_to_ascii[64]; /* Map BCD to ASCII */ +extern CONST char sim_ascii_to_six[128]; /* Map 7 bit ASCII to BCD */ +extern CONST uint8 sim_parity_table[64]; /* 64 entry odd parity table */ #ifdef __cplusplus }