Skip to content

Commit eb3406e

Browse files
committed
GoL Memory Leak fix
Removed gameoflife struct.
1 parent 21e6b4d commit eb3406e

File tree

1 file changed

+25
-33
lines changed

1 file changed

+25
-33
lines changed

wled00/FX.cpp

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5161,30 +5161,22 @@ static void setBitValue(uint8_t* byteArray, size_t n, bool value) {
51615161
else
51625162
byteArray[byteIndex] &= ~(1 << bitIndex);
51635163
}
5164-
// create game of life struct to hold cells and future cells
5165-
struct gameOfLife {
5166-
uint8_t* cells;
5167-
uint8_t* futureCells;
5168-
uint8_t gliderLength;
5169-
uint16_t oscillatorCRC;
5170-
uint16_t spaceshipCRC;
5171-
};
5164+
51725165
uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/
51735166
// and https://github.com/DougHaber/nlife-color , Modified By: Brandon Butler
51745167
if (!strip.isMatrix) return mode_static(); // not a 2D set-up
51755168

51765169
const uint16_t cols = SEGMENT.virtualWidth();
51775170
const uint16_t rows = SEGMENT.virtualHeight();
5178-
const size_t dataSize = (SEGMENT.length() / 8) + (((SEGMENT.length() % 8) != 0) ? 1 : 0); // add one byte when extra bits needed (length not a multiple of 8)
5179-
const size_t totalSize = dataSize*2 + sizeof(gameOfLife);
5171+
const size_t dataSize = ((SEGMENT.length() + 7) / 8); // round up to nearest byte
5172+
const size_t totalSize = dataSize*2 + sizeof(uint8_t) + sizeof(uint16_t)*2; // 2 byte arrays, 1 uint8_t, 2 uint16_t
51805173

51815174
if (!SEGENV.allocateData(totalSize)) return mode_static(); //allocation failed
5182-
gameOfLife* gol = reinterpret_cast<gameOfLife*>(SEGENV.data);
5183-
5184-
if (gol->cells == nullptr) {
5185-
gol->cells = new uint8_t[dataSize];
5186-
gol->futureCells = new uint8_t[dataSize];
5187-
}
5175+
byte *cells = reinterpret_cast<byte*>(SEGENV.data);
5176+
byte *futureCells = reinterpret_cast<byte*>(SEGENV.data + dataSize);
5177+
uint8_t *gliderLength = reinterpret_cast<uint8_t*>(SEGENV.data + dataSize*2);
5178+
uint16_t *oscillatorCRC = reinterpret_cast<uint16_t*>(SEGENV.data + dataSize*2 + sizeof(uint8_t));
5179+
uint16_t *spaceshipCRC = reinterpret_cast<uint16_t*>(SEGENV.data + dataSize*2 + sizeof(uint8_t) + sizeof(uint16_t));
51885180

51895181
uint16_t &generation = SEGENV.aux0; //rename aux0 and aux1 for readability (not needed)
51905182
uint16_t &pauseFrames = SEGENV.aux1;
@@ -5205,22 +5197,22 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
52055197
for (int x = 0; x < cols; x++) for (int y = 0; y < rows; y++) {
52065198
uint8_t state = (random8() < 82) ? 1 : 0; // ~32% chance of being alive
52075199
if (state == 0) {
5208-
setBitValue(gol->cells, y * cols + x, false);
5209-
setBitValue(gol->futureCells, y * cols + x, false);
5200+
setBitValue(cells, y * cols + x, false);
5201+
setBitValue(futureCells, y * cols + x, false);
52105202
if (SEGMENT.check2) continue;
52115203
SEGMENT.setPixelColorXY(x,y, !SEGMENT.check1?backgroundColor : RGBW32(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0));
52125204
}
52135205
else {
5214-
setBitValue(gol->cells, y * cols + x, true);
5215-
setBitValue(gol->futureCells, y * cols + x, true);
5206+
setBitValue(cells, y * cols + x, true);
5207+
setBitValue(futureCells, y * cols + x, true);
52165208
color = SEGMENT.color_from_palette(random8(), false, PALETTE_SOLID_WRAP, 0);
52175209
SEGMENT.setPixelColorXY(x,y,!SEGMENT.check1?color : RGBW32(color.r, color.g, color.b, 0));
52185210
}
52195211
}
52205212

