#include "builddefines.h"

#ifdef PRECOMPILEDHEADERS
	#include "TileEngine All.h"
#else
	#include "math.h"
	#include <stdio.h>
	#include <errno.h>

	#include "worlddef.h"
	#include "renderworld.h"
	#include "vsurface.h"
	#include "input.h"
	#include "sysutil.h"
	#include "wchar.h"
	#include "video.h"
	#include "vobject_blitters.h"
	#include "debug.h"
	#include "wcheck.h"
	#include "worldman.h"
	#include "jascreens.h"
	#include "edit_sys.h"
	#include "Isometric Utils.h"
	#include "line.h"
	#include "Animation Control.h"
	#include "Animation Data.h"
	#include "Timer Control.h"
	#include "Radar Screen.h"
	#include "Render Dirty.h"
	#include "Font Control.h"
	#include "Sys Globals.h"
	#include "Render Dirty.h"
	#include "lighting.h"
	#include "Overhead types.h"
	#include "Overhead.h"
	#include "weapons.h"
	#include "ai.h"
	#include "vobject.h"
	#include "render fun.h"
	#include "los.h"
	#include "interactive tiles.h"
	#include "interface cursors.h"
	#include "rotting corpses.h"
	#include "tile cache.h"
	#include "tile animation.h"
	#include "English.h"
	#include "world items.h"
	#include "GameSettings.h"
	#include "interface control.h"
	#include "Sound Control.h"
#endif

///////////////////////////
// C file include here
#include "Render Z.h"
///////////////////////////

extern	CHAR8	gDebugStr[128];
extern	BOOLEAN fLandLayerDirty	= TRUE;

extern	INT16	gsVIEWPORT_START_X;
extern	INT16	gsVIEWPORT_START_Y;
extern	INT16	gsVIEWPORT_END_Y;
extern	INT16	gsVIEWPORT_WINDOW_END_Y;
extern	INT16	gsVIEWPORT_WINDOW_START_Y;
extern	INT16	gsVIEWPORT_END_X;

UINT16	*gpZBuffer				= NULL;
BOOLEAN gfTagAnimatedTiles		= TRUE;

INT16	gsCurrentGlowFrame		= 0;
INT16	gsCurrentItemGlowFrame	= 0;

extern	BOOLEAN	gfUIShowExitEast;
extern	BOOLEAN	gfUIShowExitWest;
extern	BOOLEAN	gfUIShowExitNorth;
extern	BOOLEAN	gfUIShowExitSouth;
extern	BOOLEAN	gfTopMessageDirty;

// VIEWPORT OFFSET VALUES
// NOTE:
// THESE VALUES MUST BE MULTIPLES OF TILE SIZES!
#define	VIEWPORT_XOFFSET_S					WORLD_TILE_X*1
#define	VIEWPORT_YOFFSET_S					WORLD_TILE_Y*2
#define LARGER_VIEWPORT_XOFFSET_S			( VIEWPORT_XOFFSET_S * 3 )
#define LARGER_VIEWPORT_YOFFSET_S			( VIEWPORT_YOFFSET_S * 5 )

#define TILES_TYPE_BITMASK					0x00040000
#define TILES_TYPE_MASK						0x07ffffff
#define TILES_DIRTY							0x80000000
#define TILES_DYNAMIC						0x40000000
#define TILES_NOZWRITE						0x20000000
#define TILES_MARKED						0x10000000
#define TILES_NOZ							0x04000000
#define TILES_DOALL							0x02000000
#define TILES_OBSCURED						0x01000000

//#define TILES_MERC						0x00000400
//#define TILES_Z_BLITTER					0x00000200
//#define TILES_Z_WRITE						0x00000100
//#define TILES_SHADOW						0x00000080
//#define TILES_BACKWARDS					0x00000040

#define	MAX_RENDERED_ITEMS					3

// RENDERER FLAGS FOR DIFFERENT RENDER LEVELS
typedef enum
{
	RENDER_STATIC_LAND,						RENDER_STATIC_OBJECTS,
	RENDER_STATIC_SHADOWS,					RENDER_STATIC_STRUCTS,
	RENDER_STATIC_ROOF,						RENDER_STATIC_ONROOF,
	RENDER_STATIC_TOPMOST,					RENDER_DYNAMIC_LAND,
	RENDER_DYNAMIC_OBJECTS,					RENDER_DYNAMIC_SHADOWS,
	RENDER_DYNAMIC_STRUCT_MERCS,			RENDER_DYNAMIC_MERCS,
	RENDER_DYNAMIC_STRUCTS,					RENDER_DYNAMIC_ROOF,
	RENDER_DYNAMIC_HIGHMERCS,				RENDER_DYNAMIC_ONROOF,
	RENDER_DYNAMIC_TOPMOST,					NUM_RENDER_FX_TYPES
};

#define	SCROLL_INTERTIA_STEP1				3//6
#define	SCROLL_INTERTIA_STEP2				4//8

//#define SHORT_ROUND( x ) ( (INT16)( ( x * 1000 ) / 1000 ) )
#define SHORT_ROUND( x ) ( x )

#define	NUM_ITEM_CYCLE_COLORS				60

UINT16	us16BPPItemCycleWhiteColors[ NUM_ITEM_CYCLE_COLORS ];
UINT16	us16BPPItemCycleRedColors[ NUM_ITEM_CYCLE_COLORS ];
UINT16	us16BPPItemCycleYellowColors[ NUM_ITEM_CYCLE_COLORS ];

INT16	gsLobOutline;
INT16	gsThrowOutline;
INT16	gsGiveOutline;
INT16	gusNormalItemOutlineColor;
INT16	gusYellowItemOutlineColor;
INT16	gsRenderHeight				= 0;
BOOLEAN	gfRenderFullThisFrame		= 0;

INT16 gCenterWorldX;

//UINT8		gubIntTileCheckFlags	 = INTILE_CHECK_FULL;
UINT8		gubIntTileCheckFlags	 = INTILE_CHECK_SELECTIVE;

UINT8		ubRGBItemCycleWhiteColors[] =
{
	25,		25,		25,
	50,		50,		50,
	75,		75,		75,
	100,	100,	100,
	125,	125,	125,
	150,	150,	150,
	175,	175,	175,
	200,	200,	200,
	225,	225,	225,
	250,	250,	250,

	250,	250,	250,
	225,	225,	225,
	200,	200,	200,
	175,	175,	175,
	150,	150,	150,
	125,	125,	125,
	100,	100,	100,
	75,		75,		75,
	50,		50,		50,
	25,		25,		25,

	25,		25,		25,
	50,		50,		50,
	75,		75,		75,
	100,	100,	100,
	125,	125,	125,
	150,	150,	150,
	175,	175,	175,
	200,	200,	200,
	225,	225,	225,
	250,	250,	250,

	250,	250,	250,
	225,	225,	225,
	200,	200,	200,
	175,	175,	175,
	150,	150,	150,
	125,	125,	125,
	100,	100,	100,
	75,		75,		75,
	50,		50,		50,
	25,		25,		25,

	25,		25,		25,
	50,		50,		50,
	75,		75,		75,
	100,	100,	100,
	125,	125,	125,
	150,	150,	150,
	175,	175,	175,
	200,	200,	200,
	225,	225,	225,
	250,	250,	250,

	250,	250,	250,
	225,	225,	225,
	200,	200,	200,
	175,	175,	175,
	150,	150,	150,
	125,	125,	125,
	100,	100,	100,
	75,		75,		75,
	50,		50,		50,
	25,		25,		25
};

UINT8		ubRGBItemCycleRedColors[] =
{
	25,		0,		0,
	50,		0,		0,
	75,		0,		0,
	100,	0,		0,
	125,	0,		0,
	150,	0,		0,
	175,	0,		0,
	200,	0,		0,
	225,	0,		0,
	250,	0,		0,

	250,	0,		0,
	225,	0,		0,
	200,	0,		0,
	175,	0,		0,
	150,	0,		0,
	125,	0,		0,
	100,	0,		0,
	75,		0,		0,
	50,		0,		0,
	25,		0,		0,

	25,		0,		0,
	50,		0,		0,
	75,		0,		0,
	100,	0,		0,
	125,	0,		0,
	150,	0,		0,
	175,	0,		0,
	200,	0,		0,
	225,	0,		0,
	250,	0,		0,

	250,	0,		0,
	225,	0,		0,
	200,	0,		0,
	175,	0,		0,
	150,	0,		0,
	125,	0,		0,
	100,	0,		0,
	75,		0,		0,
	50,		0,		0,
	25,		0,		0,

	25,		0,		0,
	50,		0,		0,
	75,		0,		0,
	100,	0,		0,
	125,	0,		0,
	150,	0,		0,
	175,	0,		0,
	200,	0,		0,
	225,	0,		0,
	250,	0,		0,

	250,	0,		0,
	225,	0,		0,
	200,	0,		0,
	175,	0,		0,
	150,	0,		0,
	125,	0,		0,
	100,	0,		0,
	75,		0,		0,
	50,		0,		0,
	25,		0,		0,
};

UINT8		ubRGBItemCycleYellowColors[] =
{
	25,		25,		0,
	50,		50,		0,
	75,		75,		0,
	100,	100,	0,
	125,	125,	0,
	150,	150,	0,
	175,	175,	0,
	200,	200,	0,
	225,	225,	0,
	250,	250,	0,

	250,	250,	0,
	225,	225,	0,
	200,	200,	0,
	175,	175,	0,
	150,	150,	0,
	125,	125,	0,
	100,	100,	0,
	75,		75,		0,
	50,		50,		0,
	25,		25,		0,

	25,		25,		0,
	50,		50,		0,
	75,		75,		0,
	100,	100,	0,
	125,	125,	0,
	150,	150,	0,
	175,	175,	0,
	200,	200,	0,
	225,	225,	0,
	250,	250,	0,

	250,	250,	0,
	225,	225,	0,
	200,	200,	0,
	175,	175,	0,
	150,	150,	0,
	125,	125,	0,
	100,	100,	0,
	75,		75,		0,
	50,		50,		0,
	25,		25,		0,

	25,		25,		0,
	50,		50,		0,
	75,		75,		0,
	100,	100,	0,
	125,	125,	0,
	150,	150,	0,
	175,	175,	0,
	200,	200,	0,
	225,	225,	0,
	250,	250,	0,

	250,	250,	0,
	225,	225,	0,
	200,	200,	0,
	175,	175,	0,
	150,	150,	0,
	125,	125,	0,
	100,	100,	0,
	75,		75,		0,
	50,		50,		0,
	25,		25,		0,
};

#define NUMSPEEDS		5

UINT8	gubNewScrollXSpeeds[2][ NUMSPEEDS ]	=
{
	40, 80, 100, 180, 200,		// Non-video mode scroll
	20, 40, 80, 80, 80			// Video mode scroll
};

UINT8	gubNewScrollYSpeeds[2][ NUMSPEEDS ]	=
{
	40, 80, 100, 180, 200,		// Non-video mode scroll
	10, 20, 60, 80, 80			// Video mode scroll
};

// These speeds are only an indication of how long to do each subtile step until moving on to another
UINT8	gubNewScrollIDSpeeds[ ]		= { 10, 10, 20, 20,  20 };
UINT8	gubScrollSpeedStartID		= 2;
UINT8	gubScrollSpeedEndID			= 4;
UINT8	gubCurScrollSpeedID			= 1;
BOOLEAN	gfDoVideoScroll				= TRUE;
BOOLEAN	gfDoSubtileScroll			= FALSE;
BOOLEAN	gfScrollPending				= FALSE;
UINT32	uiLayerUsedFlags			= 0xffffffff;
UINT32	uiAdditiveLayerUsedFlags	= 0xffffffff;

// Array of shade values to use.....
#define NUM_GLOW_FRAMES				30

#if 0
INT16	gsGlowFrames[] =
{
	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
	0,	1,	2,	3,	4,	5,	6,	7,	8,	9,
	9,	8,	7,	6,	5,	4,	3,	2,	1,	0,
};
#endif

INT16	gsGlowFrames[] =
{
	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
	2,	4,	6,	8,	9,	8,	6,	4,	2,	0,
};

// This has to be the same # of frames as NUM_GLOW_FRAMES
INT16	gsFastGlowFrames[] =
{
	0,	0,	6,	7,	8,	9,	8,	7,	6,	5,
	0,	0,	6,	7,	8,	9,	8,	7,	6,	5,
	0,	0,	6,	7,	8,	9,	8,	7,	6,	5,
};

// The glow frame pointer can be adjusted to use a faster/ slower glow
INT16	*gpGlowFramePointer	= gsGlowFrames;

UINT32	gScrollDirectionFlags[ NUM_WORLD_DIRECTIONS ] =
{
	SCROLL_UP | SCROLL_RIGHT,
	SCROLL_RIGHT,
	SCROLL_DOWN | SCROLL_RIGHT,
	SCROLL_DOWN,
	SCROLL_DOWN | SCROLL_LEFT,
	SCROLL_LEFT,
	SCROLL_UP | SCROLL_LEFT,
	SCROLL_UP,
};

INT16 SCROLL_X_STEP	 =		( WORLD_TILE_X );
INT16 SCROLL_Y_STEP	 =		( WORLD_TILE_Y * 2);

/*
 *	ViewPort starting values
 *	What is viewport?
 *	So viewport are coords of map screen (tactical screen)
 *	gsViewport_xxx this variables are related with mouse regions, current rendering region ...
 *	this variables ware unnecessary with this GUI becouse they can be calculated from INTERFACE coords
 *	but i think that they can be realy usefull while we will change GUI for more customisable
 *  any questions? joker
 */
/*
INT16 gsVIEWPORT_START_X				= 0;
INT16 gsVIEWPORT_START_Y				= 0;
INT16 gsVIEWPORT_WINDOW_START_Y			= 0;
INT16 gsVIEWPORT_WINDOW_END_Y			= INTERFACE_START_Y;//do zmiany
INT16 gsVIEWPORT_END_X					= SCREEN_WIDTH;
INT16 gsVIEWPORT_END_Y					= INTERFACE_START_Y;

i changed for dynamic initialization joker
*/
// still need the global object container defined atleast once outside a header (jonathanl)
INT16 gsVIEWPORT_START_X					= 0;
INT16 gsVIEWPORT_START_Y				= 0;
INT16 gsVIEWPORT_WINDOW_START_Y			= 0;
INT16 gsVIEWPORT_WINDOW_END_Y			= INTERFACE_START_Y;
INT16 gsVIEWPORT_END_X					= SCREEN_WIDTH;
INT16 gsVIEWPORT_END_Y					= INTERFACE_START_Y;

INT16 gsTopLeftWorldX, gsTopLeftWorldY;
INT16 gsTopRightWorldX, gsTopRightWorldY;
INT16 gsBottomLeftWorldX, gsBottomLeftWorldY;
INT16 gsBottomRightWorldX, gsBottomRightWorldY;
BOOLEAN gfIgnoreScrolling = FALSE;

// WANNE: If we are talking?
// This check is used, to prevent scrolling in small maps (e.g: Rebel Basement) in higher resolution (1024x768) [2007-05-14]
BOOLEAN gfDialogControl = FALSE;

BOOLEAN	gfIgnoreScrollDueToCenterAdjust = FALSE;

// GLOBAL SCROLLING PARAMS
INT16	gTopLeftWorldLimitX,		gTopLeftWorldLimitY;
INT16	gTopRightWorldLimitX,		gTopRightWorldLimitY;
INT16	gBottomLeftWorldLimitX,		gBottomLeftWorldLimitY;
INT16	gBottomRightWorldLimitX,	gBottomRightWorldLimitY;
INT16	Slide,						gCenterWorldY;
INT16	gsTLX,		gsTLY,			gsTRX,		gsTRY;
INT16	gsBLX,		gsBLY,			gsBRX,		gsBRY;
INT16	gsCX,		gsCY;
DOUBLE	gdScaleX,	gdScaleY;

#define FASTMAPROWCOLTOPOS( r, c )		( (r) * WORLD_COLS + (c) )

BOOLEAN	gfScrollInertia = FALSE;

// GLOBALS FOR CALCULATING STARTING PARAMETERS
INT16	gsStartPointX_W,	gsStartPointY_W;
INT16	gsStartPointX_S,	gsStartPointY_S;
INT16	gsStartPointX_M,	gsStartPointY_M;
INT16	gsEndXS,			gsEndYS;
// LARGER OFFSET VERSION FOR GIVEN LAYERS
INT16	gsLStartPointX_W,	gsLStartPointY_W;
INT16	gsLStartPointX_S,	gsLStartPointY_S;
INT16	gsLStartPointX_M,	gsLStartPointY_M;
INT16	gsLEndXS,			gsLEndYS;

BOOLEAN	gfRenderScroll = FALSE;
BOOLEAN	gfScrollStart  = FALSE;
INT16	gsScrollXIncrement;
INT16	gsScrollYIncrement;
INT32	guiScrollDirection;

// Rendering flags (full, partial, etc.)
UINT32		gRenderFlags=0;

/*  You know it was static and now it will be dynamic :P
 *  any questions? joker
 */
SGPRect		gClippingRect;//			= { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT - INTERFACE_HEIGHT};
SGPRect		gOldClipRect = { 0, 0, 1024, 768 }; // 0verhaul:  This MUST mirror the gDirtyClipRect init, otherwise funkiness with video overlays will happen
INT16		gsRenderCenterX;
INT16		gsRenderCenterY;
INT16		gsRenderWorldOffsetX	= 0;  //lal was -1 : bugfix for merc screen position in tactical on high resolution
INT16		gsRenderWorldOffsetY	= 10; //lal was -1
SGPRect		gSelectRegion;
UINT32		fSelectMode				= NO_SELECT;
SGPPoint	gSelectAnchor;

typedef struct
{
	BOOLEAN	fDynamic;
	BOOLEAN	fZWrite;
	BOOLEAN	fZBlitter;
	BOOLEAN fShadowBlitter;
	BOOLEAN fLinkedListDirection;
	BOOLEAN fMerc;
	BOOLEAN	fCheckForRedundency;
	BOOLEAN	fMultiZBlitter;
	BOOLEAN fConvertTo16;
	BOOLEAN	fObscured;
} RenderFXType;

RenderFXType RenderFX[] =
{
	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE, 	// STATIC LAND
	FALSE,	TRUE,	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	// STATIC OBJECTS
	FALSE,	TRUE,	TRUE,	TRUE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	// STATIC SHADOWS
	FALSE,	TRUE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	TRUE,	// STATIC STRUCTS
	FALSE,	TRUE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	// STATIC ROOF
	FALSE,	TRUE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	TRUE,	// STATIC ONROOF
	FALSE,	TRUE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	// STATIC TOPMOST
	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	// DYNAMIC LAND
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	// DYNAMIC OBJECT
	TRUE,	FALSE,	FALSE,	TRUE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	// DYNAMIC SHADOW
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	// DYNAMIC STRUCT MERCS
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	// DYNAMIC MERCS
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	// DYNAMIC STRUCT
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	// DYNAMIC ROOF
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	// DYNAMIC HIGHMERCS
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE,	// DYNAMIC ONROOF
	TRUE,	FALSE,	TRUE,	FALSE,	TRUE,	FALSE,	FALSE,	FALSE,	FALSE,	FALSE	// DYNAMIC TOPMOST
};

UINT8 RenderFXStartIndex[] =
{
	LAND_START_INDEX,		// STATIC LAND
	OBJECT_START_INDEX,		// STATIC OBJECTS
	SHADOW_START_INDEX,		// STATIC SHADOWS
	STRUCT_START_INDEX,		// STATIC STRUCTS
	ROOF_START_INDEX,		// STATIC ROOF
	ONROOF_START_INDEX,		// STATIC ONROOF
	TOPMOST_START_INDEX,	// STATIC TOPMOST
	LAND_START_INDEX,		// DYNAMIC LAND
	OBJECT_START_INDEX,		// DYNAMIC OBJECT
	SHADOW_START_INDEX,		// DYNAMIC SHADOW
	MERC_START_INDEX,		// DYNAMIC STRUCT MERCS
	MERC_START_INDEX,		// DYNAMIC MERCS
	STRUCT_START_INDEX,		// DYNAMIC STRUCT
	ROOF_START_INDEX,		// DYNAMIC ROOF
	MERC_START_INDEX,		// DYNAMIC HIGHMERCS
	ONROOF_START_INDEX,		// DYNAMIC ONROOF
	TOPMOST_START_INDEX,	// DYNAMIC TOPMOST
};


//INT16 gsCoordArray[ 500 ][ 500 ][ 4 ];
//INT16 gsCoordArrayX;
//INT16 gsCoordArrayY;
//void SetRenderGlobals( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );
//void TempRenderTiles(UINT32 uiFlags, INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );
//void TempRenderTiles(UINT32 uiFlags, INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS, UINT8 ubNumLevels, UINT32 *puiLevels );

void ExamineZBufferForHiddenTiles( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );

//void ReRenderWorld(INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom);
void ClearMarkedTiles(void);
void CorrectRenderCenter( INT16 sRenderX, INT16 sRenderY, INT16 *pSNewX, INT16 *pSNewY );
void ScrollBackground(UINT32 uiDirection, INT16 sScrollXIncrement, INT16 sScrollYIncrement );
void CalcRenderParameters(INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom );
void ResetRenderParameters(  );


void RenderRoomInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );


#ifdef _DEBUG
//extern UINT8 gubFOVDebugInfoInfo[ WORLD_MAX ];
//extern UINT8 gubGridNoMarkers[ WORLD_MAX ];
extern UINT8 * gubFOVDebugInfoInfo;
extern UINT8 * gubGridNoMarkers;
extern UINT8 gubGridNoValue;
extern BOOLEAN gfDisplayCoverValues;
extern BOOLEAN gfDisplayGridNoVisibleValues = 0;
//extern INT16	gsCoverValue[ WORLD_MAX ];
extern INT16 *	gsCoverValue;
extern INT16	gsBestCover;
void RenderFOVDebugInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );
void RenderCoverDebugInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );
void RenderGridNoVisibleDebugInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );
#endif

void DeleteFromWorld( UINT16 usTileIndex, UINT32 uiRenderTiles, UINT16 usIndex );

void RenderHighlight( INT16 sMouseX_M, INT16 sMouseY_M, INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );
BOOLEAN CheckRenderCenter( INT16 sNewCenterX, INT16 sNewCenterY );

BOOLEAN RevealWalls(INT16 sX, INT16 sY, INT16 sRadius)
{
LEVELNODE *pStruct;
INT16 sCountX, sCountY;
UINT32 uiTile;
BOOLEAN fRerender=FALSE;
TILE_ELEMENT *TileElem;

	for(sCountY=sY-sRadius; sCountY < (sY+sRadius+2); sCountY++)
		for(sCountX=sX-sRadius; sCountX < (sX+sRadius+2); sCountX++)
		{
			uiTile=FASTMAPROWCOLTOPOS(sCountY, sCountX);
			pStruct=gpWorldLevelData[uiTile].pStructHead;

			while(pStruct!=NULL)
			{
				TileElem = &(gTileDatabase[pStruct->usIndex]);
				switch(TileElem->usWallOrientation)
				{
					case NO_ORIENTATION:
						break;

					case INSIDE_TOP_RIGHT:
					case OUTSIDE_TOP_RIGHT:
						if(sCountX >= sX)
						{
							pStruct->uiFlags|=LEVELNODE_REVEAL;
							fRerender=TRUE;
						}
						break;

					case INSIDE_TOP_LEFT:
					case OUTSIDE_TOP_LEFT:
						if(sCountY >= sY)
						{
							pStruct->uiFlags|=LEVELNODE_REVEAL;
							fRerender=TRUE;
						}
						break;
				}
				pStruct=pStruct->pNext;
			}
		}

/*
	if(fRerender)
		SetRenderFlags(RENDER_FLAG_FULL);
*/

	return(TRUE);
}

BOOLEAN ConcealWalls(INT16 sX, INT16 sY, INT16 sRadius)
{
LEVELNODE *pStruct;
INT16 sCountX, sCountY;
UINT32 uiTile;
BOOLEAN fRerender=FALSE;
TILE_ELEMENT *TileElem;


	for(sCountY=sY-sRadius; sCountY < (sY+sRadius+2); sCountY++)
		for(sCountX=sX-sRadius; sCountX < (sX+sRadius+2); sCountX++)
		{
			uiTile=FASTMAPROWCOLTOPOS(sCountY, sCountX);
			pStruct=gpWorldLevelData[uiTile].pStructHead;

			while(pStruct!=NULL)
			{
				TileElem = &(gTileDatabase[pStruct->usIndex]);
				switch(TileElem->usWallOrientation)
				{
					case NO_ORIENTATION:
						break;

					case INSIDE_TOP_RIGHT:
					case OUTSIDE_TOP_RIGHT:
						if(sCountX >= sX)
						{
							pStruct->uiFlags&=(~LEVELNODE_REVEAL);
							fRerender=TRUE;
						}
						break;

					case INSIDE_TOP_LEFT:
					case OUTSIDE_TOP_LEFT:
						if(sCountY >= sY)
						{
							pStruct->uiFlags&=(~LEVELNODE_REVEAL);
							fRerender=TRUE;
						}
						break;
				}
				pStruct=pStruct->pNext;
			}
		}

/*
	if(fRerender)
		SetRenderFlags(RENDER_FLAG_FULL);
*/

	return(TRUE);

}

void ConcealAllWalls(void)
{
LEVELNODE *pStruct;
INT32 uiCount;

	for(uiCount=0; uiCount < WORLD_MAX; uiCount++)
	{
		pStruct=gpWorldLevelData[uiCount].pStructHead;
		while(pStruct!=NULL)
		{
			pStruct->uiFlags&=(~LEVELNODE_REVEAL);
			pStruct=pStruct->pNext;
		}
	}
}


void ResetLayerOptimizing(void)
{
	uiLayerUsedFlags = 0xffffffff;
	uiAdditiveLayerUsedFlags = 0;
}

void ResetSpecificLayerOptimizing( UINT32 uiRowFlag )
{
	uiLayerUsedFlags |= uiRowFlag;
}


void SumAddiviveLayerOptimization( void )
{
	uiLayerUsedFlags = uiAdditiveLayerUsedFlags;
}

void SetRenderFlags(UINT32 uiFlags)
{
	gRenderFlags|=uiFlags;
}

void ClearRenderFlags(UINT32 uiFlags)
{
	gRenderFlags&=(~uiFlags);
}

UINT32 GetRenderFlags(void)
{
	return(gRenderFlags);
}

void RenderSetShadows(BOOLEAN fShadows)
{
	if(fShadows)
	{
		gRenderFlags|=RENDER_FLAG_SHADOWS;
	}
	else
	{
		gRenderFlags&=(~RENDER_FLAG_SHADOWS);
}
}



