diff Render.cpp @ 2155:0a1438c16c2b

Render decoupling.
author Nomad
date Thu, 09 Jan 2014 17:29:17 +0200
parents 9bd7522cdbbb
children 00bd098f6435
line wrap: on
line diff
--- a/Render.cpp	Thu Jan 09 14:36:48 2014 +0200
+++ b/Render.cpp	Thu Jan 09 17:29:17 2014 +0200
@@ -28,6 +28,7 @@
 #include "MM7.h"
 #include "Lights.h"
 #include "Level/Decoration.h"
+#include "Vis.h"
 
 //#pragma comment(lib, "lib\\legacy_dx\\lib\\ddraw.lib")
 //#pragma comment(lib, "lib\\legacy_dx\\lib\\dxguid.lib")
@@ -121,34 +122,6 @@
   return v0;
 }
 
-void Render::sub_4A19B0()
-{
-  char *result; // eax@1
-  signed int v1; // ecx@1
-  /*
-  result = (char *)&this->pBillboardRenderListD3D[0].uOpacity;
-  v1 = 1000;
-  do
-  {
-    *(_DWORD *)result = 0;
-    *((_DWORD *)result + 1) = -1;
-    *((_DWORD *)result + 3) = -1;
-    *((_DWORD *)result - 34) = 4;
-    result += 156;
-    --v1;
-  }
-  while ( v1 );
-  */
-  for( int i = 0; i < 1000; i++ )
-  {
-	this->pBillboardRenderListD3D[i].uOpacity = (RenderBillboardD3D::OpacityType)0;
-	this->pBillboardRenderListD3D[i].field_90 = -1;
-	this->pBillboardRenderListD3D[i].sParentBillboardID = -1;
-	this->pBillboardRenderListD3D[i].uNumVertices = 4;
-  }
-
-  return;
-}
 
 //----- (00440CB8) --------------------------------------------------------
 void Render::DrawBillboardList_BLV()
@@ -1915,7 +1888,7 @@
     if ( v7->std__vector_000004_size)
       a2 = -1;
     pGame->AlterGamma_ODM(a4, &a2);
-    if ( byte_4D864C && pGame->uFlags & GAME_FLAGS_1_01)
+    if ( byte_4D864C && pGame->uFlags & GAME_FLAGS_1_01_lightmap_related)
     {
       v8 = ::GetActorTintColor(a3->dimming_level, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
       v7->DrawLightmaps(/*v8, 0*/);
@@ -2077,17 +2050,6 @@
   //nullsub_1();
 }
 
-//----- (0049E756) --------------------------------------------------------
-bool Render::IsColorKeySupported(IDirectDraw4 *this_)
-{
-  DDCAPS refCaps; // [sp+0h] [bp-2F8h]@1
-  DDCAPS halCaps; // [sp+17Ch] [bp-17Ch]@1
-
-  halCaps.dwSize = 380;
-  refCaps.dwSize = 380;
-  this_->GetCaps(&halCaps, &refCaps);
-  return halCaps.dwSVBCaps & 0x40 && BYTE1(halCaps.dwSVBCKeyCaps) & 2;
-}
 
 //----- (0049E992) --------------------------------------------------------
 Render::Render()
@@ -2147,7 +2109,6 @@
 
   hd_water_tile_id = -1;
   hd_water_current_frame = 0;
-  sub_4A19B0();
 }
 
 bool Render::Initialize(OSWindow *window, bool bColoredLights, uint32_t uDetailLevel, bool bTinting)
@@ -2360,7 +2321,6 @@
     }
   }
 }
-// 4EFA80: using guessed type int dword_4EFA80;
 
 //----- (0049F1BC) --------------------------------------------------------
 void Render::SaveWinnersCertificate(const char *a1)
@@ -2670,7 +2630,7 @@
 }
 
 //----- (0049F8B5) --------------------------------------------------------
-FILE *Render::SavePCXImage(const char *Filename, unsigned short* picture_data, int width, int height)
+void Render::SavePCXImage(const char *Filename, unsigned short* picture_data, int width, int height)
 {
   FILE *result; // eax@1
   FILE *pOutFile; // edi@4
@@ -2786,9 +2746,8 @@
       v9 += width;
     }
     free(lineRGB);
