<NME> tilemap.cpp
<BEF> 
#include "utils.h"
#include "main.h"
#include "textures.h"
#include "gameobjects.h"
#include "tilemap.h"
////#include "stb-master\stb_tilemap_editor.h"
//typedef unsigned int uint;
//      void STBTE_DRAW_RECT(int x0, int y0, int x1, int y1, int color);
//      // this must draw a filled rectangle (exclusive on right/bottom)
//      // color = (r<<16)|(g<<8)|(b)
//      
//      void STBTE_DRAW_TILE(int x0, int y0,
//                    unsigned short id, int highlight, float *data);
//      // this draws the tile image identified by 'id' in one of several
//      // highlight modes (see STBTE_drawmode_* in the header section);
//      // if 'data' is NULL, it's drawing the tile in the palette; if 'data'
//      // is not NULL, it's drawing a tile on the map, and that is the data
//      // associated with that map tile
//
//#define STB_TILEMAP_EDITOR_IMPLEMENTATION
//#include "stb-master\stb_tilemap_editor.h"

extern long SHOCK_CEILING_HEIGHT;
extern long UW_CEILING_HEIGHT;

int currRoomIndex;

int getTile(int tileData)
{
	//gets tile data at bits 0-3 of the tile data
	return (tileData & 0x0F);
}

int getHeight(int tileData)
{//gets height data at bits 4-7 of the tile data
	return (tileData & 0xF0) >> 4;
}

int getDoors(long tileData)
{//gets door positions at bit 15 of the tile data
	return (tileData>>15 & 0x01);
}

int getFloorTex(unsigned char *buffer, long textureOffset, long tileData)
{//gets floor texture data at bits 10-13 of the tile data
	int val = (tileData >>10) & 0x0F;	//gets the index of the texture
//look it up in texture block for it's absolute index for wxx.tr
	return getValAtAddress(buffer,textureOffset+96+(val*2),16) +210;			//96 needed?
	//	return ((tileData >>10) & 0x0F);	//was	11
}

int getWallTex(unsigned char *buffer, long textureOffset, long tileData)
{
//gets wall texture data at bits 0-5 (+16) of the tile data(2nd part)
	//return ((tileData >>17)& 0x3F);
	int val = (tileData & 0x3F);	//gets the index of the texture
	return getValAtAddress(buffer,textureOffset+(val*2),16);
	//return (tileData& 0x3F);
}

int getFloorTexUw2(unsigned char *buffer, long textureOffset, long tileData)
{//gets floor texture data at bits 10-13 of the tile data
	int val = (tileData >>10) & 0x0F;	//gets the index of the texture
//look it up in texture block for it's absolute index for wxx.tr
	return getValAtAddress(buffer,textureOffset+(val*2),16);	
//	return ((tileData >>10) & 0x0F);	//was	11
}

int getWallTexUw2(unsigned char *buffer, long textureOffset, long tileData)
{
//gets wall texture data at bits 0-5 (+16) of the tile data(2nd part)
	//return ((tileData >>17)& 0x3F);
	int val = (tileData & 0x3F);	//gets the index of the texture
	return getValAtAddress(buffer,textureOffset+(val*2),16);
	//return (tileData& 0x3F);
}


void CleanUp(tile LevelInfo[64][64], int game)
{
	int x; int y;
	

//Reduces tile complexity. Hides hidden solids and merges matching tiles along axis.
	////if (game != SHOCK)
	////{
	////
	////for (x = 1; x<63; x++){
	////	for (y = 1; y<63; y++){
	////		if (LevelInfo[x][y].tileType ==TILE_OPEN)
	////			{
	////			if (LevelInfo[x + 1][y].floorHeight >= LevelInfo[x][y].floorHeight)
	////				{
	////				LevelInfo[x][y].East=CAULK;
	////				}
	////			if (LevelInfo[x-1][y].floorHeight >= LevelInfo[x][y].floorHeight)
	////				{
	////					LevelInfo[x][y].West = CAULK;
	////				}
	////			if (LevelInfo[x][y+1].floorHeight >= LevelInfo[x][y].floorHeight)
	////				{
	////					LevelInfo[x][y].North = CAULK;
	////				}
	////			if (LevelInfo[x][y-1].floorHeight >= LevelInfo[x][y].floorHeight)
	////				{
	////					LevelInfo[x][y].South = CAULK;
	////				}
	////			}
	////		}
	////	}
	////}


	for (x=0;x<64;x++){
		for (y=0;y<64;y++){
	//lets test this tile for visibility
	//A tile is invisible if it only touches other solid tiles and has no objects or does not have a terrain change.
		if ((LevelInfo[x][y].tileType ==0) && (LevelInfo[x][y].indexObjectList == 0)  && (LevelInfo[x][y].TerrainChange == 0)){
				switch (y)
				{
				case 0:	//bottom row
					switch (x)
					{
					case 0:	//bl corner
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y + 1].tileType == 0)
						 && (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y+1].TerrainChange == 0))
						{LevelInfo[x][y].Render =0 ; ;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					case 63://br corner
						if ((LevelInfo[x - 1][y].tileType == 0) && (LevelInfo[x][y + 1].tileType == 0)
						 && (LevelInfo[x - 1][y].TerrainChange == 0) && (LevelInfo[x][y+1].TerrainChange == 0))
						{LevelInfo[x][y].Render =0 ;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					default: // invert t
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x + 1][y].tileType == 0) 
						&& (LevelInfo[x+1][y].TerrainChange == 0) && (LevelInfo[x][y+1].TerrainChange == 0) && (LevelInfo[x+1][y].TerrainChange == 0))
						{LevelInfo[x][y].Render =0 ;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					}
					break;
				case 63: //Top row
					switch (x)
					{
					case 0:	//tl corner
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) 
						&& (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y-1].TerrainChange == 0))
						{LevelInfo[x][y].Render =0 ;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					case 63://tr corner
						if ((LevelInfo[x - 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) 
						&& (LevelInfo[x - 1][y].TerrainChange == 0) && (LevelInfo[x][y-1].TerrainChange == 0))
						{LevelInfo[x][y].Render =0 ;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					default: //  t
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) && (LevelInfo[x - 1][y].tileType == 0) 
						&& (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0) && (LevelInfo[x-1][y].TerrainChange == 0))
						{LevelInfo[x][y].Render =0;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					}	
					break;
				default: //
					switch (x)
					{
					case 0:		//left edge
						if ((LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) 
							&& (LevelInfo[x][y+1].TerrainChange == 0) && (LevelInfo[x+1][y].TerrainChange == 0) && (LevelInfo[x][y-1].TerrainChange == 0))
						{LevelInfo[x][y].Render =0;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					case 63:	//right edge
						if ((LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x - 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) 
							&& (LevelInfo[x][y+1].TerrainChange == 0) && (LevelInfo[x-1][y].TerrainChange == 0) && (LevelInfo[x][y-1].TerrainChange == 0))
						{LevelInfo[x][y].Render =0 ;break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					default:		//+
						if ((LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) && (LevelInfo[x - 1][y].tileType == 0) 
							&& (LevelInfo[x][y + 1].TerrainChange == 0) && (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0) && (LevelInfo[x-1][y].TerrainChange == 0))
						{LevelInfo[x][y].Render =0; break;}
						else {LevelInfo[x][y].Render =1 ;break;}
					}
					break;
				}
			}
		}
	}






	//return;
//if (game == SHOCK) {return;}
	int j=1 ;
	//Now lets combine the solids along particular axis
	for (x=0;x<64;x++){
		for (y=0;y<64;y++){
			if ((x == 22) && (y == 52))
				{
				printf("%d\n", LevelInfo[22][52].VisibleFaces[vSOUTH]);
				}
			if  ((LevelInfo[x][y].Grouped ==0))
			{
			j=1;
			while ((LevelInfo[x][y].Render == 1) && (LevelInfo[x][y + j].Render == 1) && (LevelInfo[x][y + j].Grouped == 0) && (LevelInfo[x][y + j].BullFrog == 0))		//&& (LevelInfo[x][y].tileType ==0) && (LevelInfo[x][y+j].tileType ==0)
			{
			//combine these two if they match and they are not already part of a group
				if (DoTilesMatch(LevelInfo[x][y],LevelInfo[x][y+j])){
					LevelInfo[x][y+j].Render =0;
					LevelInfo[x][y+j].Grouped =1;
					LevelInfo[x][y].Grouped =1;
					//LevelInfo[x][y].DimY++;
					j++;
				}
				else
				{
					break;
				}
			
			}
			LevelInfo[x][y].DimY = LevelInfo[x][y].DimY +j-1;
			j=1;
			}
		}
	}
	j=1;
//////Now combine parallel solids
////	for (x=0;x<64;x++){
////		for (y=0;y<63;y++){
////			if  ((LevelInfo[x][y].Grouped ==1) && (LevelInfo[x][y].Render  ==1))  //is a start of a group
////			{
////			//test it's next door neighbour
////				if  ((LevelInfo[x][y+1].Grouped ==1) && (LevelInfo[x][y+1].Render  ==1))	//Neighbour is also a group,
////				{
////				if (DoTilesMatch(LevelInfo[x][y],LevelInfo[x+LevelInfo[x][y+1].DimX][y+1]))//test the first tile against the opposite corner of it's neighbour
////				{
////					//they match. -> merge em.
////					LevelInfo[x][y].DimX++;
////					for ( int k =1; k <=LevelInfo[x][y+1].DimX;k++)
////					{
////					LevelInfo[k][y+1].Render =0;
////					LevelInfo[k][y+1].Grouped =1;
////					
////					}
////				}
////				}
////			}
////		}
////	}

	////Now lets combine solids along the other axis
for (y=0;y<64;y++){
		for (x=0;x<64;x++){
			if ((x == 22) && (y == 52))
				{
				printf("%d\n", LevelInfo[22][52].VisibleFaces[vSOUTH]);
				}
			if  ((LevelInfo[x][y].Grouped ==0))
			{
			j=1;
			while ((LevelInfo[x][y].Render == 1) && (LevelInfo[x + j][y].Render == 1) && (LevelInfo[x + j][y].Grouped == 0) && (LevelInfo[x + j][y].BullFrog == 0))		//&& (LevelInfo[x][y].tileType ==0) && (LevelInfo[x][y+j].tileType ==0)
			{
			//combine these two if they  match and they are not already part of a group
				if (DoTilesMatch(LevelInfo[x][y],LevelInfo[x+j][y])){
					LevelInfo[x+j][y].Render =0;
					LevelInfo[x+j][y].Grouped =1;
					LevelInfo[x][y].Grouped =1;
					//LevelInfo[x][y].DimY++;
					j++;
				}
				else
				{
					break;
				}
			
			}
			LevelInfo[x][y].DimX = LevelInfo[x][y].DimX +j-1;
			j=1;
			}
		}
	}

//Clear invisible faces on solid tiles. 
//TODO:Support all 64x64 tiles
for (y = 0; y<=63; y++){
	for (x = 0; x<=63; x++){
		if ((LevelInfo[x][y].tileType == TILE_SOLID))
			{
			int dimx = LevelInfo[x][y].DimX;
			int dimy = LevelInfo[x][y].DimY;

			if (x == 0)
				{
				LevelInfo[x][y].VisibleFaces[vWEST]=0;
				}
			if (x == 63)
				{
				LevelInfo[x][y].VisibleFaces[vEAST] = 0;
				}
			if (y == 0 )
				{
				LevelInfo[x][y].VisibleFaces[vSOUTH] = 0;
				}

			if (y == 63)
				{
				LevelInfo[x][y].VisibleFaces[vNORTH] = 0;
				}
			if ((x != 63) || (y != 63))
				{
				if ((LevelInfo[x + dimx][y].tileType == TILE_SOLID) && (LevelInfo[x + dimx][y].TerrainChange == 0) && (LevelInfo[x][y].TerrainChange == 0))//Tile to the east is a solid
					{
					LevelInfo[x][y].VisibleFaces[vEAST] = 0;
					LevelInfo[x + dimx][y].VisibleFaces[vWEST] = 0;
					}
				if ((LevelInfo[x][y + dimy].tileType == TILE_SOLID) && (LevelInfo[x][y].TerrainChange == 0) && (LevelInfo[x][y + dimy].TerrainChange == 0))//TIle to the north is a solid
					{
					LevelInfo[x][y].VisibleFaces[vNORTH] = 0;
					LevelInfo[x][y + dimy].VisibleFaces[vSOUTH] = 0;
					}
				}
			}
		}
	}