void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT32 iStartPointX_S, INT32 iStartPointY_S, INT32 iEndXS, INT32 iEndYS, UINT8 ubNumLevels, UINT32 *puiLevels, UINT16 *psLevelIDs )
{

//#if 0

	LEVELNODE		*pNode; //, *pLand, *pStruct; //*pObject, *pTopmost, *pMerc;
	SOLDIERTYPE	*pSoldier, *pSelSoldier;
	HVOBJECT		hVObject = NULL;
	ETRLEObject *pTrav;
	TILE_ELEMENT *TileElem=NULL;
	UINT32			uiDestPitchBYTES = 0;
	UINT8				*pDestBuf=NULL;
	UINT16			usAnimSurface;
	INT8				bXOddFlag = 0;
	INT32				iAnchorPosX_M, iAnchorPosY_M;
	INT32				iAnchorPosX_S, iAnchorPosY_S;
	INT32				iTempPosX_M, iTempPosY_M;
	INT32				iTempPosX_S, iTempPosY_S;
	FLOAT				dOffsetX, dOffsetY;
	FLOAT				dTempX_S, dTempY_S;
	INT32			uiTileIndex;
	UINT16			usImageIndex, *pShadeTable, *pDirtyBackPtr;
	UINT32			uiBrushWidth, uiBrushHeight, uiDirtyFlags;
	INT16				sTileHeight, sXPos, sYPos, sZLevel;
	INT16				sMouseX_M, sMouseY_M;
	BOOLEAN			fShadowBlitter=FALSE;
	BOOLEAN			fZBlitter=FALSE;
	BOOLEAN			fZWrite=FALSE;
	BOOLEAN			fLinkedListDirection=TRUE;
	BOOLEAN			fRenderTile=TRUE;
	BOOLEAN			fMerc=FALSE;
	BOOLEAN			fCheckForRedundency=FALSE;
	UINT32			uiRowFlags;
	BOOLEAN			fDynamic=TRUE;
	BOOLEAN			fEndRenderRow = FALSE;
	BOOLEAN			fEndRenderCol = FALSE;
	BOOLEAN			fPixelate=FALSE;
	BOOLEAN			fMultiZBlitter = FALSE;
	BOOLEAN			fWallTile = FALSE;
	BOOLEAN			fMultiTransShadowZBlitter = FALSE;
	INT16				sMultiTransShadowZBlitterIndex=-1;
	BOOLEAN			fTranslucencyType=FALSE;
	INT16				sX, sY;
	BOOLEAN			fTileInvisible = FALSE;
	BOOLEAN			fConvertTo16=FALSE;
	UINT32			cnt;
	static			UINT8				ubLevelNodeStartIndex[ NUM_RENDER_FX_TYPES ];
	BOOLEAN			bItemOutline;
	UINT16			usOutlineColor=0;

	static			INT32				iTileMapPos[ 500 ];
	INT32			uiMapPosIndex;
	UINT8				bBlitClipVal;
	INT8				bItemCount, bVisibleItemCount;
	//UINT16			us16BPPIndex;
	RenderFXType  RenderingFX;
	BOOLEAN				fCheckForMouseDetections = FALSE;
	static				RenderFXType  RenderFXList[ NUM_RENDER_FX_TYPES ];
	BOOLEAN				fSaveZ;
	INT16					sWorldY;
	INT16					sZOffsetX=-1;
	INT16					sZOffsetY=-1;
	BOOLEAN				fIntensityBlitter;
	INT16						gsForceSoldierZLevel;
	ROTTING_CORPSE	*pCorpse=NULL;
	BOOLEAN				fUseTileElem;
	UINT32				uiLevelNodeFlags;
	UINT32				uiTileElemFlags=0;
	INT8					bGlowShadeOffset;
	BOOLEAN				fObscured;
	BOOLEAN				fObscuredBlitter;
	INT16					sModifiedTileHeight;
	BOOLEAN				fDoRow;
	INT16					**pShadeStart;

	UINT32				uiSaveBufferPitchBYTES;
	UINT8					*pSaveBuf;
	ITEM_POOL			*pItemPool = NULL;
	BOOLEAN				fHiddenTile = FALSE;
  UINT32        uiAniTileFlags = 0;
	INT16					sZStripIndex;

	//Init some variables
	usImageIndex = 0;
	sZLevel = 0;
	uiDirtyFlags = 0;
	pShadeTable = NULL;

	// Begin Render Loop
	iAnchorPosX_M = iStartPointX_M;
	iAnchorPosY_M = iStartPointY_M;
	iAnchorPosX_S = iStartPointX_S;
	iAnchorPosY_S = iStartPointY_S;

	if(!(uiFlags&TILES_DIRTY))
		pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );


	if ( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE )
	{
		if ( ShouldCheckForMouseDetections( ) )
		{
			BeginCurInteractiveTileCheck( gubIntTileCheckFlags );
			fCheckForMouseDetections = TRUE;

			// If we are in edit mode, don't do this...
			if ( gfEditMode )
			{
				fCheckForMouseDetections = FALSE;
			}
		}
	}

	//if((uiFlags&TILES_TYPE_MASK)==TILES_STATIC_LAND)
	GetMouseXY( &sMouseX_M, &sMouseY_M );

	pDirtyBackPtr=NULL;

	if(gTacticalStatus.uiFlags&TRANSLUCENCY_TYPE)
		fTranslucencyType=TRUE;

	for ( cnt = 0; cnt < ubNumLevels; cnt++ )
	{
			ubLevelNodeStartIndex[ cnt ] = RenderFXStartIndex[ psLevelIDs[ cnt ] ];
			RenderFXList[ cnt ]					 = RenderFX[ psLevelIDs[ cnt ] ];
	}

	do
	{

		iTempPosX_M = iAnchorPosX_M;
		iTempPosY_M = iAnchorPosY_M;
		iTempPosX_S = iAnchorPosX_S;
		iTempPosY_S = iAnchorPosY_S;

		uiMapPosIndex = 0;

		// Build tile index list
		do
		{
				iTileMapPos[ uiMapPosIndex ] = FASTMAPROWCOLTOPOS( iTempPosY_M, iTempPosX_M );

				iTempPosX_S += 40;
				iTempPosX_M ++;
				iTempPosY_M --;

				uiMapPosIndex++;

		} while( iTempPosX_S < iEndXS );



		for ( cnt = 0; cnt < ubNumLevels; cnt++ )
		{

			uiRowFlags = puiLevels[ cnt ];
			fDoRow		 = TRUE;

			if ( ( uiRowFlags & TILES_ALL_DYNAMICS ) && !( uiLayerUsedFlags & uiRowFlags ) && !( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE ) )
			{
				fDoRow = FALSE;
			}

			if ( fDoRow )
			{
				iTempPosX_M = iAnchorPosX_M;
				iTempPosY_M = iAnchorPosY_M;
				iTempPosX_S = iAnchorPosX_S;
				iTempPosY_S = iAnchorPosY_S;

				fEndRenderRow	= FALSE;
				uiMapPosIndex = 0;


				if(bXOddFlag > 0)
					iTempPosX_S += 20;

				do
				{

					uiTileIndex = iTileMapPos[ uiMapPosIndex ];
					uiMapPosIndex++;

					//if ( 0 )					
					if (!TileIsOutOfBounds(uiTileIndex))
					{
						// OK, we're searching through this loop anyway, might as well check for mouse position
						// over objects...
						// Experimental!
						if ( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE )
						{
							if ( fCheckForMouseDetections && gpWorldLevelData[uiTileIndex].pStructHead != NULL )
							{
								LogMouseOverInteractiveTile( uiTileIndex );
							}
						}

						if((uiFlags&TILES_MARKED) && !(gpWorldLevelData[uiTileIndex].uiFlags&MAPELEMENT_REDRAW))
						{
							pNode=NULL;
						}
						else
						{
							//pNode = gpWorldLevelData[ uiTileIndex ].pLevelNodes[ RenderFXStartIndex[ psLevelIDs[ cnt ] ] ];
							//pNode = gpWorldLevelData[ uiTileIndex ].pLevelNodes[ 0 ];
							//pNode=NULL;
							pNode = gpWorldLevelData[ uiTileIndex ].pLevelNodes[ ubLevelNodeStartIndex[ cnt ] ];
						}

						bItemCount = 0;
						bVisibleItemCount = 0;
						pItemPool  = NULL;

						while(pNode!= NULL)
						{

							RenderingFX						= RenderFXList[ cnt ];

							fObscured							= RenderingFX.fObscured;
							fDynamic							= RenderingFX.fDynamic;

							fMerc									= RenderingFX.fMerc;
							fZWrite								= RenderingFX.fZWrite;
							fZBlitter							= RenderingFX.fZBlitter;
							fShadowBlitter				= RenderingFX.fShadowBlitter;
							fLinkedListDirection	= RenderingFX.fLinkedListDirection;
							fCheckForRedundency		= RenderingFX.fCheckForRedundency;
							fMultiZBlitter				= RenderingFX.fMultiZBlitter;
							fConvertTo16					= RenderingFX.fConvertTo16;
							fIntensityBlitter			= FALSE;
							fSaveZ								= FALSE;
							fWallTile							= FALSE;
							gsForceSoldierZLevel	= FALSE;
							pSoldier							= NULL;
							fUseTileElem								= FALSE;
							fMultiTransShadowZBlitter		= FALSE;
							fObscuredBlitter						= FALSE;
							fTranslucencyType						= TRUE;
              uiAniTileFlags        = 0;
							sZStripIndex					= -1;

							uiLevelNodeFlags			= pNode->uiFlags;

							if ( fCheckForRedundency )
							{
								if ( ( gpWorldLevelData[ uiTileIndex ].uiFlags & MAPELEMENT_REDUNDENT) )
								{
									// IF WE DONOT WANT TO RE-EVALUATE FIRST
									if ( !( gpWorldLevelData[uiTileIndex].uiFlags & MAPELEMENT_REEVALUATE_REDUNDENCY ) && !(gTacticalStatus.uiFlags & NOHIDE_REDUNDENCY ) )
									{
										pNode = NULL;
										break;
									}
								}
							}

							// Force z-buffer blitting for marked tiles ( even ground!)
							if ( (uiFlags&TILES_MARKED) )
							{
								fZBlitter							= TRUE;
							}


							//Looking up height every time here is alot better than doing it above!
							sTileHeight=gpWorldLevelData[uiTileIndex].sHeight;

							sModifiedTileHeight = ( ( ( sTileHeight / 80 ) - 1 ) * 80 );

							if ( sModifiedTileHeight < 0 )
							{
								sModifiedTileHeight = 0;
							}


							fRenderTile=TRUE;
							pDirtyBackPtr=NULL;
							if(uiLevelNodeFlags&LEVELNODE_REVEAL)
							{
								if(!fDynamic)
									fRenderTile=FALSE;
								else
									fPixelate=TRUE;
							}
							else
								fPixelate=FALSE;

							// non-type specific setup
							sXPos = (INT16)iTempPosX_S;
							sYPos = (INT16)iTempPosY_S;


							// setup for any tile type except mercs
							if(!fMerc )
							{
									if ( !( uiLevelNodeFlags & ( LEVELNODE_ROTTINGCORPSE | LEVELNODE_CACHEDANITILE ) ) )
									{
										if( ( uiLevelNodeFlags & LEVELNODE_REVEALTREES ) )
										{
											TileElem = &(gTileDatabase[pNode->usIndex + 2]);
										}
										else
										{
											TileElem = &(gTileDatabase[pNode->usIndex]);
										}

										// HANDLE INDEPENDANT-PER-TILE ANIMATIONS ( IE: DOORS, EXPLODING THINGS, ETC )
										if ( fDynamic )
										{
											if( ( uiLevelNodeFlags & LEVELNODE_ANIMATION ) )
											{
												if ( pNode->sCurrentFrame != -1 )
												{
														Assert( TileElem->pAnimData != NULL );
														TileElem = &gTileDatabase[TileElem->pAnimData->pusFrames[pNode->sCurrentFrame]];
												}
											}
										}
									}

									// Check for best translucency
									if ( uiLevelNodeFlags & LEVELNODE_USEBESTTRANSTYPE )
									{
										fTranslucencyType = FALSE;
									}

									if ( ( uiLevelNodeFlags & ( LEVELNODE_ROTTINGCORPSE | LEVELNODE_CACHEDANITILE ) ) )
									{
										if ( fDynamic )
										{
											if( !(uiLevelNodeFlags & ( LEVELNODE_DYNAMIC ) ) && !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC)  )
												fRenderTile=FALSE;
										}
										else if( (uiLevelNodeFlags & ( LEVELNODE_DYNAMIC ) ) )
											fRenderTile=FALSE;
									}
									else
									{
										// Set Tile elem flags here!
										uiTileElemFlags	= TileElem->uiFlags;
										// Set valid tile elem!
										fUseTileElem = TRUE;

										if(fDynamic || fPixelate)
										{
											if(!fPixelate)
											{
													if(!( uiTileElemFlags & ANIMATED_TILE) && !(uiTileElemFlags & DYNAMIC_TILE) && !(uiLevelNodeFlags & LEVELNODE_DYNAMIC) && !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC)  )
														fRenderTile=FALSE;
													else if(!(uiTileElemFlags&DYNAMIC_TILE) && !(uiLevelNodeFlags&LEVELNODE_DYNAMIC) && !(uiLevelNodeFlags&LEVELNODE_LASTDYNAMIC) )
												//	else if((TileElem->uiFlags&ANIMATED_TILE) )
													{
														Assert( TileElem->pAnimData != NULL );
														TileElem = &gTileDatabase[TileElem->pAnimData->pusFrames[TileElem->pAnimData->bCurrentFrame]];
														uiTileElemFlags = TileElem->uiFlags;
													}
											}

										}
										else if((uiTileElemFlags & ANIMATED_TILE) || (uiTileElemFlags & DYNAMIC_TILE) || (uiLevelNodeFlags & LEVELNODE_DYNAMIC) )
										{
											if ( !( uiFlags & TILES_OBSCURED ) || ( uiTileElemFlags & ANIMATED_TILE ) )
											{
												fRenderTile=FALSE;
											}
										}
									}

									// OK, ATE, CHECK FOR AN OBSCURED TILE AND MAKE SURE IF LEVELNODE IS SET
									// WE DON'T RENDER UNLESS WE HAVE THE RENDER FLAG SET!
									if ( fObscured )
									{
										if ( ( uiFlags & TILES_OBSCURED ) )
										{
											  if ( uiLevelNodeFlags & LEVELNODE_SHOW_THROUGH )
												{
													fObscuredBlitter = TRUE;

													// ATE: Check if this is a levelnode, and what frame we are on
													// turn off......
													//if ( ( uiLevelNodeFlags & LEVELNODE_ITEM ) && gsCurrentItemGlowFrame < 25 )
													//{
													//	fRenderTile = FALSE;
													//}
												}
												else
												{
													// Don;t render if we are not on this render loop!
													fRenderTile = FALSE;
												}
										}
										else
										{
											 if ( uiLevelNodeFlags & LEVELNODE_SHOW_THROUGH )
											 {
													fRenderTile = FALSE;

													// ATE: Check if this is a levelnode, and what frame we are on
													// turn off......
													//if ( ( uiLevelNodeFlags & LEVELNODE_ITEM ) && gsCurrentItemGlowFrame < 25 )
													//{
													//	fRenderTile = TRUE;
													//}
											 }
										}
									}


									// If flag says to do dynamic as well, render!
									if ( ( uiFlags & TILES_DOALL ) )
									{
										fRenderTile = TRUE;
									}

									// If we are on the struct layer, check for if it's hidden!
									if ( uiRowFlags & ( TILES_STATIC_STRUCTURES | TILES_DYNAMIC_STRUCTURES | TILES_STATIC_SHADOWS | TILES_DYNAMIC_SHADOWS ) )
									{
										if ( fUseTileElem )
										{
#if 0
											// DONOT RENDER IF IT'S A HIDDEN STRUCT AND TILE IS NOT REVEALED
											if ( uiTileElemFlags & HIDDEN_TILE )
											{
												// IF WORLD IS NOT REVEALED, QUIT
												#ifdef JA2EDITOR
												if ( !gfEditMode )
												#endif
												{
													if ( !(gpWorldLevelData[ uiTileIndex ].uiFlags & MAPELEMENT_REVEALED ) && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) )
													{
														//CONTINUE, DONOT RENDER
														if(!fLinkedListDirection)
															pNode = pNode->pPrevNode;
														else
															pNode = pNode->pNext;

														continue;
													}
												}
											}
#endif
										}
									}

									if(fRenderTile)
									{
										// Set flag to set layer as used
										if( fDynamic || fPixelate )
										{
											uiAdditiveLayerUsedFlags |= uiRowFlags;
										}

										if ( uiLevelNodeFlags & LEVELNODE_DYNAMICZ )
										{
											fSaveZ = TRUE;
											fZWrite = TRUE;
										}

										if ( ( uiLevelNodeFlags & LEVELNODE_CACHEDANITILE ) )
										{
											hVObject		 = gpTileCache[ pNode->pAniTile->sCachedTileID ].pImagery->vo;
											usImageIndex = pNode->pAniTile->sCurrentFrame;
                      uiAniTileFlags = pNode->pAniTile->uiFlags;

											// Position corpse based on its float position
											if ( ( uiLevelNodeFlags & LEVELNODE_ROTTINGCORPSE ) )
											{
												pCorpse = &( gRottingCorpse[ pNode->pAniTile->uiUserData ] );

												pShadeTable = pCorpse->pShades[ pNode->ubShadeLevel ];

												//pShadeTable = pCorpse->p16BPPPalette;

												dOffsetX = pCorpse->def.dXPos - gsRenderCenterX;
												dOffsetY = pCorpse->def.dYPos - gsRenderCenterY;

												// OK, if this is a corpse.... stop if not visible
												if ( pCorpse->def.bVisible != 1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) )
												{
													//CONTINUE, DONOT RENDER
													if(!fLinkedListDirection)
														pNode = pNode->pPrevNode;
													else
														pNode = pNode->pNext;

													continue;
												}
											}
											else
											{
												dOffsetX = (FLOAT)( pNode->pAniTile->sRelativeX - gsRenderCenterX );
												dOffsetY = (FLOAT)( pNode->pAniTile->sRelativeY - gsRenderCenterY );
											}

											// Calculate guy's position
											FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &dTempX_S, &dTempY_S );

											sXPos = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)dTempX_S;
											sYPos = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)dTempY_S - sTileHeight;

											// Adjust for offset position on screen
											sXPos -= gsRenderWorldOffsetX;
											sYPos -= gsRenderWorldOffsetY;

										}
										else
										{
											hVObject = TileElem->hTileSurface;
											usImageIndex=TileElem->usRegionIndex;

											// ADJUST FOR WORLD MAPELEM HIEGHT
											sYPos-=TileElem->sOffsetHeight;

											if((TileElem->uiFlags&IGNORE_WORLD_HEIGHT) )
											{
												sYPos = sYPos - sModifiedTileHeight;
												//sYPos -= sTileHeight;
											}

											if( !(uiLevelNodeFlags&LEVELNODE_IGNOREHEIGHT) && !(TileElem->uiFlags&IGNORE_WORLD_HEIGHT ))
												sYPos-=sTileHeight;

											if(!(uiFlags&TILES_DIRTY))
											{
												hVObject->pShadeCurrent=hVObject->pShades[pNode->ubShadeLevel];
												hVObject->pShade8=ubColorTables[pNode->ubShadeLevel];
											}

										}


										//ADJUST FOR RELATIVE OFFSETS
										if ( uiLevelNodeFlags & LEVELNODE_USERELPOS )
										{
											sXPos += pNode->sRelativeX;
											sYPos += pNode->sRelativeY;
										}

										if ( uiLevelNodeFlags& LEVELNODE_USEZ )
										{
											sYPos -= pNode->sRelativeZ;
										}

										//ADJUST FOR ABSOLUTE POSITIONING
										if ( uiLevelNodeFlags& LEVELNODE_USEABSOLUTEPOS )
										{
											dOffsetX = (FLOAT)(pNode->sRelativeX - gsRenderCenterX);
											dOffsetY = (FLOAT)(pNode->sRelativeY - gsRenderCenterY);

											// OK, DONT'T ASK... CONVERSION TO PROPER Y NEEDS THIS...
											dOffsetX -= CELL_Y_SIZE;

											FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &dTempX_S, &dTempY_S );

											sXPos = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)SHORT_ROUND( dTempX_S );
											sYPos = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)SHORT_ROUND( dTempY_S );

											// Adjust for offset position on screen
											sXPos -= gsRenderWorldOffsetX;
											sYPos -= gsRenderWorldOffsetY;


											sYPos -= pNode->sRelativeZ;

										}

									}

									// COUNT # OF ITEMS AT THIS LOCATION
									if ( uiLevelNodeFlags & LEVELNODE_ITEM )
									{
										// OK set item pool for this location....
										if ( bItemCount == 0 )
										{
											pItemPool = pNode->pItemPool;
										}
										else
										{
											pItemPool = pItemPool->pNext;
										}

										if ( bItemCount < MAX_RENDERED_ITEMS  )
										{
											bItemCount++;

											if ( gWorldItems[ pItemPool->iItemIndex ].bVisible == VISIBLE )
											{
												bVisibleItemCount++;
											}
										}

										// LIMIT RENDERING OF ITEMS TO ABOUT 7, DO NOT RENDER HIDDEN ITEMS TOO!
										if ( bVisibleItemCount == MAX_RENDERED_ITEMS || ( gWorldItems[ pItemPool->iItemIndex ].bVisible != VISIBLE ) || ( pItemPool->usFlags & WORLD_ITEM_DONTRENDER ) )
										{
											if ( !(gTacticalStatus.uiFlags&SHOW_ALL_ITEMS) )
											{
												//CONTINUE, DONOT RENDER
												if(!fLinkedListDirection)
													pNode = pNode->pPrevNode;
												else
													pNode = pNode->pNext;
												continue;
											}
										}

										if ( guiCurrentScreen == EDIT_SCREEN )
										{
											// ATE: If in the editor, change this to a little higher value
											if ( bItemCount == MAX_RENDERED_ITEMS )
											{
												//CONTINUE, DONOT RENDER
												if(!fLinkedListDirection)
													pNode = pNode->pPrevNode;
												else
													pNode = pNode->pNext;
												continue;
											}
										}
										if ( pItemPool->bRenderZHeightAboveLevel > 0 )
										{
											sYPos -= pItemPool->bRenderZHeightAboveLevel;
										}

									}

									// If render tile is false...
									if ( !fRenderTile )
									{
										if(!fLinkedListDirection)
											pNode = pNode->pPrevNode;
										else
											pNode = pNode->pNext;

										continue;
									}
							}

							// specific code for node types on a per-tile basis
							switch( uiRowFlags )
							{
								case TILES_STATIC_LAND:

									sZLevel = LandZLevel( iTempPosX_M, iTempPosY_M );
									break;

								case TILES_STATIC_OBJECTS:

									// ATE: Modified to use constant z level, as these are same level as land items
									sZLevel = ObjectZLevel( TileElem, pNode, uiTileElemFlags, iTempPosX_M, iTempPosY_M, sWorldY );
									break;

								case TILES_STATIC_STRUCTURES:

									StructZLevel( iTempPosX_M, iTempPosY_M );

									if ( fUseTileElem && ( TileElem->uiFlags & MULTI_Z_TILE ) )
									{
										fMultiZBlitter = TRUE;
									}

									// ATE: if we are a wall, set flag
									if ( fUseTileElem && ( TileElem->uiFlags & WALL_TILE ) )
									{
										fWallTile = TRUE;
									}

									break;

								case TILES_STATIC_ROOF:

									sZLevel = RoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY );

									// Automatically adjust height!
									sYPos -= WALL_HEIGHT;

									// ATE: Added for shadows on roofs
									if ( fUseTileElem && ( TileElem->uiFlags & ROOFSHADOW_TILE ) )
									{
										fShadowBlitter=TRUE;
									}
									break;
								case TILES_STATIC_ONROOF:

									sZLevel = OnRoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY, uiLevelNodeFlags );
									// Automatically adjust height!
									sYPos -= WALL_HEIGHT;
									break;

								case TILES_STATIC_TOPMOST:

									sZLevel = TopmostZLevel( iTempPosX_M, iTempPosY_M, sWorldY );
									break;

								case TILES_STATIC_SHADOWS:

									sZLevel = ShadowZLevel( iTempPosX_M, iTempPosY_M, sWorldY );

									if ( uiLevelNodeFlags & LEVELNODE_EXITGRID )
									{
										fIntensityBlitter = TRUE;
										fShadowBlitter		= FALSE;
									}
									break;

								case TILES_DYNAMIC_LAND:

									sZLevel = LandZLevel( iTempPosX_M, iTempPosY_M );
									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED;
									break;
								case TILES_DYNAMIC_SHADOWS:

									sZLevel = ShadowZLevel( iTempPosX_M, iTempPosY_M, sWorldY );
									//sZLevel=SHADOW_Z_LEVEL;
									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED;
									break;
								case TILES_DYNAMIC_OBJECTS:

									sZLevel = ObjectZLevel( TileElem, pNode, uiTileElemFlags, iTempPosX_M, iTempPosY_M, sWorldY );
									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED;
									break;

								case TILES_DYNAMIC_STRUCTURES:

									StructZLevel( iTempPosX_M, iTempPosY_M );
									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED;

									if ( uiTileElemFlags & Z_AWARE_DYNAMIC_TILE )
									{
										fMultiZBlitter = TRUE;
										fZBlitter = TRUE;
										fWallTile = TRUE;
										sZStripIndex = 0;
									}
									break;
								case TILES_DYNAMIC_ROOF:

									sYPos -= WALL_HEIGHT;

									sZLevel = RoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY );
									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED;
									// For now, adjust to hieght of a wall ( 50 temp, make define )
									//if ( TileElem->fType > FOOTPRINTS )
									//{
									//	sYPos -= 58;
									//}
									break;

								case TILES_DYNAMIC_ONROOF:

									sZLevel = OnRoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY, uiLevelNodeFlags );
									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED;
									// Automatically adjust height!
									sYPos -= WALL_HEIGHT;
									break;

								case TILES_DYNAMIC_TOPMOST:
									sZLevel = TopmostZLevel( iTempPosX_M, iTempPosY_M, sWorldY );
									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED;
									break;

								case TILES_DYNAMIC_MERCS:
								case TILES_DYNAMIC_HIGHMERCS:
								case TILES_DYNAMIC_STRUCT_MERCS:

									// Set flag to set layer as used
									uiAdditiveLayerUsedFlags |= uiRowFlags;

									pSoldier=pNode->pSoldier;

									if ( uiRowFlags == TILES_DYNAMIC_MERCS  )
									{
										// If we are multi-tiled, ignore here
										if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_MULTITILE_Z | SOLDIER_Z ) )
										{
											pNode = pNode->pNext;
											continue;
										}

										// If we are at a higher level, no not do anything unless we are at the highmerc stage
										if ( pSoldier->pathing.bLevel > 0 )
										{
											pNode = pNode->pNext;
											continue;
										}
									}

									if ( uiRowFlags == TILES_DYNAMIC_HIGHMERCS  )
									{
										// If we are multi-tiled, ignore here
										if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE_Z )
										{
											pNode = pNode->pNext;
											continue;
										}

										// If we are at a lower level, no not do anything unless we are at the highmerc stage
										if ( pSoldier->pathing.bLevel == 0  )
										{
											pNode = pNode->pNext;
											continue;
										}
									}


									if ( uiRowFlags == TILES_DYNAMIC_STRUCT_MERCS )
									{
										// If we are not multi-tiled, ignore here
										if ( !( pSoldier->flags.uiStatusFlags & ( SOLDIER_MULTITILE_Z | SOLDIER_Z ) ) )
										{
											// If we are at a low level, no not do anything unless we are at the merc stage
											if ( pSoldier->pathing.bLevel == 0  )
											{
												pNode = pNode->pNext;
												continue;
											}
										}

										if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_MULTITILE_Z | SOLDIER_Z ) )
										{
											fSaveZ													= TRUE;
											fZBlitter												= TRUE;

											if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE_Z )
											{
												fMultiTransShadowZBlitter				= TRUE;
											// ATE: Use one direction for queen!
											if ( pSoldier->ubBodyType == QUEENMONSTER )
											{
												sMultiTransShadowZBlitterIndex = 0;
											}
											else
											{
												sMultiTransShadowZBlitterIndex	= gOneCDirection[ pSoldier->ubDirection ];
											}
											}
											else
											{
												fZWrite = TRUE;
											}
										}

									}

									// IF we are not active, or are a placeholder for multi-tile animations do nothing
									//if ( !pSoldier->bActive  )
									if ( !pSoldier->bActive  || (uiLevelNodeFlags & LEVELNODE_MERCPLACEHOLDER) )
									{
										pNode = pNode->pNext;
										continue;
									}

									// Skip if we cannot see the guy!
									if ( pSoldier->bLastRenderVisibleValue == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS)  )
									{
										pNode = pNode->pNext;
										continue;
									}


									// Get animation surface....
									usAnimSurface = GetSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );

									if ( usAnimSurface == INVALID_ANIMATION_SURFACE )
									{
										pNode = pNode->pNext;
										continue;
									}


									// Shade guy always lighter than sceane default!
									{
										UINT8 ubShadeLevel;

										ubShadeLevel = (pNode->ubShadeLevel&0x0f);
										ubShadeLevel=__max(ubShadeLevel-2, DEFAULT_SHADE_LEVEL);
										ubShadeLevel|=(pNode->ubShadeLevel&0x30);

										if ( pSoldier->flags.fBeginFade )
										{
											pShadeTable = pSoldier->pCurrentShade = pSoldier->pShades[ pSoldier->ubFadeLevel ];
										}
										else
										{
											pShadeTable = pSoldier->pCurrentShade = pSoldier->pShades[ ubShadeLevel];
										}

									}


									// Position guy based on guy's position
									dOffsetX = pSoldier->dXPos - gsRenderCenterX;
									dOffsetY = pSoldier->dYPos - gsRenderCenterY;


									// Calculate guy's position
									FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &dTempX_S, &dTempY_S );

									sXPos = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)dTempX_S;
									sYPos = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)dTempY_S - sTileHeight;

									// Adjust for offset position on screen
									sXPos -= gsRenderWorldOffsetX;
									sYPos -= gsRenderWorldOffsetY;

									// Adjust for soldier height
									sYPos -= pSoldier->sHeightAdjustment;

									// Handle shade stuff....
									if ( !pSoldier->flags.fBeginFade )
									{
										// Special effect - draw ghost if is seen by a guy in player's team but not current guy
										// ATE: Todo: setup flag for 'bad-guy' - can releive some checks in renderer
										if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) )
										{
											if ( gusSelectedSoldier != NOBODY )
											{
												pSelSoldier = MercPtrs[ gusSelectedSoldier ];
											}
											else
											{
												pSelSoldier = NULL;
											}

											bGlowShadeOffset = 0;

											if ( gTacticalStatus.ubCurrentTeam == gbPlayerNum )
											{
												// Shade differently depending on visiblity
												if ( pSoldier->bLastRenderVisibleValue == 0 )
												{
													bGlowShadeOffset = 10;
												}

												if ( pSelSoldier != NULL )
												{
													if ( pSelSoldier->aiData.bOppList[ pSoldier->ubID ] != SEEN_CURRENTLY  )
													{
                            if ( pSoldier->usAnimState != CHARIOTS_OF_FIRE && pSoldier->usAnimState != BODYEXPLODING )
                            {
														  bGlowShadeOffset = 10;
                            }
													}
												}
											}

											if ( pSoldier->pathing.bLevel == 0 )
											{
												pShadeStart = (INT16 **) &( pSoldier->pGlowShades[ 0 ] );
											}
											else
											{
												pShadeStart = (INT16 **) &( pSoldier->pShades[ 20 ] );
											}

											// Set shade
											// If a bad guy is highlighted
											if ( gfUIHandleSelectionAboveGuy == TRUE && MercPtrs[ gsSelectedGuy ]->bSide != gbPlayerNum )
											{
												if ( gsSelectedGuy == pSoldier->ubID )
												{
													pShadeTable = (UINT16 *) pShadeStart[ gsGlowFrames[ gsCurrentGlowFrame ] + bGlowShadeOffset ];
													gsForceSoldierZLevel = TOPMOST_Z_LEVEL;
												}
												else
												{
													// Are we dealing with a not-so visible merc?
													if ( bGlowShadeOffset == 10 )
													{
														pShadeTable = pSoldier->pEffectShades[ 0 ];
													}
												}
											}
											else
											{
												// OK,not highlighted, but maybe we are in enemy's turn and they have the baton

												// AI's turn?
												if ( gTacticalStatus.ubCurrentTeam != OUR_TEAM )
												{
													// Does he have baton?
													if ( (pSoldier->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) )
													{
														pShadeTable = (UINT16 *) pShadeStart[ gpGlowFramePointer[ gsCurrentGlowFrame ] + bGlowShadeOffset ];

														if ( gpGlowFramePointer[ gsCurrentGlowFrame ] >= 7 )
														{
															gsForceSoldierZLevel = TOPMOST_Z_LEVEL;
														}
													}
												}
												else
												{
													pShadeTable = (UINT16 *) pShadeStart[ gpGlowFramePointer[ gsCurrentGlowFrame ] + bGlowShadeOffset ];

													if ( gpGlowFramePointer[ gsCurrentGlowFrame ] >= 7 )
													{
														gsForceSoldierZLevel = TOPMOST_Z_LEVEL;
													}
												}
											}

											//if ( gusSelectedSoldier != NOBODY )
											//{
											//	pSelSoldier = MercPtrs[ gusSelectedSoldier ];

												// Shade differently depending on visiblity
											//	if ( pSoldier->bVisible == 0 || ( pSelSoldier->aiData.bOppList[ pSoldier->ubID ] == 0  ) )
											//	{
													// Shade gray
											//		pShadeTable = pSoldier->pGlowShades[ gpGlowFramePointer[ gsCurrentGlowFrame ] + 10 ];
											//	}
											//}
										}
									}

									// Calculate Z level
									SoldierZLevel( pSoldier, iTempPosX_M, iTempPosY_M );

									if(!(uiFlags&TILES_DIRTY))
									{
										if ( pSoldier->flags.fForceShade )
										{
											pShadeTable = pSoldier->pForcedShade;
										}
									}

									// check if we are a merc duplicate, if so, only do minimal stuff!
									if ( pSoldier->ubID >= MAX_NUM_SOLDIERS )
									{
										// Shade gray
										pShadeTable = pSoldier->pEffectShades[ 1 ];
									}

									hVObject=gAnimSurfaceDatabase[ usAnimSurface ].hVideoObject;

									if ( hVObject == NULL )
									{
										pNode = pNode->pNext;
										continue;
									}

									// ATE: If we are in a gridno that we should not use obscure blitter, set!
									if ( !( gpWorldLevelData[ uiTileIndex ].ubExtFlags[0] & MAPELEMENT_EXT_NOBURN_STRUCT ) )
									{
										fObscuredBlitter = TRUE;
									}
									else
									{
										// ATE: Artificially increase z=level...
										sZLevel += 2;
									}


									usImageIndex=pSoldier->usAniFrame;

									uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED| BGND_FLAG_MERC;
									break;

							}

							// Adjust for interface level
							sYPos += gsRenderHeight;

							// OK, check for LEVELNODE HIDDEN...
							fHiddenTile = FALSE;

							if ( uiLevelNodeFlags & LEVELNODE_HIDDEN )
							{
								fHiddenTile = TRUE;

								if ( TileElem != NULL )
								{
									// If we are a roof and have SHOW_ALL_ROOFS on, turn off hidden tile check!
									if ( ( TileElem->uiFlags & ROOF_TILE ) && ( gTacticalStatus.uiFlags&SHOW_ALL_ROOFS ) )
									{
										// Turn off
										fHiddenTile = FALSE;
									}
								}
							}


							if( fRenderTile && !fHiddenTile )
							{
								fTileInvisible = FALSE;

								if ( ( uiLevelNodeFlags & LEVELNODE_ROTTINGCORPSE ) )
								{
									// Set fmerc flag!
									fMerc = TRUE;
									fZWrite = TRUE;

									//if ( hVObject->ppZStripInfo != NULL )
									{
										sMultiTransShadowZBlitterIndex	= GetCorpseStructIndex( &( pCorpse->def ), TRUE );
										fMultiTransShadowZBlitter = TRUE;
									}
								}

								if ( (uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC ) && !(uiFlags&TILES_DIRTY) )
								{
									// Remove flags!
									pNode->uiFlags &= (~LEVELNODE_LASTDYNAMIC );
									fZWrite = TRUE;
								}

								if ( uiLevelNodeFlags & LEVELNODE_NOWRITEZ )
								{
									fZWrite = FALSE;
								}


								if(uiFlags&TILES_NOZWRITE)
									fZWrite=FALSE;

								if ( uiFlags & TILES_NOZ )
								{
									fZBlitter							= FALSE;
								}



								if ( ( uiLevelNodeFlags & LEVELNODE_WIREFRAME ) )
								{
									if ( !gGameSettings.fOptions[ TOPTION_TOGGLE_WIREFRAME ] )
									{
										 fTileInvisible = TRUE;
									}
								}

								// RENDER
								if ( fTileInvisible )
								{

								}
								else if ( uiLevelNodeFlags & LEVELNODE_DISPLAY_AP && !( uiFlags&TILES_DIRTY ) )
								{
									pTrav = &(hVObject->pETRLEObject[usImageIndex]);
									sXPos += pTrav->sOffsetX;
									sYPos += pTrav->sOffsetY;

									if ( gfUIDisplayActionPointsInvalid )
									{
										SetFontBackground( FONT_MCOLOR_BLACK );
										SetFontForeground( FONT_MCOLOR_WHITE );
									}
									else
									{
										SetFontBackground( FONT_MCOLOR_BLACK );
										SetFontForeground( FONT_MCOLOR_WHITE );
									}

									if ( gfUIDisplayActionPointsBlack )
									{
										SetFontBackground( FONT_MCOLOR_BLACK );
										SetFontForeground( FONT_MCOLOR_BLACK );
									}

									SetFont( TINYFONT1 );
									SetFontDestBuffer( guiSAVEBUFFER , 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y, FALSE );
									VarFindFontCenterCoordinates( sXPos, sYPos, 1, 1, TINYFONT1, &sX, &sY, L"%d", pNode->uiAPCost );
									mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX,  sY , L"%d", pNode->uiAPCost );
									SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
								}
								else if ( ( uiLevelNodeFlags  & LEVELNODE_ERASEZ ) && !( uiFlags&TILES_DIRTY ) )
								{
									Zero8BPPDataTo16BPPBufferTransparent( (UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex );
									//Zero8BPPDataTo16BPPBufferTransparent( (UINT16*)gpZBuffer, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex );
								}
								else if ( ( uiLevelNodeFlags  & LEVELNODE_ITEM ) && !( uiFlags&TILES_DIRTY ) )
								{
										BOOLEAN fZBlit = FALSE;

										if ( uiRowFlags == TILES_STATIC_ONROOF || uiRowFlags == TILES_DYNAMIC_ONROOF )
										{
											usOutlineColor = gusYellowItemOutlineColor;
											bItemOutline = TRUE;
											fZBlit = TRUE;
										}
										else
										{
											usOutlineColor = gusNormalItemOutlineColor;
											bItemOutline = TRUE;
											fZBlit = TRUE;
										}

										if ( gGameSettings.fOptions[ TOPTION_GLOW_ITEMS ] )
										{
												if ( uiRowFlags == TILES_STATIC_ONROOF || uiRowFlags == TILES_DYNAMIC_ONROOF )
												{
													usOutlineColor = us16BPPItemCycleYellowColors[ gsCurrentItemGlowFrame ];
													bItemOutline = TRUE;
												}
												else
												{
													if ( gTacticalStatus.uiFlags & RED_ITEM_GLOW_ON  )
													{
														usOutlineColor = us16BPPItemCycleRedColors[ gsCurrentItemGlowFrame ];
														bItemOutline = TRUE;
													}
													else
													{
														usOutlineColor = us16BPPItemCycleWhiteColors[ gsCurrentItemGlowFrame ];
														bItemOutline = TRUE;
													}
												}
										}

									//else
										//{
										//	usOutlineColor = us16BPPItemCycleWhiteColors[ pItemPool->bFlashColor ];
										//	bItemOutline = TRUE;
										//}

										bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);

										if ( bBlitClipVal == FALSE )
										{
											if ( fZBlit )
											{
												if ( fObscuredBlitter )
												{
													Blt8BPPDataTo16BPPBufferOutlineZPixelateObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline );
												}
												else
												{
													Blt8BPPDataTo16BPPBufferOutlineZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline );
												}
											}
											else
											{
												Blt8BPPDataTo16BPPBufferOutline((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline );
											}
										}
										else if ( bBlitClipVal == TRUE )
										{
											if ( fZBlit )
											{
												if ( fObscuredBlitter )
												{
													Blt8BPPDataTo16BPPBufferOutlineZPixelateObscuredClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect );
												}
												else
												{
													Blt8BPPDataTo16BPPBufferOutlineZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect );
												}
											}
											else
											{
												Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect );
											}
										}
								}
								// ATE: Check here for a lot of conditions!
								else if ( ( ( uiLevelNodeFlags & LEVELNODE_PHYSICSOBJECT ) ) && !( uiFlags&TILES_DIRTY ) )
								{
										bItemOutline = TRUE;

										if ( uiLevelNodeFlags & LEVELNODE_PHYSICSOBJECT )
										{
											bItemOutline = FALSE;
										}

										bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);

										if ( fShadowBlitter )
										{
											if ( bBlitClipVal == FALSE )
											{
												Blt8BPPDataTo16BPPBufferShadowZNB( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex );
											}
											else
											{
												Blt8BPPDataTo16BPPBufferShadowZNBClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect );
											}
										}
										else
										{
											if ( bBlitClipVal == FALSE )
											{
												 Blt8BPPDataTo16BPPBufferOutlineZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline );
											}
											else if ( bBlitClipVal == TRUE )
											{
												 Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect );
											}
										}
								}
								else if(uiFlags&TILES_DIRTY)
								{

									if ( !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC ) )
									{
										pTrav = &(hVObject->pETRLEObject[usImageIndex]);
										uiBrushHeight	= (UINT32)pTrav->usHeight;
										uiBrushWidth = (UINT32)pTrav->usWidth;
										sXPos += pTrav->sOffsetX;
										sYPos += pTrav->sOffsetY;

										RegisterBackgroundRect(uiDirtyFlags, NULL, sXPos, sYPos, (INT16)(sXPos + uiBrushWidth), (INT16)(__min((INT16)(sYPos + uiBrushHeight), gsVIEWPORT_WINDOW_END_Y)));

										if ( fSaveZ )
										{
											RegisterBackgroundRect(uiDirtyFlags | BGND_FLAG_SAVE_Z, NULL, sXPos, sYPos, (INT16)(sXPos + uiBrushWidth), (INT16)(__min((INT16)(sYPos + uiBrushHeight), gsVIEWPORT_WINDOW_END_Y)));
										}
									}
								}
								else
								{
									if(gbPixelDepth==16)
									{
										/*if(fConvertTo16)
										{
											ConvertVObjectRegionTo16BPP(hVObject, usImageIndex, 4);
											if(CheckFor16BPPRegion(hVObject, usImageIndex, 4, &us16BPPIndex))
											{
												Blt16BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES,  hVObject, sXPos, sYPos, us16BPPIndex, &gClippingRect);
											}
										}*/

										if( fMultiTransShadowZBlitter )
										{
											if ( fZBlitter )
											{
												if ( fObscuredBlitter )
												{
													Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable );
												}
												else
												{
													Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable );
												}
											}
											else
											{
												//Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect );
											}
										}
										else if( fMultiZBlitter )
										{
											if ( fZBlitter )
											{
												if ( fObscuredBlitter )
												{
													Blt8BPPDataTo16BPPBufferTransZIncObscureClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
												}
												else
												{
													if ( fWallTile )
													{
														if ( sZStripIndex == -1 )
														{
															Blt8BPPDataTo16BPPBufferTransZIncClipZSameZBurnsThrough((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, usImageIndex);
														}
														else
														{
															Blt8BPPDataTo16BPPBufferTransZIncClipZSameZBurnsThrough((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sZStripIndex );
														}
													}
													else
													{
														Blt8BPPDataTo16BPPBufferTransZIncClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}
												}
											}
											else
											{
												Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect );
											}
										}
										else
										{
											bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);

											if ( bBlitClipVal == TRUE )
											{
												if(fPixelate)
												{
													if(fTranslucencyType)
													{
														//if(fZWrite)
														//	Blt8BPPDataTo16BPPBufferTransZClipTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
														//else
															Blt8BPPDataTo16BPPBufferTransZNBClipTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}
													else
													{
														//if(fZWrite)
														//	Blt8BPPDataTo16BPPBufferTransZClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
														//else
															Blt8BPPDataTo16BPPBufferTransZNBClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}
												}
												else if(fMerc)
												{
													if ( fZBlitter )
													{
														if ( fZWrite )
														{
															Blt8BPPDataTo16BPPBufferTransShadowZClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																					hVObject,
																																					sXPos, sYPos,
																																					usImageIndex,
																																					&gClippingRect,
																																					pShadeTable);
														}
														else
														{
															if ( fObscuredBlitter )
															{

																	Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																							hVObject,
																																							sXPos, sYPos,
																																							usImageIndex,
																																							&gClippingRect,
																																							pShadeTable);
															}
															else
															{
																Blt8BPPDataTo16BPPBufferTransShadowZNBClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																						hVObject,
																																						sXPos, sYPos,
																																						usImageIndex,
																																						&gClippingRect,
																																						pShadeTable);
															}
														}

														if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) )
														{
															pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES );

															// BLIT HERE
															Blt8BPPDataTo16BPPBufferTransShadowClip( (UINT16*)pSaveBuf, uiSaveBufferPitchBYTES,
																																				hVObject,
																																				sXPos, sYPos,
																																				usImageIndex,
																																				&gClippingRect,
																																				pShadeTable);

															UnLockVideoSurface(guiSAVEBUFFER);

															// Turn it off!
															pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE );
														}

													}
													else
													{
														Blt8BPPDataTo16BPPBufferTransShadowClip( (UINT16*)pDestBuf, uiDestPitchBYTES,
																																				hVObject,
																																				sXPos, sYPos,
																																				usImageIndex,
																																				&gClippingRect,
																																				pShadeTable);
													}
												}
												else if(fShadowBlitter)
												{
													if ( fZBlitter )
													{
														 if(fZWrite)
																Blt8BPPDataTo16BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
														 else
																Blt8BPPDataTo16BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}
													else
													{
															Blt8BPPDataTo16BPPBufferShadowClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}
												}
												else if( fIntensityBlitter)
												{
													if ( fZBlitter )
													{
														 if(fZWrite)
																Blt8BPPDataTo16BPPBufferIntensityZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
														 else
																Blt8BPPDataTo16BPPBufferIntensityZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}
													else
													{
														Blt8BPPDataTo16BPPBufferIntensityClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}
												}
												else if(fZBlitter)
												{
													if(fZWrite)
													{
														if ( fObscuredBlitter )
														{
															Blt8BPPDataTo16BPPBufferTransZClipPixelateObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
														}
														else
														{
															Blt8BPPDataTo16BPPBufferTransZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
														}
													}
													else
													{
														Blt8BPPDataTo16BPPBufferTransZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
													}

													if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) )
													{
														pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES );

														// BLIT HERE
														Blt8BPPDataTo16BPPBufferTransZClip((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);

														UnLockVideoSurface(guiSAVEBUFFER);

														// Turn it off!
														pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE );
													}

												}
												else
														Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);

											}
											else if ( bBlitClipVal == FALSE )
											{
												if(fPixelate)
												{
													if(fTranslucencyType)
													{
														if(fZWrite)
															Blt8BPPDataTo16BPPBufferTransZTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
														else
															Blt8BPPDataTo16BPPBufferTransZNBTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
													}
													else
													{
														if(fZWrite)
															Blt8BPPDataTo16BPPBufferTransZPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
														else
															Blt8BPPDataTo16BPPBufferTransZNBPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
													}
												}
												else if(fMerc)
												{
													if ( fZBlitter )
													{
														if ( fZWrite )
														{
															Blt8BPPDataTo16BPPBufferTransShadowZ( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																					hVObject,
																																					sXPos, sYPos,
																																					usImageIndex,
																																					pShadeTable);
														}
														else
														{
															if ( fObscuredBlitter )
															{
																Blt8BPPDataTo16BPPBufferTransShadowZNBObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																						hVObject,
																																						sXPos, sYPos,
																																						usImageIndex,
																																						pShadeTable);
															}
															else
															{
																Blt8BPPDataTo16BPPBufferTransShadowZNB( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																						hVObject,
																																						sXPos, sYPos,
																																						usImageIndex,
																																						pShadeTable);
															}
														}

														if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) )
														{
															pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES );

															// BLIT HERE
															Blt8BPPDataTo16BPPBufferTransShadow( (UINT16*)pSaveBuf, uiSaveBufferPitchBYTES,
																																					hVObject,
																																					sXPos, sYPos,
																																					usImageIndex,
																																					pShadeTable);

															UnLockVideoSurface(guiSAVEBUFFER);

															// Turn it off!
															pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE );
														}

													}
													else
													{

														Blt8BPPDataTo16BPPBufferTransShadow( (UINT16*)pDestBuf, uiDestPitchBYTES,
																																				hVObject,
																																				sXPos, sYPos,
																																				usImageIndex,
																																				pShadeTable);
													}
												}
												else if(fShadowBlitter)
												{
													if ( fZBlitter )
													{
													 if(fZWrite)
															Blt8BPPDataTo16BPPBufferShadowZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
														else
															Blt8BPPDataTo16BPPBufferShadowZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
													}
													else
													{
														Blt8BPPDataTo16BPPBufferShadow((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex);
													}
												}
												else if( fIntensityBlitter )
												{
													if ( fZBlitter )
													{
													 if(fZWrite)
															Blt8BPPDataTo16BPPBufferIntensityZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
														else
															Blt8BPPDataTo16BPPBufferIntensityZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
													}
													else
													{
														Blt8BPPDataTo16BPPBufferIntensity((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex);
													}
												}
												else if(fZBlitter)
												{
													if(fZWrite)
													{
														// TEST
														//Blt8BPPDataTo16BPPBufferTransZPixelate( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);

														if ( fObscuredBlitter )
														{
															Blt8BPPDataTo16BPPBufferTransZPixelateObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
														}
														else
														{
															Blt8BPPDataTo16BPPBufferTransZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
														}
													}
													else
														Blt8BPPDataTo16BPPBufferTransZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);


													if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) )
													{
														pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES );

														// BLIT HERE
														Blt8BPPDataTo16BPPBufferTransZ((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex );

														UnLockVideoSurface(guiSAVEBUFFER);

														// Turn it off!
														pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE );
													}

												}
												else
														Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex);
											}
										}
									}
									else // 8bpp section
									{
										if(fPixelate)
										{
											if(fZWrite)
												Blt8BPPDataTo8BPPBufferTransZClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
											else
												Blt8BPPDataTo8BPPBufferTransZNBClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
										}
										else if(BltIsClipped(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect))
										{
											if(fMerc)
											{
												Blt8BPPDataTo8BPPBufferTransShadowZNBClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																		hVObject,
																																		sXPos, sYPos,
																																		usImageIndex,
																																		&gClippingRect,
																																		pShadeTable);
											}
											else if(fShadowBlitter)
											 if(fZWrite)
													Blt8BPPDataTo8BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
											 else
													Blt8BPPDataTo8BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);

											else if(fZBlitter)
											{
												if(fZWrite)
													Blt8BPPDataTo8BPPBufferTransZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
												else
													Blt8BPPDataTo8BPPBufferTransZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
											}
											else
													Blt8BPPDataTo8BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect);
										}
										else
										{
											if(fMerc)
											{

												Blt8BPPDataTo16BPPBufferTransShadowZNBObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
																																		hVObject,
																																		sXPos, sYPos,
																																		usImageIndex,
																																		pShadeTable);


											//	Blt8BPPDataTo8BPPBufferTransShadowZNB( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel,
											//																							hVObject,
											//																							sXPos, sYPos,
											//																							usImageIndex,
											//																							pShadeTable);
											}
											else if(fShadowBlitter)
											{
											 if(fZWrite)
													Blt8BPPDataTo8BPPBufferShadowZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
												else
													Blt8BPPDataTo8BPPBufferShadowZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
											}
											else if(fZBlitter)
											{
												if(fZWrite)
													Blt8BPPDataTo8BPPBufferTransZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
												else
													Blt8BPPDataTo8BPPBufferTransZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex);
											}
											else
													Blt8BPPDataTo8BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex);
										}
									}
								}

								// RENDR APS ONTOP OF PLANNED MERC GUY
								if ( fRenderTile && !( uiFlags&TILES_DIRTY ) )
								{
									if ( fMerc )
									{
										if ( pSoldier != NULL && pSoldier->ubID >= MAX_NUM_SOLDIERS )
										{
											SetFont( TINYFONT1 );
											SetFontDestBuffer( guiSAVEBUFFER , 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y, FALSE );
											VarFindFontCenterCoordinates( sXPos, sYPos, 1, 1, TINYFONT1, &sX, &sY, L"%d", pSoldier->ubPlannedUIAPCost );
											mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX,  sY , L"%d", pSoldier->ubPlannedUIAPCost );
											SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
										}
									}
								}

							}

							if(!fLinkedListDirection)
								pNode = pNode->pPrevNode;
							else
								pNode = pNode->pNext;

							//pNode = NULL;
						}
					}
					else
					{
						if( gfEditMode )
						{
							//ATE: Used here in the editor to denote then an area is not in the world

							//Kris:  Fixed a couple things here...
							//  First, there was a problem with the FRAME_BUFFER already being locked which caused failures,
							//	and eventual crashes, so if it reaches this code, the buffer needs to be unlocked first, as
							//  it gets locked and unlocked internally within ColorFillVideoSurfaceArea().  I'm surprised
							//	this problem didn't surface a long time ago.  Anyway, it seems that scrolling to the bottom
							//	right hand corner of the map, would cause the end of the world to be drawn.  Now, this would
							//	only crash on my computer and not Emmons, so this should work.  Also, I changed the color
							//	from fluorescent green to black, which is easier on the eyes, and prevent the drawing of the
							//	end of the world if it would be drawn on the editor's taskbar.
							if( iTempPosY_S < INTERFACE_START_Y )
							{
								if(!(uiFlags&TILES_DIRTY))
									UnLockVideoSurface( FRAME_BUFFER );
								ColorFillVideoSurfaceArea( FRAME_BUFFER, iTempPosX_S, iTempPosY_S, (iTempPosX_S + 40), 
									( min( iTempPosY_S + 20, INTERFACE_START_Y )), Get16BPPColor( FROMRGB( 0, 0, 0 ) ) );
								if(!(uiFlags&TILES_DIRTY))
									pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
							}
						}
					}

					iTempPosX_S += 40;
					iTempPosX_M ++;
					iTempPosY_M --;

					if ( iTempPosX_S >= iEndXS )
					{
						fEndRenderRow = TRUE;
					}

				} while( !fEndRenderRow );

			}

		}
		//	} while( FALSE );

		if ( bXOddFlag > 0 )
		{
			iAnchorPosY_M ++;
		}
		else
		{
			iAnchorPosX_M ++;
		}

		bXOddFlag = !bXOddFlag;
		iAnchorPosY_S += 10;

		if ( iAnchorPosY_S >= iEndYS )
		{
			fEndRenderCol = TRUE;
		}
	}
	while( !fEndRenderCol );

	if(!(uiFlags&TILES_DIRTY))
		UnLockVideoSurface( FRAME_BUFFER );

	if ( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE )
	{
		EndCurInteractiveTileCheck( );
	}


}
/// kONIE Renderowania klastra