-    result = (FILE *)fclose(pOutFile);
-  }
-  return result;
+    fclose(pOutFile);
+  }
 }
 
 //----- (0049FBCD) --------------------------------------------------------
@@ -2803,12 +2762,6 @@
     //memset32(pTargetSurface, uColor, field_10 * field_14 / 2);
 }
 
-//----- (0049FC23) --------------------------------------------------------
-void Render::Release2()
-{
-  Release();
-  bWindowMode = 1;
-}
 
 //----- (0049FC37) --------------------------------------------------------
 void Render::Present()
@@ -3046,7 +2999,7 @@
           for (uint x = pViewport->uViewportTL_X; x < pViewport->uViewportBR_X; ++x)
           {
             //if (src[x + y * src_pitch] != (pRenderer->uTargetGMask | pRenderer->uTargetBMask))
-            if (src[x + y * src_pitch] != 0xFFF8FCF8)  // FFF8FCF8 =  Color32(Color16(g_mask | b_mask))
+            if (src[x + y * src_pitch] != 0xFF00FCF8)  // FFF8FCF8 =  Color32(Color16(g_mask | b_mask))
               dst[x + y * dst_pitch] = src[x + y * src_pitch];
           }
         }
@@ -4342,44 +4295,6 @@
     pBackBuffer4->Restore();
 }
 
-//----- (004A1884) --------------------------------------------------------
-void Render::PresentRect(RECT *a2, RECT *a3)
-{
-  IDirectDrawSurface *pFront; // eax@3
-  HRESULT v4; // eax@5
-  IDirectDrawSurface *pBack; // [sp-1Ch] [bp-1Ch]@3
-  struct tagRECT *v6; // [sp-18h] [bp-18h]@3
-  DWORD v7; // [sp-14h] [bp-14h]@3
-  DDBLTFX *v8; // [sp-10h] [bp-10h]@3
-  const char *v9; // [sp-Ch] [bp-Ch]@3
-  int v10; // [sp-8h] [bp-8h]@3
-  unsigned int v11; // [sp-4h] [bp-4h]@3
-
-  //if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
-  {
-    v11 = 0;
-    pFront = (IDirectDrawSurface *)this->pFrontBuffer4;
-    v10 = 2657;
-    v9 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Screen16.cpp";
-    v8 = 0;
-    v7 = DDBLT_WAIT;
-    v6 = a3;
-    pBack = (IDirectDrawSurface *)this->pBackBuffer4;
-  }
-  /*else
-  {
-    v11 = 0;
-    pFront = (IDirectDrawSurface *)this->pFrontBuffer2;
-    v10 = 2653;
-    v9 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Screen16.cpp";
-    v8 = 0;
-    v7 = DDBLT_WAIT;
-    v6 = a3;
-    pBack = (IDirectDrawSurface *)this->pBackBuffer2;
-  }*/
-  ErrD3D(pFront->Blt(a2, pBack, v6, v7, v8));
-}
-
 //----- (004A18F5) --------------------------------------------------------
 void Render::BltToFront(RECT *pDstRect, IDirectDrawSurface *pSrcSurface, RECT *pSrcRect, unsigned int uBltFlags)
 {
@@ -4758,7 +4673,7 @@
   /*  v9 = pGame->pLightmapBuilder;
     v65 = v9;
     v10 = v9->std__vector_000004_size;*/
-    if ( byte_4D864C && pGame->uFlags & GAME_FLAGS_1_01)
+    if ( byte_4D864C && pGame->uFlags & GAME_FLAGS_1_01_lightmap_related)
     {
       v11 = ::GetActorTintColor(a4->dimming_level, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
       pGame->pLightmapBuilder->DrawLightmaps(/*v11, 0*/);
@@ -5394,7 +5309,7 @@
     else uColor = sCorrectedColor = 0xFF109010;
   }
 
-  if (byte_4D864C && pGame->uFlags & GAME_FLAGS_1_01)
+  if (byte_4D864C && pGame->uFlags & GAME_FLAGS_1_01_lightmap_related)
   {
       __debugbreak();
       ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false));
@@ -5580,9 +5495,9 @@
     //v9 = v7;
     v28 = dimming_level & 0xFF000000;
     if ( dimming_level & 0xFF000000 )
-      pBillboardRenderListD3D[v7].uOpacity = RenderBillboardD3D::Opaque_3;
+      pBillboardRenderListD3D[v7].opacity = RenderBillboardD3D::Opaque_3;
     else
-      pBillboardRenderListD3D[v7].uOpacity = RenderBillboardD3D::Transparent;
+      pBillboardRenderListD3D[v7].opacity = RenderBillboardD3D::Transparent;
     //v10 = a3;
     pBillboardRenderListD3D[v7].field_90 = pSoftBillboard->field_44;
     pBillboardRenderListD3D[v7].sZValue = pSoftBillboard->sZValue;
@@ -5716,7 +5631,7 @@
       //v6 = v5;
       //v7 = v5;
       v8 = Billboard_ProbablyAddToListAndSortByZOrder(a2->zbuffer_depth);
-      pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_1;
+      pBillboardRenderListD3D[v8].opacity = RenderBillboardD3D::Opaque_1;
       pBillboardRenderListD3D[v8].field_90 = a2->field_44;
       pBillboardRenderListD3D[v8].sZValue = a2->sZValue;
       pBillboardRenderListD3D[v8].sParentBillboardID = a2->sParentBillboardID;
@@ -5889,7 +5804,7 @@
     v6 = v5;
     v7 = v5;
     v8 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v7));