//Clear invisible faces on diagonals
for (y = 1; y < 63; y++){
	for (x = 1; x < 63; x++){
		switch (LevelInfo[x][y].tileType)
			{
				case TILE_DIAG_NW:
					{
					if ((LevelInfo[x][y - 1].tileType == TILE_SOLID) && (LevelInfo[x][y-1].TerrainChange == 0))
						{
						LevelInfo[x][y].VisibleFaces[vSOUTH]=0;
						LevelInfo[x][y - 1].VisibleFaces[vNORTH]=0;
						}
					if ((LevelInfo[x + 1][y].tileType == TILE_SOLID) && (LevelInfo[x + 1][y].TerrainChange==0))
						{
						LevelInfo[x][y].VisibleFaces[vEAST] = 0;
						LevelInfo[x + 1][y].VisibleFaces[vWEST]=0;
						}
					}
					break;
				case TILE_DIAG_NE:
					{
					if ((LevelInfo[x][y - 1].tileType == TILE_SOLID) && (LevelInfo[x][y - 1].TerrainChange == 0))
						{
						LevelInfo[x][y].VisibleFaces[vSOUTH] = 0;
						LevelInfo[x][y - 1].VisibleFaces[vNORTH] = 0;
						}
					if ((LevelInfo[x - 1][y].tileType == TILE_SOLID) && (LevelInfo[x - 1][y].TerrainChange == 0))
						{
						LevelInfo[x][y].VisibleFaces[vWEST] = 0;
						LevelInfo[x - 1][y].VisibleFaces[vEAST] = 0;
						}
					}
					break;
				case TILE_DIAG_SE:
					{
					if ((LevelInfo[x][y + 1].tileType == TILE_SOLID) && (LevelInfo[x][y + 1].TerrainChange == 0))
						{
						LevelInfo[x][y].VisibleFaces[vNORTH] = 0;
						LevelInfo[x][y + 1].VisibleFaces[vSOUTH] = 0;
						}
					if ((LevelInfo[x - 1][y].tileType == TILE_SOLID) && (LevelInfo[x - 1][y].TerrainChange == 0))
						{
						LevelInfo[x][y].VisibleFaces[vWEST] = 0;
						LevelInfo[x - 1][y].VisibleFaces[vEAST] = 0;
						}
					}
					break;
				case TILE_DIAG_SW:
					{
					if ((LevelInfo[x][y + 1].tileType == TILE_SOLID) && (LevelInfo[x][y + 1].TerrainChange == 0))
						{
						LevelInfo[x][y].VisibleFaces[vNORTH] = 0;
						LevelInfo[x][y + 1].VisibleFaces[vSOUTH] = 0;
						}
					if ((LevelInfo[x + 1][y].tileType == TILE_SOLID) && (LevelInfo[x + 1][y].TerrainChange == 0))
						{
						LevelInfo[x][y].VisibleFaces[vEAST] = 0;
						LevelInfo[x + 1][y].VisibleFaces[vWEST] = 0;
						}
					}
					break;
			}

		}

	}

for (y = 1; y < 63; y++){
	for (x = 1; x < 63; x++){
		if ((LevelInfo[x][y].tileType == TILE_OPEN) && (LevelInfo[x][y].TerrainChange == 0) && (LevelInfo[x][y].BullFrog == 0))
			{
			if (
				((LevelInfo[x + 1][y].tileType == TILE_OPEN) && (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x + 1][y].BullFrog == 0) && (LevelInfo[x + 1][y].floorHeight >= LevelInfo[x][y].floorHeight))
				||
				(LevelInfo[x + 1][y].tileType == TILE_SOLID) && (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x + 1][y].BullFrog == 0)
				)
				{
				LevelInfo[x][y].VisibleFaces[vEAST]=0;
				}
			

			if (
				((LevelInfo[x - 1][y].tileType == TILE_OPEN) && (LevelInfo[x - 1][y].TerrainChange == 0) && (LevelInfo[x - 1][y].BullFrog == 0) && (LevelInfo[x - 1][y].floorHeight >= LevelInfo[x][y].floorHeight))
				||
				(LevelInfo[x - 1][y].tileType == TILE_SOLID) && (LevelInfo[x - 1][y].TerrainChange == 0) && (LevelInfo[x - 1][y].BullFrog == 0)
				)
				{
				LevelInfo[x][y].VisibleFaces[vWEST] = 0;
				}


			if (
				((LevelInfo[x][y + 1].tileType == TILE_OPEN) && (LevelInfo[x][y + 1].TerrainChange == 0) && (LevelInfo[x][y + 1].BullFrog == 0) && (LevelInfo[x][y + 1].floorHeight >= LevelInfo[x][y].floorHeight))
				||
				(LevelInfo[x][y + 1].tileType == TILE_SOLID) && (LevelInfo[x][y + 1].TerrainChange == 0) && (LevelInfo[x][y + 1].BullFrog == 0)
				)
				{
				LevelInfo[x][y].VisibleFaces[vNORTH] = 0;
				}

			if (
				((LevelInfo[x][y - 1].tileType == TILE_OPEN) && (LevelInfo[x][y - 1].TerrainChange == 0) && (LevelInfo[x][y - 1].BullFrog == 0) && (LevelInfo[x][y - 1].floorHeight >= LevelInfo[x][y].floorHeight))
				||
				(LevelInfo[x][y - 1].tileType == TILE_SOLID) && (LevelInfo[x][y - 1].TerrainChange == 0) && (LevelInfo[x][y - 1].BullFrog == 0)
				)
				{
				LevelInfo[x][y].VisibleFaces[vSOUTH] = 0;
				}
			}

		}
	}
//Make sure solids & opens are still consistently visible.
	for (y = 1; y < 63; y++){
		for (x = 1; x < 63; x++){

			if ((LevelInfo[x][y].tileType == TILE_SOLID) || (LevelInfo[x][y].tileType == TILE_OPEN))
				{
				int dimx = LevelInfo[x][y].DimX;
				int dimy = LevelInfo[x][y].DimY;
				if (dimx>1)
					{//Make sure the ends are set properly
					LevelInfo[x][y].VisibleFaces[vEAST] = LevelInfo[x + dimx - 1][y].VisibleFaces[vEAST];
					}
				if (dimy>1)
					{
					LevelInfo[x][y].VisibleFaces[vNORTH] = LevelInfo[x][y + dimy - 1].VisibleFaces[vNORTH];
					}

				//Check along each axis
				for (int i = 0; i < LevelInfo[x][y].DimX; i++)
					{
					if (LevelInfo[x + i][y].VisibleFaces[vNORTH] == 1)
						{
						LevelInfo[x][y].VisibleFaces[vNORTH]=1;
						}
					if (LevelInfo[x + i][y].VisibleFaces[vSOUTH] == 1)
						{
						LevelInfo[x][y].VisibleFaces[vSOUTH] = 1;
						}
					}

				for (int i = 0; i < LevelInfo[x][y].DimY; i++)
					{
					if (LevelInfo[x][y+i].VisibleFaces[vEAST] == 1)
						{
						LevelInfo[x][y].VisibleFaces[vEAST] = 1;
						}
					if (LevelInfo[x][y+i].VisibleFaces[vWEST] == 1)
						{
						LevelInfo[x][y].VisibleFaces[vWEST] = 1;
						}
					}

				}
			}
		}
	for (int y = 0; y <= 63; y++){
		LevelInfo[0][y].VisibleFaces[vEAST]=1;
		LevelInfo[63][y].VisibleFaces[vWEST] = 1;
		}
	for (int x = 0; x <= 63; x++){
		LevelInfo[x][0].VisibleFaces[vNORTH] = 1;
		LevelInfo[x][63].VisibleFaces[vSOUTH] = 1;
		}
}



int DoTilesMatch(tile &t1, tile &t2)
{//TODO:Tiles have a lot more properties now.
	//if ((t1.tileType >1) || (t1.hasElevator==1) || (t1.TerrainChange ==1) ||  (t2.hasElevator==1) || (t2.TerrainChange ==1) || (t1.isWater ==1) || (t2.isWater ==1)){	//autofail no none solid/open/special.
		if ((t1.tileType >1) || (t1.hasElevator == 1) || (t1.TerrainChange == 1) || (t2.hasElevator == 1) || (t2.TerrainChange == 1)){	//autofail no none solid/open/special.
		return 0;
	}
	else
	{
//if ((t1.floorTexture == t2.floorTexture ) && (t1.floorHeight == t2.floorHeight)
//		&& (t1.DimX==t2.DimX) && (t1.DimY == t2.DimY ) 
//		 && (t1.tileType == t2.tileType ) 
//		 && (t1.isDoor==0) && (t2.isDoor ==0)) {
//fprintf(LOGFILE,"");
//}
	if ((t1.tileType==0) && (t2.tileType == 0))	//solid
		{
		return ((t1.wallTexture==t2.wallTexture) && (t1.West == t2.West) && (t1.South == t2.South) && (t1.East == t2.East) && (t1.North == t2.North) && (t1.UseAdjacentTextures == t2.UseAdjacentTextures));
		}
	else
		{
		return (t1.shockCeilingTexture == t2.shockCeilingTexture)
			&& (t1.floorTexture == t2.floorTexture) 
			&& (t1.floorHeight == t2.floorHeight)
			&& (t1.ceilingHeight == t2.ceilingHeight )
			&& (t1.DimX==t2.DimX) && (t1.DimY == t2.DimY ) 
			&& (t1.wallTexture == t2.wallTexture)
			&& (t1.tileType == t2.tileType ) 
			&& (t1.isDoor==0) && (t2.isDoor ==0);//
		}
	}
}


int getObject(long tileData)
{
//gets object data at bits 6-15 (+16) of the tile data(2nd part)
return tileData >> 6;
}



