Skip to content

Commit

Permalink
Fix TNT floodfill crash
Browse files Browse the repository at this point in the history
  • Loading branch information
jacksonmj committed May 22, 2014
1 parent 91b4d1b commit 5e02073
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 67 deletions.
74 changes: 74 additions & 0 deletions src/simulation/CoordStack.h
@@ -0,0 +1,74 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef Simulation_CoordStack_h
#define Simulation_CoordStack_h

#include "Config.h" // for XRES and YRES
#include <exception>

class CoordStackOverflowException: public std::exception
{
public:
CoordStackOverflowException() { }
virtual const char* what() const throw()
{
return "Maximum number of entries in the coordinate stack was exceeded";
}
~CoordStackOverflowException() throw() {};
};

class CoordStack
{
private:
unsigned short (*stack)[2];
int stack_size;
const static int stack_limit = XRES*YRES;
public:
CoordStack() :
stack(NULL),
stack_size(0)
{
stack = (unsigned short(*)[2])(malloc(sizeof(unsigned short)*2*stack_limit));
}
~CoordStack()
{
if (stack) free(stack);
}
void push(int x, int y)
{
if (stack_size>=stack_limit)
throw CoordStackOverflowException();
stack[stack_size][0] = x;
stack[stack_size][1] = y;
stack_size++;
}
void pop(int& x, int& y)
{
stack_size--;
x = stack[stack_size][0];
y = stack[stack_size][1];
}
int getSize() const
{
return stack_size;
}
void clear()
{
stack_size = 0;
}
};

#endif
140 changes: 74 additions & 66 deletions src/simulation/Simulation.cpp
Expand Up @@ -13,6 +13,7 @@
#include "Air.h"
#include "Gravity.h"
#include "elements/Element.h"
#include "CoordStack.h"

//#include "graphics/Renderer.h"
//#include "graphics/Graphics.h"
Expand Down Expand Up @@ -379,78 +380,85 @@ bool Simulation::FloodFillPmapCheck(int x, int y, int type)
return (pmap[y][x]&0xFF) == type;
}

int Simulation::flood_prop_2(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype, int parttype, char * bitmap)
{
int x1, x2, i, dy = 1;
x1 = x2 = x;
while (x1>=CELL)
{
if (!FloodFillPmapCheck(x1-1, y, parttype) || bitmap[(y*XRES)+x1-1])
{
break;
}
x1--;
}
while (x2<XRES-CELL)
{
if (!FloodFillPmapCheck(x2+1, y, parttype) || bitmap[(y*XRES)+x2+1])
{
break;
}
x2++;
}
for (x=x1; x<=x2; x++)
{
i = pmap[y][x];
if (!i)
i = photons[y][x];
if (!i)
continue;
switch (proptype) {
case StructProperty::Float:
*((float*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Float;
break;

case StructProperty::ParticleType:
case StructProperty::Integer:
*((int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Integer;
break;

case StructProperty::UInteger:
*((unsigned int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.UInteger;
break;

default:
break;
}
bitmap[(y*XRES)+x] = 1;
}
if (y>=CELL+dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y-dy, parttype) && !bitmap[((y-dy)*XRES)+x])
if (!flood_prop_2(x, y-dy, propoffset, propvalue, proptype, parttype, bitmap))
return 0;
if (y<YRES-CELL-dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y+dy, parttype) && !bitmap[((y+dy)*XRES)+x])
if (!flood_prop_2(x, y+dy, propoffset, propvalue, proptype, parttype, bitmap))
return 0;
return 1;
}

int Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype)
{
int r = 0;
char * bitmap = (char *)malloc(XRES*YRES); //Bitmap for checking
memset(bitmap, 0, XRES*YRES);
r = pmap[y][x];
int i, x1, x2, dy = 1;
int did_something = 0;
int r = pmap[y][x];
if (!r)
r = photons[y][x];
if (!r)
return 1;
flood_prop_2(x, y, propoffset, propvalue, proptype, r&0xFF, bitmap);
return 0;
int parttype = (r&0xFF);
char * bitmap = (char*)malloc(XRES*YRES); //Bitmap for checking
if (!bitmap) return -1;
memset(bitmap, 0, XRES*YRES);
try
{
CoordStack cs;
cs.push(x, y);
do
{
cs.pop(x, y);
x1 = x2 = x;
x1 = x2 = x;
while (x1>=CELL)
{
if (!FloodFillPmapCheck(x1-1, y, parttype) || bitmap[(y*XRES)+x1-1])
break;
x1--;
}
while (x2<XRES-CELL)
{
if (!FloodFillPmapCheck(x2+1, y, parttype) || bitmap[(y*XRES)+x2+1])
break;
x2++;
}
for (x=x1; x<=x2; x++)
{
i = pmap[y][x];
if (!i)
i = photons[y][x];
if (!i)
continue;
switch (proptype) {
case StructProperty::Float:
*((float*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Float;
break;

case StructProperty::ParticleType:
case StructProperty::Integer:
*((int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Integer;
break;

case StructProperty::UInteger:
*((unsigned int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.UInteger;
break;

default:
break;
}
bitmap[(y*XRES)+x] = 1;
did_something = 1;
}
if (y>=CELL+dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y-dy, parttype) && !bitmap[((y-dy)*XRES)+x])
cs.push(x, y-dy);
if (y<YRES-CELL-dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y+dy, parttype) && !bitmap[((y+dy)*XRES)+x])
cs.push(x, y+dy);
} while (cs.getSize()>0);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
free(bitmap);
return -1;
}
free(bitmap);
return 0;
return did_something;
}

SimulationSample Simulation::GetSample(int x, int y)
Expand Down
1 change: 0 additions & 1 deletion src/simulation/Simulation.h
Expand Up @@ -135,7 +135,6 @@ class Simulation
void kill_part(int i);
bool FloodFillPmapCheck(int x, int y, int type);
int flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype);
int flood_prop_2(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype, int parttype, char * bitmap);
int flood_water(int x, int y, int i, int originaly, int check);
int FloodINST(int x, int y, int fullc, int cm);
void detach(int i);
Expand Down

0 comments on commit 5e02073

Please sign in to comment.