void DeleteFromWorld( UINT16 usTileIndex, UINT32 uiRenderTiles, UINT16 usIndex )
{
	switch( uiRenderTiles )
	{
		case TILES_DYNAMIC_LAND:
		case TILES_STATIC_LAND:
			RemoveLand( usTileIndex, usIndex );
			break;
		case TILES_DYNAMIC_OBJECTS:
		case TILES_STATIC_OBJECTS:
			RemoveObject( usTileIndex, usIndex );
			break;
		case TILES_STATIC_STRUCTURES:
		case TILES_DYNAMIC_STRUCTURES:
			RemoveStruct( usTileIndex, usIndex );
			break;
		case TILES_DYNAMIC_ROOF:
		case TILES_STATIC_ROOF:
			RemoveRoof( usTileIndex, usIndex );
			break;
		case TILES_STATIC_ONROOF:
			RemoveOnRoof( usTileIndex, usIndex );
			break;

		case TILES_DYNAMIC_TOPMOST:
		case TILES_STATIC_TOPMOST:
			RemoveTopmost( usTileIndex, usIndex );
			break;

	}

}



// memcpy's the background to the new scroll position, and renders the missing strip
// via the RenderStaticWorldRect. Dynamic stuff will be updated on the next frame
// by the normal render cycle
void ScrollBackground(UINT32 uiDirection, INT16 sScrollXIncrement, INT16 sScrollYIncrement )
{

	//RestoreBackgroundRects();

	if ( !gfDoVideoScroll )
	{
		// Clear z-buffer
		memset(gpZBuffer, LAND_Z_LEVEL, SCREEN_WIDTH*2* gsVIEWPORT_END_Y );

		RenderStaticWorldRect( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y, FALSE );

		FreeBackgroundRectType(BGND_FLAG_ANIMATED);
	}
	else
	{
		if ( gfRenderScroll == FALSE )
		{
			guiScrollDirection   = uiDirection;
			gfScrollStart				 = TRUE;
			gsScrollXIncrement	 = 0;
			gsScrollYIncrement	 = 0;
		}
		else
		{
			guiScrollDirection   |= uiDirection;
			gfScrollStart = FALSE;

		}

		gfRenderScroll =	TRUE;
		gsScrollXIncrement	+= sScrollXIncrement;
		gsScrollYIncrement	+= sScrollYIncrement;
	}


}

