#include "builddefines.h" /////////////////////////// // C file include here #include "Render Z.h" /////////////////////////// #ifdef PRECOMPILEDHEADERS #include "TileEngine All.h" #else #include "renderworld.h" #include "sysutil.h" #include "vobject_blitters.h" #include "debug.h" #include "wcheck.h" #include "worldman.h" #include "Radar Screen.h" #include "Render Dirty.h" #include "ai.h" #include "render fun.h" #include "interactive tiles.h" #include "tile cache.h" #include "English.h" #include "interface control.h" #include "Sound Control.h" #include "LogicalBodyTypes/Layers.h" #include "LogicalBodyTypes/BodyTypeDB.h" #endif #include "Utilities.h" UINT32 guiShieldGraphic = 0; BOOLEAN fShieldGraphicInit = FALSE; 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 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, 2560, 1600 }; SGPRect gOldClipRect = { 0, 0, 0, 0 }; 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 ); // Flugente: display a riot shield void ShowRiotShield( SOLDIERTYPE* pSoldier ) { if (pSoldier) { if (!fShieldGraphicInit) { VOBJECT_DESC VObjectDesc; // Flugente: enemy role symbols VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("Tilecache\\riotshield.sti", VObjectDesc.ImageFile); if (!AddVideoObject(&VObjectDesc, &guiShieldGraphic)) AssertMsg(0, "Missing Tilecache\\riotshield.sti"); fShieldGraphicInit = TRUE; } // Get screen pos of gridno...... INT16 sScreenX, sScreenY; GetGridNoScreenXY(pSoldier->sGridNo, &sScreenX, &sScreenY); // take height level into account if ( pSoldier->pathing.bLevel == 1 ) sScreenY -= 50; // redraw background to stop weird graphic remnants remaining // but don*t do so while scrolling, because that looks weird if ( !gfScrollPending && !gfScrollInertia) { INT32 iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sScreenX - 50, sScreenY - 60, sScreenX + 50, sScreenY + 35 ); if (iBack != -1) { SetBackgroundRectFilled(iBack); } } UINT16 offset = 0; OBJECTTYPE* pObj = pSoldier->GetEquippedRiotShield(); if (pObj) offset = Item[pObj->usItem].usRiotShieldGraphic; // try to keep the shield 'moving' alongside the soldier. This won't work perfectly, but it's better than nothing INT16 base_x = 0; INT16 base_y = 0; ConvertMapPosToWorldTileCenter( pSoldier->sGridNo, &base_x, &base_y ); INT16 dx = pSoldier->sX - base_x; INT16 dy = pSoldier->sY - base_y; INT16 offset_x = (dx - dy); INT16 offset_y = (dx + dy); BltVideoObjectFromIndex( FRAME_BUFFER, guiShieldGraphic, offset * 8 + pSoldier->ubDirection, sScreenX - 20 + offset_x, sScreenY - 60 + offset_y, VO_BLT_TRANSSHADOW, NULL ); } } 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); } } inline UINT16 * GetShadeTable(LEVELNODE * pNode, SOLDIERTYPE * pSoldier, SOLDIERTYPE * pPaletteTable, UINT32 uiFlags, INT16 * gsForceSoldierZLevel) { UINT16 * pShadeTable; // 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 = pPaletteTable->pCurrentShade = pPaletteTable->pShades[pSoldier->ubFadeLevel]; } else { pShadeTable = pPaletteTable->pCurrentShade = pPaletteTable->pShades[ubShadeLevel]; } } 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)) { SOLDIERTYPE * pSelSoldier; if (gusSelectedSoldier != NOBODY) { pSelSoldier = MercPtrs[gusSelectedSoldier]; } else { pSelSoldier = NULL; } INT8 bGlowShadeOffset; 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; } } } } INT16 ** pShadeStart; if (pSoldier->pathing.bLevel == 0) { pShadeStart = (INT16 **) & (pPaletteTable->pGlowShades[0]); } else { pShadeStart = (INT16 **) & (pPaletteTable->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 = pPaletteTable->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) { // Do 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 ]; // } //} } } 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 = pPaletteTable->pEffectShades[1]; } // Flugente: frozen soldiers appear to be in ice, which we simulate by having the soldier be fully white if (pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_CRYO]) { pShadeTable = White16BPPPalette; } return pShadeTable; } /* MONSTERS BE HERE! */ 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; BOOLEAN fObscured; BOOLEAN fObscuredBlitter; INT16 sModifiedTileHeight; BOOLEAN fDoRow; 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; } // 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.... // bio: put the logic for determining the right shade table into inline fuction (called again for logical bodytype implementation) // TODO: in case of a logical bodytype being used, the function does not have to be called here (if determining of log. bodytype is moved to the render entry fun. pShadeTable = GetShadeTable(pNode, pSoldier, pSoldier, uiFlags, &gsForceSoldierZLevel); // Calculate Z level SoldierZLevel(pSoldier, iTempPosX_M, iTempPosY_M); 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; // Flugente: frozen soldiers don't move if (pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_CRYO] && pSoldier->stats.bLife > 0) { usImageIndex = pSoldier->CryoAniFrame(); } // Flugente: riot shields if (pSoldier && pSoldier->bVisible != -1 && (pSoldier->ubDirection == NORTH || pSoldier->ubDirection == NORTHWEST || pSoldier->ubDirection == WEST) && pSoldier->IsRiotShieldEquipped()) { ShowRiotShield(pSoldier); } 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 ) ) // anv: commented out TileElem->uiFlags & ROOF_TILE because: // 1. only roof tiles get hidden in this manner anyway // 2. we might want to his and reveal again other stuff (most importantly - on roof structures) if ((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; } } using namespace LogicalBodyTypes; static BodyTypeDB * bodyTypeDB = &BodyTypeDB::Instance(); static Layers::LayerPropertiesVector::size_type numLayers = max(1, Layers::Instance().GetCount()); //defaults to 1 in case the layers.xml file could not be read // TODO: should find a better place to determine the logical body type. This function gets called like a gazillion times // every render cycle and the find provedure will get quite expensive at later stages (lots of logical body types, animations and filters!) // Should only be done once every cycle, or better yet, only and directly after a SOLDIERTYPE object has been altered (if at all possible)! BodyType * bt = NULL; if ((gGameSettings.fOptions[TOPTION_USE_LOGICAL_BODYTYPES] == TRUE) && (uiRowFlags == TILES_DYNAMIC_MERCS || uiRowFlags == TILES_DYNAMIC_HIGHMERCS || uiRowFlags == TILES_DYNAMIC_STRUCT_MERCS)) { bt = bodyTypeDB->Find(pSoldier); } UINT16 * pDefaultShadeTable = pShadeTable; RECT backRect; // Actually only needed if uiFlags & TILES_DIRTY, but must be initialized with values that make sense for the comparisons. backRect.left = SCREEN_WIDTH; backRect.top = SCREEN_HEIGHT; backRect.right = 0; backRect.bottom = 0; Layers::LayerGraphIterator layerIter; Layers::LayerGraphIterator layerEnd; if (bt != NULL) { layerIter = Layers::Instance().GetIterator(pSoldier->bMovementDirection); layerEnd = Layers::Instance().GetIterationEnd(pSoldier->bMovementDirection); } HVOBJECT hVObjectAlpha = NULL; while ((bt == NULL) || (layerIter != layerEnd)) { bool fIgnoreShadows = false; if (bt != NULL) { BodyType::LogicalSurfaceType * logSurfaceType = bt->GetLogicalSurfaceType(layerIter->index, pSoldier); if (logSurfaceType != NULL) { const Layers::LayerProperties * layerProperties = bt->GetLayerProperties(layerIter->index); fIgnoreShadows = !layerProperties->renderShadows; if (!layerProperties->render) { layerIter++; continue; } hVObject = logSurfaceType->physicalSurfaceType->hVideoObject; if (hVObject == NULL) { layerIter++; continue; } if (logSurfaceType->alphaSurfaceType != NULL) { hVObjectAlpha = logSurfaceType->alphaSurfaceType->hVideoObject; } if (logSurfaceType->paletteTable != NULL) { pShadeTable = GetShadeTable(pNode, pSoldier, (SOLDIERTYPE *)logSurfaceType->paletteTable, uiFlags, &gsForceSoldierZLevel); } else { pShadeTable = pDefaultShadeTable; } } else { layerIter++; continue; } } // 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 = 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)) { // changed the logic to determine the maximum dimensions of the needed back rect // in case of multi layering. Actual registering of back rect done after layer loop pTrav = &(hVObject->pETRLEObject[usImageIndex]); uiBrushHeight = (UINT32)pTrav->usHeight; uiBrushWidth = (UINT32)pTrav->usWidth; INT32 rLeft = sXPos + pTrav->sOffsetX; INT32 rTop = sYPos + pTrav->sOffsetY; backRect.left = min(backRect.left, rLeft); backRect.top = min(backRect.top, rTop); backRect.right = max(backRect.right, rLeft + (INT32)uiBrushWidth); backRect.bottom = max(backRect.bottom, rTop + (INT32)uiBrushHeight); } } 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) { if (hVObjectAlpha == NULL) { Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); } } else { if (hVObjectAlpha == NULL) { Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransZTransShadowIncClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); } } } 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) { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowZClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } } else { if (fObscuredBlitter) { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } } else { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowZNBClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } } } if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) { pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES); // BLIT HERE if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowClipAlpha((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowClip((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } UnLockVideoSurface(guiSAVEBUFFER); // Turn it off! pNode->uiFlags &= (~LEVELNODE_UPDATESAVEBUFFERONCE); } } else { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, pShadeTable, fIgnoreShadows); } } } 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); } } 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) { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowZAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } } else { if (fObscuredBlitter) { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowZNBObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } } else { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowZNBAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } } } if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) { pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES); // BLIT HERE if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowAlpha((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadow((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } UnLockVideoSurface(guiSAVEBUFFER); } } else { if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadow((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } } } 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); } } 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) { // why to 16BPP here?? if (hVObjectAlpha != NULL) { Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } else { Blt8BPPDataTo16BPPBufferTransShadowZNBObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, pShadeTable, fIgnoreShadows); } // 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); } } } if (bt == NULL) { break; // no logical body type found, no layers to render } layerIter++; } // background rect registration. Have to do this here, can't do it in the loop // as we don't know what the last rendered layer is upfront if (uiFlags & TILES_DIRTY) { if (!(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC)) { sXPos = (INT16)backRect.left; sYPos = (INT16)backRect.top; RegisterBackgroundRect(uiDirtyFlags, NULL, sXPos, sYPos, (INT16)backRect.right, (INT16)(__min((INT16)(backRect.bottom), gsVIEWPORT_WINDOW_END_Y))); if (fSaveZ) { RegisterBackgroundRect(uiDirtyFlags | BGND_FLAG_SAVE_Z, NULL, sXPos, sYPos, (INT16)backRect.right, (INT16)(__min((INT16)(backRect.bottom), gsVIEWPORT_WINDOW_END_Y))); } } } // unset save buffer once flag after all layers have been rendered } if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) { pNode->uiFlags &= (~LEVELNODE_UPDATESAVEBUFFERONCE); } // RENDER 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(); } } 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 // silversurfer: also ignore CTRL because this is now used for merc portrait switching if ( _KeyDown(ALT) || _KeyDown(CTRL) ) 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; } //hayden - disable mouse scrolling for window dev ease if(iDisableMouseScrolling)break; // 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++; if(gfScrollInertia == 1)//dnl ch78 271113 RestoreBackgroundRects(); // 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() { gOldClipRect.iLeft = 0; gOldClipRect.iTop = 0; gOldClipRect.iRight = SCREEN_WIDTH; gOldClipRect.iBottom = SCREEN_HEIGHT; 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; /* // Buggler: Commented out restricted Scroll ID/viewport as viewport for A10_B1 map shifts around in non-640x480 resolutions // no issue on having the usual scrollable viewport both during gameplay and in mapeditor // code may served as reference for fixing viewport issues larger than standard-sized maps on very high resolutions, e.g. UHD. case 1: // BASEMENT 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; */ default: //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; } 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 ( fOutRight ) { CorrectRenderCenter( (INT16)( gsTRX - sX_S ) , sScreenCenterY , &sNewScreenX, &sNewScreenY ); FromScreenToCellCoordinates( sNewScreenX, sNewScreenY , &sTempPosX_W, &sTempPosY_W ); sTempRenderCenterX = sTempPosX_W; sTempRenderCenterY = sTempPosY_W; fScrollGood = TRUE; } 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; } } 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, BOOLEAN fIgnoreShadows) { 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 // Original comparison ja BlitPixellate1 // Due to lobot layers having the same z-level, the comparison would pixelate merc's layers against each other. Now we pixelate ONLY if the comparison is above. 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 al, fIgnoreShadows cmp al, 0 jne BlitNTL2 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); } // Blitter Specs // 1 ) 8 to 16 bpp // 2 ) strip z-blitter // 3 ) clipped // 4 ) trans shadow - if value is 254, makes a shadow // BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset, uiLineFlag; UINT32 usHeight, usWidth, Unblitted; UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; 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(hAlphaVObject != 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; AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop esi or cl, cl js TopSkipLoop jz TSEndLine add esi, ecx push esi mov esi, AlphaPtr add esi, ecx mov AlphaPtr, esi pop esi 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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 push esi mov esi, AlphaPtr add esi, LSCount mov AlphaPtr, esi pop esi 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 push esi mov esi, AlphaPtr add esi, ecx mov AlphaPtr, esi pop esi jmp BlitLineSetup LSSkip1 : add esi, ecx // skip whole run, continue skipping push esi mov esi, AlphaPtr add esi, ecx mov AlphaPtr, esi pop esi 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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 al, fIgnoreShadows cmp al, 0 jne BlitNTL2 mov ax, [edi] mov ax, ShadeTable[eax * 2] mov[edi], ax jmp BlitNTL2 BlitNTL66 : mov ax, [edx + eax * 2] // Copy pixel push edx push ecx push ebx push esi mov esi, AlphaPtr xor ebx, ebx mov bl, [esi] pop esi push ebx push[edi] push eax call blendWithAlpha add esp, 12 pop ebx pop ecx pop edx mov[edi], ax BlitNTL2 : inc esi push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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, BOOLEAN fIgnoreShadows) { 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 al, fIgnoreShadows cmp al, 0 jne BlitNTL2 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); } // Blitter Specs // 1 ) 8 to 16 bpp // 2 ) strip z-blitter // 3 ) clipped // 4 ) trans shadow - if value is 254, makes a shadow // BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth, Unblitted; UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; 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(hAlphaVObject != 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; AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop esi or cl, cl js TopSkipLoop jz TSEndLine add esi, ecx push esi mov esi, AlphaPtr add esi, ecx mov AlphaPtr, esi pop esi 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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 push esi mov esi, AlphaPtr add esi, LSCount mov AlphaPtr, esi pop esi 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 push esi mov esi, AlphaPtr add esi, ecx mov AlphaPtr, esi pop esi jmp BlitLineSetup LSSkip1 : add esi, ecx // skip whole run, continue skipping push esi mov esi, AlphaPtr add esi, ecx mov AlphaPtr, esi pop esi 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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 al, fIgnoreShadows cmp al, 0 jne BlitNTL2 mov ax, [edi] mov ax, ShadeTable[eax * 2] mov[edi], ax jmp BlitNTL2 BlitNTL66 : mov ax, [edx + eax * 2] // Copy pixel push edx push ecx push ebx push esi mov esi, AlphaPtr xor ebx, ebx mov bl, [esi] pop esi push ebx push[edi] push eax call blendWithAlpha add esp, 12 pop ebx pop ecx pop edx mov[edi], ax BlitNTL2 : inc esi push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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 push esi mov esi, AlphaPtr inc esi mov AlphaPtr, esi pop 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;//dnl ch85 030214 if ( gusWorldRoomInfo[ usTileIndex ] != NO_ROOM ) { SetFont( SMALLCOMPFONT ); SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, gsVIEWPORT_END_Y, FALSE ); switch( gusWorldRoomInfo[ 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", gusWorldRoomInfo[ 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