int BuildTileMapUW(tile LevelInfo[64][64],ObjectItem objList[1600], long texture_map[256], char *filePath, int game, int LevelNo)
{
	FILE *file = NULL;      // File pointer
	unsigned char *lev_ark; 
	unsigned char *tmp_ark; 
	unsigned char *tex_ark; 
    int NoOfBlocks;
	long AddressOfBlockStart;
	long address_pointer;
	long textureAddress;
	long fileSize;
	int x;	
	int y;
	int i;
	int CeilingTexture=0;
	int textureMapSize;
	long AutoMapAddress=0;
	
	UW_CEILING_HEIGHT = ((128 >> 2) * 8 >>3);	//Shifts the scale of the level. Idea borrowed from abysmal
	switch (game)
	{
	case UWDEMO:	//UW Demo
		{
		char UWdemoFileToOpen[255];
		sprintf_s(UWdemoFileToOpen, 255, "%s\\data\\level13.st", filePath);
		textureMapSize=0x7a;
		if ((file = fopen(UWdemoFileToOpen, "rb")) == NULL)
			{
			fprintf(LOGFILE, "Could not open specified file\n");
			return 0;
			}
		long fileSize = getFileSize(file);
		lev_ark = new unsigned char[fileSize];
		fread(lev_ark, fileSize, 1,file);
		fclose(file);  
		
		//Get the number of blocks in this file.
		NoOfBlocks = 1;
		//Get the first map block
		AddressOfBlockStart = 0;	
		textureAddress = 0; //it's in a different file
		address_pointer =0;
		//read in the textures
		FILE *fileT = NULL; 
		//filePath = UW0_TEXTUREW_PATH;	
		sprintf_s(UWdemoFileToOpen, 255, "%s\\DATA\\level13.txm", filePath);
		if ((fileT = fopen(UWdemoFileToOpen, "rb")) == NULL)
			{
			fprintf(LOGFILE, "Could not open specified file\n");
			}
		fileSize = getFileSize(fileT);
		tex_ark = new unsigned char[fileSize];
		fread(tex_ark, fileSize, 1,fileT);
		fclose(fileT);  		
		break;		
		}
	case UW1:	//UW1
		{
		textureMapSize = 64; // 0x7a;
		if ((file = fopen(filePath, "rb")) == NULL)
			fprintf(LOGFILE,"Could not open specified file\n");
		else
			fprintf(LOGFILE,"");
		fileSize = getFileSize(file);
		lev_ark = new unsigned char[fileSize];
		fread(lev_ark, fileSize, 1,file);
		fclose(file);  
					
		//Get the number of blocks in this file.
		NoOfBlocks = ConvertInt16(lev_ark[0],lev_ark[1]);
		NoOfBlocks = getValAtAddress(lev_ark,0,32);
		//Get the first map block
		AddressOfBlockStart = getValAtAddress(lev_ark,(LevelNo * 4) + 2,32);	
		textureAddress = getValAtAddress(lev_ark,((LevelNo+18) * 4) + 2 ,32);
		AutoMapAddress = getValAtAddress(lev_ark, ((LevelNo + 27) * 4) + 2, 32);
		//long objectsAddress = AddressOfBlockStart + (64*64*4); //+ 1;
		address_pointer =0;
		break;
		}	
	
	case UW2:	//Underworld 2
		{
		textureMapSize = 70;	//0x86;
		if ((file = fopen(filePath, "rb")) == NULL)
			fprintf(LOGFILE,"Could not open specified file\n");
		else
			fprintf(LOGFILE,"");
		fileSize = getFileSize(file);
		tmp_ark = new unsigned char[fileSize];
		fread(tmp_ark, fileSize, 1,file);
		fclose(file);  

		address_pointer=0;
		int datalentest = 0;
		//unsigned char *dumplev_ark 
		//lev_ark = get_rwops_uw2dec(tmp_ark, 0, &datalentest);
		//fprintf(LOGFILE, "begin test func\n");
		//for (int i = 0; i < datalentest; i++)
		//	{
		//	fprintf(LOGFILE, "%c", dumplev_ark[i]);
		//	}
		//fprintf(LOGFILE, "\nEnd test func");
		AddressOfBlockStart = 0;

		
		NoOfBlocks=getValAtAddress(tmp_ark,0,32);	
		 //begin test
		address_pointer=6;
		for (int i = 0; i < NoOfBlocks; i++)
			{			
			fprintf(LOGFILE, "Block %d at %d\n", i, getValAtAddress(tmp_ark, (i * 4) + 6,32));
			}


		int compressionFlag=getValAtAddress(tmp_ark,address_pointer + (NoOfBlocks*4) + (LevelNo*4) ,32);
		int isCompressed =(compressionFlag>>1) & 0x01;
		//	long dataSize = address_pointer + (2*NoOfBlocks*4);	//????
		address_pointer=(LevelNo * 4) + 6;
		if (getValAtAddress(tmp_ark,address_pointer,32)==0)
			{
			fprintf(LOGFILE,"\nInvalid block address!\n");
			return -1;
			}
		if (isCompressed == 1)
			{
			int datalen;
			fprintf(LOGFILE, "\nTilemap address: %d", getValAtAddress(tmp_ark, address_pointer, 32));
			lev_ark = unpackUW2(tmp_ark,getValAtAddress(tmp_ark,address_pointer,32),&datalen);
			fprintf(LOGFILE, "begin imple func\n");
			for (int i = 0; i < datalen; i++)
				{
				fprintf(LOGFILE, "%c", lev_ark[i]);
				}
			fprintf(LOGFILE, "\nEnd imple func");

			address_pointer=address_pointer+4;
			AddressOfBlockStart=0;
			//ObjectsAddress=1024;
			address_pointer=0;
			}
		else
			{
			//fprintf(LOGFILE,"uncompressed? what do i do here???");
			int BlockStart = getValAtAddress(tmp_ark, address_pointer, 32);
			fprintf(LOGFILE, "\nTilemap address: %d", BlockStart);
			int j=0;
			AddressOfBlockStart=0;
			address_pointer = 0;
			lev_ark = new unsigned char[0x7c08];
			for (i = BlockStart; i < BlockStart + 0x7c08; i++)
				{
				lev_ark[j] = tmp_ark[i];
				j++;
				}
			} //end test*/
		
		
		//read in the textures
		//address_pointer=(LevelNo * 4) + 6 + (80*4);
		//tex_ark = tmp_ark;	//unpack(tmp_ark,getValAtAddress(tmp_ark,address_pointer,32));
		textureAddress=getValAtAddress(tmp_ark,(LevelNo * 4) + 6 + (80*4),32);	
		fprintf(LOGFILE,"\nTextures address: %d", textureAddress);
		compressionFlag=getValAtAddress(tmp_ark,(LevelNo * 4) + 6 + (80*4)+ (NoOfBlocks*4),32);
		isCompressed = (compressionFlag >> 1) & 0x01;

		if (isCompressed == 1)
			{
			int datalen;
			tex_ark = unpackUW2(tmp_ark, textureAddress, &datalen);
			textureAddress=-1;
			}
		break;
		}		
		
	}

	int offset=0;
	for (i = 0; i<textureMapSize; i++)	//256
		{//TODO: Only use this for texture lookups.
		switch (game)
			{
			case UWDEMO:
				{
				texture_map[i] = getValAtAddress(tex_ark, textureAddress + (i * 2), 16);
				//printf("%d = %d\n",i, texture_map[i]);
				if (i == 57)
					{
					CeilingTexture = texture_map[i]+210;
					}

				break; 
				}//tex_ark[textureAddress+i];break;}
			case UW1:
				{
				if (i<48)	//Wall and floor textures are int 16s
					{
					texture_map[i] = getValAtAddress(lev_ark, textureAddress + offset, 16); //(i * 2)
						offset=offset+2;
						
					}
				else if (i<=57)	//Wall and floor textures are int 16s
					{
						texture_map[i] = getValAtAddress(lev_ark, textureAddress + offset, 16)+210; //(i * 2)
						offset = offset + 2;

					}
				else
					{ //door textures are int 8s
						texture_map[i] = getValAtAddress(lev_ark, textureAddress + offset, 8) ;//+210; //(i * 1)
						offset++;
					}
				if (i == 57)
					{
					CeilingTexture = texture_map[i];
					}
				fprintf(LOGFILE,"\nTexture %d = %d (%s)", i, texture_map[i], textureMasters[texture_map[i]].desc);
				break;
				}
			case UW2:
				{
				if (textureAddress == -1)//Texture block was decompressed
					{
					//textureAddress = 0;
					if (i<64)
						{
						texture_map[i] =getValAtAddress(tex_ark,offset ,16);//tmp //textureAddress+ //(i*2)
						offset = offset + 2;
						}
					else
						{//door textures
							texture_map[i] = getValAtAddress(tex_ark, textureAddress + offset, 8);//tmp //textureAddress+//(i*2)
							offset++;
						}
					}
				else
					{
					if (i<64)
						{
						texture_map[i] =getValAtAddress(tmp_ark,textureAddress+offset,16);//tmp //textureAddress+//(i*2)
						offset = offset + 2;
						}
					else
						{//door textures
						texture_map[i] = getValAtAddress(tmp_ark, textureAddress + offset, 8);//tmp //textureAddress+//(i*2)
						offset++;
						}
					}
				fprintf(LOGFILE,"\nTexture %d = %d (%s)", i, texture_map[i],textureMasters[texture_map[i]].desc);
				if (i == 0xf)
					{
					CeilingTexture=texture_map[i];
					}
				break;
				}
			}
		}
	//Assign door textures to the object masters list
	//Depends on the correct values in the config!!
	switch (game)
	{
		case UWDEMO:
			objectMasters[320].extraInfo = texture_map[48];
			objectMasters[321].extraInfo = texture_map[49];
			objectMasters[322].extraInfo = texture_map[50];
			objectMasters[323].extraInfo = texture_map[51];
			objectMasters[324].extraInfo = texture_map[52];
			objectMasters[325].extraInfo = texture_map[53];
			break;
		case UW1:
			objectMasters[320].extraInfo = texture_map[58];
			objectMasters[321].extraInfo = texture_map[59];
			objectMasters[322].extraInfo = texture_map[60];
			objectMasters[323].extraInfo = texture_map[61];
			objectMasters[324].extraInfo = texture_map[62];
			objectMasters[325].extraInfo = texture_map[63];
			
			objectMasters[328].extraInfo = texture_map[58];
			objectMasters[329].extraInfo = texture_map[59];
			objectMasters[330].extraInfo = texture_map[60];
			objectMasters[331].extraInfo = texture_map[61];
			objectMasters[332].extraInfo = texture_map[62];
			objectMasters[333].extraInfo = texture_map[63];
			break;
		case UW2:
			objectMasters[320].extraInfo = texture_map[64];
			objectMasters[321].extraInfo = texture_map[65];
			objectMasters[322].extraInfo = texture_map[66];
			objectMasters[323].extraInfo = texture_map[67];
			objectMasters[324].extraInfo = texture_map[68];
			objectMasters[325].extraInfo = texture_map[69];
			break;
	}
	for (y=0; y<64;y++)
		{
		for (x=0; x<64;x++)
			{
				LevelInfo[x][y].tileX = x;
				LevelInfo[x][y].tileY = y;
				LevelInfo[x][y].address = AddressOfBlockStart+address_pointer;
				long FirstTileInt = getValAtAddress(lev_ark,AddressOfBlockStart+(address_pointer+0),16);
				// FirstTileInt = getValAtCoordinate(x,y,AddressOfBlockStart,lev_ark,16);
				//long SecondTileInt = (getValAtCoordinate(x,y,AddressOfBlockStart,lev_ark,32) >> 16);
				long SecondTileInt = getValAtAddress(lev_ark,AddressOfBlockStart+(address_pointer+2),16);
				//fprintf(LOGFILE, "\n%d X@%d Y@%d = %d + %d,",AddressOfBlockStart+address_pointer,x,y,FirstTileInt,SecondTileInt);
				address_pointer=address_pointer+4;

				LevelInfo[x][y].tileType = getTile(FirstTileInt) ;
				LevelInfo[x][y].floorHeight = getHeight(FirstTileInt) ;
				LevelInfo[x][y].floorHeight = ((LevelInfo[x][y].floorHeight <<3) >> 2)*8 >>3;	//Try and copy this shift from shock.

				LevelInfo[x][y].ceilingHeight = 0;//UW_CEILING_HEIGHT;	//constant for uw				
				LevelInfo[x][y].noOfNeighbours=0;
				LevelInfo[x][y].tileTested = 0;
						{
						LevelInfo[x][y].floorTexture = getFloorTexUw2(tmp_ark, textureAddress, FirstTileInt);
						//int val = (FirstTileInt >>10) & 0x0F;
						LevelInfo[x][y].floorTexture = texture_map[(FirstTileInt >>10) & 0x0F];
						LevelInfo[x][y].wallTexture = getWallTexUw2(tmp_ark, textureAddress, SecondTileInt);	
						//(tileData & 0x3F
						LevelInfo[x][y].wallTexture= texture_map[SecondTileInt & 0x3F];
						LevelInfo[x][y].floorTexture = getFloorTex(tex_ark, textureAddress, FirstTileInt);
						LevelInfo[x][y].shockCeilingTexture = LevelInfo[x][y].floorTexture;
						LevelInfo[x][y].wallTexture = getWallTex(tex_ark, textureAddress, SecondTileInt);//?
						LevelInfo[x][y].wallTexture = texture_map[SecondTileInt & 0x3F];
						break;
					case UW1:	//uw1
						LevelInfo[x][y].floorTexture = getFloorTex(lev_ark, textureAddress, FirstTileInt);
						if (LevelNo == 6)
							{//Tybals lair. Special case for the maze
							int val = (FirstTileInt >> 10) & 0x0F;
							if (val == 4)
								{//Maze floor
								LevelInfo[x][y].floorTexture = 278;
								}
							}
						LevelInfo[x][y].wallTexture = getWallTex(lev_ark, textureAddress, SecondTileInt);
						break;
					case UW2:	//uw2
						{
						LevelInfo[x][y].floorTexture = getFloorTexUw2(tmp_ark, textureAddress, FirstTileInt);
						//int val = (FirstTileInt >>10) & 0x0F;
						//TODO:restore this line
						//LevelInfo[x][y].floorTexture = texture_map[(FirstTileInt >>10) & 0x0F];
						LevelInfo[x][y].floorTexture =(FirstTileInt >> 10) & 0x0F;
						LevelInfo[x][y].wallTexture = getWallTexUw2(tmp_ark, textureAddress, SecondTileInt);	
						//(tileData & 0x3F
						LevelInfo[x][y].wallTexture= texture_map[SecondTileInt & 0x3F];
						break;
						}						
					default:
						LevelInfo[x][y].floorTexture=CAULK;
						LevelInfo[x][y].wallTexture=CAULK;
						break;
					}
				if (LevelInfo[x][y].floorTexture<0)
					{
					LevelInfo[x][y].floorTexture=0;
					}
				if (LevelInfo[x][y].wallTexture>=256)
					{
					LevelInfo[x][y].wallTexture =0;
					}					
				//UW only has a single ceiling texture so this is ignored.
				//LevelInfo[x][y].shockCeilingTexture = LevelInfo[x][y].floorTexture;					
				LevelInfo[x][y].shockCeilingTexture=CeilingTexture;
				//There is only one possible steepness in UW so I set it's properties to match a similar tile in shock.
				if (LevelInfo[x][y].tileType >=2)
					{
					LevelInfo[x][y].shockSteep = 1;
					LevelInfo[x][y].shockSteep = ((LevelInfo[x][y].shockSteep  <<3) >> 2)*8 >>3;	//Shift copied from shock
					LevelInfo[x][y].shockSlopeFlag = SLOPE_FLOOR_ONLY ;
					}

			
				//LevelInfo[x][y].isDoor = getDoors(FirstTileInt);
				
				//Different textures on solid tiles faces
				LevelInfo[x][y].North = LevelInfo[x][y].wallTexture;
				LevelInfo[x][y].South = LevelInfo[x][y].wallTexture;
				LevelInfo[x][y].East = LevelInfo[x][y].wallTexture;
				LevelInfo[x][y].West = LevelInfo[x][y].wallTexture;
				LevelInfo[x][y].Top = LevelInfo[x][y].floorTexture; 
				LevelInfo[x][y].Bottom = LevelInfo[x][y].floorTexture; 
				LevelInfo[x][y].Diagonal = LevelInfo[x][y].wallTexture;
				//First index of the linked list of objects.
				LevelInfo[x][y].indexObjectList = getObject(SecondTileInt);

				LevelInfo[x][y].Render=1;		
				LevelInfo[x][y].DimX=1;			
				LevelInfo[x][y].DimY=1;			
				LevelInfo[x][y].Grouped=0;	
				//LevelInfo[x][y].VisibleFaces = 63;
				for (int v = 0; v < 6; v++)
					{
					LevelInfo[x][y].VisibleFaces[v]=1;
					}
				LevelInfo[x][y].isWater = (textureMasters[LevelInfo[x][y].floorTexture].water == 1) && ((LevelInfo[x][y].tileType !=0) && (ENABLE_WATER==1));
				LevelInfo[x][y].isLava = (textureMasters[LevelInfo[x][y].floorTexture].lava == 1) && ((LevelInfo[x][y].tileType != 0));
				LevelInfo[x][y].waterRegion= 0;
				LevelInfo[x][y].landRegion = 0;//including connected bridges.
				LevelInfo[x][y].lavaRegion = 0;

				//Set some easy tile visible settings
				switch (LevelInfo[x][y].tileType)
					{
					case TILE_SOLID:
						//Bottom and top are invisible
						LevelInfo[x][y].VisibleFaces[0] = 0;
						LevelInfo[x][y].VisibleFaces[2] = 0;
						break;
					default:
						//Bottom is invisible
						LevelInfo[x][y].VisibleFaces[2] = 0;
						break;
					}

				//Force off water to save on compile time during testing.
				//LevelInfo[x][y].isWater=0;
				//LevelInfo[x][y].TerrainChange=0;
				//LevelInfo[x][y].hasElevator=0;
			}
		}
	for (y=0; y<64;y++)
		{
		for (x=0; x<64;x++)
			{
			if (LevelInfo[x][y].tileType >= 0) //was just solid only. Note: If textures are all wrong it's probably caused here!
				{
				//assign it's north texture
				if (y<63)
					{LevelInfo[x][y].North =LevelInfo[x][y+1].wallTexture;}
				else
					{LevelInfo[x][y].North =-1;}
				//assign it's southern
				if (y>0)
					{LevelInfo[x][y].South  =LevelInfo[x][y-1].wallTexture;}
				else
					{LevelInfo[x][y].South =-1;}
				}
				//it's east
				if (x<63)
					{LevelInfo[x][y].East =LevelInfo[x+1][y].wallTexture;}
				else
					{LevelInfo[x][y].East =-1;}
				//assign it's West
				if (x>0)
					{LevelInfo[x][y].West =LevelInfo[x-1][y].wallTexture;}
				else
					{LevelInfo[x][y].West =-1;}				
				}
			LevelInfo[x][y].UpperEast = LevelInfo[x][y].East;
			LevelInfo[x][y].UpperWest = LevelInfo[x][y].West;
			LevelInfo[x][y].UpperNorth = LevelInfo[x][y].North;
			LevelInfo[x][y].UpperSouth = LevelInfo[x][y].South;
			LevelInfo[x][y].LowerEast = LevelInfo[x][y].East;
			LevelInfo[x][y].LowerWest = LevelInfo[x][y].West;
			LevelInfo[x][y].LowerNorth = LevelInfo[x][y].North;
			LevelInfo[x][y].LowerSouth = LevelInfo[x][y].South;

			}


	//Load Automap info
	if (AutoMapAddress != 0)
		{
			int z = 0;
			for (int y = 0; y < 64; y++)
				{
				for (int x = 0; x < 64; x++)
					{
					short val = (short)getValAtAddress(lev_ark, AutoMapAddress + z, 8);
					//The automap contains one byte per tile, in the same order as the
					//level tilemap. A valid value in the low nybble means the tile is displayed
					//on the map. Valid values are the same as tile types:
					//LevelInfo[x][y].tileType = (short)(val & 0xf);
					LevelInfo[x][y].DisplayType = (short)((val >> 4) & 0xf);
					z++;
					}
				}
		}


return 1;
}









