[C++] Plugin crashes game when I restore game twice. [WORKED AROUND]

Started by Scavenger, Thu 21/01/2016 19:33:26

Previous topic - Next topic

Scavenger

EDIT: I just did a quick hack so I didn't have to delete or initalize more than once. It's a dirty hack, and it means I can only use it for my game, but eh, I can reprogram later.

Hey, I'm having quite a complex issue that I'm not sure I can solve. I'm trying to make it so that my plugin saves its state and restores it along with the regular save game, and I can make it load the state, whatever it is, just once. Trying to load a save game twice during the same process crashes the engine (with error code 0xC0000005, which I believe is array out of bounds), and the reasons why mystify me. Why would it allow you to load the game once, but not twice? What is it about the second time that makes the engine freak out?

I'm not sure how much use pasting code will be, there is a whole lot of it, but here is the save/load code I'm using, and the variables I'm saving:

Code: C++

  bool raycastOn;
  bool heightmapOn;
  double posX = 22.0, posY = 11.5; //x and y start position
  double dirX = -1.0, dirY = 0.0; //initial direction vector
  double planeX = 0.0, planeY = 0.77; //the 2d raycaster version of camera plane
  double moveSpeed = (1.0/60.0) * 3.0; //the constant value is in squares/second
  double rotSpeed =  (1.0/60.0) * 2.0; //the constant value is in radians/second
  unsigned char **worldMap;
  unsigned char **lightMap;
  int **ceilingMap;
  int **floorMap;
  int **heightMap;
  int mapWidth;
  int mapHeight;
  int textureSlot;
  struct Sprite
  {
 	double x;
	double y;
	int texture;
	unsigned char alpha;
	int blendmode;
	double uDivW;
        double uDivH;
	double vMove;
	double hMove;
	char objectinteract;
	int view;
	int frame;
	int angle;
  };
  #define numSprites 256
  Sprite sprite[numSprites] = {};

  
  #define texWidth 64
  #define texHeight 64
  unsigned char **texture;

  long sWidth=0,sHeight=0;

  struct wallType
  {
	int texture[4];
	int solid[4];
	int ignorelighting[4];
	int alpha[4];
	int blendtype[4];
	int mask[4];
	unsigned char hotspotinteract;
  };

  wallType wallData[256]={};

 unsigned char **transcolorbuffer;
 unsigned char **transalphabuffer;
 double **transzbuffer;
 bool *transslicedrawn;
 int *transwallblendmode;
 double **ZBuffer;
 double *distTable;
 short *interactionmap;
 int skybox=0;