// Render routine takes center X, Y and Z coordinate and gets world
// Coordinates for the window from that using the following functions
// For coordinate transformations

void RenderWorld( )
{
TILE_ELEMENT					*TileElem;
TILE_ANIMATION_DATA		*pAnimData;
UINT32 cnt = 0;

	gfRenderFullThisFrame = FALSE;

	// If we are testing renderer, set background to pink!
	if ( gTacticalStatus.uiFlags & DEBUGCLIFFS )
	{
		ColorFillVideoSurfaceArea( FRAME_BUFFER, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH,	gsVIEWPORT_WINDOW_END_Y, Get16BPPColor( FROMRGB( 0, 255, 0 ) ) );
		SetRenderFlags(RENDER_FLAG_FULL);
	}

	if ( gTacticalStatus.uiFlags & SHOW_Z_BUFFER )
	{
		SetRenderFlags(RENDER_FLAG_FULL);
	}


//	SetRenderFlags(RENDER_FLAG_FULL);



	// FOR NOW< HERE, UPDATE ANIMATED TILES
	if ( COUNTERDONE( ANIMATETILES ) )
	{
		RESETCOUNTER( ANIMATETILES );

		while( cnt < gusNumAnimatedTiles )
		{
			TileElem = &(gTileDatabase[ gusAnimatedTiles[ cnt ] ] );

			pAnimData = TileElem->pAnimData;

			Assert( pAnimData != NULL );

			pAnimData->bCurrentFrame++;

			if ( pAnimData->bCurrentFrame >= pAnimData->ubNumFrames )
					pAnimData->bCurrentFrame = 0;
			cnt++;
		}
	}

	// HERE, UPDATE GLOW INDEX
	if ( COUNTERDONE( GLOW_ENEMYS ) )
	{
		RESETCOUNTER( GLOW_ENEMYS );

		gsCurrentGlowFrame++;

		if ( gsCurrentGlowFrame == NUM_GLOW_FRAMES )
		{
			gsCurrentGlowFrame = 0;
		}

		gsCurrentItemGlowFrame++;

		if ( gsCurrentItemGlowFrame == NUM_ITEM_CYCLE_COLORS )
		{
			gsCurrentItemGlowFrame = 0;
		}

	}


	//RenderStaticWorldRect( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y );
	//AddBaseDirtyRect(gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y );
	//return;


//#if 0

	if(gRenderFlags&RENDER_FLAG_FULL)
	{
		gfRenderFullThisFrame = TRUE;

		gfTopMessageDirty = TRUE;

		// Dirty the interface...
		fInterfacePanelDirty = DIRTYLEVEL2;

		// Apply scrolling sets some world variables
		ApplyScrolling( gsRenderCenterX, gsRenderCenterY, TRUE, FALSE );
		ResetLayerOptimizing();

		if ( (gRenderFlags&RENDER_FLAG_NOZ ) )
		{
			RenderStaticWorldRect( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y, FALSE );

		}
		else
		{
			RenderStaticWorld();

		}


		if(!(gRenderFlags&RENDER_FLAG_SAVEOFF))
			UpdateSaveBuffer();


	}
	else if(gRenderFlags&RENDER_FLAG_MARKED)
	{
		ResetLayerOptimizing();
		RenderMarkedWorld();
		if(!(gRenderFlags&RENDER_FLAG_SAVEOFF))
			UpdateSaveBuffer();

	}

	if ( gfScrollInertia == FALSE || (gRenderFlags&RENDER_FLAG_NOZ ) || (gRenderFlags&RENDER_FLAG_FULL ) || (gRenderFlags&RENDER_FLAG_MARKED ) )
	{
		RenderDynamicWorld( );

///////////////////////////////////////////////////////////

//	ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, gsVIEWPORT_WINDOW_END_Y, BP_SCREEN_WIDTH_CENTERED, SCREEN_HEIGHT, Get16BPPColor( FROMRGB( 16, 8, 0 ) ) );

///////////////////////////////////////////////////////////
	}

	if ( gfScrollInertia )
	{
  	EmptyBackgroundRects( );
  }

	if( gRenderFlags&RENDER_FLAG_ROOMIDS )
	{
		RenderRoomInfo( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );
	}

#ifdef _DEBUG
	if( gRenderFlags&RENDER_FLAG_FOVDEBUG )
	{
		RenderFOVDebugInfo( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );
	}
	else if (gfDisplayCoverValues)
	{
		RenderCoverDebugInfo( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );
	}
	else if (gfDisplayGridNoVisibleValues)
	{
		RenderGridNoVisibleDebugInfo( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );
	}

#endif

//#endif

	//RenderStaticWorldRect( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y );
	//AddBaseDirtyRect(gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y );


	if(gRenderFlags&RENDER_FLAG_MARKED)
		ClearMarkedTiles();

	if ( gRenderFlags&RENDER_FLAG_CHECKZ && !(gTacticalStatus.uiFlags & NOHIDE_REDUNDENCY) )
	{
		ExamineZBufferRect( gsVIEWPORT_START_X, gsVIEWPORT_WINDOW_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y );
	}


	gRenderFlags&=(~(RENDER_FLAG_FULL|RENDER_FLAG_MARKED|RENDER_FLAG_ROOMIDS|RENDER_FLAG_CHECKZ));

	if ( gTacticalStatus.uiFlags & SHOW_Z_BUFFER )
	{
		// COPY Z BUFFER TO FRAME BUFFER
		UINT32	uiDestPitchBYTES;
		UINT16		*pDestBuf;
		UINT32	cnt;
		INT16		zVal;

		pDestBuf = (UINT16 *)LockVideoSurface(guiRENDERBUFFER, &uiDestPitchBYTES);

		for ( cnt = 0; cnt < (UINT32)( SCREEN_WIDTH * SCREEN_HEIGHT ); cnt++ )
		{
			// Get Z value
			zVal = gpZBuffer[ cnt ];
			pDestBuf[cnt] = zVal;
		}

		UnLockVideoSurface(guiRENDERBUFFER);
	}

}

// Start with a center X,Y,Z world coordinate and render direction
// Determine WorldIntersectionPoint and the starting block from these
// Then render away!

//ok tutaj jest renderowane przy przesuwaniu
void RenderStaticWorldRect(INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom, BOOLEAN fDynamicsToo )
{
	UINT32		uiLevelFlags[10];
	UINT16		sLevelIDs[10];
	UINT32		uiDestPitchBYTES;
	UINT8		*pDestBuf=NULL;

	// Calculate render starting parameters
	CalcRenderParameters( sLeft, sTop, sRight, sBottom );

	pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
	Assert( pDestBuf);
	memset(gpZBuffer, LAND_Z_LEVEL, uiDestPitchBYTES * gsVIEWPORT_END_Y );
	UnLockVideoSurface( FRAME_BUFFER);


	// Reset layer optimizations
	ResetLayerOptimizing( );
//#if 0

	// rendering land
	uiLevelFlags[0]		=	TILES_STATIC_LAND;
	sLevelIDs	[0]		=	RENDER_STATIC_LAND;
	RenderTiles( 0 , gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 1, uiLevelFlags, sLevelIDs );

	//rendering objects
	uiLevelFlags[0]		=	TILES_STATIC_OBJECTS;
	sLevelIDs	[0]		=	RENDER_STATIC_OBJECTS;
	RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 1, uiLevelFlags, sLevelIDs );

	if(gRenderFlags&RENDER_FLAG_SHADOWS )
	{
		// If we have to we render shadows
		uiLevelFlags[0]	=	TILES_STATIC_SHADOWS;
		sLevelIDs	[0]	=	RENDER_STATIC_SHADOWS;
		RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 1, uiLevelFlags , sLevelIDs );
	}

	uiLevelFlags[0]		=	TILES_STATIC_STRUCTURES;
	sLevelIDs	[0]		=	RENDER_STATIC_STRUCTS;
	uiLevelFlags[1]		=	TILES_STATIC_ROOF;
	sLevelIDs	[1]		=	RENDER_STATIC_ROOF;
	uiLevelFlags[2]		=	TILES_STATIC_ONROOF;
	sLevelIDs	[2]		=	RENDER_STATIC_ONROOF;
	uiLevelFlags[3]		=	TILES_STATIC_TOPMOST;
	sLevelIDs	[3]		=	RENDER_STATIC_TOPMOST;
	RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 4, uiLevelFlags, sLevelIDs );

	//ATE: Do obsucred layer!
	uiLevelFlags[0] = TILES_STATIC_STRUCTURES;
	sLevelIDs[0]		= RENDER_STATIC_STRUCTS;
	uiLevelFlags[1] = TILES_STATIC_ONROOF;
	sLevelIDs[1]		= RENDER_STATIC_ONROOF;
	RenderTiles( TILES_OBSCURED,  gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 2, uiLevelFlags, sLevelIDs );


	uiLevelFlags[0] = TILES_DYNAMIC_MERCS;
	//uiLevelFlags[1] = TILES_DYNAMIC_HIGHMERCS;

	sLevelIDs[0]    = RENDER_DYNAMIC_MERCS;
	//sLevelIDs[1]		= RENDER_DYNAMIC_HIGHMERCS;
	RenderTiles( 0, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 1, uiLevelFlags, sLevelIDs );


	if ( fDynamicsToo )
	{
		// DYNAMICS
		uiLevelFlags[0] = TILES_DYNAMIC_LAND;
		uiLevelFlags[1] = TILES_DYNAMIC_OBJECTS;
		uiLevelFlags[2] = TILES_DYNAMIC_SHADOWS;
		uiLevelFlags[3] = TILES_DYNAMIC_STRUCT_MERCS;
		uiLevelFlags[4] = TILES_DYNAMIC_MERCS;
		uiLevelFlags[5] = TILES_DYNAMIC_STRUCTURES;
		uiLevelFlags[6] = TILES_DYNAMIC_ROOF;
		uiLevelFlags[7] = TILES_DYNAMIC_HIGHMERCS;
		uiLevelFlags[8] = TILES_DYNAMIC_ONROOF;

		sLevelIDs[0]    = RENDER_DYNAMIC_LAND;
		sLevelIDs[1]    = RENDER_DYNAMIC_OBJECTS;
		sLevelIDs[2]    = RENDER_DYNAMIC_SHADOWS;
		sLevelIDs[3]    = RENDER_DYNAMIC_STRUCT_MERCS;
		sLevelIDs[4]    = RENDER_DYNAMIC_MERCS;
		sLevelIDs[5]    = RENDER_DYNAMIC_STRUCTS;
		sLevelIDs[6]    = RENDER_DYNAMIC_ROOF;
		sLevelIDs[7]    = RENDER_DYNAMIC_HIGHMERCS;
		sLevelIDs[8]    = RENDER_DYNAMIC_ONROOF;
		RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 9, uiLevelFlags , sLevelIDs );


		SumAddiviveLayerOptimization( );
	}

	ResetRenderParameters( );

	if ( !gfDoVideoScroll )
	{
		//AddBaseDirtyRect(gsVIEWPORT_START_X, gsVIEWPORT_WINDOW_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y );
		AddBaseDirtyRect(sLeft, sTop, sRight, sBottom );
	}

//#endif
}


// to jest wykonywane przy kazdym takcie zegara
void RenderStaticWorld(  )
{
	UINT32	uiLevelFlags[9];
	UINT16	sLevelIDs[9];
	UINT32	uiDestPitchBYTES;
	UINT8	*pDestBuf=NULL;

	// Calculate render starting parameters
	CalcRenderParameters( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y );

	// Clear z-buffer
	pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
	Assert( pDestBuf);
	memset(gpZBuffer, LAND_Z_LEVEL, uiDestPitchBYTES * gsVIEWPORT_END_Y );
	UnLockVideoSurface( FRAME_BUFFER);

	FreeBackgroundRectType(BGND_FLAG_ANIMATED);
	InvalidateBackgroundRects();

	// rendering land tiles
	uiLevelFlags[0]		=	TILES_STATIC_LAND;
	sLevelIDs	[0]		=	RENDER_STATIC_LAND;
	RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 1, uiLevelFlags, sLevelIDs );

	//rendering objects
	uiLevelFlags[0]		=	TILES_STATIC_OBJECTS;
	sLevelIDs	[0]		=	RENDER_STATIC_OBJECTS;
	RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 1, uiLevelFlags, sLevelIDs );

	// If we have to we render shadows
	if(gRenderFlags&RENDER_FLAG_SHADOWS )
	{
		uiLevelFlags[0]	=	TILES_STATIC_SHADOWS;
		sLevelIDs	[0]	=	RENDER_STATIC_SHADOWS;
		RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 1, uiLevelFlags , sLevelIDs );
	}

	uiLevelFlags[0]		=	TILES_STATIC_STRUCTURES;
	sLevelIDs	[0]		=	RENDER_STATIC_STRUCTS;
	uiLevelFlags[1]		=	TILES_STATIC_ROOF;
	sLevelIDs	[1]		=	RENDER_STATIC_ROOF;
	uiLevelFlags[2]		=	TILES_STATIC_ONROOF;
	sLevelIDs	[2]		=	RENDER_STATIC_ONROOF;
	uiLevelFlags[3]		=	TILES_STATIC_TOPMOST;
	sLevelIDs	[3]		=	RENDER_STATIC_TOPMOST;
	RenderTiles( 0, gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 4, uiLevelFlags, sLevelIDs );

	//ATE: Do obsucred layer!
	uiLevelFlags[0] = TILES_STATIC_STRUCTURES;
	sLevelIDs[0]		= RENDER_STATIC_STRUCTS;
	uiLevelFlags[1] = TILES_STATIC_ONROOF;
	sLevelIDs[1]		= RENDER_STATIC_ONROOF;
	RenderTiles( TILES_OBSCURED,  gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 2, uiLevelFlags, sLevelIDs );


	AddBaseDirtyRect(gsVIEWPORT_START_X, gsVIEWPORT_WINDOW_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y );
	ResetRenderParameters( );

}

void RenderMarkedWorld(void)
{
	UINT32 uiLevelFlags[4];
	UINT16		sLevelIDs[4];

	CalcRenderParameters( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y );



	RestoreBackgroundRects();
	FreeBackgroundRectType(BGND_FLAG_ANIMATED);
	InvalidateBackgroundRects();

	ResetLayerOptimizing();

	uiLevelFlags[0] = TILES_STATIC_LAND;
	uiLevelFlags[1] = TILES_STATIC_OBJECTS;
	sLevelIDs[0]		= RENDER_STATIC_LAND;
	sLevelIDs[1]		= RENDER_STATIC_OBJECTS;
	RenderTiles(TILES_MARKED,  gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 2, uiLevelFlags, sLevelIDs );

	if(gRenderFlags&RENDER_FLAG_SHADOWS)
	{
		uiLevelFlags[0] = TILES_STATIC_SHADOWS;
		sLevelIDs[0]		= RENDER_STATIC_SHADOWS;
		RenderTiles(TILES_MARKED, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 1, uiLevelFlags, sLevelIDs );
	}

	uiLevelFlags[0] = TILES_STATIC_STRUCTURES;
	sLevelIDs[0]		= RENDER_STATIC_STRUCTS;
	RenderTiles(TILES_MARKED, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 1, uiLevelFlags, sLevelIDs );

	uiLevelFlags[0] = TILES_STATIC_ROOF;
	sLevelIDs[0]		= RENDER_STATIC_ROOF;
	RenderTiles(TILES_MARKED, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 1, uiLevelFlags, sLevelIDs );

	uiLevelFlags[0] = TILES_STATIC_ONROOF;
	sLevelIDs[0]		= RENDER_STATIC_ONROOF;
	RenderTiles(TILES_MARKED, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 1, uiLevelFlags, sLevelIDs );

	uiLevelFlags[0] = TILES_STATIC_TOPMOST;
	sLevelIDs[0]		= RENDER_STATIC_TOPMOST;
	RenderTiles(TILES_MARKED, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 1, uiLevelFlags, sLevelIDs );


	 AddBaseDirtyRect(gsVIEWPORT_START_X, gsVIEWPORT_WINDOW_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y );


	ResetRenderParameters( );

}

void RenderDynamicWorld(  )
{
	UINT8		ubNumLevels;
	UINT32	uiLevelFlags[ 10 ];
	UINT16	sLevelIDs[ 10 ];

	CalcRenderParameters( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_END_Y );

	RestoreBackgroundRects();

	if(!gfTagAnimatedTiles)
	{
		uiLevelFlags[0] = TILES_DYNAMIC_OBJECTS;
		uiLevelFlags[1] = TILES_DYNAMIC_SHADOWS;
		uiLevelFlags[2] = TILES_DYNAMIC_STRUCT_MERCS;
		uiLevelFlags[3] = TILES_DYNAMIC_MERCS;
		uiLevelFlags[4] = TILES_DYNAMIC_STRUCTURES;
		uiLevelFlags[5] = TILES_DYNAMIC_HIGHMERCS;
		uiLevelFlags[6] = TILES_DYNAMIC_ROOF;
		uiLevelFlags[7] = TILES_DYNAMIC_ONROOF;
		uiLevelFlags[8] = TILES_DYNAMIC_TOPMOST;

		sLevelIDs[0]		= RENDER_DYNAMIC_OBJECTS;
		sLevelIDs[1]		= RENDER_DYNAMIC_SHADOWS;
		sLevelIDs[2]		= RENDER_DYNAMIC_STRUCT_MERCS;
		sLevelIDs[3]		= RENDER_DYNAMIC_MERCS;
		sLevelIDs[4]		= RENDER_DYNAMIC_STRUCTS;
		sLevelIDs[5]		= RENDER_DYNAMIC_MERCS;
		sLevelIDs[6]		= RENDER_DYNAMIC_ROOF;
		sLevelIDs[7]		= RENDER_DYNAMIC_ONROOF;
		sLevelIDs[8]		= RENDER_DYNAMIC_TOPMOST;

		ubNumLevels = 9;
	}
	else
	{
		gfTagAnimatedTiles=FALSE;
		//uiLevelFlags[0] = TILES_DYNAMIC_LAND;
		uiLevelFlags[0] = TILES_DYNAMIC_OBJECTS;
		uiLevelFlags[1] = TILES_DYNAMIC_SHADOWS;
		uiLevelFlags[2] = TILES_DYNAMIC_STRUCT_MERCS;
		uiLevelFlags[3] = TILES_DYNAMIC_MERCS;
		uiLevelFlags[4] = TILES_DYNAMIC_STRUCTURES;
		uiLevelFlags[5] = TILES_DYNAMIC_HIGHMERCS;
		uiLevelFlags[6] = TILES_DYNAMIC_ROOF;
		uiLevelFlags[7] = TILES_DYNAMIC_ONROOF;
		uiLevelFlags[8] = TILES_DYNAMIC_TOPMOST;

		//sLevelIDs[0]		= RENDER_DYNAMIC_LAND;
		sLevelIDs[0]		= RENDER_DYNAMIC_OBJECTS;
		sLevelIDs[1]		= RENDER_DYNAMIC_SHADOWS;
		sLevelIDs[2]		= RENDER_DYNAMIC_STRUCT_MERCS;
		sLevelIDs[3]		= RENDER_DYNAMIC_MERCS;
		sLevelIDs[4]		= RENDER_DYNAMIC_STRUCTS;
		sLevelIDs[5]		= RENDER_DYNAMIC_MERCS;
		sLevelIDs[6]		= RENDER_DYNAMIC_ROOF;
		sLevelIDs[7]		= RENDER_DYNAMIC_ONROOF;
		sLevelIDs[8]		= RENDER_DYNAMIC_TOPMOST;

		ubNumLevels = 9;
	}

	RenderTiles(TILES_DIRTY, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, ubNumLevels, uiLevelFlags, sLevelIDs );

	#ifdef JA2EDITOR
	if( !gfEditMode && !gfAniEditMode )
	#endif
	{
		RenderTacticalInterface( );
	}

	SaveBackgroundRects();

	//uiLevelFlags[0] = TILES_DYNAMIC_LAND;
	uiLevelFlags[0] = TILES_DYNAMIC_OBJECTS;
	uiLevelFlags[1] = TILES_DYNAMIC_SHADOWS;
	uiLevelFlags[2] = TILES_DYNAMIC_STRUCT_MERCS;
	uiLevelFlags[3] = TILES_DYNAMIC_MERCS;
	uiLevelFlags[4] = TILES_DYNAMIC_STRUCTURES;

	//sLevelIDs[0]    = RENDER_DYNAMIC_LAND;
	sLevelIDs[0]    = RENDER_DYNAMIC_OBJECTS;
	sLevelIDs[1]    = RENDER_DYNAMIC_SHADOWS;
	sLevelIDs[2]    = RENDER_DYNAMIC_STRUCT_MERCS;
	sLevelIDs[3]    = RENDER_DYNAMIC_MERCS;
	sLevelIDs[4]    = RENDER_DYNAMIC_STRUCTS;

	RenderTiles( 0, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 5, uiLevelFlags , sLevelIDs );


	uiLevelFlags[0] = TILES_DYNAMIC_ROOF;
	uiLevelFlags[1] = TILES_DYNAMIC_HIGHMERCS;
	uiLevelFlags[2] = TILES_DYNAMIC_ONROOF;

	sLevelIDs[0]    = RENDER_DYNAMIC_ROOF;
	sLevelIDs[1]    = RENDER_DYNAMIC_HIGHMERCS;
	sLevelIDs[2]    = RENDER_DYNAMIC_ONROOF;

	RenderTiles(0 , gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 3, uiLevelFlags, sLevelIDs );

	uiLevelFlags[0] = TILES_DYNAMIC_TOPMOST;
	sLevelIDs[0]    = RENDER_DYNAMIC_TOPMOST;

	// ATE: check here for mouse over structs.....
	RenderTiles( TILES_DYNAMIC_CHECKFOR_INT_TILE, gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS, 1, uiLevelFlags, sLevelIDs );

	SumAddiviveLayerOptimization( );

	ResetRenderParameters( );

}