int BuildTileMapShock(tile LevelInfo[64][64], ObjectItem objList[1600],long texture_map[272], char *filePath, int game, int LevelNo)
{
	unsigned char *archive_ark; 
	unsigned char *lev_ark; 
/*	unsigned char *tmp_ark; 
	unsigned char *sub_ark;*/ 
	unsigned char *tex_ark;
	unsigned char *inf_ark;
	long AddressOfBlockStart=0;
	long address_pointer=4;
	char blnLevelFound=0;
	long blockAddress =0;

//	int chunkId;
	long chunkUnpackedLength;
	long chunkType;//compression type
	long chunkPackedLength;
//	long chunkContentType;

//Read in the archive.
	FILE *file = NULL;      // File pointer
	if ((file = fopen(filePath, "rb")) == NULL)
		{
		fprintf(LOGFILE,"\nBuildTileMapSHock - Archive not found!\n");
		return -1;
		}
	long fileSize = getFileSize(file);
	//int filepos = ftell(file);	
	archive_ark = new unsigned char[fileSize];
	fread(archive_ark, fileSize, 1,file);
	fclose(file);
	
	
	
	//get the level info data from the archive
	blockAddress =getShockBlockAddress(LevelNo*100+4004,archive_ark,&chunkPackedLength,&chunkUnpackedLength,&chunkType); 
	if (blockAddress == -1) {return-1;}
	inf_ark=new unsigned char[chunkUnpackedLength];
	LoadShockChunk(blockAddress, chunkType, archive_ark, inf_ark,chunkPackedLength,chunkUnpackedLength);	
	//Process level properties (height c-space)
	long HeightUnits = getValAtAddress(inf_ark,16,32);	//Log2 value. The higher the value the lower the level height.
	if (HeightUnits > 3)	//Any higher we lose data, 
		{
		HeightUnits=3;
		}
	int cSpace = getValAtAddress(inf_ark,24,32);	//Per docs should return 1 on cyberspace. Does'nt appear to work.
	SHOCK_CEILING_HEIGHT = ((256 >> HeightUnits) * 8 >>3);	//Shifts the scale of the level.
	//long sizeV = getValAtAddress(inf_ark,0,32);
	//long sizeH = getValAtAddress(inf_ark,4,32);
	//long always6_1 = getValAtAddress(inf_ark,8,32);
	//long always6_2 = getValAtAddress(inf_ark,12,32);	
	
	//Read the main level data in
	blockAddress =getShockBlockAddress(LevelNo*100+4005,archive_ark,&chunkPackedLength,&chunkUnpackedLength,&chunkType); 
	if (blockAddress == -1) {return-1;}
	lev_ark=new unsigned char[chunkUnpackedLength]; //or 64*64*16
	LoadShockChunk(blockAddress, chunkType, archive_ark, lev_ark,chunkPackedLength,chunkUnpackedLength);
	AddressOfBlockStart=0;
	address_pointer=0;	
	

	
	//get the texture data from the archive.is never compressed?
	AddressOfBlockStart = getShockBlockAddress(4007+ LevelNo*100, archive_ark,  &chunkPackedLength, &chunkUnpackedLength,&chunkType);
	tex_ark = new unsigned char[chunkUnpackedLength];	
	for (long k=0; k< chunkUnpackedLength/2; k++)
	{
		texture_map[k] = getValAtAddress(archive_ark,AddressOfBlockStart + address_pointer,16);
		address_pointer =address_pointer+2;		//tmp_ark[AddressOfBlockStart+k];
	}
	AddressOfBlockStart=0;
	address_pointer=0;	


	//Reactor		Map 0  (chunk 40xx)
	//Levels 1-9	Map L  (chunk 4Lxx)
	//SHODAN c/space	Map 10 (chunk 50xx)
	//Delta grove	Map 11 (chunk 51xx)
	//Alpha grove	Map 12 (chunk 52xx)
	//Beta grove	Map 13 (chunk 53xx)
	//C/space L1-2    Map 14 (chunk 54xx)
	//C/space other	Map 15 (chunk 55xx)
	for (int y=0; y<64;y++)
		{
		for (int x = 0; x < 64; x++)
		{
			//Read in the tile data 
			LevelInfo[x][y].tileX = x;
			LevelInfo[x][y].tileY = y;
			LevelInfo[x][y].tileType = lev_ark[address_pointer];
			switch (LevelInfo[x][y].tileType)
			{//Need to swap some tile types around so that they conform to uw naming standards.
			case 4:	{LevelInfo[x][y].tileType = 5; break; }
			case 5:	{LevelInfo[x][y].tileType = 4; break; }
			case 7:	{LevelInfo[x][y].tileType = 8; break; }
			case 8:	{LevelInfo[x][y].tileType = 7; break; }
			}
			LevelInfo[x][y].ActualType = LevelInfo[x][y].tileType;
			LevelInfo[x][y].indexObjectList = 0;
			LevelInfo[x][y].Render = 1;
			LevelInfo[x][y].DimX = 1;
			LevelInfo[x][y].DimY = 1;
			LevelInfo[x][y].Grouped = 0;
			LevelInfo[x][y].BullFrog=0;
			for (int v = 0; v < 6; v++)
				{
				LevelInfo[x][y].VisibleFaces[v] = 1;
				}
			/* word 6 contains
				0-5	Wall texture (index into texture list)
				6-10	Ceiling texture
				11-15	Floor texture
				*/
			LevelInfo[x][y].wallTexture = texture_map[getValAtAddress(lev_ark, address_pointer + 6, 16) & 0x3F];
			LevelInfo[x][y].shockCeilingTexture = texture_map[(getValAtAddress(lev_ark, address_pointer + 6, 16) >> 6) & 0x1F];
			LevelInfo[x][y].floorTexture = texture_map[(getValAtAddress(lev_ark, address_pointer + 6, 16) >> 11) & 0x1F];

			//LevelInfo[x][y].wallTexture = 270;//debug
			//LevelInfo[x][y].shockCeilingTexture = 273;
			LevelInfo[x][y].North = LevelInfo[x][y].wallTexture;
			LevelInfo[x][y].South = LevelInfo[x][y].wallTexture;
			LevelInfo[x][y].East = LevelInfo[x][y].wallTexture;
			LevelInfo[x][y].West = LevelInfo[x][y].wallTexture;

			LevelInfo[x][y].isWater = 0;	//No swimming in shock.
			LevelInfo[x][y].landRegion=0;
			LevelInfo[x][y].lavaRegion = 0;
			LevelInfo[x][y].waterRegion = 0;
			LevelInfo[x][y].floorHeight = ((lev_ark[address_pointer + 1]) & 0x1F);
			LevelInfo[x][y].floorHeight = ((LevelInfo[x][y].floorHeight << 3) >> HeightUnits) * 8 >> 3; //Shift it for varying height scales

			LevelInfo[x][y].ceilingHeight = ((lev_ark[address_pointer + 2]) & 0x1F);
			LevelInfo[x][y].ceilingHeight = ((LevelInfo[x][y].ceilingHeight << 3) >> HeightUnits) * 8 >> 3; //Shift it for varying height scales

			LevelInfo[x][y].shockFloorOrientation = ((lev_ark[address_pointer + 1]) >> 5) & 0x3;
			LevelInfo[x][y].shockCeilOrientation = ((lev_ark[address_pointer + 2]) >> 5) & 0x3;

			//Need to know heights in various directions for alignments.
			//Will set these properly after loading levels.
			LevelInfo[x][y].shockNorthCeilHeight = LevelInfo[x][y].ceilingHeight;
			LevelInfo[x][y].shockSouthCeilHeight = LevelInfo[x][y].ceilingHeight;
			LevelInfo[x][y].shockEastCeilHeight = LevelInfo[x][y].ceilingHeight;
			LevelInfo[x][y].shockWestCeilHeight = LevelInfo[x][y].ceilingHeight;

			LevelInfo[x][y].shockSteep = (lev_ark[address_pointer + 3] & 0x0f);
			LevelInfo[x][y].shockSteep = ((LevelInfo[x][y].shockSteep << 3) >> HeightUnits) * 8 >> 3; //Shift it for varying height scales

			if ((LevelInfo[x][y].shockSteep == 0) && (LevelInfo[x][y].tileType >= 6))//If a sloped tile has no slope then it's a open tile.
			{
				LevelInfo[x][y].tileType = 1;
			}
			if ((LevelInfo[x][y].tileType == 1) && (LevelInfo[x][y].shockSteep > 0))	//similarly an open tile can't have a slope at all
			{
				LevelInfo[x][y].shockSteep = 0;
			}
			LevelInfo[x][y].indexObjectList = getValAtAddress(lev_ark, address_pointer + 4, 16);


			//if(LevelInfo[x][y].indexObjectList!=0)
			//	{
			//	fprintf(LOGFILE,"At %d %d we have: %d\n", x,y,LevelInfo[x][y].indexObjectList);
			//	}

			/*
				xxxxx0xx	Floor & ceiling, same direction
				xxxxx4xx	Floor & ceiling, ceiling opposite dir to tile type
				xxxxx8xx	Floor only
				xxxxxCxx	Ceiling only
				*/
			LevelInfo[x][y].shockSlopeFlag = (getValAtAddress(lev_ark, address_pointer + 8, 32) >> 10) & 0x03;
			LevelInfo[x][y].UseAdjacentTextures = (getValAtAddress(lev_ark, address_pointer + 8, 32) >> 8) & 0x01;
			LevelInfo[x][y].shockTextureOffset = getValAtAddress(lev_ark, address_pointer + 8, 32) & 0xF;
			//unknownflags
			//70E000E0
			//	fprintf(LOGFILE,"\nUnknownflags @ %d %d= %d",x,y, getValAtAddress(lev_ark,address_pointer+8,32) & 0x70E000E0);
			LevelInfo[x][y].shockShadeLower = (getValAtAddress(lev_ark, address_pointer + 8, 32) >> 16) & 0x0F;
			LevelInfo[x][y].shockShadeUpper = (getValAtAddress(lev_ark, address_pointer + 8, 32) >> 24) & 0x0F;
			LevelInfo[x][y].shadeUpperGlobal = 0;
			LevelInfo[x][y].shadeLowerGlobal = 0;
			LevelInfo[x][y].shockNorthOffset = LevelInfo[x][y].shockTextureOffset;
			LevelInfo[x][y].shockSouthOffset = LevelInfo[x][y].shockTextureOffset;
			LevelInfo[x][y].shockEastOffset = LevelInfo[x][y].shockTextureOffset;
			LevelInfo[x][y].shockWestOffset = LevelInfo[x][y].shockTextureOffset;

			LevelInfo[x][y].SHOCKSTATE[0] = getValAtAddress(lev_ark, address_pointer + 0xC, 8);
			LevelInfo[x][y].SHOCKSTATE[1] = getValAtAddress(lev_ark, address_pointer + 0xD, 8);
			LevelInfo[x][y].SHOCKSTATE[2] = getValAtAddress(lev_ark, address_pointer + 0xE, 8);
			LevelInfo[x][y].SHOCKSTATE[3] = getValAtAddress(lev_ark, address_pointer + 0xF, 8);
			
			//LevelInfo[x][y].indexObjectList=0;
			//if (y == 0)
			//{
			//	LevelInfo[x][y].tileType = TILE_SLOPE_N;
			//	LevelInfo[x][y].shockSlopeFlag=SLOPE_FLOOR_ONLY;
			//	LevelInfo[x][y].floorHeight=x;
			//	LevelInfo[x][y].shockSteep=11;
			//}
				address_pointer=address_pointer+16;
			}
		}
	
		for (int y=1; y<63;y++)	//skip the outer textures.
		{
		for (int x=1; x<63;x++)
			{
			//if (
			//	(LevelInfo[x][y].tileType  != TILE_OPEN) 
			//	||	((LevelInfo[x][y].tileType  != TILE_OPEN) && (LevelInfo[x][y].UseAdjacentTextures == 1))
			//	)
			//	{
			//if (LevelInfo[x][y].UseAdjacentTextures != 1)
			//	{
				if (LevelInfo[x+1][y].UseAdjacentTextures != 1)
					{
					LevelInfo[x][y].East = LevelInfo[x+1][y].wallTexture   ;
					LevelInfo[x][y].shockEastOffset =LevelInfo[x+1][y].shockTextureOffset;
					//LevelInfo[x][y].shockEastCeilHeight =LevelInfo[x+1][y].ceilingHeight - LevelInfo[x+1][y].shockSteep ;
					
					}
				if (LevelInfo[x-1][y].UseAdjacentTextures != 1)
					{					
					LevelInfo[x][y].West = LevelInfo[x-1][y].wallTexture   ;
					LevelInfo[x][y].shockWestOffset =LevelInfo[x-1][y].shockTextureOffset;
					//LevelInfo[x][y].shockWestCeilHeight =LevelInfo[x-1][y].ceilingHeight - LevelInfo[x-1][y].shockSteep ;
										
					}
				if (LevelInfo[x][y+1].UseAdjacentTextures != 1)
					{
					LevelInfo[x][y].North = LevelInfo[x][y+1].wallTexture   ;
					LevelInfo[x][y].shockNorthOffset =LevelInfo[x][y+1].shockTextureOffset;
					//LevelInfo[x][y].shockNorthCeilHeight =LevelInfo[x][y+1].ceilingHeight - LevelInfo[x][y+1].shockSteep ;
									
					}
				if (LevelInfo[x][y-1].UseAdjacentTextures != 1)
					{
					LevelInfo[x][y].South  = LevelInfo[x][y-1].wallTexture   ;
					LevelInfo[x][y].shockSouthOffset =LevelInfo[x][y-1].shockTextureOffset;
					//LevelInfo[x][y].shockSouthCeilHeight =LevelInfo[x][y-1].ceilingHeight - LevelInfo[x][y-1].shockSteep ;
					
					}
				//Need to calculate the adjustment here with the steepness and the direction of the slope.
				LevelInfo[x][y].shockEastCeilHeight= CalcNeighbourCeilHeight(LevelInfo[x][y],LevelInfo[x+1][y],fEAST);
				LevelInfo[x][y].shockWestCeilHeight= CalcNeighbourCeilHeight(LevelInfo[x][y],LevelInfo[x-1][y],fWEST);
				LevelInfo[x][y].shockNorthCeilHeight= CalcNeighbourCeilHeight(LevelInfo[x][y],LevelInfo[x][y+1],fNORTH);
				LevelInfo[x][y].shockSouthCeilHeight= CalcNeighbourCeilHeight(LevelInfo[x][y],LevelInfo[x][y-1],fSOUTH);
/*				LevelInfo[x][y].shockEastCeilHeight =LevelInfo[x+1][y].ceilingHeight - LevelInfo[x+1][y].shockSteep ;
				LevelInfo[x][y].shockWestCeilHeight =LevelInfo[x-1][y].ceilingHeight - LevelInfo[x-1][y].shockSteep ;
				LevelInfo[x][y].shockNorthCeilHeight =LevelInfo[x][y+1].ceilingHeight - LevelInfo[x][y+1].shockSteep ;
				LevelInfo[x][y].shockSouthCeilHeight =LevelInfo[x][y-1].ceilingHeight - LevelInfo[x][y-1].shockSteep ;*/	
				//}

				LevelInfo[x][y].UpperEast = LevelInfo[x][y].East;
				LevelInfo[x][y].UpperWest = LevelInfo[x][y].West;
				LevelInfo[x][y].UpperNorth = LevelInfo[x][y].North;
				LevelInfo[x][y].UpperSouth = LevelInfo[x][y].South;
				LevelInfo[x][y].LowerEast = LevelInfo[x][y].East;
				LevelInfo[x][y].LowerWest = LevelInfo[x][y].West;
				LevelInfo[x][y].LowerNorth = LevelInfo[x][y].North;
				LevelInfo[x][y].LowerSouth = LevelInfo[x][y].South;
			}
		}
return 1;
}

