Files
source/TileEngine/renderworld.cpp
T
Wanne 14750c6903 **********************************************************
** Big Maps Projects code (incl. Multiplayer v1.5 **
**********************************************************
- Merged Big Maps Project code from BMP+MP trunk (Revision: 3340)
o Complete SVN Revision history: https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP
- Before THIS merge, I made a branch of the existing 1.13 source
o SVN Branch: https://81.169.133.124/source/ja2/branches/JA2_rev.3336/src
- Removed old VS 6.0 and VS 2003 project and solutions files, because compilation is broken long time ago
- I will add VS 2010 projects and solution file in the next few days

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@3341 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2010-02-28 18:38:52 +00:00

7565 lines
207 KiB
C++

#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