BOOLEAN HandleScrollDirections( UINT32 ScrollFlags, INT16 sScrollXStep, INT16 sScrollYStep, INT16 *psTempRenderCenterX, INT16 *psTempRenderCenterY, BOOLEAN fCheckOnly )
{
	BOOLEAN fAGoodMove = FALSE, fMovedPos = FALSE;
	INT16		sTempX_W, sTempY_W;
	BOOLEAN fUpOK, fLeftOK;
	BOOLEAN fDownOK, fRightOK;
	INT16		sTempRenderCenterX, sTempRenderCenterY;

	sTempRenderCenterX = sTempRenderCenterY = 0;

	// This checking sequence just validates the values!
	if ( ScrollFlags & SCROLL_LEFT )
	{
		FromScreenToCellCoordinates( (INT16)-sScrollXStep, 0, &sTempX_W, &sTempY_W );
		sTempRenderCenterX = gsRenderCenterX + sTempX_W;
		sTempRenderCenterY = gsRenderCenterY + sTempY_W;

		fMovedPos=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );
		if ( fMovedPos )
		{
			fAGoodMove = TRUE;
		}

		if ( !fCheckOnly )
		{
			ScrollBackground(SCROLL_LEFT, sScrollXStep, sScrollYStep );
		}

	}

	if ( ScrollFlags & SCROLL_RIGHT )
	{
			FromScreenToCellCoordinates( sScrollXStep, 0, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fMovedPos=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );
			if ( fMovedPos )
			{
				fAGoodMove = TRUE;
			}

			if ( !fCheckOnly )
			{
				ScrollBackground(SCROLL_RIGHT, sScrollXStep, sScrollYStep );
			}
	}

	if ( ScrollFlags & SCROLL_UP )
	{
			FromScreenToCellCoordinates( 0, (INT16)-sScrollYStep, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fMovedPos=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );
			if ( fMovedPos )
			{
				fAGoodMove = TRUE;
			}

			if ( !fCheckOnly )
			{
				ScrollBackground(SCROLL_UP, sScrollXStep, sScrollYStep );
			}
	}

	if ( ScrollFlags & SCROLL_DOWN )
	{
			FromScreenToCellCoordinates( 0, sScrollYStep, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fMovedPos=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );
			if ( fMovedPos )
			{
				fAGoodMove = TRUE;
			}

			if ( !fCheckOnly )
			{
				ScrollBackground(SCROLL_DOWN, sScrollXStep, sScrollYStep );
			}

	}

	if ( ScrollFlags & SCROLL_UPLEFT )
	{
			// Check up
			FromScreenToCellCoordinates( 0, (INT16)-sScrollYStep, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fUpOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );

			// Check left
			FromScreenToCellCoordinates( (INT16)-sScrollXStep, 0, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fLeftOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );


			if ( fLeftOK && fUpOK )
			{
				FromScreenToCellCoordinates( (INT16)-sScrollXStep, (INT16)-sScrollYStep, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;
				fAGoodMove = TRUE;

				if ( !fCheckOnly )
				{
					ScrollBackground(SCROLL_UPLEFT, sScrollXStep, sScrollYStep );
				}

			}
			else if ( fUpOK )
			{
				fAGoodMove = TRUE;

				FromScreenToCellCoordinates( 0, (INT16)-sScrollYStep, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;

				if ( !fCheckOnly )
				{
					ScrollBackground(SCROLL_UP, sScrollXStep, sScrollYStep );
				}

			}
			else if ( fLeftOK )
			{
				fAGoodMove = TRUE;

				FromScreenToCellCoordinates( (INT16)-sScrollXStep, 0, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;

				if ( !fCheckOnly )
				{
					ScrollBackground(SCROLL_LEFT, sScrollXStep, sScrollYStep );
				}
			}
	}

	if ( ScrollFlags & SCROLL_UPRIGHT )
	{

			// Check up
			FromScreenToCellCoordinates( 0, (INT16)-sScrollYStep, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fUpOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );

			// Check right
			FromScreenToCellCoordinates( sScrollXStep, 0, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fRightOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );

			if ( fUpOK && fRightOK )
			{
				FromScreenToCellCoordinates( (INT16)sScrollXStep, (INT16)-sScrollYStep, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;
				fAGoodMove = TRUE;

				if ( !fCheckOnly )
				{
					ScrollBackground(SCROLL_UPRIGHT, sScrollXStep, sScrollYStep );
				}

			}
			else if ( fUpOK )
			{
				fAGoodMove = TRUE;

				FromScreenToCellCoordinates( 0, (INT16)-sScrollYStep, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;

				if ( !fCheckOnly )
				{
					ScrollBackground(SCROLL_UP, sScrollXStep, sScrollYStep );
				}
			}
			else if ( fRightOK )
			{
				fAGoodMove = TRUE;

				FromScreenToCellCoordinates( sScrollXStep, 0, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;

				if ( !fCheckOnly )
				{
					ScrollBackground(SCROLL_RIGHT, sScrollXStep, sScrollYStep );
				}
			}
	}

	if ( ScrollFlags & SCROLL_DOWNLEFT )
	{
			// Check down......
			FromScreenToCellCoordinates( 0, sScrollYStep, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fDownOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );

			// Check left.....
			FromScreenToCellCoordinates( (INT16)-sScrollXStep, 0, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fLeftOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );

			if ( fLeftOK && fDownOK )
			{
				fAGoodMove = TRUE;
				FromScreenToCellCoordinates( (INT16)-sScrollXStep, (INT16)sScrollYStep, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;

				if ( !fCheckOnly )
				{
					ScrollBackground(SCROLL_DOWNLEFT, sScrollXStep, sScrollYStep );
				}

			}
			else if ( fLeftOK )
			{
					FromScreenToCellCoordinates( (INT16)-sScrollXStep, 0, &sTempX_W, &sTempY_W );
					sTempRenderCenterX = gsRenderCenterX + sTempX_W;
					sTempRenderCenterY = gsRenderCenterY + sTempY_W;
					fAGoodMove = TRUE;

					if ( !fCheckOnly )
					{
						ScrollBackground(SCROLL_LEFT, sScrollXStep, sScrollYStep );
					}
			}
			else if ( fDownOK )
			{
					FromScreenToCellCoordinates( 0, sScrollYStep, &sTempX_W, &sTempY_W );
					sTempRenderCenterX = gsRenderCenterX + sTempX_W;
					sTempRenderCenterY = gsRenderCenterY + sTempY_W;
					fAGoodMove = TRUE;

					if ( !fCheckOnly )
					{
						ScrollBackground(SCROLL_DOWN, sScrollXStep, sScrollYStep );
					}
			}
	}

	if ( ScrollFlags & SCROLL_DOWNRIGHT )
	{
			// Check right
			FromScreenToCellCoordinates( sScrollXStep, 0, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fRightOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );

			// Check down
			FromScreenToCellCoordinates( 0, sScrollYStep, &sTempX_W, &sTempY_W );
			sTempRenderCenterX = gsRenderCenterX + sTempX_W;
			sTempRenderCenterY = gsRenderCenterY + sTempY_W;
			fDownOK=ApplyScrolling( sTempRenderCenterX, sTempRenderCenterY, FALSE, fCheckOnly );

			if ( fDownOK && fRightOK )
			{
				FromScreenToCellCoordinates( (INT16)sScrollXStep, (INT16)sScrollYStep, &sTempX_W, &sTempY_W );
				sTempRenderCenterX = gsRenderCenterX + sTempX_W;
				sTempRenderCenterY = gsRenderCenterY + sTempY_W;
				fAGoodMove = TRUE;

				if ( !fCheckOnly )
				{
					ScrollBackground( SCROLL_DOWNRIGHT, sScrollXStep, sScrollYStep );
				}

			}
			else if ( fDownOK )
			{
					FromScreenToCellCoordinates( 0, sScrollYStep, &sTempX_W, &sTempY_W );
					sTempRenderCenterX = gsRenderCenterX + sTempX_W;
					sTempRenderCenterY = gsRenderCenterY + sTempY_W;
					fAGoodMove = TRUE;

					if ( !fCheckOnly )
					{
						ScrollBackground( SCROLL_DOWN, sScrollXStep, sScrollYStep );
					}
			}
			else if ( fRightOK )
			{
					FromScreenToCellCoordinates( sScrollXStep, 0, &sTempX_W, &sTempY_W );
					sTempRenderCenterX = gsRenderCenterX + sTempX_W;
					sTempRenderCenterY = gsRenderCenterY + sTempY_W;
					fAGoodMove = TRUE;

					if ( !fCheckOnly )
					{
						ScrollBackground( SCROLL_RIGHT, sScrollXStep, sScrollYStep );
					}
			}

	}

	( *psTempRenderCenterX ) = sTempRenderCenterX;
	( *psTempRenderCenterY ) = sTempRenderCenterY;


	return( fAGoodMove );
}

extern BOOLEAN gfNextRefreshFullScreen;

void ScrollWorld( )
{
	UINT32		ScrollFlags = 0;
	BOOLEAN		fDoScroll = FALSE, fAGoodMove = FALSE;
	INT16	sTempRenderCenterX, sTempRenderCenterY;
	INT8	bDirection;
	INT16	sScrollXStep=-1;
	INT16 sScrollYStep=-1;
	BOOLEAN		fIgnoreInput	= FALSE;
  static    UINT8   ubOldScrollSpeed = 0;
  static    BOOLEAN fFirstTimeInSlideToMode = TRUE;


	if ( gfIgnoreScrollDueToCenterAdjust )
	{
		//	gfIgnoreScrollDueToCenterAdjust = FALSE;
		return;
	}

	if ( gfIgnoreScrolling == 1 )
	{
		return;
	}

	if ( gfIgnoreScrolling == 2 )
	{
		fIgnoreInput = TRUE;
	}

	if ( gCurrentUIMode == LOCKUI_MODE )
	{
		fIgnoreInput = TRUE;
	}


	// If in editor, ignore scrolling if any of the shift keys pressed with arrow keys
	if ( gfEditMode && ( _KeyDown(CTRL) || _KeyDown(ALT) ) )
		return;

	// Ignore if ALT DONW
	if ( _KeyDown( ALT ) )
		return;


	do
	{

		if ( gfIgnoreScrolling != 3 )
		{
			// Check for sliding			
			if (!TileIsOutOfBounds(gTacticalStatus.sSlideTarget))
			{
				 // Ignore all input...
				 // Check if we have reached out dest!
         if ( fFirstTimeInSlideToMode )
         {
           ubOldScrollSpeed = gubCurScrollSpeedID;
           fFirstTimeInSlideToMode = FALSE;
         }

         // Make faster!
         //gubCurScrollSpeedID = 2;

				 ScrollFlags = 0;
				 fDoScroll = FALSE;
				 //
				 if ( SoldierLocationRelativeToScreen( gTacticalStatus.sSlideTarget, gTacticalStatus.sSlideReason, &bDirection, &ScrollFlags ) && GridNoOnVisibleWorldTile( gTacticalStatus.sSlideTarget ) )
				 {
						ScrollFlags = gScrollDirectionFlags[ bDirection ];
						fDoScroll			= TRUE;
						fIgnoreInput	= TRUE;
				 }
				 else
				 {
						// We've stopped!
						gTacticalStatus.sSlideTarget = NOWHERE;
				 }
			}
      else
      {
        // Restore old scroll speed
        if ( !fFirstTimeInSlideToMode )
        {
          gubCurScrollSpeedID = ubOldScrollSpeed;
        }
        fFirstTimeInSlideToMode = TRUE;
      }
		}

		if ( !fIgnoreInput )
		{
			// Check keys
			if ( _KeyDown( UPARROW )  )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_UP;
			}


			if ( _KeyDown( DNARROW )  )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_DOWN;
			}


			if ( _KeyDown( RIGHTARROW )  )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_RIGHT;
			}


			if ( _KeyDown( LEFTARROW )  )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_LEFT;
			}


			// Do mouse - PUT INTO A TIMER!
			// Put a counter on starting from mouse, if we have not started already!
			if ( !gfScrollInertia && gfScrollPending == FALSE )
			{
				if ( !COUNTERDONE( STARTSCROLL ) )
				{
					break;
				}
				RESETCOUNTER( STARTSCROLL );

			}

			if ( gusMouseYPos == 0 )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_UP;
			}


			if ( gusMouseYPos >= SCREEN_HEIGHT - 1 )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_DOWN;
			}


			if ( gusMouseXPos >= SCREEN_WIDTH - 1 )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_RIGHT;
			}


			if ( gusMouseXPos == 0 )
			{
				fDoScroll = TRUE;
				ScrollFlags |= SCROLL_LEFT;
			}
		}

	} while( FALSE );


	if ( fDoScroll )
	{
			if ( gfDoSubtileScroll )
			{
				if ( gfScrollInertia > gubNewScrollIDSpeeds[ gubCurScrollSpeedID ] )
				{
					gubCurScrollSpeedID++;

					if ( gubCurScrollSpeedID > gubScrollSpeedEndID )
					{
						gubCurScrollSpeedID = gubScrollSpeedEndID;
					}
				}
			}

			//if ( !gfDoVideoScroll )
			//{
			//	gubCurScrollSpeedID = 4;
			//}


			// Adjust speed based on whether shift is down
			if ( _KeyDown( SHIFT ) )
			{
				sScrollXStep = gubNewScrollXSpeeds[ gfDoVideoScroll ][ 3 ];
				sScrollYStep = gubNewScrollYSpeeds[ gfDoVideoScroll ][ 3 ];
			}
			else
			{
				sScrollXStep = gubNewScrollXSpeeds[ gfDoVideoScroll ][ gubCurScrollSpeedID ];
				sScrollYStep = gubNewScrollYSpeeds[ gfDoVideoScroll ][ gubCurScrollSpeedID ];
			}


			// Set diagonal flags!
			if ( ( ScrollFlags & SCROLL_LEFT ) && ( ScrollFlags & SCROLL_UP ) )
			{
				ScrollFlags = SCROLL_UPLEFT;
			}
			if ( ( ScrollFlags & SCROLL_RIGHT ) && ( ScrollFlags & SCROLL_UP ) )
			{
				ScrollFlags = SCROLL_UPRIGHT;
			}
			if ( ( ScrollFlags & SCROLL_LEFT ) && ( ScrollFlags & SCROLL_DOWN ) )
			{
				ScrollFlags = SCROLL_DOWNLEFT;
			}
			if ( ( ScrollFlags & SCROLL_RIGHT ) && ( ScrollFlags & SCROLL_DOWN ) )
			{
				ScrollFlags = SCROLL_DOWNRIGHT;
			}

			fAGoodMove = HandleScrollDirections( ScrollFlags, sScrollXStep, sScrollYStep, &sTempRenderCenterX, &sTempRenderCenterY, TRUE );
	}

	// Has this been an OK scroll?
	if ( fAGoodMove )
	{
		if ( COUNTERDONE( NEXTSCROLL ) )
		{
			RESETCOUNTER( NEXTSCROLL );

			// Are we starting a new scroll?
			if ( gfScrollInertia == 0 && gfScrollPending == FALSE )
			{
					// We are starting to scroll - setup scroll pending
					gfScrollPending = TRUE;

					// Remove any interface stuff
					ClearInterface( );

					// Return so that next frame things will be erased!
					return;
			}

			// If here, set scroll pending to false
			gfScrollPending = FALSE;


			// INcrement scroll intertia
			gfScrollInertia++;

			// Now we actually begin our scrolling
			HandleScrollDirections( ScrollFlags, sScrollXStep, sScrollYStep, &sTempRenderCenterX, &sTempRenderCenterY, FALSE );

			if( gfNextRefreshFullScreen ) SetRenderFlags( RENDER_FLAG_FULL );
		}
	}
	else
	{
		// ATE: Also if scroll pending never got to scroll....
		if ( gfScrollPending == TRUE )
		{
			// Do a complete rebuild!
			gfScrollPending = FALSE;

			// Restore Interface!
			RestoreInterface( );

			// Delete Topmost blitters saved areas
			DeleteVideoOverlaysArea( );

		}

		// Check if we have just stopped scrolling!
		if ( gfScrollInertia != FALSE  )
		{
			SetRenderFlags( RENDER_FLAG_FULL | RENDER_FLAG_CHECKZ );

			// Restore Interface!
			RestoreInterface( );

			// Delete Topmost blitters saved areas
			DeleteVideoOverlaysArea( );

		}

		gfScrollInertia = FALSE;
		gfScrollPending = FALSE;

		if ( gfDoSubtileScroll )
		{
			gubCurScrollSpeedID = gubScrollSpeedStartID;
		}

	}
}


/* Initialization
 *
 * any questions? joker
 */

void InitializeViewPort()
{
	gsVIEWPORT_START_X			= 0;
	gsVIEWPORT_START_Y			= 0;
	gsVIEWPORT_WINDOW_START_Y	= 0;
	gsVIEWPORT_WINDOW_END_Y		= INTERFACE_START_Y;
	gsVIEWPORT_END_X			= SCREEN_WIDTH;
	gsVIEWPORT_END_Y			= INTERFACE_START_Y;

	gClippingRect.iLeft		= 0;
	gClippingRect.iTop		= 0;
	gClippingRect.iRight	= SCREEN_WIDTH;
	gClippingRect.iBottom	= SCREEN_HEIGHT - INTERFACE_HEIGHT;
}

void InitRenderParams( UINT8 ubRestrictionID )
{
		INT16 gsTilesX, gsTilesY;
		UINT32 cnt, cnt2;
		DOUBLE  dWorldX, dWorldY;

		switch( ubRestrictionID )
		{
			case 0:		//Default!

				gTopLeftWorldLimitX = CELL_X_SIZE;
				gTopLeftWorldLimitY = ( WORLD_ROWS / 2 ) * CELL_X_SIZE;

				gTopRightWorldLimitX = ( WORLD_COLS / 2 ) * CELL_Y_SIZE;
				gTopRightWorldLimitY = CELL_X_SIZE;

				gBottomLeftWorldLimitX = ( ( WORLD_COLS / 2 ) * CELL_Y_SIZE );
				gBottomLeftWorldLimitY = ( WORLD_ROWS * CELL_Y_SIZE );

				gBottomRightWorldLimitX = ( WORLD_COLS * CELL_Y_SIZE );
				gBottomRightWorldLimitY = ( ( WORLD_ROWS / 2 ) * CELL_X_SIZE );
				break;

			case 1:		// BAEMENT LEVEL 1

				gTopLeftWorldLimitX = ( 3 * WORLD_ROWS / 10 ) * CELL_X_SIZE;
				gTopLeftWorldLimitY = ( WORLD_ROWS / 2 ) * CELL_X_SIZE;

				gTopRightWorldLimitX = ( WORLD_ROWS / 2 ) * CELL_X_SIZE;
				gTopRightWorldLimitY = ( 3 * WORLD_COLS / 10 ) * CELL_X_SIZE;

				gBottomLeftWorldLimitX = ( WORLD_ROWS / 2 ) * CELL_X_SIZE;
				gBottomLeftWorldLimitY = ( 7 * WORLD_COLS / 10 ) * CELL_X_SIZE;

				gBottomRightWorldLimitX = ( 7 * WORLD_ROWS / 10 ) * CELL_X_SIZE;
				gBottomRightWorldLimitY = ( WORLD_ROWS / 2 ) * CELL_X_SIZE;
				break;

		}

		gCenterWorldX = ( WORLD_ROWS ) / 2 * CELL_X_SIZE;
		gCenterWorldY = ( WORLD_COLS ) / 2 * CELL_Y_SIZE;

		// Convert Bounding box into screen coords
		FromCellToScreenCoordinates( gTopLeftWorldLimitX, gTopLeftWorldLimitY, &gsTLX, &gsTLY );
		FromCellToScreenCoordinates( gTopRightWorldLimitX, gTopRightWorldLimitY, &gsTRX, &gsTRY );
		FromCellToScreenCoordinates( gBottomLeftWorldLimitX, gBottomLeftWorldLimitY, &gsBLX, &gsBLY );
		FromCellToScreenCoordinates( gBottomRightWorldLimitX, gBottomRightWorldLimitY, &gsBRX, &gsBRY );
		FromCellToScreenCoordinates( gCenterWorldX , gCenterWorldY, &gsCX, &gsCY );

		// Adjust for interface height tabbing!
		gsTLY += ROOF_LEVEL_HEIGHT;
		gsTRY += ROOF_LEVEL_HEIGHT;
		gsCY  += ( ROOF_LEVEL_HEIGHT / 2 );

		// Take these spaning distances and determine # tiles spaning
		gsTilesX = ( gsTRX - gsTLX ) / WORLD_TILE_X;
		gsTilesY = ( gsBRY - gsTRY ) / WORLD_TILE_Y;

		DebugMsg(TOPIC_JA2, DBG_LEVEL_0, String("World Screen Width %d Height %d", ( gsTRX - gsTLX ), ( gsBRY - gsTRY )));


		// Determine scale factors
		// First scale world screen coords for VIEWPORT ratio
		dWorldX = (DOUBLE)( gsTRX - gsTLX );
		dWorldY = (DOUBLE)( gsBRY - gsTRY );

		gdScaleX = (DOUBLE)RADAR_WINDOW_WIDTH /  dWorldX;
		gdScaleY = (DOUBLE)RADAR_WINDOW_HEIGHT / dWorldY;

		for ( cnt = 0, cnt2 = 0; cnt2 < NUM_ITEM_CYCLE_COLORS; cnt+=3, cnt2++ )
		{
			us16BPPItemCycleWhiteColors[ cnt2 ] = Get16BPPColor( FROMRGB( ubRGBItemCycleWhiteColors[ cnt ], ubRGBItemCycleWhiteColors[ cnt + 1 ], ubRGBItemCycleWhiteColors[ cnt + 2] ) );
			us16BPPItemCycleRedColors[ cnt2 ] = Get16BPPColor( FROMRGB( ubRGBItemCycleRedColors[ cnt ], ubRGBItemCycleRedColors[ cnt + 1 ], ubRGBItemCycleRedColors[ cnt + 2] ) );
			us16BPPItemCycleYellowColors[ cnt2 ] = Get16BPPColor( FROMRGB( ubRGBItemCycleYellowColors[ cnt ], ubRGBItemCycleYellowColors[ cnt + 1 ], ubRGBItemCycleYellowColors[ cnt + 2] ) );
		}

		gsLobOutline = Get16BPPColor( FROMRGB( 10, 200, 10 ) );
		gsThrowOutline = Get16BPPColor( FROMRGB( 253, 212, 10 ) );
		gsGiveOutline = Get16BPPColor( FROMRGB( 253, 0, 0 ) );

		gusNormalItemOutlineColor = Get16BPPColor( FROMRGB( 255, 255, 255 ) );
		gusYellowItemOutlineColor = Get16BPPColor( FROMRGB( 255, 255, 0 ) );

		// NOW GET DISTANCE SPANNING WORLD LIMITS IN WORLD COORDS
		//FromScreenToCellCoordinates( ( gTopRightWorldLimitX - gTopLeftWorldLimitX ), ( gTopRightWorldLimitY - gTopLeftWorldLimitY ), &gsWorldSpanX, &gsWorldSpanY );

		// CALCULATE 16BPP COLORS FOR ITEMS

}

// WANNE: Scrolling: Only scroll, if the map is larger than the radar map
// For example: Do not allow scrolling in Rebel Basement.
// Appy? HEahehahehahehae.....
BOOLEAN ApplyScrolling( INT16 sTempRenderCenterX, INT16 sTempRenderCenterY, BOOLEAN fForceAdjust, BOOLEAN fCheckOnly )
{
	BOOLEAN		fScrollGood = FALSE;
	BOOLEAN		fOutLeft = FALSE;
	BOOLEAN		fOutRight = FALSE;
	BOOLEAN		fOutTop = FALSE;
	BOOLEAN		fOutBottom = FALSE;


	double	dOpp, dAdj, dAngle;

	INT16 sTopLeftWorldX, sTopLeftWorldY;
	INT16 sTopRightWorldX, sTopRightWorldY;
	INT16 sBottomLeftWorldX, sBottomLeftWorldY;
	INT16 sBottomRightWorldX, sBottomRightWorldY;

	INT16 sTempPosX_W, sTempPosY_W;


	// For debug text for all 4 angles
	double at1, at2, at3, at4;

	INT16	sX_S, sY_S;
	INT16 sScreenCenterX, sScreenCenterY;
	INT16 sDistToCenterY, sDistToCenterX;
	INT16 sNewScreenX, sNewScreenY;
	INT16	sMult;

	INT16 sRadarTLX, sRadarTLY;
	INT16 sRadarBRX, sRadarBRY;
	INT16 sRadarCX, sRadarCY;
	INT16 sHeight, sWidth, sX, sY;
	// CHRISL:
	INT16			gsRadarX;
	INT16			gsRadarY;
	BOOLEAN			fAllowScrollingHorizontal = FALSE;
	BOOLEAN			fAllowScrollingVertical = FALSE;


	//Makesure it's a multiple of 5
	sMult = sTempRenderCenterX / CELL_X_SIZE;
	sTempRenderCenterX = ( sMult * CELL_X_SIZE ) + ( CELL_X_SIZE / 2 );

	//Makesure it's a multiple of 5
	sMult = sTempRenderCenterY / CELL_Y_SIZE;
	sTempRenderCenterY = ( sMult * CELL_Y_SIZE ) + ( CELL_Y_SIZE / 2 );


	// Find the diustance from render center to true world center
	sDistToCenterX = sTempRenderCenterX - gCenterWorldX;
	sDistToCenterY = sTempRenderCenterY - gCenterWorldY;

	// From render center in world coords, convert to render center in "screen" coords
	FromCellToScreenCoordinates( sDistToCenterX , sDistToCenterY, &sScreenCenterX, &sScreenCenterY );

	// Subtract screen center
	sScreenCenterX += gsCX;
	sScreenCenterY += gsCY;

	// Adjust for offset position on screen
	sScreenCenterX -= 0;
	sScreenCenterY -= 10;


	// Get corners in screen coords
	// TOP LEFT
	sX_S = ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2;
	sY_S = ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2;

	sTopLeftWorldX = sScreenCenterX  - sX_S;
	sTopLeftWorldY = sScreenCenterY  - sY_S;

	sTopRightWorldX = sScreenCenterX  + sX_S;
	sTopRightWorldY = sScreenCenterY  - sY_S;

	sBottomLeftWorldX = sScreenCenterX  - sX_S;
	sBottomLeftWorldY = sScreenCenterY  + sY_S;

	sBottomRightWorldX = sScreenCenterX  + sX_S;
	sBottomRightWorldY = sScreenCenterY  + sY_S;


	// WANNE: Scrolling bugfix, if we are talking in a small tactical map (e.g: Rebel Basement) in high resolution (1024x768)[2007-05-14]
	// Determine radar coordinates
	sRadarCX	= (INT16)( gsCX * gdScaleX );
	sRadarCY	= (INT16)( gsCY * gdScaleY );

	if( guiCurrentScreen == MAP_SCREEN )
	{
		gsRadarX = RADAR_WINDOW_STRAT_X;
		gsRadarY = RADAR_WINDOW_STRAT_Y;
	}
	else if ( gsCurInterfacePanel == SM_PANEL )
	{
		gsRadarX = RADAR_WINDOW_SM_X;
		gsRadarY = RADAR_WINDOW_SM_Y;
	}
	else
	{
		gsRadarX = RADAR_WINDOW_TM_X;
		gsRadarY = RADAR_WINDOW_TM_Y;
	}


	sWidth		= ( RADAR_WINDOW_WIDTH );
	sHeight		= ( RADAR_WINDOW_HEIGHT );
	sX				= gsRadarX;
	sY				= gsRadarY;


	sRadarTLX = (INT16)( ( sTopLeftWorldX * gdScaleX ) - sRadarCX  + sX + ( sWidth /2 ) );
	sRadarTLY = (INT16)( ( sTopLeftWorldY * gdScaleY ) - sRadarCY + gsRadarY + ( sHeight /2 ) );
	sRadarBRX = (INT16)( ( sBottomRightWorldX * gdScaleX ) - sRadarCX + sX + ( sWidth /2 ) );
	sRadarBRY = (INT16)( ( sBottomRightWorldY * gdScaleY ) - sRadarCY + gsRadarY + ( sHeight /2 ) );

	// WANNE: Scrolling bugfix, if we are talking in a small tactical map (e.g: Rebel Basement) in high resolution (1024x768)[2007-05-14]
	if ((sRadarBRX - sRadarTLX) <= RADAR_WINDOW_WIDTH)
	{
		fAllowScrollingHorizontal = TRUE;
	}

	if ((sRadarBRY - sRadarTLY) <= RADAR_WINDOW_HEIGHT)
	{
		fAllowScrollingVertical = TRUE;
	}

	if ((fAllowScrollingHorizontal == FALSE || fAllowScrollingVertical == FALSE) && (gfDialogControl == TRUE))
	{
		gfDialogControl = FALSE;
		return (FALSE);
	}

	// WANNE: Scrolling bugfix for small maps in high resolution (eg: Rebel Basement)
	//if ((fAllowScrollingHorizontal || fAllowScrollingVertical) && gfDialogControl)
	//{

	// Get angles
	// TOP LEFT CORNER FIRST
	dOpp = sTopLeftWorldY - gsTLY;
	dAdj = sTopLeftWorldX - gsTLX;

	dAngle = (double)atan2( dAdj, dOpp );
	at1 = dAngle * 180 / PI;

	if ( dAngle < 0 )
	{
		fOutLeft = TRUE;
	}
	else	if ( dAngle > PI/2 )
	{
		fOutTop = TRUE;
	}

	// TOP RIGHT CORNER
	dOpp = sTopRightWorldY - gsTRY;
	dAdj = gsTRX - sTopRightWorldX;

	dAngle = (double)atan2( dAdj, dOpp );
	at2 = dAngle * 180 / PI;

	if ( dAngle < 0 )
	{
		fOutRight = TRUE;
	}
	else if ( dAngle > PI/2 )
	{
		fOutTop = TRUE;
	}


	// BOTTOM LEFT CORNER
	dOpp = gsBLY - sBottomLeftWorldY;
	dAdj = sBottomLeftWorldX - gsBLX;

	dAngle = (double)atan2( dAdj, dOpp );
	at3 = dAngle * 180 / PI;

	if ( dAngle < 0 )
	{
		fOutLeft = TRUE;
	}
	else if ( dAngle > PI/2 )
	{
		fOutBottom = TRUE;
	}

	// BOTTOM RIGHT CORNER
	dOpp = gsBRY - sBottomRightWorldY;
	dAdj = gsBRX - sBottomRightWorldX;

	dAngle = (double)atan2( dAdj, dOpp );
	at4 = dAngle * 180 / PI;

	if ( dAngle < 0 )
	{
		fOutRight = TRUE;
	}
	else if ( dAngle > PI/2 )
	{
		fOutBottom = TRUE;
	}

	sprintf( gDebugStr, "Angles: %d %d %d %d", (int)at1, (int)at2, (int)at3, (int)at4 );

	if ( !fOutRight && !fOutLeft && !fOutTop && !fOutBottom )
	{
		fScrollGood = TRUE;
	}

	// If in editor, anything goes
	if ( gfEditMode && _KeyDown( SHIFT ) )
	{
		fScrollGood = TRUE;
	}

	// Reset some UI flags
	gfUIShowExitEast								= FALSE;
	gfUIShowExitWest								= FALSE;
	gfUIShowExitNorth								= FALSE;
	gfUIShowExitSouth								= FALSE;


	if ( !fScrollGood )
	{
		// Force adjustment, if true
		if ( fForceAdjust )
		{
			if ( fOutTop )
			{
				// Adjust screen coordinates on the Y!
				CorrectRenderCenter( sScreenCenterX, (INT16)(gsTLY + sY_S ), &sNewScreenX, &sNewScreenY );
				FromScreenToCellCoordinates( sNewScreenX, sNewScreenY , &sTempPosX_W, &sTempPosY_W );

				sTempRenderCenterX = sTempPosX_W;
				sTempRenderCenterY = sTempPosY_W;

				fScrollGood = TRUE;
			}

			if ( fOutBottom )
			{
				// OK, Ajust this since we get rounding errors in our two different calculations.
				CorrectRenderCenter( sScreenCenterX, (INT16)(gsBLY - sY_S - 50 ), &sNewScreenX, &sNewScreenY );
				FromScreenToCellCoordinates( sNewScreenX, sNewScreenY , &sTempPosX_W, &sTempPosY_W );

				sTempRenderCenterX = sTempPosX_W;
				sTempRenderCenterY = sTempPosY_W;
				fScrollGood = TRUE;
			}

			if ( fOutLeft )
			{
				CorrectRenderCenter( (INT16)( gsTLX + sX_S ) , sScreenCenterY , &sNewScreenX, &sNewScreenY );
				FromScreenToCellCoordinates( sNewScreenX, sNewScreenY , &sTempPosX_W, &sTempPosY_W );

				sTempRenderCenterX = sTempPosX_W;
				sTempRenderCenterY = sTempPosY_W;

				fScrollGood = TRUE;
			}

			if ( fOutRight )
			{
				CorrectRenderCenter( (INT16)( gsTRX - sX_S ) , sScreenCenterY , &sNewScreenX, &sNewScreenY );
				FromScreenToCellCoordinates( sNewScreenX, sNewScreenY , &sTempPosX_W, &sTempPosY_W );

				sTempRenderCenterX = sTempPosX_W;
				sTempRenderCenterY = sTempPosY_W;
				fScrollGood = TRUE;
			}

		}
		else
		{
			if ( fOutRight )
			{
				// Check where our cursor is!
				if ( gusMouseXPos >= SCREEN_WIDTH - 1 )
				{
					gfUIShowExitEast = TRUE;
				}
			}

			if ( fOutLeft )
			{
				// Check where our cursor is!
				if ( gusMouseXPos == 0 )
				{
					gfUIShowExitWest = TRUE;
				}
			}

			if ( fOutTop )
			{
				// Check where our cursor is!
				if ( gusMouseYPos == 0 )
				{
					gfUIShowExitNorth = TRUE;
				}
			}

			if ( fOutBottom )
			{
				// Check where our cursor is!
				if ( gusMouseYPos >= SCREEN_HEIGHT - 1 )
				{
					gfUIShowExitSouth = TRUE;
				}
			}

		}
	}


	if ( fScrollGood )
	{
		if ( !fCheckOnly )
		{
				sprintf( gDebugStr, "Center: %d %d ", (int)gsRenderCenterX, (int)gsRenderCenterY );

				//Makesure it's a multiple of 5
				sMult = sTempRenderCenterX / CELL_X_SIZE;

				gsRenderCenterX = ( sMult * CELL_X_SIZE ) + ( CELL_X_SIZE / 2 );

				//Makesure it's a multiple of 5
					sMult = sTempRenderCenterY / CELL_Y_SIZE;

				gsRenderCenterY = ( sMult * CELL_Y_SIZE ) + ( CELL_Y_SIZE / 2 );

				//gsRenderCenterX = sTempRenderCenterX;
				//gsRenderCenterY = sTempRenderCenterY;


				gsTopLeftWorldX = sTopLeftWorldX - gsTLX;
					gsTopRightWorldX = sTopRightWorldX - gsTLX;
					gsBottomLeftWorldX = sBottomLeftWorldX - gsTLX;
					gsBottomRightWorldX = sBottomRightWorldX - gsTLX;

				gsTopLeftWorldY = sTopLeftWorldY - gsTLY;
				gsTopRightWorldY = sTopRightWorldY - gsTLY;
				gsBottomLeftWorldY = sBottomLeftWorldY - gsTLY;
				gsBottomRightWorldY = sBottomRightWorldY - gsTLY;

        SetPositionSndsVolumeAndPanning( );
		}

		return( TRUE );
	}

	return( FALSE );
	//}

	//return ( FALSE );
}


