diff --git a/I650/i650_sys.c b/I650/i650_sys.c index 475371bd2..ec6c48702 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 */ @@ -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,133 @@ 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; + + t_stat r = (cdr_dev.detach)(uptr); + + sim_unregister_internal_device(dptr); + + free(uptr); + free(dptr); + + return r; +} - // read card from deck - for (i=0; i<80; i++) image[i] = DeckImage[(nc + card) * 80 + i]; +// Read a card from the first UNIT of any cdr DEVICE, but in particular from +// one created by deck_open(). +static t_stat deck_card_read(DEVICE *dptr, uint16 CardImage[80]) +{ + UNIT *uptr = dptr->units; + t_stat r = sim_read_card(uptr, CardImage); - r = sim_punch_card(uptr, image); - if (r != CDSE_OK) break; // abnormal termination on error + if (r == CDSE_EMPTY) { + r = CDSE_EOF; } - // deattach file from cdr unit 0 - (cdr_dev.detach)(uptr); + for (int i = 0; i < 80; i++) { + CardImage[i] &= 0xFFF; + } 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 deck_card_write(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 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 +890,92 @@ 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 ) { + DEVICE *dev0, *dev1, *dev2; + + 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; nc nCards) nCards1 = nCards; + + for (int i = 0; i < nCards1; i++) { + uint16 CardImage[80]; + + r = deck_card_read(dev0, CardImage); + if (r != CDSE_OK) { + sim_messagef(r, "Cannot read enough cards from source deck (%s)\n", fn0); + break; + } + deck_card_write(dev1, CardImage); + } + + for (;;) { + uint16 CardImage[80]; + + r = deck_card_read(dev0, CardImage); + if (r == CDSE_EOF) { + break; + } else if (r != CDSE_OK) { + sim_messagef(r, "Cannot read card from source deck (%s)\n", fn0); + break; + } + deck_card_write(dev2, CardImage); + } + + // 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 +1109,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 +1120,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,6 +1138,10 @@ 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) { @@ -1108,20 +1150,40 @@ static t_stat deck_join_cmd(CONST char *cptr) 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); + DEVICE *cdrSrc; + 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 = deck_card_read(cdrSrc, image); + if (r == CDSE_EOF) { + break; + } else if (r != CDSE_OK) { + sim_messagef(r, "Cannot read card from deck to print (%s)\n", fnSrc); + break; + } + r = deck_card_write(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); @@ -1136,7 +1198,6 @@ static t_stat deck_print_cmd(CONST char *cptr) char fn[4*CBUFSIZE]; t_stat r; - uint16 *DeckImage = NULL; int nCards; while (sim_isspace (*cptr)) cptr++; // trim leading spc @@ -1146,16 +1207,29 @@ 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); + DEVICE *cdr; + 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 = deck_card_read(cdr, image); + if (r == CDSE_EOF) { + 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 +1240,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 +1265,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; nc