int CalcNeighbourCeilHeight(tile &t1, tile &t2,int Direction)
{//TODO:Test me. I'm terrible.
// fNORTH 32
// fSOUTH 16
// fEAST 8
// fWEST 4
	if  ((t2.tileType <=1) ||(t2.shockSlopeFlag == SLOPE_FLOOR_ONLY))
		{//Don't need to do anything since it has a flat ceiling.
		return t2.ceilingHeight;
		}
	else
		{
		//return t2.ceilingHeight;
		switch (Direction)
			{
			case fNORTH:
				{	
				switch (t2.tileType)
					{
					case TILE_SLOPE_N:
					case TILE_SLOPE_S:
						if ((t2.shockSlopeFlag == SLOPE_BOTH_OPPOSITE) ||(t2.shockSlopeFlag == SLOPE_CEILING_ONLY))
							{
							return t2.ceilingHeight+t2.shockSteep ;
							}
						else
							{
							return t2.ceilingHeight;
							}
							break;
					default:
						return t2.ceilingHeight;
						break;
					}
				}	
			case fSOUTH:
				{
				switch (t2.tileType)
					{
					case TILE_SLOPE_S:
					case TILE_SLOPE_N:
						if ((t2.shockSlopeFlag == SLOPE_BOTH_OPPOSITE) ||(t2.shockSlopeFlag == SLOPE_CEILING_ONLY))
							{
							return t2.ceilingHeight+t2.shockSteep ;
							}
						else
							{
							return t2.ceilingHeight;
							}
							break;
					default:
						return t2.ceilingHeight;
						break;
					}
				//if (t2.tileType == TILE_SLOPE_S)
				//	{
				//	if ((t2.shockSlopeFlag == SLOPE_BOTH_OPPOSITE) ||(t2.shockSlopeFlag == SLOPE_CEILING_ONLY))
				//		{
				//		return t2.ceilingHeight+t2.shockSteep ;
				//		}
				//	else
				//		{
				//		return t2.ceilingHeight;
				//		}
				//	}
				break;
				}	
			case fEAST:
				{
				switch (t2.tileType)
					{
					case TILE_SLOPE_E:
					case TILE_SLOPE_W:
						if ((t2.shockSlopeFlag == SLOPE_BOTH_OPPOSITE) ||(t2.shockSlopeFlag == SLOPE_CEILING_ONLY))
							{
							return t2.ceilingHeight+t2.shockSteep ;
							}
						else
							{
							return t2.ceilingHeight;
							}
							break;
					default:
						return t2.ceilingHeight;
						break;
					}
				}	
			case fWEST:
				{
				switch (t2.tileType)
					{
					case TILE_SLOPE_W:
					case TILE_SLOPE_E:
						if ((t2.shockSlopeFlag == SLOPE_BOTH_OPPOSITE) ||(t2.shockSlopeFlag == SLOPE_CEILING_ONLY))
							{
							return t2.ceilingHeight+t2.shockSteep ;
							}
						else
							{
							return t2.ceilingHeight;
							}
							break;
					default:
						return t2.ceilingHeight;
						break;
					}
				}
			}
		}
	return t2.ceilingHeight;
}