-    pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_1;
+    pBillboardRenderListD3D[v8].opacity = RenderBillboardD3D::Opaque_1;
     pBillboardRenderListD3D[v8].field_90 = a2->field_44;
     pBillboardRenderListD3D[v8].sZValue = a2->sZValue;
     pBillboardRenderListD3D[v8].sParentBillboardID = a2->sParentBillboardID;
@@ -6109,9 +6024,9 @@
   pBillboardRenderListD3D[v8].sParentBillboardID = a2->sParentBillboardID;
 
   if (a2->sTintColor & 0xFF000000)
-    pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_3;
+    pBillboardRenderListD3D[v8].opacity = RenderBillboardD3D::Opaque_3;
   else
-    pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Transparent;
+    pBillboardRenderListD3D[v8].opacity = RenderBillboardD3D::Transparent;
 }
 
 
@@ -6240,7 +6155,7 @@
   v5 = Billboard_ProbablyAddToListAndSortByZOrder(depth);
   pBillboardRenderListD3D[v5].field_90 = 0;
   pBillboardRenderListD3D[v5].sParentBillboardID = -1;
-  pBillboardRenderListD3D[v5].uOpacity = RenderBillboardD3D::Opaque_2;
+  pBillboardRenderListD3D[v5].opacity = RenderBillboardD3D::Opaque_2;
   pBillboardRenderListD3D[v5].pTexture = 0;
   pBillboardRenderListD3D[v5].uNumVertices = a1->uNumVertices;
   pBillboardRenderListD3D[v5].z_order = depth;
@@ -6496,12 +6411,12 @@
   }
 }
 
