diff --git a/I650/i650_cdp.c b/I650/i650_cdp.c index 3cfa31fd9..d63d445d4 100644 --- a/I650/i650_cdp.c +++ b/I650/i650_cdp.c @@ -1403,7 +1403,7 @@ uint32 cdp_cmd(UNIT * uptr, uint16 cmd, uint16 addr) image[i] = 0; } else { // punch char - h = sim_ascii_to_hol(c); + h = ascii_to_hol(c); image[i] = h; } } diff --git a/I650/i650_cdr.c b/I650/i650_cdr.c index aad48028e..cccf08b88 100644 --- a/I650/i650_cdr.c +++ b/I650/i650_cdr.c @@ -103,7 +103,7 @@ int decode_8word_wiring(uint16 image[80], int bCheckForHiPunch) // read word digits for (iDigit=0;iDigit<10;iDigit++) { c1 = image[iCol++]; - c2 = sim_hol_to_ascii(c1); // convert to ascii + c2 = hol_to_ascii(c1); // convert to ascii if ((c1 == 0xA00) || (c2 == '?')) { c1 = 0xA00; c2 = '?'; // the punched value +0 should be represented by ascii ? } @@ -120,7 +120,7 @@ int decode_8word_wiring(uint16 image[80], int bCheckForHiPunch) if ((iCol==10) && (c2 == '-')) NegPunch= 1; // allow a minus on col 10 c1 = c1 & 0x3FF; // remove X and Y punches - c2 = sim_hol_to_ascii(c1); // convert to ascii again + c2 = hol_to_ascii(c1); // convert to ascii again c2 = c2 - '0'; // convert ascii to binary digit if (c2 > 9) c2 = 0; // nondigits chars interpreted as zero d = d * 10 + c2; @@ -174,7 +174,7 @@ void decode_soap_symb_info(uint16 image[80]) i2=0; for (i=40;i<80;i++) { c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); c2 = (strchr(mem_to_ascii, toupper(c2))) ? c2:' '; if (c2 == '~') c2 = ' '; if ((i==47) || (i==50) || (i==56)) buf[i2++] = ' '; // add space separation between op, da, ia fields @@ -267,7 +267,7 @@ void decode_soap_wiring(uint16 image[80], int bMultiPass) // keep 026 fortran charset for (i=0;i<80;i++) { c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); c2 = (strchr(mem_to_ascii, toupper(c2))) ? c2:' '; if (c2 == '~') c2 = ' '; buf[i] = (char) c2; @@ -348,7 +348,7 @@ void decode_supersoap_wiring(uint16 image[80]) // keep 026 fortran charset for (i=0;i<80;i++) { c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); c2 = (strchr(mem_to_ascii, toupper(c2))) ? c2:' '; if (c2 == '~') c2 = ' '; buf[i] = (char) c2; @@ -456,7 +456,7 @@ void decode_is_wiring(uint16 image[80]) // keep 0..9,+,-,, replace anything else by for (i=0;i<80;i++) { c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); buf[i] = (strchr("+-0123456789", c2)) ? ((char) (c2)):' '; } buf[80] = 0; // terminate string @@ -582,7 +582,7 @@ void decode_it_wiring(uint16 image[80]) // keep 026 fortran charset for (i=0;i<80;i++) { c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); c2 = (strchr(mem_to_ascii, toupper(c2))) ? c2:' '; if (c2 == '~') c2 = ' '; buf[i] = (char) c2; @@ -732,7 +732,7 @@ int decode_ra_wiring(uint16 image[80], int HiPunch) for (i=0;i<80;i++) { IsNeg = hbuf[i]=0; c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); c2 = toupper(c2); if ((c1 == 0xA00) || (c2 == '?') || c2 == '+') { hbuf[i]=1; c2='0'; // '0' or blank + HiPunch Y(12) @@ -888,7 +888,7 @@ int decode_fds_wiring(uint16 image[80], int HiPunch) for (i=0;i<80;i++) { IsNeg =0; c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); c2 = toupper(c2); if ((c1 == 0xA00) || (c2 == '?') || c2 == '+') { c2='0'; // '0' or blank + HiPunch Y(12) @@ -1063,7 +1063,7 @@ void decode_fortransit_wiring(uint16 image[80]) // keep 026 fortran charset for (i=0;i<80;i++) { c1 = image[i]; - c2 = sim_hol_to_ascii(c1); + c2 = hol_to_ascii(c1); c2 = toupper(c2); c2 = (strchr(mem_to_ascii, c2)) ? c2:' '; if (c2 == '~') c2 = ' '; @@ -1156,7 +1156,7 @@ uint32 cdr_cmd(UNIT * uptr, uint16 cmd, uint16 addr) // make local copy of card for debug output for (i=0; i<80; i++) - cbuf[i] = sim_hol_to_ascii(image[i]); + cbuf[i] = hol_to_ascii(image[i]); cbuf[80] = 0; // terminate string sim_debug(DEBUG_DETAIL, &cpu_dev, "Read Card: %s\n", sim_trim_endspc(cbuf)); diff --git a/I650/i650_defs.h b/I650/i650_defs.h index c6fd127cd..e02a4153e 100644 --- a/I650/i650_defs.h +++ b/I650/i650_defs.h @@ -172,8 +172,8 @@ extern struct card_wirings { extern char digits_ascii[31]; extern char mem_to_ascii[101]; extern int ascii_to_NN(int ch); -extern uint16 sim_ascii_to_hol(char c); -extern char sim_hol_to_ascii(uint16 hol); +extern uint16 ascii_to_hol(char c); +extern char hol_to_ascii(uint16 hol); /* Generic devices common to all */ extern DEVICE cpu_dev; diff --git a/I650/i650_sys.c b/I650/i650_sys.c index 475371bd2..0d248e95b 100644 --- a/I650/i650_sys.c +++ b/I650/i650_sys.c @@ -72,6 +72,7 @@ const char *sim_stop_messages[SCPE_BASE] = { }; static t_stat ibm650_deck_cmd(int32 arg, CONST char *buf); +static t_stat deck_close(DEVICE *dptr); static CTAB aux_cmds [] = { /* Name Action Routine Argument Help String */ @@ -134,7 +135,7 @@ char digits_ascii[31] = { '!', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', /* 0-9 w/Negative Punch X(11) */ 0}; -uint16 ascii_to_hol[128] = { +uint16 ascii_to_hol_tab[128] = { /* Control */ 0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000, /*0-37*/ /*Control*/ @@ -178,19 +179,19 @@ uint16 ascii_to_hol[128] = { 0x604, 0x602, 0x601, 0x406, 0x806, 0x006, 0x005,0xf000 }; -uint16 sim_ascii_to_hol(char c) +uint16 ascii_to_hol(char c) { - return ascii_to_hol[c & 127]; + return ascii_to_hol_tab[c & 127]; } -char sim_hol_to_ascii(uint16 hol) +char hol_to_ascii(uint16 hol) { int c; hol = hol & 0x0fff; // ignore extra high bits, if any if (hol == 0xa00) return '?'; // +0 if (hol == 0x600) return '!'; // -0 for (c=31;c<127;c++) { - if (ascii_to_hol[c] == hol) { + if (ascii_to_hol_tab[c] == hol) { // take in consideration the aliases between hol and ascii to return // char as for 026 FORT charset // hol = 0x022 -> 8-4 punches -> "-" or "'" or "@". Must be "-" @@ -665,13 +666,11 @@ int Shift_Digits(t_int64 * d, int nDigits) first destination deck file second destination deck file - when using as source both or can have same name as the currently + when using as source both or can NOT have same name as the currently attached file to cdp device. On command execution, cdp gest its file detached. file1 and file are created (overwritten if already exists). - when using as source both or can have same name as . - is completly read by SimH in its internal buffer (room for 10K cards) - and then splitted to and . + when using as source both or can NOT have same name as . carddeck join join several deck files into a new one @@ -682,10 +681,7 @@ int Shift_Digits(t_int64 * d, int nDigits) ... destination deck file - any source file , , etc can have same name as destination file . - Each source file is completly read in turn by SimH in its internal buffer (room for 10K cards) - and then written on destination file. This allos to append une deck on the top/end of - another one. + No file , , etc can have same name as destination file . carddeck print print deck on console, and on simulated IBM 407 is any file is attached to cpd0 @@ -695,163 +691,125 @@ int Shift_Digits(t_int64 * d, int nDigits) carddeck echolasty - number of cards to display (upo to 10) + number of cards to display should be cdr1 to cdr3. Unit for Take hopper - switches: if present mut be just after carddeck and before deck operation + switches: if present must be just after carddeck and before deck operation -Q quiet return status. */ -/* - * Allocate space for a card deck of nCards cards. - */ -uint16 *deck_alloc(int nCards) +// Open a card deck. This dynamically creates a DEVICE with a single UNIT for +// the card reader or punch. When done with the deck, call deck_close(). +// Returns the DEVICE pointer by reference (from there it can find the UNIT easily). +static t_stat deck_open(DEVICE **device, CONST char *fn, t_bool write) { - return malloc(nCards * 80 * sizeof(uint16)); -} - -/* - * Free a deck previously obtained from deck_alloc(). - */ -void deck_free(uint16 *deck) -{ - free(deck); -} + int32 old_switches = sim_switches; + DEVICE *dptr = calloc(sizeof(DEVICE), 1); + UNIT *uptr = calloc(sizeof(UNIT), 1); -// Load card file fn and add its cards to -// DeckImage array, up to a max of MAX_CARDS_IN_DECK. -// If DeckImagePtr is NULL, allocates a deck (for now, fixed at -// MAX_CARDS_IN_DECK, but there is potential to make this flexible -// and reduce the size to actually used size). -// Uses cdr0 device/unit. -t_stat deck_load(CONST char *fn, uint16 ** DeckImagePtr, int * nCards) -{ - UNIT * uptr = &cdr_unit[0]; - uint16 * DeckImage; - uint16 image[80]; - t_stat r, r2; - int i; - uint16 c; + *device = NULL; - // set flags for read only - uptr->flags |= UNIT_RO; + // Clone a normal card reader/punch device. + *dptr = cdr_dev; + dptr->units = uptr; + dptr->numunits = 1; - // attach file to cdr unit 0 - r = (cdr_dev.attach)(uptr, fn); - if (r != SCPE_OK) return r; + // Set the unit to default values by cloning unit 0. + *uptr = cdr_unit[0]; - DeckImage = *DeckImagePtr; - if (!DeckImage) { - DeckImage = deck_alloc(MAX_CARDS_IN_DECK); - } - - // read all cards from file - while (1) { - - if (*nCards >= MAX_CARDS_IN_DECK) { - r = sim_messagef (SCPE_IERR, "Too many cards\n"); - break; - } - r = sim_read_card(uptr, image); - if ((r == CDSE_EOF) || (r == CDSE_EMPTY)) { - r = SCPE_OK; break; // normal termination on card file read finished - } else if (r != CDSE_OK) { - break; // abnormal termination on error - } - // add card read to deck - for (i=0; i<80; i++) { - c = image[i]; - DeckImage[*nCards * 80 + i] = c & 0xFFF; - } - *nCards = *nCards + 1; + // set flags for read only or write + if (write) { + uptr->flags &= ~UNIT_RO; + sim_switches |= SWMASK ('N'); + } else { + uptr->flags |= UNIT_RO; } - *DeckImagePtr = DeckImage; + sim_register_internal_device(dptr); - // deattach file from cdr unit 0 - r2 = (cdr_dev.detach)(uptr); - if (r == SCPE_OK) r = r2; + // attach file to cdr + t_stat r = (cdr_dev.attach)(uptr, fn); + sim_switches = old_switches; if (r != SCPE_OK) { - // Special case: allow caller to bail out without needing to free the deck. - deck_free(DeckImage); - *DeckImagePtr = NULL; - return r; + deck_close(dptr); + return r; } + *device = dptr; + return SCPE_OK; } -// write nCards starting at card from DeckImage array to file fn -// uses cdr0 device/unit -t_stat deck_save(CONST char *fn, uint16 * DeckImage, int card, int nCards) +// Closes a device created by deck_open(). +// It deletes the DEVICE and the UNIT. +static t_stat deck_close(DEVICE *dptr) { - UNIT * uptr = &cdr_unit[0]; - uint16 image[80]; - t_stat r; - int i,nc; - - // set flags for create new file - uptr->flags &= ~UNIT_RO; - sim_switches |= SWMASK ('N'); - - // attach file to cdr unit 0 - r = (cdr_dev.attach)(uptr, fn); - if (r != SCPE_OK) return r; - - // write cards to file - for (nc=0;nc= MAX_CARDS_IN_DECK) { - r = sim_messagef (SCPE_IERR, "Reading outside of Deck\n"); - break; - } + UNIT *uptr = dptr->units; - // read card from deck - for (i=0; i<80; i++) image[i] = DeckImage[(nc + card) * 80 + i]; + t_stat r = (cdr_dev.detach)(uptr); - r = sim_punch_card(uptr, image); - if (r != CDSE_OK) break; // abnormal termination on error - } + sim_unregister_internal_device(dptr); + + free(uptr); + free(dptr); + + return r; +} - // deattach file from cdr unit 0 - (cdr_dev.detach)(uptr); +// Read a card from the first UNIT of any cdr DEVICE, but in particular from +// one created by deck_open(). +static t_stat read_card(DEVICE *dptr, uint16 CardImage[80]) +{ + UNIT *uptr = dptr->units; + t_stat r = sim_read_card(uptr, CardImage); return r; } -// echo/print nCards from DeckImage array + +// Write a card to the first unit of any cdr DEVICE, but in particular to +// one created by deck_open(). +static t_stat write_card(DEVICE *dptr, uint16 CardImage[80]) +{ + UNIT *uptr = dptr->units; + + t_stat r = sim_punch_card(uptr, CardImage); + + return r; +} + +// echo/print the card from CardImage array // uses cdp0 device/unit -void deck_print_echo(uint16 * DeckImage, int nCards, int bPrint, int bEcho) +void deck_print_echo(uint16 CardImage[80], int bPrint, int bEcho) { char line[81]; - int i,c,nc; + int i,c; uint16 hol; - for (nc=0; nc '3') ) { // is a file } else { + DEVICE *dptr; + UNIT *uptr; + // is cdp1 cdp2 or cdp3 device dptr = find_unit (gbuf, &uptr); /* locate unit */ if (dptr == NULL) /* found dev? */ @@ -918,16 +875,6 @@ static t_stat deck_split_cmd(CONST char *cptr) // read source deck nCards = 0; - r = deck_load(fn0, &DeckImage, &nCards); - if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fn0); - - // calc nCards1 = cards in first deck - if (tail) { - // calc cards remaining when last nCardCount are removed from source deck - nCards1 = nCards - nCards1; - if (nCards1 < 0) nCards1 = 0; - } - if (nCards1 > nCards) nCards1 = nCards; while (sim_isspace (*cptr)) cptr++; // trim leading spc cptr = get_glyph_quoted (cptr, fn1, 0); // get next param: filename 1 @@ -935,63 +882,90 @@ static t_stat deck_split_cmd(CONST char *cptr) while (sim_isspace (*cptr)) cptr++; // trim leading spc cptr = get_glyph_quoted (cptr, fn2, 0); // get next param: filename 2 if (fn2[0] == 0) return sim_messagef (SCPE_ARG, "Missing second filename\n"); + + if (strcmp(fn0, fn1) == 0 || strcmp(fn0, fn2) == 0) { + return sim_messagef (SCPE_ARG, "Destination file name (%s) same as source file name\n", fn0); + } - if (bSplit5CD ) { + r = deck_open(&dev0, fn0, 0); + if (r != SCPE_OK) return sim_messagef (r, "Cannot open source deck (%s)\n", fn0); + + // create (so far empty) output decks + r = deck_open(&dev1, fn1, 1); + if (r != SCPE_OK) { + deck_close(dev0); + return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn1); + } + + r = deck_open(&dev2, fn2, 1); + if (r != SCPE_OK) { + deck_close(dev0); + deck_close(dev1); + return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn1); + } + + if (bSplit5CD) { // separate 5cd deck - uint16 *DeckImage1 = deck_alloc(nCards); - uint16 *DeckImage2 = deck_alloc(nCards); - int i, nc, nc1, nc2, bFound; + int i, nc1, nc2, bFound; uint16 hol; nc1 = nc2 = 0; - for (nc=0; ncunits[0]); + + // calc nCards1 = cards to go to first output deck + if (tail) { + // calc cards remaining when last nCards1 are removed from source deck + + nCards1 = nCards - nCards1; + if (nCards1 < 0) nCards1 = 0; + } + if (nCards1 > nCards) nCards1 = nCards; + + { + int i; + + for (i = 0; i < nCards1; i++) { + uint16 CardImage[80]; + + r = read_card(dev0, CardImage); + if (r != CDSE_OK) { + sim_messagef(r, "Cannot read enough cards from source deck (%s)\n", fn0); + break; + } + write_card(dev1, CardImage); + } + } + + for (;;) { + uint16 CardImage[80]; + + r = read_card(dev0, CardImage); + if (r == CDSE_EOF || r == CDSE_EMPTY) { + break; + } else if (r != CDSE_OK) { + sim_messagef(r, "Cannot read card from source deck (%s)\n", fn0); + break; + } + write_card(dev2, CardImage); } - r = deck_save(fn2, DeckImage, nCards1, nCards-nCards1); - deck_free(DeckImage); + // decks are no longer needed + r = deck_close(dev0); + r = deck_close(dev1); if (r != SCPE_OK) { - return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0); + sim_messagef (r, "Cannot close destination deck1 (%s)\n", fn1); + } + r = deck_close(dev2); + if (r != SCPE_OK) { + sim_messagef (r, "Cannot close destination deck2 (%s)\n", fn2); } if ((sim_switches & SWMASK ('Q')) == 0) { @@ -1072,6 +1088,8 @@ static t_stat deck_split_cmd(CONST char *cptr) } // carddeck join ... as +// Aargh, one of the usages is "carddeck join deck_it_header.dck deck_it.dck as deck_it.dck" +// with the output file the same as one of the inputs... static t_stat deck_join_cmd(CONST char *cptr) { char fnSrc[4*CBUFSIZE]; @@ -1081,7 +1099,6 @@ static t_stat deck_join_cmd(CONST char *cptr) char gbuf[4*CBUFSIZE]; t_stat r; - uint16 *DeckImage = NULL; int i,nDeck, nCards, nCards1; cptr0 = cptr; @@ -1100,28 +1117,52 @@ static t_stat deck_join_cmd(CONST char *cptr) if (fnDest[0] == 0) return sim_messagef (SCPE_ARG, "Missing destination filename\n"); if (*cptr) return sim_messagef (SCPE_ARG, "Extra unknown parameters after destination filename\n"); + DEVICE *devDest; + r = deck_open(&devDest, fnDest, 1); + if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck (%s)\n", fnDest); + cptr = cptr0; // restore cptr to scan source filenames nDeck = nCards = 0; while (1) { + DEVICE *cdrSrc; while (sim_isspace (*cptr)) cptr++; // trim leading spc if (cptrAS == cptr) break; // break if reach "AS" cptr = get_glyph_quoted (cptr, fnSrc, 0); // get next param: source filename if (fnSrc[0] == 0) return sim_messagef (SCPE_ARG, "Missing source filename\n"); + if (strcmp(fnSrc, fnDest) == 0) return sim_messagef (SCPE_ARG, "Source file name (%s) equal to Destination file name\n", fnSrc); // read source deck nCards1 = nCards; - r = deck_load(fnSrc, &DeckImage, &nCards); - if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fnSrc); + r = deck_open(&cdrSrc, fnSrc, 0); + if (r != SCPE_OK) { + deck_close(devDest); + return sim_messagef(r, "Cannot read source deck (%s)\n", fnSrc); + } + + for (;;) { + uint16 image[80]; + + r = read_card(cdrSrc, image); + if (r == CDSE_EOF || r == CDSE_EMPTY) { + break; + } else if (r != CDSE_OK) { + sim_messagef(r, "Cannot read card from deck to print (%s)\n", fnSrc); + break; + } + r = write_card(devDest, image); + if (r != CDSE_OK) { + sim_messagef(r, "Cannot write card (%s)\n", fnDest); + break; + } + nCards++; + } + deck_close(cdrSrc); nDeck++; - if ((sim_switches & SWMASK ('Q')) == 0) { sim_messagef (SCPE_OK, "Source Deck %d has %d cards (%s)\n", nDeck, nCards - nCards1, fnSrc); } } - r = deck_save(fnDest, DeckImage, 0, nCards); - deck_free(DeckImage); - if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck (%s)\n", fnDest); if ((sim_switches & SWMASK ('Q')) == 0) { sim_messagef (SCPE_OK, "Destination Deck has %d cards (%s)\n", nCards, fnDest); @@ -1134,9 +1175,9 @@ static t_stat deck_join_cmd(CONST char *cptr) static t_stat deck_print_cmd(CONST char *cptr) { char fn[4*CBUFSIZE]; + DEVICE *cdr; t_stat r; - uint16 *DeckImage = NULL; int nCards; while (sim_isspace (*cptr)) cptr++; // trim leading spc @@ -1146,16 +1187,28 @@ static t_stat deck_print_cmd(CONST char *cptr) // read deck to be printed (-1 to convert to ascii value, not hol) nCards = 0; - r = deck_load(fn, &DeckImage, &nCards); - if (r != SCPE_OK) return sim_messagef (r, "Cannot read deck to print (%s)\n", fn); + r = deck_open(&cdr, fn, 0); + if (r != SCPE_OK) return sim_messagef(r, "Cannot read deck to print (%s)\n", fn); + + for (;;) { + uint16 image[80]; + + r = read_card(cdr, image); + if (r == CDSE_EOF || r == CDSE_EMPTY) { + break; + } else if (r != CDSE_OK) { + sim_messagef(r, "Cannot read card from deck to print (%s)\n", fn); + break; + } + deck_print_echo(image, 1,1); + nCards++; + } - deck_print_echo(DeckImage, nCards, 1,1); + deck_close(cdr); if ((sim_switches & SWMASK ('Q')) == 0) { sim_messagef (SCPE_OK, "Printed Deck with %d cards (%s)\n", nCards, fn); } - - deck_free(DeckImage); return SCPE_OK; } @@ -1166,8 +1219,7 @@ static t_stat deck_echolast_cmd(CONST char *cptr) char gbuf[4*CBUFSIZE]; t_stat r; - uint16 *DeckImage = NULL; - int i,nc,nCards, ic, nh, ncdr; + int nc,nCards, ic, nh, ncdr; while (sim_isspace (*cptr)) cptr++; // trim leading spc @@ -1192,23 +1244,18 @@ static t_stat deck_echolast_cmd(CONST char *cptr) // get nCards form read card take hopper buffer // that is, print last nCards read - DeckImage = deck_alloc(nCards); - // get last nCards cards, so // first card to echo is count ones before last one nh = ReadStakerLast[ncdr] - (nCards-1); nh = nh % MAX_CARDS_IN_READ_STAKER_HOPPER; - for (nc=0; nchopper_cards - uptr->pos) - ((col & CARD_EOF) ? 1 : 0)); } +/* Returns the number of cards available to read with CDSE_OK status. */ +t_addr +sim_card_input_hopper_ok_count(UNIT *uptr) { + struct card_context *data = (struct card_context *)uptr->card_ctx; + uint16 col; + int i; + + if (data == NULL || data->images == NULL) + return 0; /* attached? */ + + if (uptr->pos >= data->hopper_cards) + return 0; + + /* Check each card to see if it has an EOF or ERR marker. */ + for (i = uptr->pos; i < data->hopper_cards; i++) { + col = (*data->images)[i][0]; + if (col & (CARD_EOF | CARD_ERR)) + break; + } + + return i - uptr->pos; +} + t_addr sim_card_output_hopper_count(UNIT *uptr) { struct card_context *data = (struct card_context *)uptr->card_ctx; diff --git a/sim_card.h b/sim_card.h index c29cec4d4..0e0e023dd 100644 --- a/sim_card.h +++ b/sim_card.h @@ -126,6 +126,7 @@ 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_input_hopper_ok_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);