void setBridgeBits(tile LevelInfo[64][64], ObjectItem objList[1600])
	{//So I know if the tile contains a bridge
	ObjectItem currObj;
	for (int x = 0; x<64; x++)
		{
		for (int y = 0; y<64; y++)
			{
			if (LevelInfo[x][y].indexObjectList != 0)
				{
				currObj = objList[LevelInfo[x][y].indexObjectList];
				do
					{
					if ((objectMasters[objList[currObj.index].item_id].type == BRIDGE))
						{
						if (currObj.flags < 2)//Only tag the tiles if this is a standard bridge
							{
							LevelInfo[x][y].hasBridge = 1;
							}
						else
							{
							LevelInfo[x][y].hasBridge = 0;
							}
						}
					currObj = objList[currObj.next];
					} while (currObj.index != 0);
				}
			}
		}
}


void SetExitBits(tile LevelInfo[64][64], ObjectItem objList[1600])
	{//Sets when a tile contains a move trigger that links to a teleport trap that goes to another level.
	ObjectItem currObj;
	for (int x = 0; x<64; x++)
		{
		for (int y = 0; y<64; y++)
			{
			LevelInfo[x][y].hasExit=0;
			if (LevelInfo[x][y].indexObjectList != 0)
				{
				currObj = objList[LevelInfo[x][y].indexObjectList];
				do
					{
					if ((objectMasters[objList[currObj.index].item_id].type == A_MOVE_TRIGGER))
						{
						//Now check what it links to.
						if (currObj.link > 0)
							{
							ObjectItem triggerTarget = objList[currObj.link];
							if ((objectMasters[triggerTarget.item_id].type == A_TELEPORT_TRAP))
								{
								if (triggerTarget.zpos > 0)
									{//This is a teleport that goes to another level.
									LevelInfo[x][y].hasExit = 1;
									}
								}
							}
						}
					currObj = objList[currObj.next];
					} while (currObj.index != 0);
				}
			}

		}
	}

void setDoorBits(tile LevelInfo[64][64], ObjectItem objList[1600])
{//So I know if the tile contains a door.
ObjectItem currObj;
for (int x=0; x<64;x++)
	{
	for (int y=0;y<64;y++)
		{
		if (LevelInfo[x][y].indexObjectList !=0)
			{
			currObj = objList[LevelInfo[x][y].indexObjectList];
			do  
				{
				if ((objectMasters[objList[currObj.index].item_id].type == DOOR ) 
						|| (objectMasters[objList[currObj.index].item_id].type == HIDDENDOOR )
							|| (objectMasters[objList[currObj.index].item_id].type == PORTCULLIS))
				 {
					if (currObj.Angle1 >0)
					{
						//This door is a flat grating. I don't support that yet!
						break;
					}
					else
					{
					LevelInfo[x][y].isDoor = 1;
					LevelInfo[x][y].DoorIndex = currObj.index;
					}
					break;
					}
				else
				{
					if (objectMasters[objList[currObj.index].item_id].type == SHOCK_DOOR)
						{
						LevelInfo[x][y].shockDoor = 1;
						LevelInfo[x][y].DoorIndex = currObj.index;
						}
				}
				currObj=objList[currObj.next];
				}while (currObj.index !=0);
			}
		}
	
	}
}

void setPatchBits(tile LevelInfo[64][64], ObjectItem objList[1600])
{//So I know the tile contains a patch object. No longer needed?
ObjectItem currObj;
for (int x=0; x<64;x++)
	{
	for (int y=0;y<64;y++)
		{
		if (LevelInfo[x][y].indexObjectList !=0)
			{
			currObj = objList[LevelInfo[x][y].indexObjectList];
			do  
				{
				if ((objectMasters[objList[currObj.index].item_id].type == TMAP_SOLID ) || (objectMasters[objList[currObj.index].item_id].type == TMAP_CLIP ))
					{
					LevelInfo[x][y].hasPatch= 1;
//					LevelInfo[x][y].PatchIndex = currObj.index;
					break;
					}
				currObj=objList[currObj.next];
				}while (currObj.index !=0);
			}
		}
	
	}
}

void setElevatorBits(tile LevelInfo[64][64], ObjectItem objList[1600])
{//So I know the tile contains an elevator.
//Note for shock this is set when I read in the object. I should probably do the same for UW.
ObjectItem currObj;
for (int x=0; x<64;x++)
	{
	for (int y=0;y<64;y++)
		{
		if (LevelInfo[x][y].indexObjectList !=0)
			{
			currObj = objList[LevelInfo[x][y].indexObjectList];
			do  
				{
				if ((objectMasters[objList[currObj.index].item_id].type == A_DO_TRAP ) && (currObj.quality==3))
					{
					LevelInfo[x][y].hasElevator= 1;
					//LevelInfo[x][y].ElevatorIndex = currObj.index;
					currObj.tileX=x;
					currObj.tileY=y;
					break;
					}
				currObj=objList[currObj.next];
				}while (currObj.index !=0);
			}
		}
	
	}	
	
}

void setTerrainChangeBits(tile LevelInfo[64][64], ObjectItem objList[1600])
{//So I know that the tile terrains changes and I can later render both versions of the tile.
ObjectItem currObj;
for (int x=0; x<64;x++)
	{
	for (int y=0;y<64;y++)
		{
		if (LevelInfo[x][y].indexObjectList !=0)
			{
			currObj = objList[LevelInfo[x][y].indexObjectList];
			do  
				{
				if (objectMasters[objList[currObj.index].item_id].type == A_CHANGE_TERRAIN_TRAP )
					{
					LevelInfo[x][y].TerrainChange= 1;
					//LevelInfo[x][y].TerrainChangeIndex = currObj.index;
					//Need to flag the range of tiles affected. X/y of the object gives the dimensions
					for (int j=x; j<= x+currObj.x; j++ )
						{
						for (int k=y; k<= y+currObj.y; k++  )
							{
							LevelInfo[j][k].TerrainChange = 1;
							LevelInfo[j][k].TerrainChangeIndices[LevelInfo[j][k].TerrainChangeCount]=currObj.index;
							LevelInfo[j][k].TerrainChangeCount++;
							//LevelInfo[j][k].isWater  = 0;// turn off water in terrain change tiles
							if (LevelInfo[j][k].isDoor==1)//The tile contains a door. I need to make sure the door is created at the height of the tile.
								{
								objList[LevelInfo[j][k].DoorIndex].zpos = objList[currObj.index].zpos;
								}
							}						
						}
					currObj.tileX=x;
					currObj.tileY=y;
					//break;
					}
				currObj=objList[currObj.next];
				}while (currObj.index !=0);
			}
		}
	
	}	
	
}

void SetContainerInUse(int game, tile LevelInfo[64][64], ObjectItem objList[1600], int index)
	{
	//Take a container/npc and set inuseflag for it contents. 
	ObjectItem currobj = objList[index];
	//currobj.InUseFlag == 1;
	objList[index].InUseFlag=1;
	if (currobj.link != 0)
		{//Object has contents.
		ObjectItem tmpObj = objList[currobj.link];//Get the first item in the contents.
		objList[tmpObj.index].InUseFlag=1;
		if ((isContainer(tmpObj)) || (objectMasters[tmpObj.item_id].type == NPC))
			{//If the first item is a container recursively set it's flag
			SetContainerInUse(game, LevelInfo, objList, tmpObj.index);
			}
		//Now loop through the linked list.
		if (tmpObj.next > 0)
			{
			while (tmpObj.next > 0)
				{
				tmpObj = objList[tmpObj.next];
				objList[tmpObj.index].InUseFlag = 1;
				//if the next object is a countainer loop through it.
				if ((isContainer(tmpObj)) || (objectMasters[tmpObj.item_id].type == NPC))
					{//If the first item is a container recursively set it's flag
					SetContainerInUse(game, LevelInfo, objList, tmpObj.index);
					}
				}
			}
		tmpObj.InUseFlag = 1;
		}
	}

void setObjectTileXY(int game, tile LevelInfo[64][64], ObjectItem objList[1600])
{//Justs some useful info to know.
//ObjectItem currObj;
//objList[954].link = 0;
for (int x=0; x<64;x++)
	{
	for (int y=0;y<64;y++)
		{
		if (LevelInfo[x][y].indexObjectList !=0)
			{
			long nextObj=LevelInfo[x][y].indexObjectList;
			while (nextObj!=0)
				{
				objList[nextObj].tileX=x;
				objList[nextObj].tileY=y;
				objList[nextObj].InUseFlag = 1;
				if ((isContainer(objList[nextObj])) || (objectMasters[objList[nextObj].item_id].type == NPC))
					{
					SetContainerInUse(game, LevelInfo,objList, objList[nextObj].index);
					}
				else if (objectMasters[objList[nextObj].item_id].type == A_CREATE_OBJECT_TRAP)
					{
					if (objList[nextObj].InUseFlag == 0)
						{
						objList[nextObj].tileX = x;
						objList[nextObj].tileY = y;
						objList[nextObj].InUseFlag = 1;
						}
						if ( 
							(objectMasters[objList[objList[nextObj].link].item_id].type == NPC)
								&& 
								(objList[objList[nextObj].link].InUseFlag==0)
								)
							{
							SetContainerInUse(game, LevelInfo, objList, objList[objList[nextObj].link].index);
							}
						}
					
				nextObj=objList[nextObj].next;
				}
			}
		}	

	for (int i = 0; i < 1024;i++)
		{//Make sure triggers and traps are created.
		if (objList[i].InUseFlag == 0)
			{
			if ((isTrigger(objList[i]) )|| (isTrap(objList[i])))
				{
				objList[i].InUseFlag=1;
				}
			}
		}

	}

//Set traps to create at the point where they are first linked.
for (int i = 0; i < 1024; i++)
	{
	int nextLink =0; 
	if ((isTrap(objList[i])) && (objList[i].InUseFlag == 1))
		{
		int nextLink =objList[i].link;
		int x = objList[i].tileX;
		int y = objList[i].tileY;
		while ((isTrap(objList[nextLink])) && (nextLink != 0))
			{
			if (objList[nextLink].InUseFlag != 1)
				{
				objList[nextLink].tileX = x;
				objList[nextLink].tileY = y;
				objList[nextLink].InUseFlag = 1;
				nextLink = objList[nextLink].link;
				if (objectMasters[objList[nextLink].item_id].type == A_DELETE_OBJECT_TRAP)
					{
					nextLink = 0;
					}
				}
			else
				{
				nextLink=0;
				}
			}
		}
	}
}