void ClearMarkedTiles(void)
{
	INT32 uiCount;

	for(uiCount=0; uiCount < WORLD_MAX; uiCount++)
		gpWorldLevelData[uiCount].uiFlags&=(~MAPELEMENT_REDRAW);

}

// @@ATECLIP TO WORLD!
void InvalidateWorldRedundencyRadius(INT16 sX, INT16 sY, INT16 sRadius)
{
	INT16 sCountX, sCountY;
	UINT32 uiTile;

	SetRenderFlags( RENDER_FLAG_CHECKZ );

	for(sCountY=sY-sRadius; sCountY < (sY+sRadius+2); sCountY++)
	{
		for(sCountX=sX-sRadius; sCountX < (sX+sRadius+2); sCountX++)
		{
			uiTile=FASTMAPROWCOLTOPOS(sCountY, sCountX);

			gpWorldLevelData[uiTile].uiFlags |= MAPELEMENT_REEVALUATE_REDUNDENCY;

		}
	}
}


void InvalidateWorldRedundency( )
{
	INT32 uiCount;

	SetRenderFlags( RENDER_FLAG_CHECKZ );

	for(uiCount=0; uiCount < WORLD_MAX; uiCount++)
		gpWorldLevelData[uiCount].uiFlags |= MAPELEMENT_REEVALUATE_REDUNDENCY;

}

#define	Z_STRIP_DELTA_Y  ( Z_SUBLAYERS * 10 )

/**********************************************************************************************
 Blt8BPPDataTo16BPPBufferTransZIncClip

	Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit
	buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the
	pixel's Z level is below that of the current pixel, it is written on, and the Z value is
	updated to the current value,	for any non-transparent pixels. The Z-buffer is 16 bit, and
	must be the same dimensions (including Pitch) as the destination.

**********************************************************************************************/
BOOLEAN Blt8BPPDataTo16BPPBufferTransZIncClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion)
{
	UINT16 *p16BPPPalette;
	UINT32 uiOffset;
	UINT32 usHeight, usWidth, Unblitted;
	UINT8	 *SrcPtr, *DestPtr, *ZPtr;
	UINT32 LineSkip;
  ETRLEObject *pTrav;
	INT32	 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount;
	INT32  ClipX1, ClipY1, ClipX2, ClipY2;
	UINT16 usZLevel, usZStartLevel, usZColsToGo, usZStartIndex, usCount, usZIndex, usZStartCols;
	INT8 *pZArray;
	ZStripInfo *pZInfo;

	// Assertions
	Assert( hSrcVObject != NULL );
	Assert( pBuffer != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;

	if(clipregion==NULL)
	{
		ClipX1=ClippingRect.iLeft;
		ClipY1=ClippingRect.iTop;
		ClipX2=ClippingRect.iRight;
		ClipY2=ClippingRect.iBottom;
	}
	else
	{
		ClipX1=clipregion->iLeft;
		ClipY1=clipregion->iTop;
		ClipX2=clipregion->iRight;
		ClipY2=clipregion->iBottom;
	}

	// Calculate rows hanging off each side of the screen
	LeftSkip=__min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth);
	RightSkip=__min(max(ClipX2, (iTempX+(INT32)usWidth)) - ClipX2, (INT32)usWidth);
	TopSkip=__min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight);
	BottomSkip=__min(__max(ClipY2, (iTempY+(INT32)usHeight)) - ClipY2, (INT32)usHeight);

	// calculate the remaining rows and columns to blit
	BlitLength=((INT32)usWidth-LeftSkip-RightSkip);
	BlitHeight=((INT32)usHeight-TopSkip-BottomSkip);

	// check if whole thing is clipped
	if((LeftSkip >=(INT32)usWidth) || (RightSkip >=(INT32)usWidth))
		return(TRUE);

	// check if whole thing is clipped
	if((TopSkip >=(INT32)usHeight) || (BottomSkip >=(INT32)usHeight))
		return(TRUE);

	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	p16BPPPalette = hSrcVObject->pShadeCurrent;
	LineSkip=(uiDestPitchBYTES-(BlitLength*2));

	if(hSrcVObject->ppZStripInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}
	// setup for the z-column blitting stuff
	pZInfo=hSrcVObject->ppZStripInfo[usIndex];
	if(pZInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}

	usZStartLevel=(UINT16)((INT16)usZValue+((INT16)pZInfo->bInitialZChange*Z_STRIP_DELTA_Y));
	// set to odd number of pixels for first column

	if(LeftSkip > pZInfo->ubFirstZStripWidth)
	{
		usZStartCols=(LeftSkip - pZInfo->ubFirstZStripWidth);
		usZStartCols=20-(usZStartCols%20);
	}
	else if(LeftSkip < pZInfo->ubFirstZStripWidth)
		usZStartCols=(UINT16)(pZInfo->ubFirstZStripWidth - LeftSkip);
	else
		usZStartCols=20;

	usZColsToGo=usZStartCols;

	pZArray=pZInfo->pbZChange;

	if(LeftSkip >= pZInfo->ubFirstZStripWidth)
	{
		// Index into array after doing left clipping
		usZStartIndex=1 + ((LeftSkip-pZInfo->ubFirstZStripWidth)/20);

		//calculates the Z-value after left-side clipping
		if(usZStartIndex)
		{
			for(usCount=0; usCount < usZStartIndex; usCount++)
			{
				switch(pZArray[usCount])
				{
					case -1:	usZStartLevel-=Z_STRIP_DELTA_Y;
										break;
					case 0:		//no change
										break;
					case 1:		usZStartLevel+=Z_STRIP_DELTA_Y;
										break;
				}
			}
		}
	}
	else
		usZStartIndex=0;

	usZLevel=usZStartLevel;
	usZIndex=usZStartIndex;

	__asm {

		mov		esi, SrcPtr
		mov		edi, DestPtr
		mov		edx, p16BPPPalette
		xor		eax, eax
		mov		ebx, ZPtr
		xor		ecx, ecx

		cmp		TopSkip, 0							// check for nothing clipped on top
		je		LeftSkipSetup


// Skips the number of lines clipped at the top
TopSkipLoop:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		TopSkipLoop
		jz		TSEndLine

		add		esi, ecx
		jmp		TopSkipLoop

TSEndLine:
		dec		TopSkip
		jnz		TopSkipLoop


// Start of line loop

// Skips the pixels hanging outside the left-side boundry
LeftSkipSetup:

		mov		Unblitted, 0					// Unblitted counts any pixels left from a run
		mov		eax, LeftSkip					// after we have skipped enough left-side pixels
		mov		LSCount, eax					// LSCount counts how many pixels skipped so far
		or		eax, eax
		jz		BlitLineSetup					// check for nothing to skip

LeftSkipLoop:

		mov		cl, [esi]
		inc		esi

		or		cl, cl
		js		LSTrans

		cmp		ecx, LSCount
		je		LSSkip2								// if equal, skip whole, and start blit with new run
		jb		LSSkip1								// if less, skip whole thing

		add		esi, LSCount					// skip partial run, jump into normal loop for rest
		sub		ecx, LSCount
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitNTL1							// *** jumps into non-transparent blit loop

LSSkip2:
		add		esi, ecx							// skip whole run, and start blit with new run
		jmp		BlitLineSetup


LSSkip1:
		add		esi, ecx							// skip whole run, continue skipping
		sub		LSCount, ecx
		jmp		LeftSkipLoop


LSTrans:
		and		ecx, 07fH
		cmp		ecx, LSCount
		je		BlitLineSetup					// if equal, skip whole, and start blit with new run
		jb		LSTrans1							// if less, skip whole thing

		sub		ecx, LSCount							// skip partial run, jump into normal loop for rest
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitTransparent				// *** jumps into transparent blit loop


LSTrans1:
		sub		LSCount, ecx					// skip whole run, continue skipping
		jmp		LeftSkipLoop

//-------------------------------------------------
// setup for beginning of line

BlitLineSetup:
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0

BlitDispatch:

		cmp		LSCount, 0							// Check to see if we're done blitting
		je		RightSkipLoop

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		RSLoop2

//--------------------------------
// blitting non-transparent pixels

		and		ecx, 07fH

BlitNTL1:
		mov		ax, [ebx]								// check z-level of pixel
		cmp		ax, usZLevel
		jae		BlitNTL2

		mov		ax, usZLevel						// update z-level of pixel
		mov		[ebx], ax

		xor		eax, eax
		mov		al, [esi]								// copy pixel
		mov		ax, [edx+eax*2]
		mov		[edi], ax

BlitNTL2:
		inc		esi
		add		edi, 2
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitNTL6

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitNTL5								// dir = 0 no change
		js		BlitNTL4								// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_STRIP_DELTA_Y
		jmp		BlitNTL5

BlitNTL4:
		sub		dx, Z_STRIP_DELTA_Y

BlitNTL5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitNTL6:
		dec		LSCount									// decrement pixel length to blit
		jz		RightSkipLoop						// done blitting the visible line

		dec		ecx
		jnz		BlitNTL1								// continue current run

		jmp		BlitDispatch						// done current run, go for another


//----------------------------
// skipping transparent pixels

BlitTransparent:									// skip transparent pixels

		and		ecx, 07fH

BlitTrans2:

		add		edi, 2									// move up the destination pointer
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitTrans1

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitTrans5							// dir = 0 no change
		js		BlitTrans4							// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_STRIP_DELTA_Y
		jmp		BlitTrans5

BlitTrans4:
		sub		dx, Z_STRIP_DELTA_Y

BlitTrans5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitTrans1:

		dec		LSCount									// decrement the pixels to blit
		jz		RightSkipLoop						// done the line

		dec		ecx
		jnz		BlitTrans2

		jmp		BlitDispatch

//---------------------------------------------
// Scans the ETRLE until it finds an EOL marker

RightSkipLoop:


RSLoop1:
		mov		al, [esi]
		inc		esi
		or		al, al
		jnz		RSLoop1

RSLoop2:

		dec		BlitHeight
		jz		BlitDone
		add		edi, LineSkip
		add		ebx, LineSkip

// reset all the z-level stuff for a new line

		mov		ax, usZStartLevel
		mov		usZLevel, ax
		mov		ax, usZStartIndex
		mov		usZIndex, ax
		mov		ax, usZStartCols
		mov		usZColsToGo, ax


		jmp		LeftSkipSetup


BlitDone:
	}

	return(TRUE);
}


/**********************************************************************************************
 Blt8BPPDataTo16BPPBufferTransZIncClipSaveZBurnsThrough

	Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit
	buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the
	pixel's Z level is below that of the current pixel, it is written on, and the Z value is
	updated to the current value,	for any non-transparent pixels. The Z-buffer is 16 bit, and
	must be the same dimensions (including Pitch) as the destination.

**********************************************************************************************/
BOOLEAN Blt8BPPDataTo16BPPBufferTransZIncClipZSameZBurnsThrough( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 usZStripIndex )
{
	UINT16 *p16BPPPalette;
	UINT32 uiOffset;
	UINT32 usHeight, usWidth, Unblitted;
	UINT8	 *SrcPtr, *DestPtr, *ZPtr;
	UINT32 LineSkip;
  ETRLEObject *pTrav;
	INT32	 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount;
	INT32  ClipX1, ClipY1, ClipX2, ClipY2;
	UINT16 usZLevel, usZStartLevel, usZColsToGo, usZStartIndex, usCount, usZIndex, usZStartCols;
	INT8 *pZArray;
	ZStripInfo *pZInfo;

	// Assertions
	Assert( hSrcVObject != NULL );
	Assert( pBuffer != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;

	if(clipregion==NULL)
	{
		ClipX1=ClippingRect.iLeft;
		ClipY1=ClippingRect.iTop;
		ClipX2=ClippingRect.iRight;
		ClipY2=ClippingRect.iBottom;
	}
	else
	{
		ClipX1=clipregion->iLeft;
		ClipY1=clipregion->iTop;
		ClipX2=clipregion->iRight;
		ClipY2=clipregion->iBottom;
	}

	// Calculate rows hanging off each side of the screen
	LeftSkip=__min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth);
	RightSkip=__min(max(ClipX2, (iTempX+(INT32)usWidth)) - ClipX2, (INT32)usWidth);
	TopSkip=__min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight);
	BottomSkip=__min(__max(ClipY2, (iTempY+(INT32)usHeight)) - ClipY2, (INT32)usHeight);

	// calculate the remaining rows and columns to blit
	BlitLength=((INT32)usWidth-LeftSkip-RightSkip);
	BlitHeight=((INT32)usHeight-TopSkip-BottomSkip);

	// check if whole thing is clipped
	if((LeftSkip >=(INT32)usWidth) || (RightSkip >=(INT32)usWidth))
		return(TRUE);

	// check if whole thing is clipped
	if((TopSkip >=(INT32)usHeight) || (BottomSkip >=(INT32)usHeight))
		return(TRUE);

	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	p16BPPPalette = hSrcVObject->pShadeCurrent;
	LineSkip=(uiDestPitchBYTES-(BlitLength*2));

	if(hSrcVObject->ppZStripInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}
	// setup for the z-column blitting stuff
	pZInfo=hSrcVObject->ppZStripInfo[ usZStripIndex ];
	if(pZInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}

	usZStartLevel=(UINT16)((INT16)usZValue+((INT16)pZInfo->bInitialZChange*Z_STRIP_DELTA_Y));
	// set to odd number of pixels for first column

	if(LeftSkip > pZInfo->ubFirstZStripWidth)
	{
		usZStartCols=(LeftSkip - pZInfo->ubFirstZStripWidth);
		usZStartCols=20-(usZStartCols%20);
	}
	else if(LeftSkip < pZInfo->ubFirstZStripWidth)
		usZStartCols=(UINT16)(pZInfo->ubFirstZStripWidth - LeftSkip);
	else
		usZStartCols=20;

	usZColsToGo=usZStartCols;

	pZArray=pZInfo->pbZChange;

	if(LeftSkip >= pZInfo->ubFirstZStripWidth)
	{
		// Index into array after doing left clipping
		usZStartIndex=1 + ((LeftSkip-pZInfo->ubFirstZStripWidth)/20);

		//calculates the Z-value after left-side clipping
		if(usZStartIndex)
		{
			for(usCount=0; usCount < usZStartIndex; usCount++)
			{
				switch(pZArray[usCount])
				{
					case -1:	usZStartLevel-=Z_STRIP_DELTA_Y;
										break;
					case 0:		//no change
										break;
					case 1:		usZStartLevel+=Z_STRIP_DELTA_Y;
										break;
				}
			}
		}
	}
	else
		usZStartIndex=0;

	usZLevel=usZStartLevel;
	usZIndex=usZStartIndex;

	__asm {

		mov		esi, SrcPtr
		mov		edi, DestPtr
		mov		edx, p16BPPPalette
		xor		eax, eax
		mov		ebx, ZPtr
		xor		ecx, ecx

		cmp		TopSkip, 0							// check for nothing clipped on top
		je		LeftSkipSetup


// Skips the number of lines clipped at the top
TopSkipLoop:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		TopSkipLoop
		jz		TSEndLine

		add		esi, ecx
		jmp		TopSkipLoop

TSEndLine:
		dec		TopSkip
		jnz		TopSkipLoop


// Start of line loop

// Skips the pixels hanging outside the left-side boundry
LeftSkipSetup:

		mov		Unblitted, 0					// Unblitted counts any pixels left from a run
		mov		eax, LeftSkip					// after we have skipped enough left-side pixels
		mov		LSCount, eax					// LSCount counts how many pixels skipped so far
		or		eax, eax
		jz		BlitLineSetup					// check for nothing to skip

LeftSkipLoop:

		mov		cl, [esi]
		inc		esi

		or		cl, cl
		js		LSTrans

		cmp		ecx, LSCount
		je		LSSkip2								// if equal, skip whole, and start blit with new run
		jb		LSSkip1								// if less, skip whole thing

		add		esi, LSCount					// skip partial run, jump into normal loop for rest
		sub		ecx, LSCount
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitNTL1							// *** jumps into non-transparent blit loop

LSSkip2:
		add		esi, ecx							// skip whole run, and start blit with new run
		jmp		BlitLineSetup


LSSkip1:
		add		esi, ecx							// skip whole run, continue skipping
		sub		LSCount, ecx
		jmp		LeftSkipLoop


LSTrans:
		and		ecx, 07fH
		cmp		ecx, LSCount
		je		BlitLineSetup					// if equal, skip whole, and start blit with new run
		jb		LSTrans1							// if less, skip whole thing

		sub		ecx, LSCount							// skip partial run, jump into normal loop for rest
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitTransparent				// *** jumps into transparent blit loop


LSTrans1:
		sub		LSCount, ecx					// skip whole run, continue skipping
		jmp		LeftSkipLoop

//-------------------------------------------------
// setup for beginning of line

BlitLineSetup:
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0

BlitDispatch:

		cmp		LSCount, 0							// Check to see if we're done blitting
		je		RightSkipLoop

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		RSLoop2

//--------------------------------
// blitting non-transparent pixels

		and		ecx, 07fH

BlitNTL1:
		mov		ax, [ebx]								// check z-level of pixel
		cmp		ax, usZLevel
		ja		BlitNTL2

		mov		ax, usZLevel						// update z-level of pixel
		mov		[ebx], ax

		xor		eax, eax
		mov		al, [esi]								// copy pixel
		mov		ax, [edx+eax*2]
		mov		[edi], ax

BlitNTL2:
		inc		esi
		add		edi, 2
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitNTL6

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitNTL5								// dir = 0 no change
		js		BlitNTL4								// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_STRIP_DELTA_Y
		jmp		BlitNTL5

BlitNTL4:
		sub		dx, Z_STRIP_DELTA_Y

BlitNTL5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitNTL6:
		dec		LSCount									// decrement pixel length to blit
		jz		RightSkipLoop						// done blitting the visible line

		dec		ecx
		jnz		BlitNTL1								// continue current run

		jmp		BlitDispatch						// done current run, go for another


//----------------------------
// skipping transparent pixels

BlitTransparent:									// skip transparent pixels

		and		ecx, 07fH

BlitTrans2:

		add		edi, 2									// move up the destination pointer
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitTrans1

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitTrans5							// dir = 0 no change
		js		BlitTrans4							// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_STRIP_DELTA_Y
		jmp		BlitTrans5

BlitTrans4:
		sub		dx, Z_STRIP_DELTA_Y

BlitTrans5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitTrans1:

		dec		LSCount									// decrement the pixels to blit
		jz		RightSkipLoop						// done the line

		dec		ecx
		jnz		BlitTrans2

		jmp		BlitDispatch

//---------------------------------------------
// Scans the ETRLE until it finds an EOL marker

RightSkipLoop:


RSLoop1:
		mov		al, [esi]
		inc		esi
		or		al, al
		jnz		RSLoop1

RSLoop2:

		dec		BlitHeight
		jz		BlitDone
		add		edi, LineSkip
		add		ebx, LineSkip

// reset all the z-level stuff for a new line

		mov		ax, usZStartLevel
		mov		usZLevel, ax
		mov		ax, usZStartIndex
		mov		usZIndex, ax
		mov		ax, usZStartCols
		mov		usZColsToGo, ax


		jmp		LeftSkipSetup


BlitDone:
	}

	return(TRUE);
}