-//----- ( ) --------------------------------------------------------
-unsigned int Render::_4A52F1(unsigned int this_, float a3)
+//----- (004A52F1) --------------------------------------------------------
+void Render::ScreenFade(unsigned int color, float t)
 {
   unsigned int v3; // esi@1
-  double v4; // st7@2
-  double v5; // st7@6
+  //double v4; // st7@2
+  //double v5; // st7@6
   double v6; // st6@6
   unsigned int v7; // eax@6
   double v8; // st5@6
@@ -6536,36 +6451,22 @@
   unsigned int v37; // [sp+8Ch] [bp-14h]@7
   int v38; // [sp+90h] [bp-10h]@7
   double v39; // [sp+94h] [bp-Ch]@6
-  float v40; // [sp+9Ch] [bp-4h]@6
-
-  __debugbreak();
-
-  Render* ecx0 = this;
+  int v40; // [sp+9Ch] [bp-4h]@6
+
   v3 = 0;
 
-  if (!this->pRenderD3D)
-    __debugbreak(); // sw render
-
   //{
-    v4 = a3;
-    if ( a3 <= 1.0 )
-    {
-      if ( v4 < 0.0 )
-        v4 = 0.0;
-    }
-    else
-    {
-      v4 = 1.0;
-    }
-    __debugbreak(); // banker's rounding again
-    a3 = v4 * 255.0;
-    v39 = a3 + 6.7553994e15;
-    LODWORD(v40) = LODWORD(v39);
-    v5 = (double)(signed int)pViewport->uViewportTL_X;
-    v36[0].pos.x = v5;
+  if (t > 1.0f)
+    t = 1.0f;
+  else if (t < 0.0f)
+    t = 0.0f;
+
+    v40 = (char)floorf(t * 255.0f + 0.5f);
+    //v5 = (double)(signed int)pViewport->uViewportTL_X;
+    v36[0].pos.x = pViewport->uViewportTL_X;
     v6 = (double)(signed int)pViewport->uViewportTL_Y;
-    v7 = this_ | (LODWORD(v39) << 24);
-    this_ = pViewport->uViewportBR_Y + 1;
+    v7 = color | (v40 << 24);
+    //this_ = pViewport->uViewportBR_Y + 1;
     v36[0].specular = 0;
     v36[0].pos.y = v6;
     v36[0].diffuse = v7;
@@ -6579,7 +6480,7 @@
     v36[2].specular = 0;
     v36[3].specular = 0;
     v36[0].texcoord.y = 0.0;
-    v36[1].pos.x = v5;
+    v36[1].pos.x = pViewport->uViewportTL_X;
     v8 = (double)(pViewport->uViewportBR_Y + 1);
     v36[1].pos.y = v8;
     v36[1].pos.z = 0.0;
@@ -6706,7 +6607,6 @@
       while ( v32 != 1 );
     }
   }*/
-  return result;
 }
 
 //----- (004A5B81) --------------------------------------------------------
@@ -6891,7 +6791,7 @@
 }
 
 //----- (004A6E7E) --------------------------------------------------------