Code: C++

	if (event == AGSE_SAVEGAME)
	{
		for (int i = 0; i < MAX_OVERLAYS; ++i)
			{
				engine->FWrite(&overlay[i].sprite, sizeof(int), data);
				engine->FWrite(&overlay[i].spritemask, sizeof(int), data);
				engine->FWrite(&overlay[i].x, sizeof(int), data);
				engine->FWrite(&overlay[i].y, sizeof(int), data);
				engine->FWrite(&overlay[i].level, sizeof(int), data);
				engine->FWrite(&overlay[i].trans, sizeof(int), data);
				engine->FWrite(&overlay[i].blendtype, sizeof(int), data);
				engine->FWrite(&overlay[i].enabled, sizeof(bool), data);
			}
		engine->FWrite(&clutslot, sizeof(int), data);
		engine->FWrite(&drawreflections, sizeof(int), data);
		for (int j = 0; j < 256; ++j)
			{
				engine->FWrite(&cycle_remap[j], sizeof(unsigned char), data);
			}
		for (int j = 0; j < 256; ++j)
			{
				engine->FWrite(&objectivepal[j].r, sizeof(unsigned char), data);
				engine->FWrite(&objectivepal[j].b, sizeof(unsigned char), data);
				engine->FWrite(&objectivepal[j].g, sizeof(unsigned char), data);
			}
		for (int j = 0; j < 256; ++j)
			{
				engine->FWrite(&sprite[j].x, sizeof(double), data);
				engine->FWrite(&sprite[j].y, sizeof(double), data);
				engine->FWrite(&sprite[j].texture, sizeof(int), data);
				engine->FWrite(&sprite[j].alpha, sizeof(unsigned char), data);
				engine->FWrite(&sprite[j].uDivW, sizeof(double), data);
				engine->FWrite(&sprite[j].uDivH, sizeof(double), data);
				engine->FWrite(&sprite[j].vMove, sizeof(double), data);
				engine->FWrite(&sprite[j].hMove, sizeof(double), data);
				engine->FWrite(&sprite[j].objectinteract, sizeof(char), data);
				engine->FWrite(&sprite[j].view, sizeof(int), data);
				engine->FWrite(&sprite[j].frame, sizeof(int), data);
				engine->FWrite(&sprite[j].angle, sizeof(int), data);
			}
		for (int j = 0; j < 256; ++j)
			{
				for (int k = 0; k < 4;++k)
					{
						engine->FWrite(&wallData[j].texture[k], sizeof(int), data);
						engine->FWrite(&wallData[j].solid[k], sizeof(int), data);
						engine->FWrite(&wallData[j].ignorelighting[k], sizeof(int), data);
						engine->FWrite(&wallData[j].alpha[k], sizeof(int), data);
						engine->FWrite(&wallData[j].blendtype[k], sizeof(int), data);
						engine->FWrite(&wallData[j].mask[k], sizeof(int), data);
					}
				engine->FWrite(&wallData[j].hotspotinteract, sizeof(char), data);
			}
		engine->FWrite(&raycastOn, sizeof(bool), data);
		engine->FWrite(&heightmapOn, sizeof(bool), data);
		engine->FWrite(&posX, sizeof(double), data);
		engine->FWrite(&posY, sizeof(double), data);
		engine->FWrite(&dirX, sizeof(double), data);
		engine->FWrite(&dirY, sizeof(double), data);
		engine->FWrite(&planeX, sizeof(double), data);
		engine->FWrite(&planeY, sizeof(double), data);
		engine->FWrite(&moveSpeed, sizeof(double), data);
		engine->FWrite(&rotSpeed, sizeof(double), data);
		engine->FWrite(&sWidth, sizeof(long), data);
		engine->FWrite(&sHeight, sizeof(long), data);
		engine->FWrite(&mapWidth, sizeof(int), data);
		engine->FWrite(&mapHeight, sizeof(int), data);
		if (raycastOn) //If the raycaster is active, we have additional data to save.
		{
			for (int i = 0; i < mapWidth;++i)
				for (int j = 0;j < mapHeight;++j)
				{
					engine->FWrite(&worldMap [i][j], sizeof(unsigned char), data);
					engine->FWrite(&lightMap [i][j], sizeof(unsigned char), data);
					engine->FWrite(&ceilingMap [i][j], sizeof(int), data);
					engine->FWrite(&floorMap [i][j], sizeof(int), data);
					engine->FWrite(&heightMap [i][j], sizeof(int), data);
				}
		}
		engine->FWrite(extureSlot, sizeof(int), data);
		engine->FWrite(&skybox, sizeof(int), data);
	}
	if (event == AGSE_RESTOREGAME)
	{


		for (int i = 0; i < MAX_OVERLAYS; ++i)
			{
				engine->FRead(&overlay[i].sprite, sizeof(int), data);
				engine->FRead(&overlay[i].spritemask, sizeof(int), data);
				engine->FRead(&overlay[i].x, sizeof(int), data);
				engine->FRead(&overlay[i].y, sizeof(int), data);
				engine->FRead(&overlay[i].level, sizeof(int), data);
				engine->FRead(&overlay[i].trans, sizeof(int), data);
				engine->FRead(&overlay[i].blendtype, sizeof(int), data);
				engine->FRead(&overlay[i].enabled, sizeof(bool), data);
			}
		engine->FRead(&clutslot, sizeof(int), data);
		engine->FRead(&drawreflections, sizeof(int), data);
		for (int j = 0; j < 256; ++j)
			{
				engine->FRead(&cycle_remap[j], sizeof(unsigned char), data);
			}
		for (int j = 0; j < 256; ++j) //Save Objective Palette, for palette mixing.
			{
				engine->FRead(&objectivepal[j].r, sizeof(unsigned char), data);
				engine->FRead(&objectivepal[j].b, sizeof(unsigned char), data);
				engine->FRead(&objectivepal[j].g, sizeof(unsigned char), data);
			}
		for (int j = 0; j < 256; ++j) //Save Raycaster Sprite struct, 256 instances.
			{
				engine->FRead(&sprite[j].x, sizeof(double), data);
				engine->FRead(&sprite[j].y, sizeof(double), data);
				engine->FRead(&sprite[j].texture, sizeof(int), data);
				engine->FRead(&sprite[j].alpha, sizeof(unsigned char), data);
				engine->FRead(&sprite[j].uDivW, sizeof(double), data);
				engine->FRead(&sprite[j].uDivH, sizeof(double), data);
				engine->FRead(&sprite[j].vMove, sizeof(double), data);
				engine->FRead(&sprite[j].hMove, sizeof(double), data);
				engine->FRead(&sprite[j].objectinteract, sizeof(char), data);
				engine->FRead(&sprite[j].view, sizeof(int), data);
				engine->FRead(&sprite[j].frame, sizeof(int), data);
				engine->FRead(&sprite[j].angle, sizeof(int), data);
			}
		for (int j = 0; j < 256; ++j) //Save Raycaster wall type data.
			{
				for (int k = 0; k < 4;++k)
					{
						engine->FRead(&wallData[j].texture[k], sizeof(int), data);
						engine->FRead(&wallData[j].solid[k], sizeof(int), data);
						engine->FRead(&wallData[j].ignorelighting[k], sizeof(int), data);
						engine->FRead(&wallData[j].alpha[k], sizeof(int), data);
						engine->FRead(&wallData[j].blendtype[k], sizeof(int), data);
						engine->FRead(&wallData[j].mask[k], sizeof(int), data);
					}
				engine->FRead(&wallData[j].hotspotinteract, sizeof(char), data);
			}
		//Delete worldmap data if it exists.
		if (worldMap)
			{
				for (int j = 0;j < mapHeight;++j)
				{
					delete [] worldMap [j];
					delete [] lightMap [j];
					delete [] ceilingMap [j];
					delete [] floorMap [j];
					delete [] heightMap [j];
				}
				delete [] worldMap;
				delete [] lightMap;
				delete [] ceilingMap;
				delete [] floorMap;
				delete [] heightMap;
			}
		if (transcolorbuffer) //delete the buffers and dynamic arrays before loading new ones.
		{
			for (int x=0;x<sWidth;x++)
			{
				delete [] transcolorbuffer[x];
				delete [] transalphabuffer[x];
				delete [] transzbuffer[x];
				delete [] ZBuffer[x];
			}
		}
		engine->FRead(&raycastOn, sizeof(bool), data);
		engine->FRead(&heightmapOn, sizeof(bool), data);
		engine->FRead(&posX, sizeof(double), data);
		engine->FRead(&posY, sizeof(double), data);
		engine->FRead(&dirX, sizeof(double), data);
		engine->FRead(&dirY, sizeof(double), data);
		engine->FRead(&planeX, sizeof(double), data);
		engine->FRead(&planeY, sizeof(double), data);
		engine->FRead(&moveSpeed, sizeof(double), data);
		engine->FRead(&rotSpeed, sizeof(double), data);
		engine->FRead(&sWidth, sizeof(long), data);
		engine->FRead(&sHeight, sizeof(long), data);
		engine->FRead(&mapWidth, sizeof(int), data);
		engine->FRead(&mapHeight, sizeof(int), data);
		if (raycastOn) //If the raycaster is currently running, we have additional data to load.
			{
				worldMap = new unsigned char*[mapWidth];
				lightMap = new unsigned char*[mapWidth];
				ceilingMap = new int*[mapWidth];
				floorMap = new int*[mapWidth];	
				heightMap = new int*[mapWidth];
				for (int i = 0; i < mapWidth;++i)
					{
						worldMap[i] = new unsigned char[mapHeight];
						lightMap[i] = new unsigned char[mapHeight];
						floorMap[i] = new int[mapHeight];
						ceilingMap[i] = new int[mapHeight];
						heightMap[i] = new int[mapHeight];
						for (int j = 0;j < mapHeight;++j)
						{
							engine->FRead(&worldMap [i][j], sizeof(unsigned char), data);
							engine->FRead(&lightMap [i][j], sizeof(unsigned char), data);
							engine->FRead(&ceilingMap [i][j], sizeof(int), data);
							engine->FRead(&floorMap [i][j], sizeof(int), data);
							engine->FRead(&heightMap [i][j], sizeof(int), data);
						}
					}
				engine->FRead(extureSlot, sizeof(int), data);
				engine->FRead(&skybox, sizeof(int), data);
				//Reinitialize all the buffers and stuff.
				if (textureSlot) MakeTextures (textureSlot);
				delete [] transcolorbuffer;
				transcolorbuffer = new unsigned char*[sWidth];
				delete [] transalphabuffer;
				transalphabuffer = new unsigned char*[sWidth];
				delete [] transslicedrawn;
				transslicedrawn = new bool[sWidth];
				delete [] transzbuffer;
				transzbuffer = new double*[sWidth];
				delete [] transwallblendmode;
				transwallblendmode = new int [mapWidth];
				delete [] ZBuffer;
				ZBuffer = new double*[sWidth];
				delete [] distTable;
				distTable = new double[sHeight+(sHeight>>1)];
				delete [] interactionmap;
				interactionmap = new short[sWidth*sHeight];
				for (int y=0;y<sHeight+(sHeight>>1);y++)
				{
					distTable [y] = sHeight / (2.0 * y - sHeight);
				}
				for (int x=0;x<sWidth;x++)
				{
					transcolorbuffer[x] = new unsigned char [sHeight*(mapWidth)]();
					transalphabuffer[x] = new unsigned char [sHeight*(mapWidth)]();
					transzbuffer[x] = new double [sHeight*(mapWidth)]();
					ZBuffer[x] = new double [sHeight];
					transslicedrawn [x] = false;
				}
			}
		LoadCLUT (clutslot);
	}


I can supply anything else that's needed, but I'm getting a little confused with why it's doing it. It's kind of disheartening, as it works perfectly the first time. If it had just crashed the first time, I'd know I was doing something majorly wrong. But these kinds of bugs are really out of my league at the moment. See, the error messages that AGS kicks out when the plugin crashes doesn't really help me, as I don't know what line in my code corresponds to what offset in the error message. Is there any way I can check it at all?

SMF spam blocked by CleanTalk