/**********************************************************************************************
 Blt8BPPDataTo16BPPBufferTransZIncObscureClip

	Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit
	buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the
	pixel's Z level is below that of the current pixel, it is written on, and the Z value is
	updated to the current value,	for any non-transparent pixels. The Z-buffer is 16 bit, and
	must be the same dimensions (including Pitch) as the destination.

	//ATE: This blitter makes the values that are =< z value pixellate rather than not
	// render at all

**********************************************************************************************/
BOOLEAN Blt8BPPDataTo16BPPBufferTransZIncObscureClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion)
{
	UINT16 *p16BPPPalette;
	UINT32 uiOffset, uiLineFlag;
	UINT32 usHeight, usWidth, Unblitted;
	UINT8	 *SrcPtr, *DestPtr, *ZPtr;
	UINT32 LineSkip;
  ETRLEObject *pTrav;
	INT32	 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount;
	INT32  ClipX1, ClipY1, ClipX2, ClipY2;
	UINT16 usZLevel, usZStartLevel, usZColsToGo, usZStartIndex, usCount, usZIndex, usZStartCols;
	INT8 *pZArray;
	ZStripInfo *pZInfo;

	// Assertions
	Assert( hSrcVObject != NULL );
	Assert( pBuffer != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;


	if(clipregion==NULL)
	{
		ClipX1=ClippingRect.iLeft;
		ClipY1=ClippingRect.iTop;
		ClipX2=ClippingRect.iRight;
		ClipY2=ClippingRect.iBottom;
	}
	else
	{
		ClipX1=clipregion->iLeft;
		ClipY1=clipregion->iTop;
		ClipX2=clipregion->iRight;
		ClipY2=clipregion->iBottom;
	}

	// Calculate rows hanging off each side of the screen
	LeftSkip=__min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth);
	RightSkip=__min(max(ClipX2, (iTempX+(INT32)usWidth)) - ClipX2, (INT32)usWidth);
	TopSkip=__min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight);
	BottomSkip=__min(__max(ClipY2, (iTempY+(INT32)usHeight)) - ClipY2, (INT32)usHeight);

	uiLineFlag=(iTempY&1);

	// calculate the remaining rows and columns to blit
	BlitLength=((INT32)usWidth-LeftSkip-RightSkip);
	BlitHeight=((INT32)usHeight-TopSkip-BottomSkip);

	// check if whole thing is clipped
	if((LeftSkip >=(INT32)usWidth) || (RightSkip >=(INT32)usWidth))
		return(TRUE);

	// check if whole thing is clipped
	if((TopSkip >=(INT32)usHeight) || (BottomSkip >=(INT32)usHeight))
		return(TRUE);

	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	p16BPPPalette = hSrcVObject->pShadeCurrent;
	LineSkip=(uiDestPitchBYTES-(BlitLength*2));

	if(hSrcVObject->ppZStripInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}
	// setup for the z-column blitting stuff
	pZInfo=hSrcVObject->ppZStripInfo[usIndex];
	if(pZInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}

	usZStartLevel=(UINT16)((INT16)usZValue+((INT16)pZInfo->bInitialZChange*Z_STRIP_DELTA_Y));
	// set to odd number of pixels for first column

	if(LeftSkip > pZInfo->ubFirstZStripWidth)
	{
		usZStartCols=(LeftSkip - pZInfo->ubFirstZStripWidth);
		usZStartCols=20-(usZStartCols%20);
	}
	else if(LeftSkip < pZInfo->ubFirstZStripWidth)
		usZStartCols=(UINT16)(pZInfo->ubFirstZStripWidth - LeftSkip);
	else
		usZStartCols=20;

	usZColsToGo=usZStartCols;

	pZArray=pZInfo->pbZChange;

	if(LeftSkip >= pZInfo->ubFirstZStripWidth)
	{
		// Index into array after doing left clipping
		usZStartIndex=1 + ((LeftSkip-pZInfo->ubFirstZStripWidth)/20);

		//calculates the Z-value after left-side clipping
		if(usZStartIndex)
		{
			for(usCount=0; usCount < usZStartIndex; usCount++)
			{
				switch(pZArray[usCount])
				{
					case -1:	usZStartLevel-=Z_STRIP_DELTA_Y;
										break;
					case 0:		//no change
										break;
					case 1:		usZStartLevel+=Z_STRIP_DELTA_Y;
										break;
				}
			}
		}
	}
	else
		usZStartIndex=0;

	usZLevel=usZStartLevel;
	usZIndex=usZStartIndex;

	__asm {

		mov		esi, SrcPtr
		mov		edi, DestPtr
		mov		edx, p16BPPPalette
		xor		eax, eax
		mov		ebx, ZPtr
		xor		ecx, ecx

		cmp		TopSkip, 0							// check for nothing clipped on top
		je		LeftSkipSetup


// Skips the number of lines clipped at the top
TopSkipLoop:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		TopSkipLoop
		jz		TSEndLine

		add		esi, ecx
		jmp		TopSkipLoop

TSEndLine:

		xor		uiLineFlag, 1
		dec		TopSkip
		jnz		TopSkipLoop


// Start of line loop

// Skips the pixels hanging outside the left-side boundry
LeftSkipSetup:

		mov		Unblitted, 0					// Unblitted counts any pixels left from a run
		mov		eax, LeftSkip					// after we have skipped enough left-side pixels
		mov		LSCount, eax					// LSCount counts how many pixels skipped so far
		or		eax, eax
		jz		BlitLineSetup					// check for nothing to skip

LeftSkipLoop:

		mov		cl, [esi]
		inc		esi

		or		cl, cl
		js		LSTrans

		cmp		ecx, LSCount
		je		LSSkip2								// if equal, skip whole, and start blit with new run
		jb		LSSkip1								// if less, skip whole thing

		add		esi, LSCount					// skip partial run, jump into normal loop for rest
		sub		ecx, LSCount
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitNTL1							// *** jumps into non-transparent blit loop

LSSkip2:
		add		esi, ecx							// skip whole run, and start blit with new run
		jmp		BlitLineSetup


LSSkip1:
		add		esi, ecx							// skip whole run, continue skipping
		sub		LSCount, ecx
		jmp		LeftSkipLoop


LSTrans:
		and		ecx, 07fH
		cmp		ecx, LSCount
		je		BlitLineSetup					// if equal, skip whole, and start blit with new run
		jb		LSTrans1							// if less, skip whole thing

		sub		ecx, LSCount							// skip partial run, jump into normal loop for rest
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitTransparent				// *** jumps into transparent blit loop


LSTrans1:
		sub		LSCount, ecx					// skip whole run, continue skipping
		jmp		LeftSkipLoop

//-------------------------------------------------
// setup for beginning of line

BlitLineSetup:
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0

BlitDispatch:

		cmp		LSCount, 0							// Check to see if we're done blitting
		je		RightSkipLoop

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		RSLoop2

//--------------------------------
// blitting non-transparent pixels

		and		ecx, 07fH

BlitNTL1:
		mov		ax, [ebx]								// check z-level of pixel
		cmp		ax, usZLevel
		jae		BlitPixellate1
		jmp   BlitPixel1

BlitPixellate1:

		// OK, DO PIXELLATE SCHEME HERE!
		test	uiLineFlag, 1
		jz		BlitSkip1

		test	edi, 2
		jz		BlitNTL2
		jmp		BlitPixel1

BlitSkip1:
		test	edi, 2
		jnz		BlitNTL2

BlitPixel1:

		mov		ax, usZLevel						// update z-level of pixel
		mov		[ebx], ax

		xor		eax, eax
		mov		al, [esi]								// copy pixel
		mov		ax, [edx+eax*2]
		mov		[edi], ax

BlitNTL2:
		inc		esi
		add		edi, 2
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitNTL6

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitNTL5								// dir = 0 no change
		js		BlitNTL4								// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_STRIP_DELTA_Y
		jmp		BlitNTL5

BlitNTL4:
		sub		dx, Z_STRIP_DELTA_Y

BlitNTL5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitNTL6:
		dec		LSCount									// decrement pixel length to blit
		jz		RightSkipLoop						// done blitting the visible line

		dec		ecx
		jnz		BlitNTL1								// continue current run

		jmp		BlitDispatch						// done current run, go for another


//----------------------------
// skipping transparent pixels

BlitTransparent:									// skip transparent pixels

		and		ecx, 07fH

BlitTrans2:

		add		edi, 2									// move up the destination pointer
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitTrans1

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitTrans5							// dir = 0 no change
		js		BlitTrans4							// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_STRIP_DELTA_Y
		jmp		BlitTrans5

BlitTrans4:
		sub		dx, Z_STRIP_DELTA_Y

BlitTrans5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitTrans1:

		dec		LSCount									// decrement the pixels to blit
		jz		RightSkipLoop						// done the line

		dec		ecx
		jnz		BlitTrans2

		jmp		BlitDispatch

//---------------------------------------------
// Scans the ETRLE until it finds an EOL marker

RightSkipLoop:


RSLoop1:
		mov		al, [esi]
		inc		esi
		or		al, al
		jnz		RSLoop1

RSLoop2:

		xor		uiLineFlag, 1
		dec		BlitHeight
		jz		BlitDone
		add		edi, LineSkip
		add		ebx, LineSkip

// reset all the z-level stuff for a new line

		mov		ax, usZStartLevel
		mov		usZLevel, ax
		mov		ax, usZStartIndex
		mov		usZIndex, ax
		mov		ax, usZStartCols
		mov		usZColsToGo, ax


		jmp		LeftSkipSetup


BlitDone:
	}

	return(TRUE);
}


// Blitter Specs
// 1 ) 8 to 16 bpp
// 2 ) strip z-blitter
// 3 ) clipped
// 4 ) trans shadow - if value is 254, makes a shadow
//
BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette )
{
	UINT32 uiOffset, uiLineFlag;
	UINT32 usHeight, usWidth, Unblitted;
	UINT8	 *SrcPtr, *DestPtr, *ZPtr;
	UINT32 LineSkip;
  ETRLEObject *pTrav;
	INT32	 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount;
	INT32  ClipX1, ClipY1, ClipX2, ClipY2;
	UINT16 usZLevel, usZStartLevel, usZColsToGo, usZStartIndex, usCount, usZIndex, usZStartCols;
	INT8 *pZArray;
	ZStripInfo *pZInfo;

	// Assertions
	Assert( hSrcVObject != NULL );
	Assert( pBuffer != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;

	if(clipregion==NULL)
	{
		ClipX1=ClippingRect.iLeft;
		ClipY1=ClippingRect.iTop;
		ClipX2=ClippingRect.iRight;
		ClipY2=ClippingRect.iBottom;
	}
	else
	{
		ClipX1=clipregion->iLeft;
		ClipY1=clipregion->iTop;
		ClipX2=clipregion->iRight;
		ClipY2=clipregion->iBottom;
	}

	// Calculate rows hanging off each side of the screen
	LeftSkip=__min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth);
	RightSkip=__min(max(ClipX2, (iTempX+(INT32)usWidth)) - ClipX2, (INT32)usWidth);
	TopSkip=__min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight);
	BottomSkip=__min(__max(ClipY2, (iTempY+(INT32)usHeight)) - ClipY2, (INT32)usHeight);

	uiLineFlag=(iTempY&1);

	// calculate the remaining rows and columns to blit
	BlitLength=((INT32)usWidth-LeftSkip-RightSkip);
	BlitHeight=((INT32)usHeight-TopSkip-BottomSkip);

	// check if whole thing is clipped
	if((LeftSkip >=(INT32)usWidth) || (RightSkip >=(INT32)usWidth))
		return(TRUE);

	// check if whole thing is clipped
	if((TopSkip >=(INT32)usHeight) || (BottomSkip >=(INT32)usHeight))
		return(TRUE);

	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	LineSkip=(uiDestPitchBYTES-(BlitLength*2));

	if(hSrcVObject->ppZStripInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}
	// setup for the z-column blitting stuff
	pZInfo=hSrcVObject->ppZStripInfo[sZIndex];
	if(pZInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}

	usZStartLevel=(UINT16)((INT16)usZValue+((INT16)pZInfo->bInitialZChange*Z_SUBLAYERS*10));

	if(LeftSkip > pZInfo->ubFirstZStripWidth)
	{
		usZStartCols=(LeftSkip - pZInfo->ubFirstZStripWidth);
		usZStartCols=20-(usZStartCols%20);
	}
	else if(LeftSkip < pZInfo->ubFirstZStripWidth)
		usZStartCols=(UINT16)(pZInfo->ubFirstZStripWidth - LeftSkip);
	else
		usZStartCols=20;

	// set to odd number of pixels for first column
	usZColsToGo=usZStartCols;

	pZArray=pZInfo->pbZChange;

	if(LeftSkip >= usZColsToGo)
	{
		// Index into array after doing left clipping
		usZStartIndex=1 + ((LeftSkip-pZInfo->ubFirstZStripWidth)/20);

		//calculates the Z-value after left-side clipping
		if(usZStartIndex)
		{
			for(usCount=0; usCount < usZStartIndex; usCount++)
			{
				switch(pZArray[usCount])
				{
					case -1:	usZStartLevel-=Z_SUBLAYERS;
										break;
					case 0:		//no change
										break;
					case 1:		usZStartLevel+=Z_SUBLAYERS;
										break;
				}
			}
		}
	}
	else
		usZStartIndex=0;

	usZLevel=usZStartLevel;
	usZIndex=usZStartIndex;

	__asm {

		mov		esi, SrcPtr
		mov		edi, DestPtr
		mov		edx, p16BPPPalette
		xor		eax, eax
		mov		ebx, ZPtr
		xor		ecx, ecx

		cmp		TopSkip, 0							// check for nothing clipped on top
		je		LeftSkipSetup


// Skips the number of lines clipped at the top
TopSkipLoop:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		TopSkipLoop
		jz		TSEndLine

		add		esi, ecx
		jmp		TopSkipLoop

TSEndLine:

		xor		uiLineFlag, 1
		dec		TopSkip
		jnz		TopSkipLoop


// Start of line loop

// Skips the pixels hanging outside the left-side boundry
LeftSkipSetup:

		mov		Unblitted, 0					// Unblitted counts any pixels left from a run
		mov		eax, LeftSkip					// after we have skipped enough left-side pixels
		mov		LSCount, eax					// LSCount counts how many pixels skipped so far
		or		eax, eax
		jz		BlitLineSetup					// check for nothing to skip

LeftSkipLoop:

		mov		cl, [esi]
		inc		esi

		or		cl, cl
		js		LSTrans

		cmp		ecx, LSCount
		je		LSSkip2								// if equal, skip whole, and start blit with new run
		jb		LSSkip1								// if less, skip whole thing

		add		esi, LSCount					// skip partial run, jump into normal loop for rest
		sub		ecx, LSCount
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitNTL1							// *** jumps into non-transparent blit loop

LSSkip2:
		add		esi, ecx							// skip whole run, and start blit with new run
		jmp		BlitLineSetup


LSSkip1:
		add		esi, ecx							// skip whole run, continue skipping
		sub		LSCount, ecx
		jmp		LeftSkipLoop


LSTrans:
		and		ecx, 07fH
		cmp		ecx, LSCount
		je		BlitLineSetup					// if equal, skip whole, and start blit with new run
		jb		LSTrans1							// if less, skip whole thing

		sub		ecx, LSCount							// skip partial run, jump into normal loop for rest
		mov		eax, BlitLength
		mov		LSCount, eax

		mov		Unblitted, 0
		jmp		BlitTransparent				// *** jumps into transparent blit loop


LSTrans1:
		sub		LSCount, ecx					// skip whole run, continue skipping
		jmp		LeftSkipLoop

//-------------------------------------------------
// setup for beginning of line

BlitLineSetup:
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0

BlitDispatch:

		cmp		LSCount, 0							// Check to see if we're done blitting
		je		RightSkipLoop

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		RSLoop2

//--------------------------------
// blitting non-transparent pixels

		and		ecx, 07fH

BlitNTL1:
		mov		ax, [ebx]								// check z-level of pixel
		cmp		ax, usZLevel
		jae		BlitPixellate1
		jmp		BlitPixel1

BlitPixellate1:

		// OK, DO PIXELLATE SCHEME HERE!
		test	uiLineFlag, 1
		jz		BlitSkip1

		test	edi, 2
		jz		BlitNTL2
		jmp		BlitPixel1

BlitSkip1:
		test	edi, 2
		jnz		BlitNTL2

BlitPixel1:

		mov		ax, usZLevel						// update z-level of pixel
		mov		[ebx], ax

		// Check for shadow...
		xor		eax, eax
		mov		al, [esi]
		cmp		al, 254
		jne		BlitNTL66

		mov		ax, [edi]
		mov		ax, ShadeTable[eax*2]
		mov		[edi], ax
		jmp		BlitNTL2

BlitNTL66:

		mov		ax, [edx+eax*2]					// Copy pixel
		mov		[edi], ax

BlitNTL2:
		inc		esi
		add		edi, 2
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitNTL6

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitNTL5								// dir = 0 no change
		js		BlitNTL4								// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_SUBLAYERS
		jmp		BlitNTL5

BlitNTL4:
		sub		dx, Z_SUBLAYERS

BlitNTL5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitNTL6:
		dec		LSCount									// decrement pixel length to blit
		jz		RightSkipLoop						// done blitting the visible line

		dec		ecx
		jnz		BlitNTL1								// continue current run

		jmp		BlitDispatch						// done current run, go for another


//----------------------------
// skipping transparent pixels

BlitTransparent:									// skip transparent pixels

		and		ecx, 07fH

BlitTrans2:

		add		edi, 2									// move up the destination pointer
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitTrans1

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitTrans5							// dir = 0 no change
		js		BlitTrans4							// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_SUBLAYERS
		jmp		BlitTrans5

BlitTrans4:
		sub		dx, Z_SUBLAYERS

BlitTrans5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitTrans1:

		dec		LSCount									// decrement the pixels to blit
		jz		RightSkipLoop						// done the line

		dec		ecx
		jnz		BlitTrans2

		jmp		BlitDispatch

//---------------------------------------------
// Scans the ETRLE until it finds an EOL marker

RightSkipLoop:


RSLoop1:
		mov		al, [esi]
		inc		esi
		or		al, al
		jnz		RSLoop1

RSLoop2:

		xor		uiLineFlag, 1
		dec		BlitHeight
		jz		BlitDone
		add		edi, LineSkip
		add		ebx, LineSkip

// reset all the z-level stuff for a new line

		mov		ax, usZStartLevel
		mov		usZLevel, ax
		mov		ax, usZStartIndex
		mov		usZIndex, ax
		mov		ax, usZStartCols
		mov		usZColsToGo, ax


		jmp		LeftSkipSetup


BlitDone:
	}

	return(TRUE);
}




void CorrectRenderCenter( INT16 sRenderX, INT16 sRenderY, INT16 *pSNewX, INT16 *pSNewY )
{
	INT16 sScreenX, sScreenY;
	INT16 sNumXSteps, sNumYSteps;

	// Use radar scale values to get screen values, then convert ot map values, rounding to nearest middle tile
	sScreenX = (INT16) sRenderX;
	sScreenY = (INT16) sRenderY;

	// Adjust for offsets!
	sScreenX += 0;
	sScreenY += 10;

	// Adjust to viewport start!
	sScreenX -= ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 );
	sScreenY -= ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 );

	//Make sure these coordinates are multiples of scroll steps
	sNumXSteps = sScreenX  / gubNewScrollXSpeeds[ gfDoVideoScroll ][ gubCurScrollSpeedID ];
	sNumYSteps = sScreenY  / gubNewScrollYSpeeds[ gfDoVideoScroll ][ gubCurScrollSpeedID ];


	sScreenX = ( sNumXSteps * gubNewScrollXSpeeds[ gfDoVideoScroll ][ gubCurScrollSpeedID ] );
	sScreenY = ( sNumYSteps * gubNewScrollYSpeeds[ gfDoVideoScroll ][ gubCurScrollSpeedID ]);

	// Adjust back
	sScreenX += ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 );
	sScreenY += ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 );

	*pSNewX = sScreenX;
	*pSNewY = sScreenY;

}



// Blitter Specs
// 1 ) 8 to 16 bpp
// 2 ) strip z-blitter
// 3 ) clipped
// 4 ) trans shadow - if value is 254, makes a shadow
//
BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette )
{
	UINT32 uiOffset;
	UINT32 usHeight, usWidth, Unblitted;
	UINT8	 *SrcPtr, *DestPtr, *ZPtr;
	UINT32 LineSkip;
  ETRLEObject *pTrav;
	INT32	 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount;
	INT32  ClipX1, ClipY1, ClipX2, ClipY2;
	UINT16 usZLevel, usZStartLevel, usZColsToGo, usZStartIndex, usCount, usZIndex, usZStartCols;
	INT8 *pZArray;
	ZStripInfo *pZInfo;

	// Assertions
	Assert( hSrcVObject != NULL );
	Assert( pBuffer != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;

	if(clipregion==NULL)
	{
		ClipX1=ClippingRect.iLeft;
		ClipY1=ClippingRect.iTop;
		ClipX2=ClippingRect.iRight;
		ClipY2=ClippingRect.iBottom;
	}
	else
	{
		ClipX1=clipregion->iLeft;
		ClipY1=clipregion->iTop;
		ClipX2=clipregion->iRight;
		ClipY2=clipregion->iBottom;
	}

	// Calculate rows hanging off each side of the screen
	LeftSkip=__min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth);
	RightSkip=__min(max(ClipX2, (iTempX+(INT32)usWidth)) - ClipX2, (INT32)usWidth);
	TopSkip=__min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight);
	BottomSkip=__min(__max(ClipY2, (iTempY+(INT32)usHeight)) - ClipY2, (INT32)usHeight);

	// calculate the remaining rows and columns to blit
	BlitLength=((INT32)usWidth-LeftSkip-RightSkip);
	BlitHeight=((INT32)usHeight-TopSkip-BottomSkip);

	// check if whole thing is clipped
	if((LeftSkip >=(INT32)usWidth) || (RightSkip >=(INT32)usWidth))
		return(TRUE);

	// check if whole thing is clipped
	if((TopSkip >=(INT32)usHeight) || (BottomSkip >=(INT32)usHeight))
		return(TRUE);

	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
	LineSkip=(uiDestPitchBYTES-(BlitLength*2));

	if(hSrcVObject->ppZStripInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}
	// setup for the z-column blitting stuff
	pZInfo=hSrcVObject->ppZStripInfo[sZIndex];
	if(pZInfo==NULL)
	{
		DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object"));
		return(FALSE);
	}

	usZStartLevel=(UINT16)((INT16)usZValue+((INT16)pZInfo->bInitialZChange*Z_SUBLAYERS*10));

	if(LeftSkip > pZInfo->ubFirstZStripWidth)
	{
		usZStartCols=(LeftSkip - pZInfo->ubFirstZStripWidth);
		usZStartCols=20-(usZStartCols%20);
	}
	else if(LeftSkip < pZInfo->ubFirstZStripWidth)
		usZStartCols=(UINT16)(pZInfo->ubFirstZStripWidth - LeftSkip);
	else
		usZStartCols=20;

	// set to odd number of pixels for first column
	usZColsToGo=usZStartCols;

	pZArray=pZInfo->pbZChange;

	if(LeftSkip >= usZColsToGo)
	{
		// Index into array after doing left clipping
		usZStartIndex=1 + ((LeftSkip-pZInfo->ubFirstZStripWidth)/20);

		//calculates the Z-value after left-side clipping
		if(usZStartIndex)
		{
			for(usCount=0; usCount < usZStartIndex; usCount++)
			{
				switch(pZArray[usCount])
				{
					case -1:	usZStartLevel-=Z_SUBLAYERS;
										break;
					case 0:		//no change
										break;
					case 1:		usZStartLevel+=Z_SUBLAYERS;
										break;
				}
			}
		}
	}
	else
		usZStartIndex=0;

	usZLevel=usZStartLevel;
	usZIndex=usZStartIndex;

	__asm {

		mov		esi, SrcPtr
		mov		edi, DestPtr
		mov		edx, p16BPPPalette
		xor		eax, eax
		mov		ebx, ZPtr
		xor		ecx, ecx

		cmp		TopSkip, 0							// check for nothing clipped on top
		je		LeftSkipSetup


// Skips the number of lines clipped at the top
TopSkipLoop:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		TopSkipLoop
		jz		TSEndLine

		add		esi, ecx
		jmp		TopSkipLoop

TSEndLine:
		dec		TopSkip
		jnz		TopSkipLoop


// Start of line loop

// Skips the pixels hanging outside the left-side boundry
LeftSkipSetup:

		mov		Unblitted, 0					// Unblitted counts any pixels left from a run
		mov		eax, LeftSkip					// after we have skipped enough left-side pixels
		mov		LSCount, eax					// LSCount counts how many pixels skipped so far
		or		eax, eax
		jz		BlitLineSetup					// check for nothing to skip

LeftSkipLoop:

		mov		cl, [esi]
		inc		esi

		or		cl, cl
		js		LSTrans

		cmp		ecx, LSCount
		je		LSSkip2								// if equal, skip whole, and start blit with new run
		jb		LSSkip1								// if less, skip whole thing

		add		esi, LSCount					// skip partial run, jump into normal loop for rest
		sub		ecx, LSCount
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0
		jmp		BlitNTL1							// *** jumps into non-transparent blit loop

LSSkip2:
		add		esi, ecx							// skip whole run, and start blit with new run
		jmp		BlitLineSetup


LSSkip1:
		add		esi, ecx							// skip whole run, continue skipping
		sub		LSCount, ecx
		jmp		LeftSkipLoop


LSTrans:
		and		ecx, 07fH
		cmp		ecx, LSCount
		je		BlitLineSetup					// if equal, skip whole, and start blit with new run
		jb		LSTrans1							// if less, skip whole thing

		sub		ecx, LSCount							// skip partial run, jump into normal loop for rest
		mov		eax, BlitLength
		mov		LSCount, eax

		mov		Unblitted, 0
		jmp		BlitTransparent				// *** jumps into transparent blit loop


LSTrans1:
		sub		LSCount, ecx					// skip whole run, continue skipping
		jmp		LeftSkipLoop

//-------------------------------------------------
// setup for beginning of line

BlitLineSetup:
		mov		eax, BlitLength
		mov		LSCount, eax
		mov		Unblitted, 0

BlitDispatch:

		cmp		LSCount, 0							// Check to see if we're done blitting
		je		RightSkipLoop

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		RSLoop2

//--------------------------------
// blitting non-transparent pixels

		and		ecx, 07fH

BlitNTL1:
		mov		ax, [ebx]								// check z-level of pixel
		cmp		ax, usZLevel
		ja		BlitNTL2

		mov		ax, usZLevel						// update z-level of pixel
		mov		[ebx], ax

		// Check for shadow...
		xor		eax, eax
		mov		al, [esi]
		cmp		al, 254
		jne		BlitNTL66

		mov		ax, [edi]
		mov		ax, ShadeTable[eax*2]
		mov		[edi], ax
		jmp		BlitNTL2

BlitNTL66:

		mov		ax, [edx+eax*2]					// Copy pixel
		mov		[edi], ax

BlitNTL2:
		inc		esi
		add		edi, 2
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitNTL6

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitNTL5								// dir = 0 no change
		js		BlitNTL4								// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_SUBLAYERS
		jmp		BlitNTL5

BlitNTL4:
		sub		dx, Z_SUBLAYERS

BlitNTL5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitNTL6:
		dec		LSCount									// decrement pixel length to blit
		jz		RightSkipLoop						// done blitting the visible line

		dec		ecx
		jnz		BlitNTL1								// continue current run

		jmp		BlitDispatch						// done current run, go for another


//----------------------------
// skipping transparent pixels

BlitTransparent:									// skip transparent pixels

		and		ecx, 07fH

BlitTrans2:

		add		edi, 2									// move up the destination pointer
		add		ebx, 2

		dec		usZColsToGo
		jnz		BlitTrans1

// update the z-level according to the z-table

		push	edx
		mov		edx, pZArray						// get pointer to array
		xor		eax, eax
		mov		ax, usZIndex						// pick up the current array index
		add		edx, eax
		inc		eax											// increment it
		mov		usZIndex, ax						// store incremented value

		mov		al, [edx]								// get direction instruction
		mov		dx, usZLevel						// get current z-level

		or		al, al
		jz		BlitTrans5							// dir = 0 no change
		js		BlitTrans4							// dir < 0 z-level down
																	// dir > 0 z-level up (default)
		add		dx, Z_SUBLAYERS
		jmp		BlitTrans5

BlitTrans4:
		sub		dx, Z_SUBLAYERS

BlitTrans5:
		mov		usZLevel, dx						// store the now-modified z-level
		mov		usZColsToGo, 20					// reset the next z-level change to 20 cols
		pop		edx

BlitTrans1:

		dec		LSCount									// decrement the pixels to blit
		jz		RightSkipLoop						// done the line

		dec		ecx
		jnz		BlitTrans2

		jmp		BlitDispatch

//---------------------------------------------
// Scans the ETRLE until it finds an EOL marker

RightSkipLoop:


RSLoop1:
		mov		al, [esi]
		inc		esi
		or		al, al
		jnz		RSLoop1

RSLoop2:

		dec		BlitHeight
		jz		BlitDone
		add		edi, LineSkip
		add		ebx, LineSkip

// reset all the z-level stuff for a new line

		mov		ax, usZStartLevel
		mov		usZLevel, ax
		mov		ax, usZStartIndex
		mov		usZIndex, ax
		mov		ax, usZStartCols
		mov		usZColsToGo, ax


		jmp		LeftSkipSetup


BlitDone:
	}

	return(TRUE);
}




void RenderRoomInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS )
{
	INT8				bXOddFlag = 0;
	INT16				sAnchorPosX_M, sAnchorPosY_M;
	INT16				sAnchorPosX_S, sAnchorPosY_S;
	INT16				sTempPosX_M, sTempPosY_M;
	INT16				sTempPosX_S, sTempPosY_S;
	BOOLEAN			fEndRenderRow = FALSE, fEndRenderCol = FALSE;
	INT16				sX, sY;
	INT32			usTileIndex;//dnl ch56 141009
	UINT32			uiDestPitchBYTES;
	UINT8				*pDestBuf;


	// Begin Render Loop
	sAnchorPosX_M = sStartPointX_M;
	sAnchorPosY_M = sStartPointY_M;
	sAnchorPosX_S = sStartPointX_S;
	sAnchorPosY_S = sStartPointY_S;

	pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );

	do
	{

		fEndRenderRow = FALSE;
		sTempPosX_M = sAnchorPosX_M;
		sTempPosY_M = sAnchorPosY_M;
		sTempPosX_S = sAnchorPosX_S;
		sTempPosY_S = sAnchorPosY_S;

		if(bXOddFlag > 0)
			sTempPosX_S += 20;


		do
		{

			usTileIndex=FASTMAPROWCOLTOPOS( sTempPosY_M, sTempPosX_M );

			if ( usTileIndex < GRIDSIZE	)
			{
				sX = sTempPosX_S + ( WORLD_TILE_X / 2 ) - 5;
				sY = sTempPosY_S + ( WORLD_TILE_Y / 2 ) - 5;

				// THIS ROOM STUFF IS ONLY DONE IN THE EDITOR...
				// ADJUST BY SHEIGHT
				sY -= gpWorldLevelData[ usTileIndex ].sHeight;
				//sY += gsRenderHeight;

				if ( gubWorldRoomInfo[ usTileIndex ] != NO_ROOM )
				{
					SetFont( SMALLCOMPFONT );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, gsVIEWPORT_END_Y, FALSE );
					switch( gubWorldRoomInfo[ usTileIndex ] % 5 )
					{
						case 0:		SetFontForeground( FONT_GRAY3 );	break;
						case 1:		SetFontForeground( FONT_YELLOW );	break;
						case 2:		SetFontForeground( FONT_LTRED );	break;
						case 3:		SetFontForeground( FONT_LTBLUE );	break;
						case 4:   SetFontForeground( FONT_LTGREEN );break;
					}
					mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX,  sY , L"%d", gubWorldRoomInfo[ usTileIndex ] );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
				}
			}

			sTempPosX_S += 40;
			sTempPosX_M ++;
			sTempPosY_M --;

			if ( sTempPosX_S >= sEndXS )
			{
				fEndRenderRow = TRUE;
			}

		} while( !fEndRenderRow );

		if ( bXOddFlag > 0 )
		{
			sAnchorPosY_M ++;
		}
		else
		{
			sAnchorPosX_M ++;
		}


		bXOddFlag = !bXOddFlag;
		sAnchorPosY_S += 10;

		if ( sAnchorPosY_S >= sEndYS )
		{
			fEndRenderCol = TRUE;
		}

	}
	while( !fEndRenderCol );

	UnLockVideoSurface( FRAME_BUFFER );

}


