I650: Avoid allocating large card decks on the stack.
Allocate them dynamically instead.
This commit is contained in:
parent
3ffd20c1fa
commit
b6ae88bd1c
1 changed files with 86 additions and 27 deletions
113
I650/i650_sys.c
113
I650/i650_sys.c
|
@ -705,25 +705,49 @@ int Shift_Digits(t_int64 * d, int nDigits)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// load card file fn and add its cards to
|
/*
|
||||||
// DeckImage array, up to a max of nMaxCards
|
* Allocate space for a card deck of nCards cards.
|
||||||
// increment nCards with the number of added cards
|
*/
|
||||||
// uses cdr0 device/unit
|
uint16 *deck_alloc(int nCards)
|
||||||
t_stat deck_load(CONST char *fn, uint16 * DeckImage, int * nCards)
|
{
|
||||||
|
return malloc(nCards * 80 * sizeof(uint16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free a deck previously obtained from deck_alloc().
|
||||||
|
*/
|
||||||
|
void deck_free(uint16 *deck)
|
||||||
|
{
|
||||||
|
free(deck);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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];
|
UNIT * uptr = &cdr_unit[0];
|
||||||
uint16 image[80];
|
uint16 * DeckImage;
|
||||||
|
uint16 image[80];
|
||||||
t_stat r, r2;
|
t_stat r, r2;
|
||||||
int i;
|
int i;
|
||||||
uint16 c;
|
uint16 c;
|
||||||
|
|
||||||
// set flags for read only
|
// set flags for read only
|
||||||
uptr->flags |= UNIT_RO;
|
uptr->flags |= UNIT_RO;
|
||||||
|
|
||||||
// attach file to cdr unit 0
|
// attach file to cdr unit 0
|
||||||
r = (cdr_dev.attach)(uptr, fn);
|
r = (cdr_dev.attach)(uptr, fn);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
|
|
||||||
|
DeckImage = *DeckImagePtr;
|
||||||
|
if (!DeckImage) {
|
||||||
|
DeckImage = deck_alloc(MAX_CARDS_IN_DECK);
|
||||||
|
}
|
||||||
|
|
||||||
// read all cards from file
|
// read all cards from file
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
@ -745,10 +769,17 @@ t_stat deck_load(CONST char *fn, uint16 * DeckImage, int * nCards)
|
||||||
*nCards = *nCards + 1;
|
*nCards = *nCards + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*DeckImagePtr = DeckImage;
|
||||||
|
|
||||||
// deattach file from cdr unit 0
|
// deattach file from cdr unit 0
|
||||||
r2 = (cdr_dev.detach)(uptr);
|
r2 = (cdr_dev.detach)(uptr);
|
||||||
if (r == SCPE_OK) r = r2;
|
if (r == SCPE_OK) r = r2;
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) {
|
||||||
|
// Special case: allow caller to bail out without needing to free the deck.
|
||||||
|
deck_free(DeckImage);
|
||||||
|
*DeckImagePtr = NULL;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -840,7 +871,7 @@ static t_stat deck_split_cmd(CONST char *cptr)
|
||||||
int bSplit5CD = 0;
|
int bSplit5CD = 0;
|
||||||
int bSplitPAT = 0;
|
int bSplitPAT = 0;
|
||||||
|
|
||||||
uint16 DeckImage[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage = NULL;
|
||||||
int nCards, nCards1, tail;
|
int nCards, nCards1, tail;
|
||||||
|
|
||||||
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
||||||
|
@ -887,7 +918,7 @@ static t_stat deck_split_cmd(CONST char *cptr)
|
||||||
|
|
||||||
// read source deck
|
// read source deck
|
||||||
nCards = 0;
|
nCards = 0;
|
||||||
r = deck_load(fn0, DeckImage, &nCards);
|
r = deck_load(fn0, &DeckImage, &nCards);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fn0);
|
if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fn0);
|
||||||
|
|
||||||
// calc nCards1 = cards in first deck
|
// calc nCards1 = cards in first deck
|
||||||
|
@ -907,8 +938,8 @@ static t_stat deck_split_cmd(CONST char *cptr)
|
||||||
|
|
||||||
if (bSplit5CD ) {
|
if (bSplit5CD ) {
|
||||||
// separate 5cd deck
|
// separate 5cd deck
|
||||||
uint16 DeckImage1[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage1 = deck_alloc(nCards);
|
||||||
uint16 DeckImage2[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage2 = deck_alloc(nCards);
|
||||||
int i, nc, nc1, nc2, bFound;
|
int i, nc, nc1, nc2, bFound;
|
||||||
uint16 hol;
|
uint16 hol;
|
||||||
|
|
||||||
|
@ -947,11 +978,20 @@ static t_stat deck_split_cmd(CONST char *cptr)
|
||||||
nc2++;
|
nc2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// input deck is no longer needed
|
||||||
|
deck_free(DeckImage);
|
||||||
// save output decks
|
// save output decks
|
||||||
r = deck_save(fn1, DeckImage1, 0, nc1);
|
r = deck_save(fn1, DeckImage1, 0, nc1);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0);
|
deck_free(DeckImage1);
|
||||||
|
if (r != SCPE_OK) {
|
||||||
|
deck_free(DeckImage2);
|
||||||
|
return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn1);
|
||||||
|
}
|
||||||
r = deck_save(fn2, DeckImage2, 0, nc2);
|
r = deck_save(fn2, DeckImage2, 0, nc2);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0);
|
deck_free(DeckImage2);
|
||||||
|
if (r != SCPE_OK) {
|
||||||
|
return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn2);
|
||||||
|
}
|
||||||
if (nc2 == 0) remove(fn2); // delete file2 if empty
|
if (nc2 == 0) remove(fn2); // delete file2 if empty
|
||||||
if ((sim_switches & SWMASK ('Q')) == 0) {
|
if ((sim_switches & SWMASK ('Q')) == 0) {
|
||||||
sim_messagef (SCPE_OK, "Deck with 5 words-per-card splitted %d/%d cards\n", nc1, nc2);
|
sim_messagef (SCPE_OK, "Deck with 5 words-per-card splitted %d/%d cards\n", nc1, nc2);
|
||||||
|
@ -961,8 +1001,8 @@ static t_stat deck_split_cmd(CONST char *cptr)
|
||||||
|
|
||||||
if (bSplitPAT) {
|
if (bSplitPAT) {
|
||||||
// separate pat deck
|
// separate pat deck
|
||||||
uint16 DeckImage1[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage1 = deck_alloc(nCards);
|
||||||
uint16 DeckImage2[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage2 = deck_alloc(nCards);
|
||||||
int i, nc, nc1, nc2, bFound;
|
int i, nc, nc1, nc2, bFound;
|
||||||
uint16 hol;
|
uint16 hol;
|
||||||
|
|
||||||
|
@ -990,24 +1030,39 @@ static t_stat deck_split_cmd(CONST char *cptr)
|
||||||
nc2++;
|
nc2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
deck_free(DeckImage);
|
||||||
// save output decks
|
// save output decks
|
||||||
r = deck_save(fn1, DeckImage1, 0, nc1);
|
r = deck_save(fn1, DeckImage1, 0, nc1);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0);
|
deck_free(DeckImage1);
|
||||||
|
if (r != SCPE_OK) {
|
||||||
|
deck_free(DeckImage2);
|
||||||
|
return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn1);
|
||||||
|
}
|
||||||
r = deck_save(fn2, DeckImage2, 0, nc2);
|
r = deck_save(fn2, DeckImage2, 0, nc2);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0);
|
deck_free(DeckImage2);
|
||||||
|
if (r != SCPE_OK) {
|
||||||
|
return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn2);
|
||||||
|
}
|
||||||
if (nc2 == 0) remove(fn2); // delete file2 if empty
|
if (nc2 == 0) remove(fn2); // delete file2 if empty
|
||||||
if ((sim_switches & SWMASK ('Q')) == 0) {
|
if ((sim_switches & SWMASK ('Q')) == 0) {
|
||||||
sim_messagef (SCPE_OK, "Deck with availability-card splitted %d/%d cards\n", nc1, nc2);
|
sim_messagef (SCPE_OK, "Deck with availability-card splitted %d/%d cards\n", nc1, nc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// split based on card count
|
// split based on card count
|
||||||
r = deck_save(fn1, DeckImage, 0, nCards1);
|
r = deck_save(fn1, DeckImage, 0, nCards1);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0);
|
if (r != SCPE_OK) {
|
||||||
|
deck_free(DeckImage);
|
||||||
|
return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0);
|
||||||
|
}
|
||||||
|
|
||||||
r = deck_save(fn2, DeckImage, nCards1, nCards-nCards1);
|
r = deck_save(fn2, DeckImage, nCards1, nCards-nCards1);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0);
|
deck_free(DeckImage);
|
||||||
|
if (r != SCPE_OK) {
|
||||||
|
return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0);
|
||||||
|
}
|
||||||
|
|
||||||
if ((sim_switches & SWMASK ('Q')) == 0) {
|
if ((sim_switches & SWMASK ('Q')) == 0) {
|
||||||
sim_messagef (SCPE_OK, "Deck splitted to %d/%d cards\n", nCards1, nCards-nCards1);
|
sim_messagef (SCPE_OK, "Deck splitted to %d/%d cards\n", nCards1, nCards-nCards1);
|
||||||
|
@ -1026,7 +1081,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
|
||||||
char gbuf[4*CBUFSIZE];
|
char gbuf[4*CBUFSIZE];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
uint16 DeckImage[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage = NULL;
|
||||||
int i,nDeck, nCards, nCards1;
|
int i,nDeck, nCards, nCards1;
|
||||||
|
|
||||||
cptr0 = cptr;
|
cptr0 = cptr;
|
||||||
|
@ -1047,7 +1102,6 @@ static t_stat deck_join_cmd(CONST char *cptr)
|
||||||
|
|
||||||
cptr = cptr0; // restore cptr to scan source filenames
|
cptr = cptr0; // restore cptr to scan source filenames
|
||||||
nDeck = nCards = 0;
|
nDeck = nCards = 0;
|
||||||
memset(DeckImage, 0, sizeof(DeckImage));
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
||||||
|
@ -1057,7 +1111,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
|
||||||
|
|
||||||
// read source deck
|
// read source deck
|
||||||
nCards1 = nCards;
|
nCards1 = nCards;
|
||||||
r = deck_load(fnSrc, DeckImage, &nCards);
|
r = deck_load(fnSrc, &DeckImage, &nCards);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fnSrc);
|
if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fnSrc);
|
||||||
nDeck++;
|
nDeck++;
|
||||||
|
|
||||||
|
@ -1066,6 +1120,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r = deck_save(fnDest, DeckImage, 0, nCards);
|
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 (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck (%s)\n", fnDest);
|
||||||
|
|
||||||
if ((sim_switches & SWMASK ('Q')) == 0) {
|
if ((sim_switches & SWMASK ('Q')) == 0) {
|
||||||
|
@ -1081,7 +1136,7 @@ static t_stat deck_print_cmd(CONST char *cptr)
|
||||||
char fn[4*CBUFSIZE];
|
char fn[4*CBUFSIZE];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
uint16 DeckImage[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage = NULL;
|
||||||
int nCards;
|
int nCards;
|
||||||
|
|
||||||
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
||||||
|
@ -1091,7 +1146,7 @@ static t_stat deck_print_cmd(CONST char *cptr)
|
||||||
|
|
||||||
// read deck to be printed (-1 to convert to ascii value, not hol)
|
// read deck to be printed (-1 to convert to ascii value, not hol)
|
||||||
nCards = 0;
|
nCards = 0;
|
||||||
r = deck_load(fn, DeckImage, &nCards);
|
r = deck_load(fn, &DeckImage, &nCards);
|
||||||
if (r != SCPE_OK) return sim_messagef (r, "Cannot read deck to print (%s)\n", fn);
|
if (r != SCPE_OK) return sim_messagef (r, "Cannot read deck to print (%s)\n", fn);
|
||||||
|
|
||||||
deck_print_echo(DeckImage, nCards, 1,1);
|
deck_print_echo(DeckImage, nCards, 1,1);
|
||||||
|
@ -1099,6 +1154,8 @@ static t_stat deck_print_cmd(CONST char *cptr)
|
||||||
if ((sim_switches & SWMASK ('Q')) == 0) {
|
if ((sim_switches & SWMASK ('Q')) == 0) {
|
||||||
sim_messagef (SCPE_OK, "Printed Deck with %d cards (%s)\n", nCards, fn);
|
sim_messagef (SCPE_OK, "Printed Deck with %d cards (%s)\n", nCards, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deck_free(DeckImage);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -1109,7 +1166,7 @@ static t_stat deck_echolast_cmd(CONST char *cptr)
|
||||||
char gbuf[4*CBUFSIZE];
|
char gbuf[4*CBUFSIZE];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
uint16 DeckImage[80 * MAX_CARDS_IN_DECK];
|
uint16 *DeckImage = NULL;
|
||||||
int i,nc,nCards, ic, nh, ncdr;
|
int i,nc,nCards, ic, nh, ncdr;
|
||||||
|
|
||||||
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
while (sim_isspace (*cptr)) cptr++; // trim leading spc
|
||||||
|
@ -1135,6 +1192,7 @@ static t_stat deck_echolast_cmd(CONST char *cptr)
|
||||||
|
|
||||||
// get nCards form read card take hopper buffer
|
// get nCards form read card take hopper buffer
|
||||||
// that is, print last nCards read
|
// that is, print last nCards read
|
||||||
|
DeckImage = deck_alloc(nCards);
|
||||||
|
|
||||||
// get last nCards cards, so
|
// get last nCards cards, so
|
||||||
// first card to echo is count ones before last one
|
// first card to echo is count ones before last one
|
||||||
|
@ -1149,6 +1207,7 @@ static t_stat deck_echolast_cmd(CONST char *cptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
deck_print_echo(DeckImage, nCards, 0,1);
|
deck_print_echo(DeckImage, nCards, 0,1);
|
||||||
|
deck_free(DeckImage);
|
||||||
|
|
||||||
if ((sim_switches & SWMASK ('Q')) == 0) {
|
if ((sim_switches & SWMASK ('Q')) == 0) {
|
||||||
sim_messagef (SCPE_OK, "Last %d cards from Read take Hopper\n", nCards);
|
sim_messagef (SCPE_OK, "Last %d cards from Read take Hopper\n", nCards);
|
||||||
|
|
Loading…
Add table
Reference in a new issue