-void Render::_4A6E7E(unsigned int a2, unsigned int a3, Texture *a4)
+void Render::DrawTranslucent(unsigned int a2, unsigned int a3, Texture *a4)
 {
   //unsigned __int16 *v4; // eax@4
   int v5; // edx@4
@@ -8685,8 +8585,8 @@
 
   for (int i = uNumBillboardsToDraw - 1; i >= 0; --i)
   {
-    if (pBillboardRenderListD3D[i].uOpacity != RenderBillboardD3D::NoBlend)
-      SetBillboardBlendOptions(pBillboardRenderListD3D[i].uOpacity);
+    if (pBillboardRenderListD3D[i].opacity != RenderBillboardD3D::NoBlend)
+      SetBillboardBlendOptions(pBillboardRenderListD3D[i].opacity);
     
 
     pRenderD3D->pDevice->SetTexture(0, pBillboardRenderListD3D[i].pTexture);
@@ -9395,3 +9295,302 @@
   pRenderer->PackPCXpicture(pixels, 150, 112, data, 1000000, out_screenshot_size);
   free(pixels);
 }
+
+
+//----- (0046A7C8) --------------------------------------------------------
+int Render::_46A6AC_spell_render_d3d(int a1, int a2, int a3)
+{
+  unsigned int v3; // eax@2
+  unsigned int v5; // eax@2
+  unsigned int v6; // eax@4
+  int v10; // ecx@11
+  unsigned int v12; // [sp+10h] [bp-14h]@1
+  int v15; // [sp+1Ch] [bp-8h]@1
+  unsigned int a1a; // [sp+20h] [bp-4h]@1
+
+  v15 = 0;
+  v12 = GetBillboardDrawListSize();
+  if ( (signed int)GetBillboardDrawListSize() > 0 )
+  {
+    for ( a1a = 0; (signed int)a1a < (signed int)v12; ++a1a )
+    {
+      v3 = GetParentBillboardID(a1a);
+      v5 = (unsigned __int16)pBillboardRenderList[v3].object_pid;
+      if ( PID_TYPE(v5) == OBJECT_Actor)
+      {
+        if ( pBillboardRenderList[v3].sZValue <= (unsigned int)(a3 << 16) )
+        {
+          v6 = PID_ID(v5);
+          if ( pActors[v6].uAIState != Dead && pActors[v6].uAIState != Dying && pActors[v6].uAIState != Removed
+            && pActors[v6].uAIState != Disabled && pActors[v6].uAIState != Summoned )
+          {
+            if ( pGame->pVisInstance->DoesRayIntersectBillboard((double)a3, a1a) )
+            {
+              if ( v15 < a2 - 1 )
+              {
+                __debugbreak();// *(int *)(a1 + 4 * v10) = v6; что это такое?
+                v10 = v15++;
+                *(int *)(a1 + 4 * v10) = v6;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return v15;
+}
+
+
+
+
+void Render::BeginLightmaps()
+{
+  ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP));
+
+  if (bUsingSpecular)
+    pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE);
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, FALSE));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, pGame->pIndoorCameraD3D->LoadTextureAndGetHardwarePtr("effpar03")));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE));
+}
+
+void Render::EndLightmaps()
+{
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE));
+
+  if (bUsingSpecular)
+  {
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, uFogColor));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0));
+  }
+}
+
+
+void Render::BeginLightmaps2()
+{
+  if (bUsingSpecular)
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE));
+ 
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, FALSE));
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, pGame->pIndoorCameraD3D->LoadTextureAndGetHardwarePtr("effpar03")));
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE));
+}
+
+
+void Render::EndLightmaps2()
+{
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW));
+
+  if (bUsingSpecular)
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE));
+}
+
+
+
+//----- (00437C96) --------------------------------------------------------
+void Render::do_draw_debug_line_d3d(const RenderVertexD3D3 *pLineBegin, signed int sDiffuseBegin, const RenderVertexD3D3 *pLineEnd, signed int sDiffuseEnd, float z_stuff)
+{
+  double v6; // st7@2
+  //IDirect3DDevice3 *v7; // eax@2
+  HRESULT v8; // eax@2
+  std::string v9; // [sp-18h] [bp-60h]@3
+  const char *v10; // [sp-Ch] [bp-54h]@2
+  const char *v11; // [sp-8h] [bp-50h]@2
+  int v12; // [sp-4h] [bp-4Ch]@2
+  RenderVertexD3D3 v13[2]; // [sp+8h] [bp-40h]@2
+
+  //if ( pRenderer->pRenderD3D )
+  {
+    v6 = 0.001 - z_stuff;
+    memcpy(v13, pLineBegin, 0x20u);
+    memcpy(&v13[1], pLineEnd, sizeof(v13[1]));
+    v13[0].pos.z = v6;
+    v13[1].pos.z = v6;
+    v13[0].diffuse = sDiffuseBegin;
+    v13[1].diffuse = sDiffuseEnd;
+    ErrD3D(pRenderD3D->pDevice->SetTexture(0, nullptr));
+    ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+           D3DPT_LINELIST,
+           452,
+           v13,
+           2,
+           16));
+  }
+}
+
+
+void Render::DrawLines(const RenderVertexD3D3 *vertices, unsigned int num_vertices)
+{
+  ErrD3D(pRenderD3D->pDevice->SetTexture(0, nullptr));
+  ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_LINELIST,
+              D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+              (void *)vertices,
+              num_vertices,
+              D3DDP_DONOTLIGHT));
+}
+
+
+void Render::DrawFansTransparent(const RenderVertexD3D3 *vertices, unsigned int num_vertices)
+{
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false));
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA));
+  
+  ErrD3D(pRenderD3D->pDevice->SetTexture(0, nullptr));
+  ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                (void *)vertices,
+                num_vertices,
+                28));
+
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE));
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE));
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE));
+}
+
+
+void Render::BeginDecals()
+{
+  // code chunk from 0049C304
+  if (bUsingSpecular)
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP));
+
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, FALSE));
+
+  ErrD3D(pRenderD3D->pDevice->SetTexture(0, pGame->pIndoorCameraD3D->LoadTextureAndGetHardwarePtr("hwsplat04")));
+}
+
+
+void Render::EndDecals()
+{
+  // code chunk from 0049C304
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO));
+
+  if (bUsingSpecular)
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE));
+}
+
+
+
+//----- (0049C095) --------------------------------------------------------
+void Render::DrawDecal(Decal *pDecal, float z_bias)
+{
+  signed int v21; // [sp+Ch] [bp-864h]@15
+  RenderVertexD3D3 pVerticesD3D[64]; // [sp+20h] [bp-850h]@6
+
+  if (pDecal->uNumVertices < 3)
+  {
+    Log::Warning(L"Decal has < 3 vertices");
+    return;
+  }
+
+  float color_mult;
+  if ( pDecal->field_C1C & 1 )
+    color_mult = 1.0;
+  else
+    color_mult = pDecal->field_C18->_43B570_get_color_mult_by_time();
+
+  for (uint i = 0; i < pDecal->uNumVertices; ++i)
+  {
+    uint uTint = Render::GetActorTintColor(pDecal->pVertices[i].vWorldViewPosition.x, pDecal->field_C14, 0, 0, nullptr);
+
+    uint uTintR = (uTint >> 16) & 0xFF,
+         uTintG = (uTint >> 8) & 0xFF,
+         uTintB = uTint & 0xFF;
+
+    uint uDecalColorMultR = (pDecal->uColorMultiplier >> 16) & 0xFF,
+         uDecalColorMultG = (pDecal->uColorMultiplier >> 8) & 0xFF,
+         uDecalColorMultB = pDecal->uColorMultiplier & 0xFF;
+
+    uint uFinalR = floorf(uTintR / 255.0 * color_mult * uDecalColorMultR + 0.0f),
+         uFinalG = floorf(uTintG / 255.0 * color_mult * uDecalColorMultG + 0.0f),
+         uFinalB = floorf(uTintB / 255.0 * color_mult * uDecalColorMultB + 0.0f);
+
+
+    float v15;
+    if (fabs(z_bias) < 1e-5)
+      v15 = 1.0 - 1.0 / ((1.0f / pGame->pIndoorCameraD3D->GetShadingDistMist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0);
+     else
+     {
+      v15 = 1.0 - 1.0 / ((1.0f / pGame->pIndoorCameraD3D->GetShadingDistMist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0) - z_bias;
+      if (v15 < 0.000099999997)
+        v15 = 0.000099999997;
+     }
+
+    pVerticesD3D[i].pos.z = v15;
+
+    pVerticesD3D[i].pos.x = pDecal->pVertices[i].vWorldViewProjX;
+    pVerticesD3D[i].pos.y = pDecal->pVertices[i].vWorldViewProjY;
+    pVerticesD3D[i].texcoord.x = pDecal->pVertices[i].u;
+    pVerticesD3D[i].texcoord.y = pDecal->pVertices[i].v;
+    pVerticesD3D[i].diffuse = (uFinalR << 16) | (uFinalG << 8) | uFinalB;
+    pVerticesD3D[i].specular = 0;
+    pVerticesD3D[i].rhw = 1.0 / pDecal->pVertices[i].vWorldViewPosition.x;
+  }
+
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    v21 = D3DDP_DONOTLIGHT | D3DDP_DONOTCLIP | D3DDP_DONOTUPDATEEXTENTS;
+  else
+    v21 = D3DDP_DONOTLIGHT;
+
+  ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+            pVerticesD3D,
+            pDecal->uNumVertices,
+            v21));
+}
+
+
+void Render::DrawSpecialEffectsQuad(const RenderVertexD3D3 *vertices, IDirect3DTexture2 *texture)
+{
+  ErrD3D(pRenderD3D->pDevice->SetTexture(0, texture));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_ALWAYS));
+  ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                                     D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                                     (void *)vertices, 4, 28));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE));
+  ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESS));
+}
\ No newline at end of file