/************************************************************************************** DRAW.CPP ***************************************************************************************/ #include "tde.h" /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** a_lTableMM : Min-max array contains : | X_l | X_r | X_t_l | Y_t_l | X_t_r | Y_t_r | blank | blank | **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ TDE_tdl1616 a_lTableMM[768][8]; /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** Semi-transparency masks for 16 bits Force to 0 each component's last bit **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ unsigned short sMask_565 = 0xF7DE; // 1111 0111 1101 1110 unsigned short sMask_655 = 0xFBDE; // 1111 1011 1101 1110 unsigned short sMask_556 = 0xF7BE; // 1111 0111 1011 1110 unsigned short sMask_555 = 0x7BDE; // 0111 1011 1101 1110 /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vDrawSuperObject16 VERSION : 2.0 / Valérie 1.0 / Franck AIM : Display a super object (for sprites) **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vDrawSuperObject16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObject) { TDE_tdxValue xScaledSpriteW, xScaledSpriteH, xSpriteCenterX, xSpriteCenterY, xSpriteCornerX, xSpriteCornerY, xScaledSourceW, xScaledSourceH, xSourceCornerX, xSourceCornerY; long lPitchDest, lPitchSrc, lViewPortW, lViewPortH; short si; TDE_tdsRect stSrcRect, stDestRect; TDE_tdsSprite *p_stSprite = p_stSuperObject->p_stSprite; stSrcRect.lPitch = lPitchSrc = ((long)(p_stSprite->stPicture.xSrcPitch))>>C_TDEDEC; stDestRect.lPitch = lPitchDest = (p_stViewAttrib->lPitch)>>C_TDEDEC; lViewPortW = p_stViewAttrib->dwWidth; lViewPortH = p_stViewAttrib->dwHeight; // xValues xScaledSpriteW = TDE_M_Mul(lViewPortW , p_stSprite->stDim.xX); xScaledSpriteH = TDE_M_Mul(lViewPortH , p_stSprite->stDim.xY); xSpriteCenterX = TDE_M_Mul(lViewPortW , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX); xSpriteCenterY = TDE_M_Mul(lViewPortH , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY); xSpriteCornerX = xSpriteCenterX - TDE_M_Div(xScaledSpriteW,2); xSpriteCornerY = xSpriteCenterY - TDE_M_Div(xScaledSpriteH,2); xSourceCornerX = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stSourceOrigin.xX); xSourceCornerY = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stSourceOrigin.xY); xScaledSourceW = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stDim.xX); xScaledSourceH = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stDim.xY); // Destination rectangle iTDE_vFillsRect(&stDestRect, xSpriteCornerX - xSpriteCenterX, xSpriteCornerY - xSpriteCenterY, xScaledSpriteW, xScaledSpriteH); // Transformation for (si=0; si<4; si++) { TDE_vMulMatrixByVertex(&(p_stSuperObject->stModifiedMatrix.a4_xS), &(stDestRect.tdsSommet[si]), &(stDestRect.tdsSommet[si])); stDestRect.tdsSommet[si].xX += xSpriteCenterX; stDestRect.tdsSommet[si].xY += xSpriteCenterY; } // Source rectangle iTDE_vFillsRect(&stSrcRect, xSourceCornerX, xSourceCornerY, xScaledSourceW, xScaledSourceH); stDestRect.p_usPointer = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); stSrcRect.p_usPointer = (TDE_tdxPixel *)(p_stSprite->stPicture.lp_Data); if (!p_stSprite->cSemiTransparent) { iTDE_vBlit(&stSrcRect, &stDestRect); } else { iTDE_vBlit_Transparency(&stSrcRect, &stDestRect, p_stSprite->alpha); } } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vDrawSuperObjectFast16 VERSION : 2.0 / Valérie 1.0 / Franck AIM : Display a super object (for sprites) without stretch **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vDrawSuperObjectFast16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObject) { TDE_tdxValue xScaledSpriteW, xScaledSpriteH, xSpriteCenterX, xSpriteCenterY, xSpriteCornerX, xSpriteCornerY, xScaledSourceW, xScaledSourceH, xSourceCornerX, xSourceCornerY; long lPitchDest, lPitchSrc, lViewPortW, lViewPortH; short si; TDE_tdsRect stSrcRect, stDestRect; TDE_tdsSprite *p_stSprite = p_stSuperObject->p_stSprite; stSrcRect.lPitch = lPitchSrc = ((long)(p_stSprite->stPicture.xSrcPitch))>>C_TDEDEC; stDestRect.lPitch = lPitchDest = (p_stViewAttrib->lPitch)>>C_TDEDEC; lViewPortW = p_stViewAttrib->dwWidth; lViewPortH = p_stViewAttrib->dwHeight; // xValues xSourceCornerX = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stSourceOrigin.xX); xSourceCornerY = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stSourceOrigin.xY); xScaledSourceW = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stDim.xX); xScaledSourceH = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stDim.xY); xScaledSpriteW = xScaledSourceW; xScaledSpriteH = xScaledSourceH; xSpriteCenterX = TDE_M_Mul(lViewPortW , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX); xSpriteCenterY = TDE_M_Mul(lViewPortH , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY); xSpriteCornerX = xSpriteCenterX - TDE_M_Div(xScaledSpriteW,2); xSpriteCornerY = xSpriteCenterY - TDE_M_Div(xScaledSpriteH,2); // Destination rectangle iTDE_vFillsRect(&stDestRect, xSpriteCornerX - xSpriteCenterX, xSpriteCornerY - xSpriteCenterY, xScaledSpriteW, xScaledSpriteH); for (si=0; si<4; si++) { stDestRect.tdsSommet[si].xX += xSpriteCenterX; stDestRect.tdsSommet[si].xY += xSpriteCenterY; } // Source rectangle iTDE_vFillsRect(&stSrcRect, xSourceCornerX, xSourceCornerY, xScaledSourceW, xScaledSourceH); stDestRect.p_usPointer = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); stSrcRect.p_usPointer = (TDE_tdxPixel *)(p_stSprite->stPicture.lp_Data); iTDE_vBlitFast(&stSrcRect, &stDestRect); } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vFastDrawMemorySpriteAbsolute VERSION : 2.0 / Valérie 1.0 / Franck AIM : Display a sprite stored in memory ! ATTENTION ! : The sprite has to be defined with absolute coordinates **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vFastDrawMemorySpriteAbsolute(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObject, TDE_tdsRect *p_stScreenRect) { TDE_tdxValue xScaledSpriteW, xScaledSpriteH, xSpriteCenterX, xSpriteCenterY, xSpriteCornerX, xSpriteCornerY; long lPitchDest, lViewPortW, lViewPortH; TDE_tdsRect stDestRect, stClippedDestRect; TDE_tdsMemZone stSource; TDE_tdsSprite *p_stSprite = p_stSuperObject->p_stSprite; // clipping value 0->no clipped, 1->clipped to screen rect, 2->clipped to SO clipping rectangle char clipped = 0; stDestRect.lPitch = lPitchDest = (p_stViewAttrib->lPitch)>>C_TDEDEC; lViewPortW = p_stViewAttrib->dwWidth; lViewPortH = p_stViewAttrib->dwHeight; // xValues xScaledSpriteW = p_stSprite->stDim.xX; // absolute dimensions xScaledSpriteH = p_stSprite->stDim.xY; xSpriteCenterX = p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX; xSpriteCenterY = p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY; xSpriteCornerX = xSpriteCenterX - TDE_M_Div(xScaledSpriteW, 2) + 0.5; xSpriteCornerY = xSpriteCenterY - TDE_M_Div(xScaledSpriteH, 2) + 0.5; // Destination rectangle iTDE_vFillsRect(&stDestRect, xSpriteCornerX, xSpriteCornerY, xScaledSpriteW, xScaledSpriteH); // Out of screen ? if ( (long)(stDestRect.tdsSommet[0].xX)>p_stScreenRect->tdsSommet[1].xX) return; if ( (long)(stDestRect.tdsSommet[2].xX)tdsSommet[0].xX) return; if ( (long)(stDestRect.tdsSommet[0].xY)>p_stScreenRect->tdsSommet[3].xY) return; if ( (long)(stDestRect.tdsSommet[2].xY)tdsSommet[0].xY) return; // Clipped ? if ( ( (long)(stDestRect.tdsSommet[0].xX)tdsSommet[0].xX) || ( (long)(stDestRect.tdsSommet[1].xX)>p_stScreenRect->tdsSommet[1].xX) || ( (long)(stDestRect.tdsSommet[0].xY)tdsSommet[0].xY) || ( (long)(stDestRect.tdsSommet[3].xY)>p_stScreenRect->tdsSommet[3].xY) ) { clipped = 1; } if (p_stSuperObject->p_stSOClipRect) clipped = 2; if (clipped) { //iTDE_vAdjustScreenRectForClip(&stDestRect, &stClippedDestRect, lViewPortW, lViewPortH); if ( clipped == 1) iTDE_vAdjustScreenRectToClipRect(&stDestRect, &stClippedDestRect, p_stScreenRect); else if ( clipped == 2) iTDE_vAdjustScreenRectToClipRect(&stDestRect, &stClippedDestRect, p_stSuperObject->p_stSOClipRect); stClippedDestRect.p_usPointer = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); stSource.p_usPointer = p_stSprite->v_pData + // recal TDE_M_ValueToLong ( ( TDE_M_ValueToLong(stClippedDestRect.tdsSommet[0].xY) - TDE_M_ValueToLong(stDestRect.tdsSommet[0].xY) )*xScaledSpriteW ) + ( TDE_M_ValueToLong(stClippedDestRect.tdsSommet[0].xX) - TDE_M_ValueToLong(stDestRect.tdsSommet[0].xX) ); stSource.stDim.xX = xScaledSpriteW; stSource.stDim.xY = xScaledSpriteH; stSource.xMagicColor = p_stSprite->xMagicColor; if (p_stSprite->c_NZ) { iTDE_vBlitClipMemory_NZ(&stSource, &stClippedDestRect); } else { iTDE_vBlitClipMemory(&stSource, &stClippedDestRect); } } else { stDestRect.p_usPointer = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); stSource.p_usPointer = (TDE_tdxPixel *)(p_stSprite->v_pData); stSource.stDim.xX = xScaledSpriteW; stSource.stDim.xY = xScaledSpriteH; stSource.xMagicColor = p_stSprite->xMagicColor; if (p_stSprite->c_NZ) { iTDE_vBlitFastMemory_NZ(&stSource, &stDestRect); } else { iTDE_vBlitFastMemory(&stSource, &stDestRect); } } } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vFastDrawMemorySpriteAbsoluteInvert VERSION : 2.0 / Valérie 1.0 / Franck AIM : Display a sprite stored in memory ! ATTENTION ! : The sprite has to be defined with absolute coordinates **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vFastDrawMemorySpriteAbsoluteInvert(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObject, TDE_tdsRect *p_stScreenRect) { TDE_tdxValue xScaledSpriteW, xScaledSpriteH, xSpriteCenterX, xSpriteCenterY, xSpriteCornerX, xSpriteCornerY; long lPitchDest, lViewPortW, lViewPortH; TDE_tdsRect stDestRect, stClippedDestRect; TDE_tdsMemZone stSource; TDE_tdsSprite *p_stSprite = p_stSuperObject->p_stSprite; char clipped = 0; stDestRect.lPitch = lPitchDest = (p_stViewAttrib->lPitch)>>C_TDEDEC; lViewPortW = p_stViewAttrib->dwWidth; lViewPortH = p_stViewAttrib->dwHeight; // xValues xScaledSpriteW = p_stSprite->stDim.xX; // absolute dimensions xScaledSpriteH = p_stSprite->stDim.xY; xSpriteCenterX = p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX; xSpriteCenterY = p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY; xSpriteCornerX = xSpriteCenterX - TDE_M_Div(xScaledSpriteW, 2) + 0.5; xSpriteCornerY = xSpriteCenterY - TDE_M_Div(xScaledSpriteH, 2) + 0.5; // Destination rectangle /* iTDE_vFillsRect(&stDestRect, xSpriteCornerX - xSpriteCenterX, xSpriteCornerY - xSpriteCenterY, xScaledSpriteW, xScaledSpriteH); for (si=0; si<4; si++) { stDestRect.tdsSommet[si].xX += xSpriteCenterX; stDestRect.tdsSommet[si].xY += xSpriteCenterY; } */ iTDE_vFillsRect(&stDestRect, xSpriteCornerX, xSpriteCornerY, xScaledSpriteW, xScaledSpriteH); // Out of screen ? if ( (long)(stDestRect.tdsSommet[0].xX)>p_stScreenRect->tdsSommet[1].xX) return; if ( (long)(stDestRect.tdsSommet[2].xX)tdsSommet[0].xX) return; if ( (long)(stDestRect.tdsSommet[0].xY)>p_stScreenRect->tdsSommet[3].xY) return; if ( (long)(stDestRect.tdsSommet[2].xY)tdsSommet[0].xY) return; // Clipped ? if ( ( (long)(stDestRect.tdsSommet[0].xX)tdsSommet[0].xX) || ( (long)(stDestRect.tdsSommet[1].xX)>p_stScreenRect->tdsSommet[1].xX) || ( (long)(stDestRect.tdsSommet[0].xY)tdsSommet[0].xY) || ( (long)(stDestRect.tdsSommet[3].xY)>p_stScreenRect->tdsSommet[3].xY) ) { clipped = 1; } if (p_stSuperObject->p_stSOClipRect) clipped = 2; if ( clipped == 1 ) { //iTDE_vAdjustScreenRectForClip(&stDestRect, &stClippedDestRect, lViewPortW, lViewPortH); if ( clipped == 1) iTDE_vAdjustScreenRectToClipRect(&stDestRect, &stClippedDestRect, p_stScreenRect); else if ( clipped == 2) iTDE_vAdjustScreenRectToClipRect(&stDestRect, &stClippedDestRect, p_stSuperObject->p_stSOClipRect); stClippedDestRect.p_usPointer = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); stSource.p_usPointer = p_stSprite->v_pData + // recal TDE_M_ValueToLong ( ( TDE_M_ValueToLong(stClippedDestRect.tdsSommet[0].xY) - TDE_M_ValueToLong(stDestRect.tdsSommet[0].xY) )*xScaledSpriteW ) + ( TDE_M_ValueToLong(stClippedDestRect.tdsSommet[0].xX) - TDE_M_ValueToLong(stDestRect.tdsSommet[0].xX) ); stSource.stDim.xX = xScaledSpriteW; stSource.stDim.xY = xScaledSpriteH; stSource.xMagicColor = p_stSprite->xMagicColor; if (p_stSprite->c_NZ) { iTDE_vBlitClipMemory_Invert_NZ(&stSource, &stClippedDestRect); } else { iTDE_vBlitClipMemory_Invert(&stSource, &stClippedDestRect); } } else { stDestRect.p_usPointer = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); stSource.p_usPointer = (TDE_tdxPixel *)(p_stSprite->v_pData); stSource.stDim.xX = xScaledSpriteW; stSource.stDim.xY = xScaledSpriteH; stSource.xMagicColor = p_stSprite->xMagicColor; if (p_stSprite->c_NZ) { iTDE_vBlitFastMemory_Invert_NZ(&stSource, &stDestRect); } else { iTDE_vBlitFastMemory_Invert(&stSource, &stDestRect); } } } void TDE_vFastDrawBackGround(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObject) { TDE_tdsSprite *p_stSprite = p_stSuperObject->p_stSprite; TDE_tdxPixel *src, *dest; dest = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); src = p_stSprite->v_pData; //iTDE_vBackground((long *)src, (long *)dest); } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vDrawSuperObjectClipped16 VERSION : 2.0 / Valérie 1.0 / Franck AIM : Display a super object with clipping (for sprites) **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vDrawSuperObjectClipped16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObject) { TDE_tdxValue xScaledSpriteW, xScaledSpriteH, xSpriteCenterX, xSpriteCenterY, xSpriteCornerX, xSpriteCornerY, xSourceCornerX, xSourceCornerY, xScaledSourceW, xScaledSourceH; long lPitchDest, lPitchSrc, lViewPortW, lViewPortH; short si; TDE_tdsRect stSrcRect, stDestRect, stClippedDestRect, stSrcFlippedRect, stSrcClippedRect; TDE_tdsSprite *p_stSprite = p_stSuperObject->p_stSprite; stSrcRect.lPitch = lPitchSrc = ((long)(p_stSprite->stPicture.xSrcPitch))>>C_TDEDEC; stDestRect.lPitch = lPitchDest = (p_stViewAttrib->lPitch)>>C_TDEDEC; lViewPortW = p_stViewAttrib->dwWidth; lViewPortH = p_stViewAttrib->dwHeight; // xValues xScaledSpriteW = TDE_M_Mul(lViewPortW , p_stSprite->stDim.xX); xScaledSpriteH = TDE_M_Mul(lViewPortH , p_stSprite->stDim.xY); xSpriteCenterX = TDE_M_Mul(lViewPortW , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX); xSpriteCenterY = TDE_M_Mul(lViewPortH , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY); xSpriteCornerX = xSpriteCenterX - TDE_M_Div(xScaledSpriteW,2); xSpriteCornerY = xSpriteCenterY - TDE_M_Div(xScaledSpriteH,2); xSourceCornerX = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stSourceOrigin.xX); xSourceCornerY = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stSourceOrigin.xY); xScaledSourceW = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stDim.xX); xScaledSourceH = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stDim.xY); // Screen rectangle iTDE_vFillsRect(&stDestRect, xSpriteCornerX - xSpriteCenterX, xSpriteCornerY - xSpriteCenterY, xScaledSpriteW, xScaledSpriteH); // Transformation for ( si=0; si<4; si++ ) { TDE_vMulMatrixByVertex(&(p_stSuperObject->stModifiedMatrix.a4_xS), &(stDestRect.tdsSommet[si]), &(stDestRect.tdsSommet[si])); stDestRect.tdsSommet[si].xX += xSpriteCenterX; stDestRect.tdsSommet[si].xY += xSpriteCenterY; } // Out of screen if ( (long)(stDestRect.tdsSommet[0].xX)>lViewPortW ) return; if ( (long)(stDestRect.tdsSommet[2].xX)<0 ) return; if ( (long)(stDestRect.tdsSommet[0].xY)>lViewPortH ) return; if ( (long)(stDestRect.tdsSommet[2].xY)<0 ) return; // Adjust destination rectangle for clipping iTDE_vAdjustScreenRectForClip(&stDestRect, &stClippedDestRect, lViewPortW, lViewPortH); stClippedDestRect.p_usPointer = (TDE_tdxPixel *)(p_stViewAttrib->p_cVirtualScreen); // Source rectangle iTDE_vFillsRect(&stSrcRect, xSourceCornerX, xSourceCornerY, xScaledSourceW, xScaledSourceH); stSrcRect.p_usPointer = (TDE_tdxPixel *)(p_stSprite->stPicture.lp_Data); // Adjust source rectangle for flip iTDE_vAdjustRectToFlip(&stSrcRect, &stSrcFlippedRect, p_stSprite->cFlip); // Adjust source rectangle for clip iTDE_vAdjustSourceRectForClip(&stDestRect, &stSrcFlippedRect, &stSrcClippedRect, lViewPortW, lViewPortH); // Drawing loop if ( !p_stSprite->cSemiTransparent ) { iTDE_vBlit(&stSrcClippedRect, &stClippedDestRect); } else { iTDE_vBlit_Transparency(&stSrcClippedRect, &stClippedDestRect, p_stSprite->alpha); } } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vCalculateIntermediateVertex VERSION : 2.0 / Valérie 1.0 / Franck AIM : Calculate the clipped vertex between two points **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vCalculateIntermediateVertex(TDE_tdsClippedVertex1616 *Result_Point, TDE_tdsClippedVertex1616 *Point1, TDE_tdsClippedVertex1616 *Point2, TDE_tdl1616 lValue1, TDE_tdl1616 lValue2, TDE_tdl1616 lInterValue) { TDE_tdl1616 lInvert; lInvert = TDE_DIV ( (lInterValue-lValue2) , (lValue1-lValue2) ); Result_Point->Point.lX = Point2->Point.lX + TDE_MUL( (Point1->Point.lX) - (Point2->Point.lX), lInvert ) ; Result_Point->Point.lY = Point2->Point.lY + TDE_MUL( (Point1->Point.lY) - (Point2->Point.lY), lInvert ) ; Result_Point->TexPoint.lX = Point2->TexPoint.lX + TDE_MUL( Point1->TexPoint.lX - Point2->TexPoint.lX, lInvert ); Result_Point->TexPoint.lY = Point2->TexPoint.lY + TDE_MUL( Point1->TexPoint.lY - Point2->TexPoint.lY, lInvert ); } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_lClipPolygon VERSION : 2.0 / Valérie 1.0 / Franck AIM : Clip a polygon **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ long TDE_cClipPolygon(char cNB_SOMMETS, TDE_tdsClippedVertex1616 *p_stClipped_Line, long lWidth, long lHeight) { char cNB_SOMMETS2, cIndix, cVertexIndix, cClipped_NB_Sommets, cOver; TDE_tdl1616 lYemin1616, lYemax1616, lXemin1616, lXemax1616; TDE_tdsClippedVertex1616 *p_stCLineInter1, *p_stCLineInter2, *p_stCLine2Inter, p_stClipped_Line_2[20]; lYemin1616 = 1<<16; lYemax1616 = (lHeight-1)<<16; lXemin1616 = 1<<16; lXemax1616 = (lWidth-1)<<16; // Top cutting cVertexIndix = (char)(cNB_SOMMETS-1); cClipped_NB_Sommets = 0; p_stCLineInter2 = &p_stClipped_Line[cVertexIndix]; p_stCLineInter1 = &p_stClipped_Line[0]; p_stCLine2Inter = &p_stClipped_Line_2[0]; for (cIndix=0; cIndixPoint.lY>=lYemin1616) cOver = 1; if (p_stCLineInter2->Point.lY>=lYemin1616) cOver |= 2; switch (cOver&3) { case 3: *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets++; break; case 1: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter1, p_stCLineInter2, p_stCLineInter1->Point.lY, p_stCLineInter2->Point.lY, lYemin1616); *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets += 2; break; case 2: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter2, p_stCLineInter1, p_stCLineInter2->Point.lY, p_stCLineInter1->Point.lY, lYemin1616); cClipped_NB_Sommets++; break; } p_stCLineInter2 = p_stCLineInter1; p_stCLineInter1++; } if (cClipped_NB_Sommets<2) return(0); cNB_SOMMETS2 = cClipped_NB_Sommets; // Bottom cutting cVertexIndix = (char)(cNB_SOMMETS2-1); cClipped_NB_Sommets = 0; p_stCLineInter2 = &p_stClipped_Line_2[cVertexIndix]; p_stCLineInter1 = &p_stClipped_Line_2[0]; p_stCLine2Inter = &p_stClipped_Line[0]; for (cIndix=0; cIndixPoint.lY<=lYemax1616) cOver = 1; if (p_stCLineInter2->Point.lY<=lYemax1616) cOver |= 2; switch (cOver&3) { case 3: *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets++; break; case 1: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter1, p_stCLineInter2, p_stCLineInter1->Point.lY, p_stCLineInter2->Point.lY, lYemax1616); *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets += 2; break; case 2: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter2, p_stCLineInter1, p_stCLineInter2->Point.lY, p_stCLineInter1->Point.lY, lYemax1616); cClipped_NB_Sommets++; break; } p_stCLineInter2 = p_stCLineInter1; p_stCLineInter1++; } if (cClipped_NB_Sommets<2) return(0); cNB_SOMMETS = cClipped_NB_Sommets; // Left cutting cVertexIndix= (char)(cNB_SOMMETS-1); cClipped_NB_Sommets = 0; p_stCLineInter2 = &p_stClipped_Line[cVertexIndix]; p_stCLineInter1 = &p_stClipped_Line[0]; p_stCLine2Inter = &p_stClipped_Line_2[0]; for (cIndix=0; cIndixPoint.lX>=lXemin1616) cOver = 1; if (p_stCLineInter2->Point.lX>=lXemin1616) cOver |= 2; switch (cOver&3) { case 3: *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets++; break; case 1: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter1, p_stCLineInter2, p_stCLineInter1->Point.lX, p_stCLineInter2->Point.lX, lXemin1616); *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets += 2; break; case 2: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter2, p_stCLineInter1, p_stCLineInter2->Point.lX, p_stCLineInter1->Point.lX, lXemin1616); cClipped_NB_Sommets++; break; } p_stCLineInter2 = p_stCLineInter1; p_stCLineInter1++; } if (cClipped_NB_Sommets<2) return(0); // Right cutting cNB_SOMMETS2 = cClipped_NB_Sommets; cVertexIndix = (char)(cNB_SOMMETS2-1); cClipped_NB_Sommets = 0; p_stCLineInter2 = &p_stClipped_Line_2[cVertexIndix]; p_stCLineInter1 = &p_stClipped_Line_2[0]; p_stCLine2Inter = p_stClipped_Line; for (cIndix=0; cIndixPoint.lX<=lXemax1616) cOver = 1; if (p_stCLineInter2->Point.lX<=lXemax1616) cOver |= 2; switch (cOver&3) { case 3: *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets++; break; case 1: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter1, p_stCLineInter2, p_stCLineInter1->Point.lX, p_stCLineInter2->Point.lX, lXemax1616); *(p_stCLine2Inter++) = *p_stCLineInter1; cClipped_NB_Sommets += 2; break; case 2: TDE_vCalculateIntermediateVertex(p_stCLine2Inter++, p_stCLineInter2, p_stCLineInter1, p_stCLineInter2->Point.lX, p_stCLineInter1->Point.lX, lXemax1616); cClipped_NB_Sommets++; break; } p_stCLineInter2 = p_stCLineInter1; p_stCLineInter1++; } if (cClipped_NB_Sommets<2) return(0); return(cClipped_NB_Sommets); } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vFillTableMM VERSION : 2.0 / Valérie 1.0 / Franck AIM : Fill the Min-Max Table **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vFillTableMM(long lStart, long lLenght, long lColumn, TDE_tdl1616 lValue1, TDE_tdl1616 lValue2) { TDE_tdl1616 *p_MMStart, *p_MMEnd; TDE_tdl1616 lVinc; if (lValue2 != lValue1) { lVinc = TDE_DIV( lValue2-lValue1 , (lLenght<<16) ); p_MMStart = &a_lTableMM[lStart][lColumn]; p_MMEnd = p_MMStart + (lLenght<<3); for (;p_MMStartp_stSprite; // Variables for alpha-transparency short sBlueMask = 0x001F; // 0000 0000 0001 1111 -> obtain blue component short sGreenMask = 0x07E0; // 0000 0111 1110 0000 -> obtain green component // short sRedMask = 0xF800; // 1111 1000 0000 0000 -> obtain red component short sB, sG, sR; char cIndix1, cIndix2; unsigned char *p_cAcc15, *p_cAcc25, *p_cAcc16, *p_cAcc26; lPitSrc = ((long)(p_stSprite->stPicture.xSrcPitch))>>C_TDEDEC; lPitDest = (p_stViewAttrib->lPitch)>>C_TDEDEC; lgW = p_stViewAttrib->dwWidth; lgH = p_stViewAttrib->dwHeight; // xValues xW = TDE_M_Mul(lgW , p_stSprite->stDim.xX); xH = TDE_M_Mul(lgH , p_stSprite->stDim.xY); xXc = TDE_M_Mul(lgW , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX); xYc = TDE_M_Mul(lgH , p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY); xXs = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stSourceOrigin.xX); xYs = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stSourceOrigin.xY); xWs = TDE_M_Mul(p_stSprite->stPicture.xWidth , p_stSprite->stDim.xX); xHs = TDE_M_Mul(p_stSprite->stPicture.xHeight , p_stSprite->stDim.xY); xX = xXc - TDE_M_Div(xW,2); xY = xYc - TDE_M_Div(xH,2); p_usOfs = p_usL = (TDE_tdxPixel *)(p_stSprite->stPicture.lp_Data); p_usDest = (TDE_tdxPixel *)p_stViewAttrib->p_cVirtualScreen; if (((xX+xW)<=1.0)||(xX>=lgW)) return; if (((xY+xH)<=1.0)||(xY>=lgH)) return; xPolygon[0].Point.xX = xX-xXc; xPolygon[0].Point.xY = xY-xYc; xPolygon[1].Point.xX = xX+xW-xXc; xPolygon[1].Point.xY = xY-xYc; xPolygon[2].Point.xX = xX+xW-xXc; xPolygon[2].Point.xY = xY+xH-xYc; xPolygon[3].Point.xX = xX-xXc; xPolygon[3].Point.xY = xY+xH-xYc; for (si=0; si<4; si++) { TDE_vMulMatrixByVertex(&(p_stSuperObject->stModifiedMatrix.a4_xRxS), &xPolygon[si].Point, &xPolygon[si].Point); xPolygon[si].Point.xX += xXc; xPolygon[si].Point.xY += xYc; } xPolygon[0].TexPoint.xX = xPolygon[3].TexPoint.xX = xXs; xPolygon[1].TexPoint.xX = xPolygon[2].TexPoint.xX = xXs+xWs; xPolygon[0].TexPoint.xY = xPolygon[1].TexPoint.xY = xYs; xPolygon[2].TexPoint.xY = xPolygon[3].TexPoint.xY = xYs+xHs; // xPolygon -> Polygon for (si=0; si<4; si++) { Polygon[si].Point.lX = TDE_M_ValueTo1616(xPolygon[si].Point.xX); Polygon[si].Point.lY = TDE_M_ValueTo1616(xPolygon[si].Point.xY); Polygon[si].TexPoint.lX = TDE_M_ValueTo1616(xPolygon[si].TexPoint.xX); Polygon[si].TexPoint.lY = TDE_M_ValueTo1616(xPolygon[si].TexPoint.xY); } // Clip lNBSommets = TDE_cClipPolygon(4, Polygon, lgW, lgH); // 16:16 -> int for (si=0; si>=16; // Fills min-max table if (lNBSommets>2) { Ptr1 = &Polygon[0]; Ptr2 = &Polygon[lNBSommets-1]; lYmin = Ptr2->Point.lY; lYmax = Ptr2->Point.lY; for (si=0; siPoint.lYPoint.lY; if (Ptr1->Point.lY>lYmax) lYmax = Ptr1->Point.lY; if (Ptr2->Point.lYPoint.lY) { // Right TDE_vFillTableMM(Ptr2->Point.lY, Ptr1->Point.lY-Ptr2->Point.lY, 1, Ptr2->Point.lX, Ptr1->Point.lX); TDE_vFillTableMM(Ptr2->Point.lY, Ptr1->Point.lY-Ptr2->Point.lY, 4, Ptr2->TexPoint.lX, Ptr1->TexPoint.lX); TDE_vFillTableMM(Ptr2->Point.lY, Ptr1->Point.lY-Ptr2->Point.lY, 5, Ptr2->TexPoint.lY, Ptr1->TexPoint.lY); } else if (Ptr2->Point.lY>Ptr1->Point.lY) { // Left TDE_vFillTableMM(Ptr1->Point.lY, Ptr2->Point.lY-Ptr1->Point.lY, 0, (Ptr1->Point.lX), (Ptr2->Point.lX)); TDE_vFillTableMM(Ptr1->Point.lY, Ptr2->Point.lY-Ptr1->Point.lY, 2, (Ptr1->TexPoint.lX), (Ptr2->TexPoint.lX)); TDE_vFillTableMM(Ptr1->Point.lY, Ptr2->Point.lY-Ptr1->Point.lY, 3, (Ptr1->TexPoint.lY), (Ptr2->TexPoint.lY)); } Ptr2=Ptr1; Ptr1++; } } // Is the sprite out of screen (Y) ? if ((lYmin>=(lgH-1))||(lYmax<=1)) return; // Increments calculation lMiddle = lYmin+((lYmax-lYmin)>>1); if ((lMiddle<0)||(lMiddle>768)) return; // debug T_H = &a_lTableMM[lMiddle][0]; ldX = *(T_H+1) - *(T_H); lUg = *(T_H+2); lVg = *(T_H+3); lUd = *(T_H+4); lVd = *(T_H+5); if (ldX>0) { ldU = TDE_DIV((lUd-lUg),ldX); ldV = TDE_DIV((lVd-lVg),ldX); } else return; ldE = lPitSrc*(ldV>>16)+(ldU>>16); ldF = ((ldV>>1)&0x7FFF)+((ldU<<15)&0x7FFF0000); T_H = &a_lTableMM[lYmin][0]; p_usDest += lYmin*lPitDest; ldY = lYmax-lYmin; // Main loop if (!p_stSprite->cSemiTransparent) { // No semi-transparency for (si=0; si>16; lXd = *(T_H+1)>>16; lUg = *(T_H+2); lVg = *(T_H+3); lF = ((lVg>>1)&0x7FFF)+((lUg<<15)&0x7FFF0000); p_usOfs = p_usL + lPitSrc*(lVg>>16)+(lUg>>16); p_usDestSave = p_usDest; p_usDestEnd = p_usDest+lXd; for (p_usDest=p_usDest+lXg; p_usDestp_cL) // debug c = *p_usOfs; if (c>0) *p_usDest = c; lF += ldF; p_usOfs += ldE; if (lF&0x8000) {lF&=0xFFFF7FFF; p_usOfs+=lPitSrc; } if (lF&0x80000000) {lF&=0x7FFFFFFF; p_usOfs++; } } p_usDest = p_usDestSave + lPitDest; } return; } else { cIndix1 = ((char)(p_stSprite->alpha*64))&0x3F; cIndix2 = 63-cIndix1; p_cAcc15 = &(a_cTransparencyTable5[cIndix1][0]); p_cAcc25 = &(a_cTransparencyTable5[cIndix2][0]); p_cAcc16 = &(a_cTransparencyTable6[cIndix1][0]); p_cAcc26 = &(a_cTransparencyTable6[cIndix2][0]); // semi-transparency for (si=0; si>16; lXd = *(T_H+1)>>16; lUg = *(T_H+2); lVg = *(T_H+3); lF = ((lVg>>1)&0x7FFF)+((lUg<<15)&0x7FFF0000); p_usOfs = p_usL + lPitSrc*(lVg>>16)+(lUg>>16); p_usDestSave = p_usDest; p_usDestEnd = p_usDest + lXd; for (p_usDest=p_usDest+lXg; p_usDest0) { usBackPixel = *p_usDest; sB = *(p_cAcc15 + (usBackPixel & sBlueMask)) + *(p_cAcc25+ (usSpritePixel & sBlueMask)); sG = *(p_cAcc16 + ((usBackPixel & sGreenMask)>>5)) + *(p_cAcc26 + ((usSpritePixel & sGreenMask)>>5)); sR = *(p_cAcc15 + (usBackPixel>>11)) + *(p_cAcc25 + (usSpritePixel>>11)); *p_usDest = sB+(sG<<5)+(sR<<11); } lF += ldF; p_usOfs += ldE; if (lF&0x8000) {lF&=0xFFFF7FFF; p_usOfs+=lPitSrc; } if (lF&0x80000000) {lF&=0x7FFFFFFF; p_usOfs++; } } p_usDest = p_usDestSave + lPitDest; } } // if (!p_stSprite->cSemiTransparent ....) } void TDE_vResetTable() { short si, sj; for (si=0; si<768; si++) { for (sj=0; sj<8; sj++) a_lTableMM[si][sj] = 0; } } void TDE_vSendObjectsToViewPort(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObject, TDE_p_stSuperObject *ZList) { //TDE_tdsSuperObject *p_stSuperObjectTemp; // Reset matrices stack (!) ResetMatrixStack((TDE_tdsCamera *)(p_stViewAttrib->p_vSpecificToXD)); // Init Z list TDE_vInitZList(ZList); // Rebuild all SuperObjects matrices TDE_vCreateSuperObjectDescendancyMatrices(p_stSuperObject); // Build Z list TDE_vBuildHierarchy(p_stSuperObject, ZList); } /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** NAME : TDE_vSendListToViewPort VERSION : 2.0 / Valérie 1.0 / Franck AIM : Send Z liste to a viewport Disposable functions : TDE_vDrawSuperObject16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObjet); TDE_vDrawSuperObjectFast16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObjet); TDE_vDrawMemSprite_Abs_16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObjet); TDE_vDrawSuperObjectRotated16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObjet); TDE_vDrawSuperObjectClipped16(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_tdsSuperObject *p_stSuperObjet); **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ void TDE_vSendListToViewPort(GLD_tdpstViewportAttributes p_stViewAttrib, TDE_p_stSuperObject *ZList, TDE_tdsRect *stClipScreenRect, BOOL bViewPortLocked) { TDE_tdsSuperObject *p_stSuperObjectTemp; short si; // Draw ZList if (bViewPortLocked) { // Viewport is locked : draw everything but True Type text for (si=0; sip_stNextZList) { if (p_stSuperObjectTemp->p_vPointer != NULL) { switch (p_stSuperObjectTemp->eType) { case TDE_eOT_SPRITE: TDE_vFastDrawMemorySpriteAbsolute(p_stViewAttrib, p_stSuperObjectTemp, stClipScreenRect); break; case TDE_eOT_TEXTBOX: TDE_vDrawTextInABox(p_stViewAttrib, p_stSuperObjectTemp, TRUE); break; case TDE_eOT_LINE: TDE_vDrawSuperObjectLineAbs(p_stViewAttrib, p_stSuperObjectTemp); break; case TDE_eOT_EMPTY: break; } } } } } else { // Viewport is not locked : draw nothing but True Type text for (si=0; sip_stNextZList) { if (p_stSuperObjectTemp->p_vPointer != NULL) { switch (p_stSuperObjectTemp->eType) { case TDE_eOT_TEXTBOX: TDE_vDrawTextInABox(p_stViewAttrib, p_stSuperObjectTemp, FALSE); break; case TDE_eOT_EMPTY: break; } } } } } }