52215213
//Clear CRCs
5222-
gol->oscillatorCRC = 0;
5223-
gol->spaceshipCRC = 0;
5214+
*oscillatorCRC = 0;
5215+
*spaceshipCRC = 0;
52245216

52255217
//Calculate glider length LCM(rows,cols)*4
52265218
uint8_t a = rows;
@@ -5230,14 +5222,14 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
52305222
b = a % b;
52315223
a = t;
52325224
}
5233-
gol->gliderLength = cols * rows / a * 4;
5225+
*gliderLength = cols * rows / a * 4;
52345226
return FRAMETIME;
52355227
}
52365228
//Redraw immediately if overlay to avoid flicker
52375229
if (SEGMENT.check2) {
52385230
for (int x = 0; x < cols; x++) for (int y = 0; y < rows; y++) {
52395231
//redraw foreground/alive
5240-
if (getBitValue(gol->cells, y * cols + x)) {
5232+
if (getBitValue(cells, y * cols + x)) {
52415233
color = SEGMENT.getPixelColorXY(x,y);
52425234
SEGMENT.setPixelColorXY(x,y, !SEGMENT.check1?color : RGBW32(color.r, color.g, color.b, 0));
52435235
}
@@ -5271,7 +5263,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
52715263
}
52725264
cIndex = cY * cols + cX;
52735265
// count neighbors and store upto 3 neighbor colors
5274-
if (getBitValue(gol->cells, cIndex)) { //if alive
5266+
if (getBitValue(cells, cIndex)) { //if alive
52755267
neighbors++;
52765268
color = SEGMENT.getPixelColorXY(cX, cY);
52775269
if (color == backgroundColor) continue; //parent just died, color lost
@@ -5281,16 +5273,16 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
52815273
}
52825274

52835275
// Rules of Life
5284-
bool cellValue = getBitValue(gol->cells, y * cols + x);
5276+
bool cellValue = getBitValue(cells, y * cols + x);
52855277
if ((cellValue) && (neighbors < 2 || neighbors > 3)) {
52865278
// Loneliness or overpopulation
52875279
cellChanged = true;
5288-
setBitValue(gol->futureCells, y * cols + x, false);
5280+
setBitValue(futureCells, y * cols + x, false);
52895281
if (!SEGMENT.check2) SEGMENT.setPixelColorXY(x,y, !SEGMENT.check1?backgroundColor : RGBW32(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0));
52905282
}
52915283
else if (!(cellValue) && (neighbors == 3)) {
52925284
// Reproduction
5293-
setBitValue(gol->futureCells, y * cols + x, true);
5285+
setBitValue(futureCells, y * cols + x, true);
52945286
cellChanged = true;
52955287
// find dominant color and assign it to a cell
52965288
// no longer storing colors, if parent dies the color is lost
@@ -5311,21 +5303,21 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
53115303
}
53125304
}
53135305
//update cell values
5314-
memcpy(gol->cells, gol->futureCells, dataSize);
5306+
memcpy(cells, futureCells, dataSize);
53155307

53165308
// Get current crc value
5317-
uint16_t crc = crc16((const unsigned char*)gol->cells, dataSize);
5309+
uint16_t crc = crc16((const unsigned char*)cells, dataSize);
53185310

53195311
bool repetition = false;
5320-
if (!cellChanged || crc == gol->oscillatorCRC || crc == gol->spaceshipCRC) repetition = true; //check if cell changed this gen and compare previous stored crc values
5312+
if (!cellChanged || crc == *oscillatorCRC || crc == *spaceshipCRC) repetition = true; //check if cell changed this gen and compare previous stored crc values
53215313
if (repetition) {
53225314
generation = 0; // reset on next call
53235315
pauseFrames = 50;
53245316
return FRAMETIME;
53255317
}
53265318
// Update CRC values
5327-
if (generation % 16 == 0) gol->oscillatorCRC = crc;
5328-
if (generation % gol->gliderLength == 0) gol->spaceshipCRC = crc;
5319+
if (generation % 16 == 0) *oscillatorCRC = crc;
5320+
if (generation % *gliderLength == 0) *spaceshipCRC = crc;
53295321

53305322
generation++;
53315323
SEGENV.step = strip.now;

0 commit comments

Comments
 (0)