#ifdef _DEBUG

void RenderFOVDebugInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS )
{
	INT8				bXOddFlag = 0;
	INT16				sAnchorPosX_M, sAnchorPosY_M;
	INT16				sAnchorPosX_S, sAnchorPosY_S;
	INT16				sTempPosX_M, sTempPosY_M;
	INT16				sTempPosX_S, sTempPosY_S;
	BOOLEAN			fEndRenderRow = FALSE, fEndRenderCol = FALSE;
	UINT16			usTileIndex;
	INT16				sX, sY;
	UINT32			uiDestPitchBYTES;
	UINT8				*pDestBuf;


	// Begin Render Loop
	sAnchorPosX_M = sStartPointX_M;
	sAnchorPosY_M = sStartPointY_M;
	sAnchorPosX_S = sStartPointX_S;
	sAnchorPosY_S = sStartPointY_S;

	pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );

	do
	{

		fEndRenderRow = FALSE;
		sTempPosX_M = sAnchorPosX_M;
		sTempPosY_M = sAnchorPosY_M;
		sTempPosX_S = sAnchorPosX_S;
		sTempPosY_S = sAnchorPosY_S;

		if(bXOddFlag > 0)
			sTempPosX_S += 20;


		do
		{

			usTileIndex=FASTMAPROWCOLTOPOS( sTempPosY_M, sTempPosX_M );

			if ( usTileIndex < GRIDSIZE	)
			{
				sX = sTempPosX_S + ( WORLD_TILE_X / 2 ) - 5;
				sY = sTempPosY_S + ( WORLD_TILE_Y / 2 ) - 5;

				// Adjust for interface level
				sY -= gpWorldLevelData[ usTileIndex ].sHeight;
				sY += gsRenderHeight;

				if ( gubFOVDebugInfoInfo[ usTileIndex ] != 0 )
				{
					SetFont( SMALLCOMPFONT );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, gsVIEWPORT_END_Y, FALSE );
					SetFontForeground( FONT_GRAY3 );
					mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX,  sY , L"%d", gubFOVDebugInfoInfo[ usTileIndex ] );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );


					Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, gTileDatabase[0].hTileSurface, sTempPosX_S, sTempPosY_S, 0, &gClippingRect );

				}

			  if ( gubGridNoMarkers[ usTileIndex ] == gubGridNoValue )
				{
					SetFont( SMALLCOMPFONT );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, gsVIEWPORT_END_Y, FALSE );
					SetFontForeground( FONT_FCOLOR_YELLOW );
					mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX,  sY + 4 , L"x" );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
				}

			}

			sTempPosX_S += 40;
			sTempPosX_M ++;
			sTempPosY_M --;

			if ( sTempPosX_S >= sEndXS )
			{
				fEndRenderRow = TRUE;
			}

		} while( !fEndRenderRow );

		if ( bXOddFlag > 0 )
		{
			sAnchorPosY_M ++;
		}
		else
		{
			sAnchorPosX_M ++;
		}


		bXOddFlag = !bXOddFlag;
		sAnchorPosY_S += 10;

		if ( sAnchorPosY_S >= sEndYS )
		{
			fEndRenderCol = TRUE;
		}

	}
	while( !fEndRenderCol );

	UnLockVideoSurface( FRAME_BUFFER );

}

void RenderCoverDebugInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS )
{
	INT8				bXOddFlag = 0;
	INT16				sAnchorPosX_M, sAnchorPosY_M;
	INT16				sAnchorPosX_S, sAnchorPosY_S;
	INT16				sTempPosX_M, sTempPosY_M;
	INT16				sTempPosX_S, sTempPosY_S;
	BOOLEAN			fEndRenderRow = FALSE, fEndRenderCol = FALSE;
	UINT16			usTileIndex;
	INT16				sX, sY;
	UINT32			uiDestPitchBYTES;
	UINT8				*pDestBuf;


	// Begin Render Loop
	sAnchorPosX_M = sStartPointX_M;
	sAnchorPosY_M = sStartPointY_M;
	sAnchorPosX_S = sStartPointX_S;
	sAnchorPosY_S = sStartPointY_S;

	pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );

	do
	{

		fEndRenderRow = FALSE;
		sTempPosX_M = sAnchorPosX_M;
		sTempPosY_M = sAnchorPosY_M;
		sTempPosX_S = sAnchorPosX_S;
		sTempPosY_S = sAnchorPosY_S;

		if(bXOddFlag > 0)
			sTempPosX_S += 20;


		do
		{

			usTileIndex=FASTMAPROWCOLTOPOS( sTempPosY_M, sTempPosX_M );

			if ( usTileIndex < GRIDSIZE	)
			{
				sX = sTempPosX_S + ( WORLD_TILE_X / 2 ) - 5;
				sY = sTempPosY_S + ( WORLD_TILE_Y / 2 ) - 5;

				// Adjust for interface level
				sY -= gpWorldLevelData[ usTileIndex ].sHeight;
				sY += gsRenderHeight;

				if (gsCoverValue[ usTileIndex] != 0x7F7F)
				{
					SetFont( SMALLCOMPFONT );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, gsVIEWPORT_END_Y, FALSE );
					if (usTileIndex == gsBestCover)
					{
						SetFontForeground( FONT_MCOLOR_RED );
					}
					else if (gsCoverValue[ usTileIndex ] < 0)
					{
						SetFontForeground( FONT_MCOLOR_WHITE );
					}
					else
					{
						SetFontForeground( FONT_GRAY3 );
					}
					mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX,  sY , L"%d", gsCoverValue[ usTileIndex ] );
					SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
				}

			}

			sTempPosX_S += 40;
			sTempPosX_M ++;
			sTempPosY_M --;

			if ( sTempPosX_S >= sEndXS )
			{
				fEndRenderRow = TRUE;
			}

		} while( !fEndRenderRow );

		if ( bXOddFlag > 0 )
		{
			sAnchorPosY_M ++;
		}
		else
		{
			sAnchorPosX_M ++;
		}


		bXOddFlag = !bXOddFlag;
		sAnchorPosY_S += 10;

		if ( sAnchorPosY_S >= sEndYS )
		{
			fEndRenderCol = TRUE;
		}

	}
	while( !fEndRenderCol );

	UnLockVideoSurface( FRAME_BUFFER );

}


void RenderGridNoVisibleDebugInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS )
{
	INT8				bXOddFlag = 0;
	INT16				sAnchorPosX_M, sAnchorPosY_M;
	INT16				sAnchorPosX_S, sAnchorPosY_S;
	INT16				sTempPosX_M, sTempPosY_M;
	INT16				sTempPosX_S, sTempPosY_S;
	BOOLEAN			fEndRenderRow = FALSE, fEndRenderCol = FALSE;
	INT16				sX, sY;
	INT32			usTileIndex;//dnl ch56 141009
	UINT32			uiDestPitchBYTES;
	UINT8				*pDestBuf;


	// Begin Render Loop
	sAnchorPosX_M = sStartPointX_M;
	sAnchorPosY_M = sStartPointY_M;
	sAnchorPosX_S = sStartPointX_S;
	sAnchorPosY_S = sStartPointY_S;

	pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );

	do
	{

		fEndRenderRow = FALSE;
		sTempPosX_M = sAnchorPosX_M;
		sTempPosY_M = sAnchorPosY_M;
		sTempPosX_S = sAnchorPosX_S;
		sTempPosY_S = sAnchorPosY_S;

		if(bXOddFlag > 0)
			sTempPosX_S += 20;


		do
		{

			usTileIndex=FASTMAPROWCOLTOPOS( sTempPosY_M, sTempPosX_M );

			if ( usTileIndex < GRIDSIZE	)
			{
				sX = sTempPosX_S + ( WORLD_TILE_X / 2 ) - 5;
				sY = sTempPosY_S + ( WORLD_TILE_Y / 2 ) - 5;

				// Adjust for interface level
				sY -= gpWorldLevelData[ usTileIndex ].sHeight;
				sY += gsRenderHeight;

				SetFont( SMALLCOMPFONT );
				SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, gsVIEWPORT_END_Y, FALSE );

				if ( !GridNoOnVisibleWorldTile( usTileIndex ) )
				{
					SetFontForeground( FONT_MCOLOR_RED );
				}
				else
				{
					SetFontForeground( FONT_GRAY3 );
				}
				mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX,  sY , L"%d", usTileIndex );
				SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );

			}

			sTempPosX_S += 40;
			sTempPosX_M ++;
			sTempPosY_M --;

			if ( sTempPosX_S >= sEndXS )
			{
				fEndRenderRow = TRUE;
			}

		} while( !fEndRenderRow );

		if ( bXOddFlag > 0 )
		{
			sAnchorPosY_M ++;
		}
		else
		{
			sAnchorPosX_M ++;
		}


		bXOddFlag = !bXOddFlag;
		sAnchorPosY_S += 10;

		if ( sAnchorPosY_S >= sEndYS )
		{
			fEndRenderCol = TRUE;
		}

	}
	while( !fEndRenderCol );

	UnLockVideoSurface( FRAME_BUFFER );

}


#endif


void ExamineZBufferRect( INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom)
{
	CalcRenderParameters( sLeft, sTop, sRight, sBottom );

	ExamineZBufferForHiddenTiles( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );

}


void ExamineZBufferForHiddenTiles( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS )
{
	INT8				bXOddFlag = 0;
	INT16				sAnchorPosX_M, sAnchorPosY_M;
	INT16				sAnchorPosX_S, sAnchorPosY_S;
	INT16				sTempPosX_M, sTempPosY_M;
	INT16				sTempPosX_S, sTempPosY_S;
	BOOLEAN			fEndRenderRow = FALSE, fEndRenderCol = FALSE;
	UINT16			usTileIndex;
	INT16				sX, sY, sWorldX, sZLevel;
	UINT32			uiDestPitchBYTES;
	UINT8				*pDestBuf;
	TILE_ELEMENT *TileElem;
	INT8			bBlitClipVal;
	LEVELNODE		*pObject;


	// Begin Render Loop
	sAnchorPosX_M = sStartPointX_M;
	sAnchorPosY_M = sStartPointY_M;
	sAnchorPosX_S = sStartPointX_S;
	sAnchorPosY_S = sStartPointY_S;

	pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );

	// Get VObject for first land peice!
	TileElem = &(gTileDatabase[ FIRSTTEXTURE1 ] );


	do
	{

		fEndRenderRow = FALSE;
		sTempPosX_M = sAnchorPosX_M;
		sTempPosY_M = sAnchorPosY_M;
		sTempPosX_S = sAnchorPosX_S;
		sTempPosY_S = sAnchorPosY_S;

		if(bXOddFlag > 0)
			sTempPosX_S += 20;


		do
		{

			usTileIndex=FASTMAPROWCOLTOPOS( sTempPosY_M, sTempPosX_M );

			if ( usTileIndex < GRIDSIZE	)
			{
				// ATE: Don;t let any vehicle sit here....
				if ( FindStructure( usTileIndex, ( STRUCTURE_MOBILE ) ) )
				{
					// Continue...
					goto ENDOFLOOP;
				}

				sX = sTempPosX_S;
				sY = sTempPosY_S - gpWorldLevelData[usTileIndex].sHeight;

				// Adjust for interface level
				sY += gsRenderHeight;

				// Caluluate zvalue
				// Look for anything less than struct layer!
				GetWorldXYAbsoluteScreenXY( sTempPosX_M, sTempPosY_M, &sWorldX, &sZLevel);

				sZLevel += gsRenderHeight;

				sZLevel=(sZLevel*Z_SUBLAYERS)+STRUCT_Z_LEVEL;

				if ( gpWorldLevelData[usTileIndex].uiFlags & MAPELEMENT_REEVALUATE_REDUNDENCY )
				{
					bBlitClipVal = BltIsClippedOrOffScreen(TileElem->hTileSurface, sX, sY, TileElem->usRegionIndex, &gClippingRect);

					if ( bBlitClipVal == FALSE )
					{
						// Set flag to not evaluate again!
						gpWorldLevelData[usTileIndex].uiFlags &= (~MAPELEMENT_REEVALUATE_REDUNDENCY );

						// OK, first do some rules with exceptions
						// Don't let this happen for roads!
						pObject = gpWorldLevelData[usTileIndex ].pObjectHead;

						if ( IsTileRedundent( uiDestPitchBYTES, gpZBuffer, sZLevel, TileElem->hTileSurface, sX, sY, TileElem->usRegionIndex ) )
						{
							// Mark in the world!
							gpWorldLevelData[ usTileIndex ].uiFlags |= MAPELEMENT_REDUNDENT;
						}
						else
						{
							// Un Mark in the world!
							gpWorldLevelData[ usTileIndex ].uiFlags &= (~MAPELEMENT_REDUNDENT);
						}

					}
				}
			}

ENDOFLOOP:

			sTempPosX_S += 40;
			sTempPosX_M ++;
			sTempPosY_M --;

			if ( sTempPosX_S >= sEndXS )
			{
				fEndRenderRow = TRUE;
			}

		} while( !fEndRenderRow );

		if ( bXOddFlag > 0 )
		{
			sAnchorPosY_M ++;
		}
		else
		{
			sAnchorPosX_M ++;
		}


		bXOddFlag = !bXOddFlag;
		sAnchorPosY_S += 10;

		if ( sAnchorPosY_S >= sEndYS )
		{
			fEndRenderCol = TRUE;
		}

	}
	while( !fEndRenderCol );

	UnLockVideoSurface( FRAME_BUFFER );

}



void CalcRenderParameters(INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom )
{
	INT16 sTempPosX_W, sTempPosY_W;
	INT16 sRenderCenterX_W, sRenderCenterY_W;
	INT16 sOffsetX_W, sOffsetY_W, sOffsetX_S, sOffsetY_S;

	gOldClipRect = gClippingRect;

	// Set new clipped rect
	gClippingRect.iLeft = __max( gsVIEWPORT_START_X, sLeft);
	gClippingRect.iRight = __min( gsVIEWPORT_END_X, sRight);
	gClippingRect.iTop = __max( gsVIEWPORT_WINDOW_START_Y, sTop);
	gClippingRect.iBottom = __min(gsVIEWPORT_WINDOW_END_Y, sBottom);

	gsEndXS = sRight + VIEWPORT_XOFFSET_S;
	gsEndYS = sBottom + VIEWPORT_YOFFSET_S;

	sRenderCenterX_W = gsRenderCenterX;
	sRenderCenterY_W = gsRenderCenterY;

	// STEP THREE - determine starting point in world coords
	// a) Determine where in screen coords to start rendering
	gsStartPointX_S = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) - (sLeft - VIEWPORT_XOFFSET_S);
	gsStartPointY_S = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) - (sTop - VIEWPORT_YOFFSET_S);


	// b) Convert these distances into world distances
	FromScreenToCellCoordinates( gsStartPointX_S, gsStartPointY_S, &sTempPosX_W, &sTempPosY_W );

	// c) World start point is Render center minus this distance
	gsStartPointX_W = sRenderCenterX_W - sTempPosX_W;
	gsStartPointY_W = sRenderCenterY_W - sTempPosY_W;

	// NOTE: Increase X map value by 1 tile to offset where on screen we are...
	if ( gsStartPointX_W > 0 )
		gsStartPointX_W += CELL_X_SIZE;

	// d) screen start point is screen distances minus screen center
	gsStartPointX_S = sLeft - VIEWPORT_XOFFSET_S;
	gsStartPointY_S = sTop - VIEWPORT_YOFFSET_S;

	// STEP FOUR - Determine Start block
	// a) Find start block
	gsStartPointX_M = ( gsStartPointX_W  ) / CELL_X_SIZE;
	gsStartPointY_M = ( gsStartPointY_W  ) / CELL_Y_SIZE;

	// STEP 5 - Determine Deltas for center and find screen values
	//Make sure these coordinates are multiples of scroll steps
	sOffsetX_W = abs( gsStartPointX_W ) - ( abs( ( gsStartPointX_M * CELL_X_SIZE ) ) );
	sOffsetY_W = abs( gsStartPointY_W ) - ( abs( ( gsStartPointY_M * CELL_Y_SIZE ) ) );

	FromCellToScreenCoordinates( sOffsetX_W, sOffsetY_W, &sOffsetX_S, &sOffsetY_S );

	if ( gsStartPointY_W < 0 )
	{
		gsStartPointY_S	+= 0;//(sOffsetY_S/2);
	}
	else
	{
		gsStartPointY_S	-= sOffsetY_S;
	}
	gsStartPointX_S	-= sOffsetX_S;


	// Set globals for render offset
	if ( gsRenderWorldOffsetX == -1 )
	{
		gsRenderWorldOffsetX = sOffsetX_S;
	}

	if ( gsRenderWorldOffsetY == -1 )
	{
		gsRenderWorldOffsetY = sOffsetY_S;
	}

	/////////////////////////////////////////
	//ATE: CALCULATE LARGER OFFSET VALUES
	gsLEndXS = sRight + LARGER_VIEWPORT_XOFFSET_S;
	gsLEndYS = sBottom + LARGER_VIEWPORT_YOFFSET_S;

		// STEP THREE - determine starting point in world coords
	// a) Determine where in screen coords to start rendering
	gsLStartPointX_S = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) - (sLeft - LARGER_VIEWPORT_XOFFSET_S);
	gsLStartPointY_S = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) - (sTop - LARGER_VIEWPORT_YOFFSET_S);


	// b) Convert these distances into world distances
	FromScreenToCellCoordinates( gsLStartPointX_S, gsLStartPointY_S, &sTempPosX_W, &sTempPosY_W );

	// c) World start point is Render center minus this distance
	gsLStartPointX_W = sRenderCenterX_W - sTempPosX_W;
	gsLStartPointY_W = sRenderCenterY_W - sTempPosY_W;

	// NOTE: Increase X map value by 1 tile to offset where on screen we are...
	if ( gsLStartPointX_W > 0 )
		gsLStartPointX_W += CELL_X_SIZE;

	// d) screen start point is screen distances minus screen center
	gsLStartPointX_S = sLeft - LARGER_VIEWPORT_XOFFSET_S;
	gsLStartPointY_S = sTop - LARGER_VIEWPORT_YOFFSET_S;

	// STEP FOUR - Determine Start block
	// a) Find start block
	gsLStartPointX_M = ( gsLStartPointX_W  ) / CELL_X_SIZE;
	gsLStartPointY_M = ( gsLStartPointY_W  ) / CELL_Y_SIZE;

	// Adjust starting screen coordinates
	gsLStartPointX_S	-= sOffsetX_S;

	if ( gsLStartPointY_W < 0 )
	{
		gsLStartPointY_S	+= 0;
		gsLStartPointX_S	-= 20;
	}
	else
	{
		gsLStartPointY_S	-= sOffsetY_S;
	}

}

void ResetRenderParameters(  )
{
	// Restore clipping rect
	gClippingRect =	gOldClipRect;
}




BOOLEAN Zero8BPPDataTo16BPPBufferTransparent( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex )
{
	UINT32 uiOffset;
	UINT32 usHeight, usWidth;
	UINT8	 *SrcPtr, *DestPtr;
	UINT32 LineSkip;
	ETRLEObject *pTrav;
	INT32	 iTempX, iTempY;


	// Assertions
	Assert( hSrcVObject != NULL );
	Assert( pBuffer != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;

	// Validations
	CHECKF( iTempX >= 0 );
	CHECKF( iTempY >= 0 );


	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX*2);
	LineSkip=(uiDestPitchBYTES-(usWidth*2));

	__asm {

		mov		esi, SrcPtr
		mov		edi, DestPtr
		xor		eax, eax
		xor		ebx, ebx
		xor		ecx, ecx

BlitDispatch:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		BlitDoneLine

//BlitNonTransLoop:

		clc
		rcr		cl, 1
		jnc		BlitNTL2

		mov		[edi], ax

		inc		esi
		add		edi, 2

BlitNTL2:
		clc
		rcr		cl, 1
		jnc		BlitNTL3

		mov		[edi], ax

		mov		[edi+2], ax

		add		esi, 2
		add		edi, 4

BlitNTL3:

		or		cl, cl
		jz		BlitDispatch

		xor		ebx, ebx

BlitNTL4:

		mov		[edi], ax

		mov		[edi+2], ax

		mov		[edi+4], ax

		mov		[edi+6], ax

		add		esi, 4
		add		edi, 8
		dec		cl
		jnz		BlitNTL4

		jmp		BlitDispatch

BlitTransparent:

		and		ecx, 07fH
//		shl		ecx, 1
		add   ecx, ecx
		add		edi, ecx
		jmp		BlitDispatch


BlitDoneLine:

		dec		usHeight
		jz		BlitDone
		add		edi, LineSkip
		jmp		BlitDispatch


BlitDone:
	}

	return(TRUE);

}


BOOLEAN Blt8BPPDataTo16BPPBufferTransInvZ( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex )
{
	UINT16 *p16BPPPalette;
	UINT32 uiOffset;
	UINT32 usHeight, usWidth;
	UINT8	 *SrcPtr, *DestPtr, *ZPtr;
	UINT32 LineSkip;
	ETRLEObject *pTrav;
	INT32	 iTempX, iTempY;


	// Assertions
	Assert( hSrcVObject != NULL );
	Assert( pBuffer != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;

	// Validations
	CHECKF( iTempX >= 0 );
	CHECKF( iTempY >= 0 );


	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX*2);
	ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*iTempY) + (iTempX*2);
	p16BPPPalette = hSrcVObject->pShadeCurrent;
	LineSkip=(uiDestPitchBYTES-(usWidth*2));

	__asm {

		mov		esi, SrcPtr
		mov		edi, DestPtr
		mov		edx, p16BPPPalette
		xor		eax, eax
		mov		ebx, ZPtr
		xor		ecx, ecx

BlitDispatch:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		BlitDoneLine

//BlitNonTransLoop:

		xor		eax, eax

BlitNTL4:

		mov		ax, usZValue
		cmp		ax, [ebx]
		jne		BlitNTL5

		//mov		[ebx], ax

		xor		ah, ah
		mov		al, [esi]
		mov		ax, [edx+eax*2]
		mov		[edi], ax

BlitNTL5:
		inc		esi
		inc		edi
		inc		ebx
		inc		edi
		inc		ebx

		dec		cl
		jnz		BlitNTL4

		jmp		BlitDispatch


BlitTransparent:

		and		ecx, 07fH
//		shl		ecx, 1
		add   ecx, ecx
		add		edi, ecx
		add		ebx, ecx
		jmp		BlitDispatch


BlitDoneLine:

		dec		usHeight
		jz		BlitDone
		add		edi, LineSkip
		add		ebx, LineSkip
		jmp		BlitDispatch


BlitDone:
	}

	return(TRUE);

}



BOOLEAN IsTileRedundent( UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex )
{
	UINT16 *p16BPPPalette;
	UINT32 uiOffset;
	UINT32 usHeight, usWidth;
	UINT8	 *SrcPtr, *ZPtr;
	UINT32 LineSkip;
	ETRLEObject *pTrav;
	INT32	 iTempX, iTempY;
	BOOLEAN		fHidden = TRUE;


	// Assertions
	Assert( hSrcVObject != NULL );

	// Get Offsets from Index into structure
	pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
	usHeight				= (UINT32)pTrav->usHeight;
	usWidth					= (UINT32)pTrav->usWidth;
	uiOffset				= pTrav->uiDataOffset;

	// Add to start position of dest buffer
	iTempX = iX + pTrav->sOffsetX;
	iTempY = iY + pTrav->sOffsetY;

	// Validations
	CHECKF( iTempX >= 0 );
	CHECKF( iTempY >= 0 );


	SrcPtr= (UINT8 *)hSrcVObject->pPixData + uiOffset;
	ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*iTempY) + (iTempX*2);
	p16BPPPalette = hSrcVObject->pShadeCurrent;
	LineSkip=(uiDestPitchBYTES-(usWidth*2));

	__asm {

		mov		esi, SrcPtr
		mov		edx, p16BPPPalette
		xor		eax, eax
		mov		ebx, ZPtr
		xor		ecx, ecx

BlitDispatch:

		mov		cl, [esi]
		inc		esi
		or		cl, cl
		js		BlitTransparent
		jz		BlitDoneLine

//BlitNonTransLoop:

		xor		eax, eax

BlitNTL4:

		mov		ax, usZValue
		cmp		ax, [ebx]
		jle		BlitNTL5


		//    Set false, flag
		mov   fHidden, 0
		jmp		BlitDone


BlitNTL5:
		inc		esi
		inc		ebx
		inc		ebx

		dec		cl
		jnz		BlitNTL4

		jmp		BlitDispatch


BlitTransparent:

		and		ecx, 07fH
//		shl		ecx, 1
		add   ecx, ecx
		add		ebx, ecx
		jmp		BlitDispatch


BlitDoneLine:

		dec		usHeight
		jz		BlitDone
		add		ebx, LineSkip
		jmp		BlitDispatch


BlitDone:
	}

	return(fHidden);

}

void SetMercGlowFast( )
{
	//gpGlowFramePointer	= gsFastGlowFrames;
}

void SetMercGlowNormal( )
{
	gpGlowFramePointer	= gsGlowFrames;
}



#if 0
		if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_MOVING )
		{
			if ( sZOffsetY > 0 )
			{
				sZOffsetY++;
			}
			if ( sZOffsetX > 0 )
			{
				sZOffsetX++;
			}
		}

		sZOffsetX = pNode->pStructureData->pDBStructureRef->pDBStructure->bZTileOffsetX;\
			sZOffsetY = pNode->pStructureData->pDBStructureRef->pDBStructure->bZTileOffsetY;\


	if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ) )\
	{\
		sZOffsetX = pNode->pStructureData->pDBStructureRef->pDBStructure->bZTileOffsetX;\
		sZOffsetY = pNode->pStructureData->pDBStructureRef->pDBStructure->bZTileOffsetY;\
\
		sWorldY = GetMapXYWorldY( sMapX + sZOffsetX, sMapY + sZOffsetY );\
	}\
	else

#endif


void SetRenderCenter( INT16 sNewX, INT16 sNewY )
{
	if ( gfIgnoreScrolling == 1 )
	{
		return;
	}

	// Apply these new coordinates to the renderer!
	ApplyScrolling( sNewX, sNewY, TRUE , FALSE );

	// Set flag to ignore scrolling this frame
	gfIgnoreScrollDueToCenterAdjust = TRUE;

	// Set full render flag!
	// DIRTY THE WORLD!
	SetRenderFlags(RENDER_FLAG_FULL);

	gfPlotNewMovement = TRUE;

	if ( gfScrollPending == TRUE )
	{
		// Do a complete rebuild!
		gfScrollPending = FALSE;

		// Restore Interface!
		RestoreInterface( );

		// Delete Topmost blitters saved areas
		DeleteVideoOverlaysArea( );

	}

	gfScrollInertia = FALSE;

}

#ifdef _DEBUG
void RenderFOVDebug( )
{
	RenderFOVDebugInfo( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );
}

void RenderCoverDebug( )
{
	RenderCoverDebugInfo( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );
}

void RenderGridNoVisibleDebug( )
{
	RenderGridNoVisibleDebugInfo( gsStartPointX_M, gsStartPointY_M, gsStartPointX_S, gsStartPointY_S, gsEndXS, gsEndYS );
}

#endif
