Skip to content

Commit

Permalink
I650: Avoid allocating large card decks on the stack.
Browse files Browse the repository at this point in the history
Allocate them dynamically instead.
  • Loading branch information
Rhialto committed Jun 3, 2024
1 parent 4396394 commit 3c6f40e
Showing 1 changed file with 84 additions and 26 deletions.
110 changes: 84 additions & 26 deletions I650/i650_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
// increment nCards with the number of added cards
// uses cdr0 device/unit
t_stat deck_load(CONST char *fn, uint16 * DeckImage, int * nCards)
/*
* Allocate space for a card deck of nCards cards.
*/
uint16 *deck_alloc(int nCards)
{
return malloc(nCards * 80);
}

/*
* Free a deck previously obtained from deck_alloc().
*/
uint16 *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];
uint16 image[80];
uint16 * DeckImage;
uint16 image[80];
t_stat r, r2;
int i;
uint16 c;

// set flags for read only
uptr->flags |= UNIT_RO;
uptr->flags |= UNIT_RO;

// attach file to cdr unit 0
r = (cdr_dev.attach)(uptr, fn);
if (r != SCPE_OK) return r;

DeckImage = *DeckImagePtr;
if (!DeckImage) {
DeckImage = deck_alloc(MAX_CARDS_IN_DECK);
}

// read all cards from file
while (1) {

Expand All @@ -745,10 +769,17 @@ t_stat deck_load(CONST char *fn, uint16 * DeckImage, int * nCards)
*nCards = *nCards + 1;
}

*DeckImagePtr = DeckImage;

// deattach file from cdr unit 0
r2 = (cdr_dev.detach)(uptr);
if (r == SCPE_OK) r = r2;
if (r != SCPE_OK) return r;
if (r == SCPE_OK) r = r2;
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;
}
Expand Down Expand Up @@ -840,7 +871,7 @@ static t_stat deck_split_cmd(CONST char *cptr)
int bSplit5CD = 0;
int bSplitPAT = 0;

uint16 DeckImage[80 * MAX_CARDS_IN_DECK];
uint16 *DeckImage = NULL;
int nCards, nCards1, tail;

while (sim_isspace (*cptr)) cptr++; // trim leading spc
Expand Down Expand Up @@ -887,7 +918,7 @@ static t_stat deck_split_cmd(CONST char *cptr)

// read source deck
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);

// calc nCards1 = cards in first deck
Expand All @@ -907,8 +938,8 @@ static t_stat deck_split_cmd(CONST char *cptr)

if (bSplit5CD ) {
// separate 5cd deck
uint16 DeckImage1[80 * MAX_CARDS_IN_DECK];
uint16 DeckImage2[80 * MAX_CARDS_IN_DECK];
uint16 *DeckImage1 = deck_alloc(nCards);
uint16 *DeckImage2 = deck_alloc(nCards);
int i, nc, nc1, nc2, bFound;
uint16 hol;

Expand Down Expand Up @@ -947,11 +978,20 @@ static t_stat deck_split_cmd(CONST char *cptr)
nc2++;
}
}
// input deck is no longer needed
deck_free(DeckImage);
// save output decks
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);
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 ((sim_switches & SWMASK ('Q')) == 0) {
sim_messagef (SCPE_OK, "Deck with 5 words-per-card splitted %d/%d cards\n", nc1, nc2);
Expand All @@ -961,8 +1001,8 @@ static t_stat deck_split_cmd(CONST char *cptr)

if (bSplitPAT) {
// separate pat deck
uint16 DeckImage1[80 * MAX_CARDS_IN_DECK];
uint16 DeckImage2[80 * MAX_CARDS_IN_DECK];
uint16 *DeckImage1 = deck_alloc(nCards);
uint16 *DeckImage2 = deck_alloc(nCards);
int i, nc, nc1, nc2, bFound;
uint16 hol;

Expand Down Expand Up @@ -990,24 +1030,39 @@ static t_stat deck_split_cmd(CONST char *cptr)
nc2++;
}
}
deck_free(DeckImage);
// save output decks
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);
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 ((sim_switches & SWMASK ('Q')) == 0) {
sim_messagef (SCPE_OK, "Deck with availability-card splitted %d/%d cards\n", nc1, nc2);
}

return SCPE_OK;
}

// split based on card count
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);
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) {
sim_messagef (SCPE_OK, "Deck splitted to %d/%d cards\n", nCards1, nCards-nCards1);
Expand All @@ -1026,7 +1081,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
char gbuf[4*CBUFSIZE];
t_stat r;

uint16 DeckImage[80 * MAX_CARDS_IN_DECK];
uint16 *DeckImage = NULL;
int i,nDeck, nCards, nCards1;

cptr0 = cptr;
Expand All @@ -1047,7 +1102,7 @@ static t_stat deck_join_cmd(CONST char *cptr)

cptr = cptr0; // restore cptr to scan source filenames
nDeck = nCards = 0;
memset(DeckImage, 0, sizeof(DeckImage));
//memset(DeckImage, 0, sizeof(DeckImage));
while (1) {

while (sim_isspace (*cptr)) cptr++; // trim leading spc
Expand All @@ -1057,7 +1112,7 @@ static t_stat deck_join_cmd(CONST char *cptr)

// read source deck
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);
nDeck++;

Expand All @@ -1066,6 +1121,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
}
}
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) {
Expand All @@ -1081,7 +1137,7 @@ static t_stat deck_print_cmd(CONST char *cptr)
char fn[4*CBUFSIZE];
t_stat r;

uint16 DeckImage[80 * MAX_CARDS_IN_DECK];
uint16 *DeckImage = NULL;
int nCards;

while (sim_isspace (*cptr)) cptr++; // trim leading spc
Expand All @@ -1091,14 +1147,16 @@ 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);
r = deck_load(fn, &DeckImage, &nCards);
if (r != SCPE_OK) return sim_messagef (r, "Cannot read deck to print (%s)\n", fn);

deck_print_echo(DeckImage, nCards, 1,1);

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;
}
Expand Down

0 comments on commit 3c6f40e

Please sign in to comment.