void MergeWaterRegions(tile LevelInfo[64][64])
{
int currRegion;
currRegion =1;
	for (int x = 0; x<64; x++)
	{
		for (int y = 0; y<64; y++)
		{
		if (LevelInfo[x][y].hasBridge != 1)
			{
			if ((LevelInfo[x][y].isWater == 1) && (LevelInfo[x][y].waterRegion == 0))//Unset water region.
				{
				LevelInfo[x][y].waterRegion = currRegion;
				MergeCurrentWaterRegion(LevelInfo, currRegion, x, y);
				currRegion++;
				}
			}
		}
	}
}

void MergeCurrentWaterRegion(tile LevelInfo[64][64], int currRegion, int x, int y)
{
	//north
	if ((LevelInfo[x][y+1].isWater==1) && (LevelInfo[x][y+1].waterRegion == 0))
		{
		LevelInfo[x][y + 1].waterRegion = currRegion;
		MergeCurrentWaterRegion(LevelInfo, currRegion, x, y+1);
		}
	//south
	if ((LevelInfo[x][y - 1].isWater == 1) && (LevelInfo[x][y - 1].waterRegion == 0))
	{
	LevelInfo[x][y - 1].waterRegion = currRegion;
		MergeCurrentWaterRegion(LevelInfo, currRegion, x , y-1);
	}
	//east
	if ((LevelInfo[x + 1][y].isWater == 1) && (LevelInfo[x + 1][y].waterRegion == 0))
	{
	LevelInfo[x + 1][y].waterRegion = currRegion;
		MergeCurrentWaterRegion(LevelInfo, currRegion, x+1, y);
	}
	//west
	if ((LevelInfo[x - 1][y].isWater == 1) && (LevelInfo[x - 1][y].waterRegion == 0))
	{
	LevelInfo[x - 1][y].waterRegion = currRegion;
		MergeCurrentWaterRegion(LevelInfo, currRegion, x-1, y);
	}
}



void MergeLavaRegions(tile LevelInfo[64][64])
	{
	int currRegion;
	currRegion = 1;
	for (int x = 0; x<64; x++)
		{
		for (int y = 0; y<64; y++)
			{
			if (LevelInfo[x][y].hasBridge != 1)
				{
				if ((LevelInfo[x][y].isLava == 1) && (LevelInfo[x][y].lavaRegion == 0))//Unset lava region.
					{
					LevelInfo[x][y].lavaRegion = currRegion;
					MergeCurrentLavaRegion(LevelInfo, currRegion, x, y);
					currRegion++;
					}
				}
			}
		}
	}

void MergeCurrentLavaRegion(tile LevelInfo[64][64], int currRegion, int x, int y)
	{
	//north
	if ((LevelInfo[x][y + 1].isLava == 1) && (LevelInfo[x][y + 1].lavaRegion == 0))
		{
		LevelInfo[x][y + 1].lavaRegion = currRegion;
		MergeCurrentLavaRegion(LevelInfo, currRegion, x, y + 1);
		}
	//south
	if ((LevelInfo[x][y - 1].isLava == 1) && (LevelInfo[x][y - 1].lavaRegion == 0))
		{
		LevelInfo[x][y - 1].lavaRegion = currRegion;
		MergeCurrentLavaRegion(LevelInfo, currRegion, x, y - 1);
		}
	//east
	if ((LevelInfo[x + 1][y].isLava == 1) && (LevelInfo[x + 1][y].lavaRegion == 0))
		{
		LevelInfo[x + 1][y].lavaRegion = currRegion;
		MergeCurrentLavaRegion(LevelInfo, currRegion, x + 1, y);
		}
	//west
	if ((LevelInfo[x - 1][y].isLava == 1) && (LevelInfo[x - 1][y].lavaRegion == 0))
		{
		LevelInfo[x - 1][y].lavaRegion = currRegion;
		MergeCurrentLavaRegion(LevelInfo, currRegion, x - 1, y);
		}
	}

void setTileNeighbourCount(tile LevelInfo[64][64])
{ 

	for (int x = 0; x<64; x++)
	{
		for (int y = 0; y<64; y++)
		{
			if (LevelInfo[x][y].tileType != TILE_SOLID)
			{
			
			//test north
				if (y != 63)
					{
					if (LevelInfo[x][y + 1].tileType!=TILE_SOLID)
						{
						LevelInfo[x][y].noOfNeighbours++;
						}
					}

			//test south
				if (y != 0)
				{
					if (LevelInfo[x][y - 1].tileType != TILE_SOLID)
					{
						LevelInfo[x][y].noOfNeighbours++;
					}
				}
	
			//test east
				if (x != 63)
				{
					if (LevelInfo[x+1][y].tileType != TILE_SOLID)
					{
						LevelInfo[x][y].noOfNeighbours++;
					}
				}

			//test west
				if (y != 0)
				{
					if (LevelInfo[x-1][y].tileType != TILE_SOLID)
					{
						LevelInfo[x][y].noOfNeighbours++;
					}
				}
			}
			else
			{
				LevelInfo[x][y].noOfNeighbours=0;
			}
		}
	}
}

void setCorridors(tile LevelInfo[64][64], int *RoomIndex)
{
return;
//int corridorIndex=1;
	for (int x = 0; x<64; x++)
	{
		for (int y = 0; y<64; y++)
		{
			if (((LevelInfo[x][y].noOfNeighbours == 1) || (LevelInfo[x][y].noOfNeighbours == 2))
				&&
				(LevelInfo[x][y].tileTested == 0)  && (LevelInfo[x][y].isDoor == 0) && (LevelInfo[x][y].isWater == 0))
				{
				if (*RoomIndex == 17)
				{
					fprintf(LOGFILE,"");
				}
				int currentCorridorCount=0;
				MergeCorridors(LevelInfo, &currentCorridorCount, *RoomIndex, x, y,0);
				if (currentCorridorCount >= 4)
					{//Found a corridor
						ResetTileTests(LevelInfo);
						LevelInfo[x][y].isCorridor = 1;
						LevelInfo[x][y].landRegion = *RoomIndex;
						MergeCorridors(LevelInfo, &currentCorridorCount, *RoomIndex, x, y, 1);
						*RoomIndex = *RoomIndex +1;
					}
				}
		}

	}

}

void MergeCorridors(tile LevelInfo[64][64], int *currentCorridorCount, int corridorIndex, int x, int y, int SetValue)
{
	if (((LevelInfo[x][y].noOfNeighbours == 1) || (LevelInfo[x][y].noOfNeighbours == 2))
		&&
		((LevelInfo[x][y].tileTested == 0)) && (LevelInfo[x][y].isDoor == 0) && (LevelInfo[x][y].isWater == 0))
			{
	
			if (LevelInfo[x][y].tileTested != 1)
				{
				*currentCorridorCount = *currentCorridorCount+1;
				LevelInfo[x][y].tileTested = 1;

				//test north
				if (y < 63)
					{
					MergeCorridors(LevelInfo, currentCorridorCount, corridorIndex, x, y + 1,SetValue);
					}

				//test south
				if (y > 0)
					{
					MergeCorridors(LevelInfo, currentCorridorCount, corridorIndex, x, y - 1, SetValue);
					}

				//test east
				if (x < 63)
					{
					MergeCorridors(LevelInfo, currentCorridorCount, corridorIndex, x + 1, y, SetValue);
					}
				//test west
				if (x > 0)
					{
					MergeCorridors(LevelInfo, currentCorridorCount, corridorIndex, x - 1, y, SetValue);
					}
				
				if (SetValue == 1)
					{
						LevelInfo[x][y].isCorridor = 1;
						LevelInfo[x][y].landRegion = corridorIndex;
					}
			}
		else
			{
			LevelInfo[x][y].tileTested = 1;
			}
	
	}
}


void setRooms(tile LevelInfo[64][64],int *RoomIndex)
{
	ResetTileTests(LevelInfo);
	for (int x = 0; x<64; x++)
	{
		for (int y = 0; y<64; y++)
		{
		currRoomIndex = *RoomIndex;
			if (isMergeableRoom(LevelInfo,x,y))
				{//Start Merging
				MergeCurrentRoomRegion(LevelInfo, *RoomIndex, x, y);
				LevelInfo[x][y].landRegion = *RoomIndex;
				*RoomIndex = *RoomIndex+1;
				}
		}
	}
}

void MergeCurrentRoomRegion(tile LevelInfo[64][64], int currRegion, int x, int y)
{
	//north
if (isMergeableRoom(LevelInfo, x, y + 1))
	{
		LevelInfo[x][y+1].landRegion = currRegion;
		MergeCurrentRoomRegion(LevelInfo, currRegion, x, y + 1);
	}
	//south
if (isMergeableRoom(LevelInfo, x, y - 1))
	{
		LevelInfo[x][y-1].landRegion = currRegion;
		MergeCurrentRoomRegion(LevelInfo, currRegion, x, y - 1);
	}
	//east
if (isMergeableRoom(LevelInfo, x + 1, y))
	{
		LevelInfo[x+1][y].landRegion = currRegion;
		MergeCurrentRoomRegion(LevelInfo, currRegion, x + 1, y);
	}
	//west
if (isMergeableRoom(LevelInfo, x - 1, y))
	{
		LevelInfo[x-1][y].landRegion = currRegion;
		MergeCurrentRoomRegion(LevelInfo, currRegion, x - 1, y);
	}
}


void ResetTileTests(tile LevelInfo[64][64])
{
	for (int x = 0; x<64; x++)
	{
		for (int y = 0; y<64; y++)
		{
			LevelInfo[x][y].tileTested=0;
		}
	}
}

int isMergeableRoom(tile LevelInfo[64][64], int x, int y)
{

if (
	(LevelInfo[x][y].isWater == 0)
	&&
	(LevelInfo[x][y].isLava == 0)
	&&
	(LevelInfo[x][y].tileType != TILE_SOLID)
	&&
	(LevelInfo[x][y].landRegion == 0)
	)
	{
	return 1;
	}
else
	{
	if ((LevelInfo[x][y].hasBridge == 1) && (LevelInfo[x][y].bridgeRegion == 0))
		{
		LevelInfo[x][y].bridgeRegion = currRoomIndex;
		return 1;
		}
	else
		{
		return 0;
		}	
	}
/*
	if (
		(LevelInfo[x][y].isDoor == 0)
		&&
		(LevelInfo[x][y].isWater == 0)
		&&
		(LevelInfo[x][y].shockDoor == 0)
		&&
		(LevelInfo[x][y].tileType != TILE_SOLID)
		&&
		(LevelInfo[x][y].isCorridor==0)
		&&
		(LevelInfo[x][y].roomRegion==0)
		)
		{
		return 1;
		}
	else
		{
		return 0;
		}
		*/
}


void CleanUp(tile LevelInfo[64][64], int game, int CleanupType, int tileType, int Surface)
{
int j;
	switch (CleanupType)
	{
	case CLEANUPHIDDEN:
		{
		CleanUpHiddenTiles(LevelInfo, game);
		break;
		}
	case CLEANUPXAXIS:
		{
		j = 1;
		//Now lets combine the solids along particular axis
		for (int x = 0; x<64; x++){
			for (int y = 0; y<63; y++){
				if ((LevelInfo[x][y].Grouped == 0) && (LevelInfo[x][y].tileType==tileType))
				{
					j = 1;
					while ((LevelInfo[x][y].Render == 1) && (LevelInfo[x][y + j].Render == 1) && (LevelInfo[x][y + j].Grouped == 0))		//&& (LevelInfo[x][y].tileType ==0) && (LevelInfo[x][y+j].tileType ==0)
					{
						//combine these two if they match and they are not already part of a group
						if (DoTilesMatch(LevelInfo[x][y], LevelInfo[x][y + j],Surface)){
							LevelInfo[x][y + j].Render = 0;
							LevelInfo[x][y + j].Grouped = 1;
							LevelInfo[x][y].Grouped = 1;
							//LevelInfo[x][y].DimY++;
							j++;
						}
						else
						{
							break;
						}

					}
					LevelInfo[x][y].DimY = LevelInfo[x][y].DimY + j - 1;
					j = 1;
				}
			}
		}
		break;
		}
	case CLEANUPYAXIS:
		{
		for (int y = 0; y<64; y++)
			{
			for (int x = 0; x<63; x++)
				{
				if ((LevelInfo[x][y].Grouped == 0) && (LevelInfo[x][y].tileType == tileType))
					{
						j = 1;
						while ((LevelInfo[x][y].Render == 1) && (LevelInfo[x + j][y].Render == 1) && (LevelInfo[x + j][y].Grouped == 0))		//&& (LevelInfo[x][y].tileType ==0) && (LevelInfo[x][y+j].tileType ==0)
						{
							//combine these two if they match and they are not already part of a group
							if (DoTilesMatch(LevelInfo[x][y], LevelInfo[x + j][y],Surface)){
								LevelInfo[x + j][y].Render = 0;
								LevelInfo[x + j][y].Grouped = 1;
								LevelInfo[x][y].Grouped = 1;
								//LevelInfo[x][y].DimY++;
								j++;
							}
							else
							{
								break;
							}

						}
						LevelInfo[x][y].DimX = LevelInfo[x][y].DimX + j - 1;
						j = 1;
					}
				}
			}
		}
	}
}

void ResetCleanup(tile LevelInfo[64][64], int game)
{//Resets tile cleanup so I can retest with new rules.
	for (int y = 0; y <= 63; y++)
	{
		for (int x = 0; x <= 63; x++)
		{
			LevelInfo[x][y].Render = 1;
			LevelInfo[x][y].Grouped = 0;
			LevelInfo[x][y].DimX = 1;
			LevelInfo[x][y].DimY = 1;
			LevelInfo[x][y].UpperEast = LevelInfo[x][y].East;
			LevelInfo[x][y].UpperWest = LevelInfo[x][y].West;
			LevelInfo[x][y].UpperNorth = LevelInfo[x][y].North;
			LevelInfo[x][y].UpperSouth = LevelInfo[x][y].South;
		}
	}
}


void CleanUpHiddenTiles(tile LevelInfo[64][64], int game)
{
	for (int x = 0; x<64; x++){
		for (int y = 0; y<64; y++){
			//lets test this tile for visibility
			//A tile is invisible if it only touches other solid tiles and has no objects or does not have a terrain change.
			if ((LevelInfo[x][y].tileType == 0) && (LevelInfo[x][y].indexObjectList == 0) && (LevelInfo[x][y].TerrainChange == 0)){
				switch (y)
				{
				case 0:	//bottom row
					switch (x)
					{
					case 0:	//bl corner
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y + 1].tileType == 0)
							&& (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y + 1].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0;; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					case 63://br corner
						if ((LevelInfo[x - 1][y].tileType == 0) && (LevelInfo[x][y + 1].tileType == 0)
							&& (LevelInfo[x - 1][y].TerrainChange == 0) && (LevelInfo[x][y + 1].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					default: // invert t
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x + 1][y].tileType == 0)
							&& (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y + 1].TerrainChange == 0) && (LevelInfo[x + 1][y].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					}
					break;
				case 63: //Top row
					switch (x)
					{
					case 0:	//tl corner
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0)
							&& (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					case 63://tr corner
						if ((LevelInfo[x - 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0)
							&& (LevelInfo[x - 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					default: //  t
						if ((LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) && (LevelInfo[x - 1][y].tileType == 0)
							&& (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0) && (LevelInfo[x - 1][y].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					}
					break;
				default: //
					switch (x)
					{
					case 0:		//left edge
						if ((LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0)
							&& (LevelInfo[x][y + 1].TerrainChange == 0) && (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					case 63:	//right edge
						if ((LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x - 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0)
							&& (LevelInfo[x][y + 1].TerrainChange == 0) && (LevelInfo[x - 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					default:		//+
						if ((LevelInfo[x][y + 1].tileType == 0) && (LevelInfo[x + 1][y].tileType == 0) && (LevelInfo[x][y - 1].tileType == 0) && (LevelInfo[x - 1][y].tileType == 0)
							&& (LevelInfo[x][y + 1].TerrainChange == 0) && (LevelInfo[x + 1][y].TerrainChange == 0) && (LevelInfo[x][y - 1].TerrainChange == 0) && (LevelInfo[x - 1][y].TerrainChange == 0))
						{
							LevelInfo[x][y].Render = 0; break;
						}
						else { LevelInfo[x][y].Render = 1; break; }
					}
					break;
				}
			}
		}
	}
}


int DoTilesMatch(tile &t1, tile &t2, int Surface)
{//TODO:Tiles have a lot more properties now.
	if ((t1.hasElevator == 1) || (t1.TerrainChange == 1) || (t2.hasElevator == 1) || (t2.TerrainChange == 1) || (t1.isWater != t2.isWater) || (t2.BullFrog == 1) || (t2.BullFrog == 1))
		{	//autofail on special or changes to water
		return 0;
		}

	switch (Surface)
	{
	case SURFACE_FLOOR:
		{
		if ((t1.tileType == 0) && (t2.tileType == 0))	//solid
			{
			return ((t1.wallTexture == t2.wallTexture) 
				&& (t1.West == t2.West) && (t1.South == t2.South) 
				&& (t1.East == t2.East) && (t1.North == t2.North) 
				&& (t1.UseAdjacentTextures == t2.UseAdjacentTextures));
			}
		else
		{
			return (t1.shockCeilingTexture == t2.shockCeilingTexture)
				&& (t1.floorTexture == t2.floorTexture)
				&& (t1.floorHeight == t2.floorHeight)
				&& (t1.isWater == t2.isWater)
				&& (t1.DimX == t2.DimX) && (t1.DimY == t2.DimY)
				&& (t1.LowerWest == t2.LowerWest) && (t1.LowerSouth == t2.LowerSouth) && (t1.LowerEast == t2.LowerEast) && (t1.LowerNorth == t2.LowerNorth) 
				&& (t1.UseAdjacentTextures == t2.UseAdjacentTextures)
				&& (t1.tileType == t2.tileType);
		}
		break;
		}
	case SURFACE_CEIL:
		{
		if ((t1.tileType == 0) && (t2.tileType == 0))	//solid
		{
			return ((t1.wallTexture == t2.wallTexture) && (t1.West == t2.West) && (t1.South == t2.South) && (t1.East == t2.East) && (t1.North == t2.North) && (t1.UseAdjacentTextures == t2.UseAdjacentTextures));
		}
		else
		{
			return (t1.shockCeilingTexture == t2.shockCeilingTexture)
				&& (t1.ceilingHeight == t2.ceilingHeight)
				&& (t1.DimX == t2.DimX) && (t1.DimY == t2.DimY)
				&& (t1.UpperWest == t2.UpperWest) && (t1.UpperSouth == t2.UpperSouth) && (t1.UpperEast == t2.UpperEast) && (t1.UpperNorth == t2.UpperNorth)
				&& (t1.UseAdjacentTextures == t2.UseAdjacentTextures)
				&& (t1.tileType == t2.tileType);
		}
		break;
		}	
	default:
		return 0;
	}
	//return (t1.shockCeilingTexture == t2.shockCeilingTexture)
	//	&& (t1.floorTexture == t2.floorTexture)
	//	&& (t1.floorHeight == t2.floorHeight)
	//	&& (t1.ceilingHeight == t2.ceilingHeight)
	//	&& (t1.DimX == t2.DimX) && (t1.DimY == t2.DimY)
	//	&& (t1.wallTexture == t2.wallTexture)
	//	&& (t1.tileType == t2.tileType)
	//	&& (t1.isDoor == 0) && (t2.isDoor == 0);

}

void CaulkHiddenWalls(tile LevelInfo[64][64], int game, int surface)
{
	for (int x = 1; x < 62; x++)
		{
		for (int y = 1; y < 62; y++)
			{
			if (LevelInfo[x][y].tileType == TILE_OPEN)
				{
				switch (surface)
					{
					case SURFACE_CEIL:
						{
						if (((LevelInfo[x][y].ceilingHeight == LevelInfo[x][y + 1].ceilingHeight) 
								&& (LevelInfo[x][y + 1].tileType == TILE_OPEN)) || (LevelInfo[x][y + 1].tileType == TILE_SOLID))
							{
							LevelInfo[x][y].UpperNorth=CAULK;
							}
						if (((LevelInfo[x][y].ceilingHeight == LevelInfo[x][y - 1].ceilingHeight) 
								&& (LevelInfo[x][y - 1].tileType == TILE_OPEN)) || (LevelInfo[x][y - 1].tileType == TILE_SOLID))
							{
							LevelInfo[x][y].UpperSouth = CAULK;
							}
						if (((LevelInfo[x][y].ceilingHeight == LevelInfo[x+1][y].ceilingHeight) 
								&& (LevelInfo[x+1][y].tileType == TILE_OPEN)) || (LevelInfo[x+1][y].tileType == TILE_SOLID))
							{
							LevelInfo[x][y].UpperEast = CAULK;
							}
						if (((LevelInfo[x][y].ceilingHeight == LevelInfo[x-1][y].ceilingHeight) 
								&& (LevelInfo[x - 1][y].tileType == TILE_OPEN)) || (LevelInfo[x - 1][y].tileType == TILE_SOLID))
						{
							LevelInfo[x][y].UpperWest = CAULK;
						}
						break;
						}
					case SURFACE_FLOOR:
						{
							if ((((LevelInfo[x][y].floorHeight == LevelInfo[x][y + 1].floorHeight) 
								&& (LevelInfo[x][y + 1].tileType == TILE_OPEN)) || (LevelInfo[x][y + 1].tileType == TILE_SOLID))
								&& (LevelInfo[x][y+1].isWater==0))
							{
								LevelInfo[x][y].LowerNorth = CAULK;
							}
							if ((((LevelInfo[x][y].floorHeight == LevelInfo[x][y - 1].floorHeight) 
								&& (LevelInfo[x][y - 1].tileType == TILE_OPEN)) || (LevelInfo[x][y - 1].tileType == TILE_SOLID))
								&& (LevelInfo[x][y - 1].isWater == 0))
							{
								LevelInfo[x][y].LowerSouth = CAULK;
							}
							if ((((LevelInfo[x][y].floorHeight == LevelInfo[x + 1][y].floorHeight) 
								&& (LevelInfo[x + 1][y].tileType == TILE_OPEN)) || (LevelInfo[x + 1][y].tileType == TILE_SOLID))
								&& (LevelInfo[x+1][y].isWater == 0))
							{
								LevelInfo[x][y].LowerEast = CAULK;
							}
							if ((((LevelInfo[x][y].floorHeight == LevelInfo[x - 1][y].floorHeight) 
								&& (LevelInfo[x - 1][y].tileType == TILE_OPEN)) || (LevelInfo[x - 1][y].tileType == TILE_SOLID))
								&& (LevelInfo[x-1][y].isWater == 0))
							{
								LevelInfo[x][y].LowerWest = CAULK;
							}
						break;
						}
					}
				}
			}
		}
}
<MSG> Musings on the change to/from Traps

Texture fix to change terrain trap in UW2
<DFF> @@ -849,7 +849,9 @@ int BuildTileMapUW(tile LevelInfo[64][64],ObjectItem objList[1600], long texture
 						{
 						LevelInfo[x][y].floorTexture = getFloorTexUw2(tmp_ark, textureAddress, FirstTileInt);
 						//int val = (FirstTileInt >>10) & 0x0F;
-						LevelInfo[x][y].floorTexture = texture_map[(FirstTileInt >>10) & 0x0F];
+						//TODO:restore this line
+						//LevelInfo[x][y].floorTexture = texture_map[(FirstTileInt >>10) & 0x0F];
+						LevelInfo[x][y].floorTexture =(FirstTileInt >> 10) & 0x0F;
 						LevelInfo[x][y].wallTexture = getWallTexUw2(tmp_ark, textureAddress, SecondTileInt);	
 						//(tileData & 0x3F
 						LevelInfo[x][y].wallTexture= texture_map[SecondTileInt & 0x3F];

Musings on the change to/from Traps