changeset 871:710cf848ad24

Particle engine made working.
author Nomad
date Mon, 01 Apr 2013 13:39:19 +0200
parents d061180f2b42
children 2db21a810d48
files Game.cpp Indoor.cpp IndoorCameraD3D.cpp IndoorCameraD3D.h Outdoor.cpp ParticleEngine.cpp ParticleEngine.h Render.cpp UiGame.cpp Viewport.cpp mm7_1.cpp mm7_2.cpp mm7_3.cpp mm7_4.cpp mm7_5.cpp mm7_6.cpp mm7_data.h
diffstat 17 files changed, 276 insertions(+), 319 deletions(-) [+]
line wrap: on
line diff
--- a/Game.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/Game.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -671,7 +671,7 @@
   {
     v11 = &vis_face_filter;
     v10 = &vis_sprite_filter_2;
-    depth = GetPickDepth();
+    depth = pGame->pIndoorCameraD3D->GetPickDepth();
   }
   else
   {
--- a/Indoor.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/Indoor.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -373,8 +373,8 @@
 
   _this.field_0_timer = pEventTimer->uTotalGameTimeElapsed;
   _this.field_1C_mb_fov = 65;
-  _this.vPosition.x = pParty->vPosition.x - fixpoint_mul(stru_5C6E00->Cos(pParty->sRotationY), pParty->y_rotation_granularity);
-  _this.vPosition.y = pParty->vPosition.y - fixpoint_mul(stru_5C6E00->Sin(pParty->sRotationY), pParty->y_rotation_granularity);
+  _this.vPosition.x = pParty->vPosition.x - fixpoint_sub0(stru_5C6E00->Cos(pParty->sRotationY), pParty->y_rotation_granularity);
+  _this.vPosition.y = pParty->vPosition.y - fixpoint_sub0(stru_5C6E00->Sin(pParty->sRotationY), pParty->y_rotation_granularity);
   _this.vPosition.z = pParty->vPosition.z + pParty->sEyelevel;
   _this.sRotationX = pParty->sRotationX;
   _this.sRotationY = pParty->sRotationY;
@@ -3171,16 +3171,16 @@
                         HIDWORD(v33) = v32 >> 16;*/
                         //fixpoint_div(v1->x - v2->x, v1->y - v2->y);
                         //_a58 = v33 / (v1->y - v2->y);
-                        //_a59 = fixpoint_mul(_a58, sY - v2->y);
+                        //_a59 = fixpoint_sub0(_a58, sY - v2->y);
             auto x_div_y = fixpoint_div(v1->x - v2->x, v1->y - v2->y);
-            auto res = fixpoint_mul(x_div_y, sY - v2->y);  // a / b * c  - looks like projection 
+            auto res = fixpoint_sub0(x_div_y, sY - v2->y);  // a / b * c  - looks like projection 
             if (res + v2->x > sX)
               ++v54;
           }
           else
           {
             auto x_div_y = fixpoint_div(v2->x - v1->x, v2->y - v1->y);
-            auto res = fixpoint_mul(x_div_y, sY - v1->y);
+            auto res = fixpoint_sub0(x_div_y, sY - v1->y);
 
             if (res + v1->x > sX)
               ++v54;
@@ -3191,7 +3191,7 @@
                         LODWORD(v33) = v32 << 16;
                         HIDWORD(v33) = v32 >> 16;
                         _a58 = v33 / (v2->y - v1->y);
-                        _a59 = fixpoint_mul(_a58, sY - v1->y);
+                        _a59 = fixpoint_sub0(_a58, sY - v1->y);
 
                         if (_a59 + pVertices[k].x > sX)
                           ++v54;*/
--- a/IndoorCameraD3D.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/IndoorCameraD3D.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -94,6 +94,17 @@
   //v1->vdestructor_ptr = &stru8_pvdtor;
 }
 
+
+//----- (0043643E) --------------------------------------------------------
+float IndoorCameraD3D::GetPickDepth()
+{
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    return pOutdoorCamera->uPickDepth;
+  else
+    return 16192.0;
+}
+
+
 //----- (004364C5) --------------------------------------------------------
 void IndoorCameraD3D::ViewTransfrom_OffsetUV(RenderVertexSoft *pVertices, unsigned int uNumVertices, RenderVertexSoft *pOutVertices, stru320 *a5)
 {
--- a/IndoorCameraD3D.h	Thu Mar 28 00:37:58 2013 +0400
+++ b/IndoorCameraD3D.h	Mon Apr 01 13:39:19 2013 +0200
@@ -157,6 +157,7 @@
   bool IsCulled(struct BLVFace *pFace);
   void ViewTransfrom_OffsetUV(struct RenderVertexSoft *pVertices, unsigned int uNumVertices, struct RenderVertexSoft *pOutVertices, struct stru320 *a5);
   char ApplyViewTransform_TrueIfStillVisible(int x, int y, int z, signed int *pOutX, int *pOutZ, int *pOutY, char bDoNotShow);
+  float GetPickDepth();
 
   void DebugDrawPortal(struct BLVFace *pFace);
 
--- a/Outdoor.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/Outdoor.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -92,8 +92,8 @@
 
   pIndoorCamera->sRotationX = pParty->sRotationX;
   pIndoorCamera->sRotationY = pParty->sRotationY;
-  pIndoorCamera->pos.x = pParty->vPosition.x - fixpoint_mul(stru_5C6E00->Cos(pParty->sRotationY), pParty->y_rotation_granularity);
-  pIndoorCamera->pos.y = pParty->vPosition.y - fixpoint_mul(stru_5C6E00->Sin(pParty->sRotationY), pParty->y_rotation_granularity);
+  pIndoorCamera->pos.x = pParty->vPosition.x - fixpoint_sub0(stru_5C6E00->Cos(pParty->sRotationY), pParty->y_rotation_granularity);
+  pIndoorCamera->pos.y = pParty->vPosition.y - fixpoint_sub0(stru_5C6E00->Sin(pParty->sRotationY), pParty->y_rotation_granularity);
   pIndoorCamera->pos.z = pParty->vPosition.z + pParty->sEyelevel;
   if (bRedraw || pRenderer->pRenderD3D)
   {
--- a/ParticleEngine.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/ParticleEngine.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -68,20 +68,20 @@
       v4->flt_18 = a2->flt_18;
       v5 = a2->uDiffuse;
       v4->uParticleColor = v5;
-      v4->uLightColor = v5;
+      v4->uLightColor_bgr = v5;
       //v6 = (v4->uType & 4) == 0;
       v4->timeToLive = a2->timeToLive;
       v4->uTextureID = a2->uTextureID;
       v4->flt_28 = a2->flt_28;
       if (v4->type & ParticleType_Rotating)
       {
-        v4->field_38 = (unsigned __int8)rand() - 128;
-        v4->_rotation = rand();
+        v4->rotation_speed = (rand() % 256) - 128;
+        v4->angle = rand();
       }
       else
       {
-        v4->field_38 = 0;
-        v4->_rotation = 0;
+        v4->rotation_speed = 0;
+        v4->angle = 0;
       }
     }
   }
@@ -117,12 +117,12 @@
 void ParticleEngine::UpdateParticles()
 {
   unsigned int time; // edi@1
-  int v5; // eax@3
-  char v6; // sf@4
+  //int v5; // eax@3
+  //char v6; // sf@4
   float v7; // ST4C_4@11
   double v8; // st7@12
-  int v9; // eax@12
-  double v10; // st7@14
+  //int v9; // eax@12
+  //double v10; // st7@14
   signed int v19; // [sp+38h] [bp-14h]@1
   int v20; // [sp+3Ch] [bp-10h]@1
   unsigned int time_; // [sp+40h] [bp-Ch]@1
@@ -133,29 +133,32 @@
   v19 = 500;
   time_ = pMiscTimer->bPaused == 0 ? pEventTimer->uTimeElapsed : 0;
 
-  for (uint i = uStartParticle; i < uEndParticle; ++i)
+  for (uint i = uStartParticle; i <= uEndParticle; ++i)
   {
     auto p = pParticles + i;
 
-      v5 = p->type;
       if (p->type == ParticleType_Invalid)
         continue;
 
-        v6 = (p->timeToLive - time) < 0;
+      if (p->timeToLive <= time)
+      {
+        p->timeToLive = 0;
+        p->type = ParticleType_Invalid;
+        continue;
+      }
         p->timeToLive -= time;
-        if (v6)
-          p->type = ParticleType_Invalid;
-        else
-        {
-          if ( BYTE1(v5) & 2 )
+
+          if (p->type & ParticleType_Line)
           {
             p->_x = p->x;
             p->_y = p->y;
             p->_z = p->z;
           }
-          if ( v5 & 1 )
+
+          if (p->type & ParticleType_1)
             p->flt_18 = p->flt_18 - (double)(signed int)time_ * 5.0;
-          if ( v5 & 8 )
+
+          if (p->type & ParticleType_8)
           {
             v7 = (double)(signed int)time_;
             *(float *)&p->x += (double)(rand() % 5 - 2) * v7 / 16.0f;
@@ -163,23 +166,24 @@
             *(float *)&p->z += (double)(rand() % 5 + 4) * v7 / 16.0f;
           }
           v8 = (double)(signed int)time_ / 128.0f;
-          v9 = (signed int)(time * p->field_38) / 16;
-          *(float *)&p->x += v8 * p->flt_10;
-          *(float *)&p->y += v8 * p->flt_14;
-          *(float *)&p->z += v8 * p->flt_18;
-          p->_rotation += v9;
+          //v9 = (signed int)(time * p->rotation_speed) / 16;
+
+          p->x += v8 * p->flt_10;
+          p->y += v8 * p->flt_14;
+          p->z += v8 * p->flt_18;
+
+          p->angle += time * p->rotation_speed / 16;
           v22 = 2 * p->timeToLive;
-          if ( 2 * p->timeToLive >= 255 )
+          if (v22 >= 255 )
             v22 = 255;
-          v10 = (double)v22 * 0.0039215689;
-          p->uLightColor = (uint)floorf(p->b + 0.5) |
-                           ((uint)floorf(p->g + 0.5) << 8) |
-                           ((uint)floorf(p->r + 0.5) << 16);
+          //v10 = (double)v22 * 0.0039215689;
+          p->uLightColor_bgr = ((uint)floorf(p->b * (v22 / 255.0f) + 0.5) << 16) |
+                               ((uint)floorf(p->g * (v22 / 255.0f) + 0.5) << 8) |
+                               ((uint)floorf(p->r * (v22 / 255.0f) + 0.5) << 0);
           if ( i < v19 )
             v19 = i;
           if ( i > v20 )
             v20 = i;
-        }
   }
 
   uEndParticle = v20;
@@ -187,12 +191,12 @@
 }
 
 //----- (0048AE74) --------------------------------------------------------
-bool ParticleEngine::ViewProject_TrueIfStillVisible(unsigned int uParticleID)
+bool ParticleEngine::ViewProject_TrueIfStillVisible_BLV(unsigned int uParticleID)
 {
   Particle *pParticle; // esi@1
   //double v56; // ST28_8@2
-  float v4; // eax@4
-  double v5; // ST34_8@4
+  //float v4; // eax@4
+  //double v5; // ST34_8@4
   signed __int64 v6; // qtt@4
   //double v7; // st7@4
   //float v8; // ST18_4@4
@@ -202,7 +206,7 @@
   //double v12; // ST4C_8@7
   double v13; // ST4C_8@7
   int v14; // ecx@7
-  signed __int64 v15; // qtt@7
+  //signed __int64 v15; // qtt@7
   int v16; // eax@7
   int v17; // edx@7
   float v18; // edx@7
@@ -212,21 +216,21 @@
   int v22; // ebx@8
   int v23; // ecx@10
   int v24; // edi@10
-  double v25; // ST44_8@12
-  double v26; // ST4C_8@12
+  //double v25; // ST44_8@12
+  //double v26; // ST4C_8@12
   int v27; // edi@12
   int v28; // ST40_4@12
   int v29; // ecx@12
-  signed __int64 v30; // qtt@12
+  //signed __int64 v30; // qtt@12
   int v31; // eax@12
   int v32; // edx@12
   float v33; // edx@12
-  int v34; // eax@12
+  //int v34; // eax@12
   int v35; // ecx@12
   int v36; // ST38_4@13
   int v37; // ST30_4@15
   int v38; // eax@16
-  signed __int64 v40; // qtt@18
+  //signed __int64 v40; // qtt@18
   int v41; // eax@18
   int v42; // ecx@18
   int v43; // eax@18
@@ -278,9 +282,10 @@
         v14 = z;
         HIDWORD(v13) = (unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
         HIDWORD(a5) = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16;
-        LODWORD(v15) = pBLVRenderParams->field_40 << 16;
-        HIDWORD(v15) = pBLVRenderParams->field_40 >> 16;
-        v16 = v15 / z;
+        //LODWORD(v15) = pBLVRenderParams->field_40 << 16;
+        //HIDWORD(v15) = pBLVRenderParams->field_40 >> 16;
+        //v16 = v15 / z;
+        v16 = fixpoint_div(pBLVRenderParams->field_40, z);
         v17 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
         pParticle->_screenspace_scale = v16;
         _uParticleID = (unsigned __int64)(v16 * (signed __int64)(a6 + v17)) >> 16;
@@ -315,30 +320,27 @@
     {
       if (pParticle->type & ParticleType_Line)
       {
-        v25 = pParticle->_x + 6.7553994e15;
-        int _uParticleID = (LODWORD(v25) - pBLVRenderParams->vPartyPos.x) << 16;
-        v26 = pParticle->_y + 6.7553994e15;
-        y = (LODWORD(v26) - pBLVRenderParams->vPartyPos.y) << 16;
-        HIDWORD(v25) = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-        v27 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-            - HIDWORD(v25);
-        z = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-          - HIDWORD(v25);
+        //v25 = pParticle->_x + 6.7553994e15;
+        int _uParticleID = ((int)floorf(pParticle->_x + 0.5f) - pBLVRenderParams->vPartyPos.x) << 16;
+        //v26 = pParticle->_y + 6.7553994e15;
+        y = ((int)floorf(pParticle->_y + 0.5f) - pBLVRenderParams->vPartyPos.y) << 16;
+        auto _hiword_v25 = (__int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+        v27 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - _hiword_v25;
+        z = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - _hiword_v25;
         v28 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-        a5 = pParticle->_z + 6.7553994e15;
-        v29 = (LODWORD(a5) - pBLVRenderParams->vPartyPos.z) << 16;
-        LODWORD(v30) = pBLVRenderParams->field_40 << 16;
-        HIDWORD(v30) = pBLVRenderParams->field_40 >> 16;
-        v31 = v30 / z;
+        //a5 = pParticle->_z + 6.7553994e15;
+        v29 = ((int)floorf(pParticle->_z + 0.5f) - pBLVRenderParams->vPartyPos.z) << 16;
+        //LODWORD(v30) = pBLVRenderParams->field_40 << 16;
+        //HIDWORD(v30) = pBLVRenderParams->field_40 >> 16;
+        //v31 = v30 / z;
+        v31 = fixpoint_div(pBLVRenderParams->field_40, z);
         v32 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
         pParticle->_screenspace_scale = v31;
         _uParticleID = (unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16;
-        LODWORD(v33) = pBLVRenderParams->uViewportCenterX
-                     - ((signed int)((unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16) >> 16);
-        v34 = pParticle->_screenspace_scale;
+        LODWORD(v33) = pBLVRenderParams->uViewportCenterX - ((signed int)((unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16) >> 16);
+        //v34 = pParticle->_screenspace_scale;
         pParticle->uScreenSpaceZ = v33;
-        v35 = pBLVRenderParams->uViewportCenterY
-            - ((signed int)((unsigned __int64)(v34 * (signed __int64)v29) >> 16) >> 16);
+        v35 = pBLVRenderParams->uViewportCenterY - ((signed int)((unsigned __int64)(pParticle->_screenspace_scale * (signed __int64)v29) >> 16) >> 16);
         pParticle->sZValue2 = v27;
         pParticle->uScreenSpaceW = v35;
       }
@@ -359,9 +361,9 @@
     v38 = abs(v22);
     if ( v38 >= (signed int)_uParticleID )
     {
-      LODWORD(v40) = pBLVRenderParams->field_40 << 16;
-      HIDWORD(v40) = pBLVRenderParams->field_40 >> 16;
-      v41 = v40 / z;
+      //LODWORD(v40) = pBLVRenderParams->field_40 << 16;
+      //HIDWORD(v40) = pBLVRenderParams->field_40 >> 16;
+      v41 = fixpoint_div(pBLVRenderParams->field_40, z);
       pParticle->_screenspace_scale = v41;
       _uParticleID = (unsigned __int64)(v41 * (signed __int64)a2) >> 16;
       v42 = pBLVRenderParams->uViewportCenterX - ((signed int)((unsigned __int64)(v41 * (signed __int64)a2) >> 16) >> 16);
@@ -395,11 +397,11 @@
     return false;
   pGame->pIndoorCameraD3D->Project(x, y, z, &pParticle->uScreenSpaceX, &pParticle->uScreenSpaceY);
   pParticle->flt_5C = pGame->pIndoorCameraD3D->fov_x;
-  v4 = pParticle->flt_5C;
+  //v4 = pParticle->flt_5C;
   pParticle->flt_60 = pGame->pIndoorCameraD3D->fov_y;
-  v5 = v4 + 6.7553994e15;
+  //v5 = v4 + 6.7553994e15;
   LODWORD(v6) = 0;
-  HIDWORD(v6) = SLOWORD(v5);
+  HIDWORD(v6) = floorf(pParticle->flt_5C + 0.5f);
   //v7 = pParticle->flt_28;
   pParticle->_screenspace_scale = v6 / x;
   //v8 = v7;
@@ -412,151 +414,144 @@
 
 
 //----- (0048B5B3) --------------------------------------------------------
-bool ParticleEngine::_48B5B3(unsigned int uID)
+bool ParticleEngine::ViewProject_TrueIfStillVisible_ODM(unsigned int uID)
 {
-  ParticleEngine *v2; // ST18_4@1
+  //ParticleEngine *v2; // ST18_4@1
   int v3; // ebx@1
   int v4; // edi@1
   int v5; // ecx@1
   Particle *v6; // esi@1
-  double v7; // ST14_8@2
-  double v8; // ST34_8@4
-  double v9; // ST3C_8@4
-  int v10; // ST50_4@4
+  //double v7; // ST14_8@2
+  //double v8; // ST34_8@4
+  //double v9; // ST3C_8@4
+  //int v10; // ST50_4@4
   int v11; // ST44_4@4
-  double v12; // ST48_8@4
+  //double v12; // ST48_8@4
   signed __int64 v13; // qtt@4
-  int v14; // eax@4
-  int v15; // ST28_4@4
+  //int v14; // eax@4
+  //int v15; // ST28_4@4
   int v16; // edi@6
   int v17; // eax@6
-  double v18; // ST2C_8@8
-  double v19; // ST34_8@8
-  int v20; // ST50_4@8
-  double v21; // ST34_8@8
+  //double v18; // ST2C_8@8
+  //double v19; // ST34_8@8
+  //int v20; // ST50_4@8
+  //double v21; // ST34_8@8
   signed __int64 v22; // qtt@8
-  int v23; // eax@8
-  int v24; // ST28_4@8
-  int v25; // edx@8
+  //int v23; // eax@8
+  //int v24; // ST28_4@8
+  //int v25; // edx@8
   int v26; // edx@9
-  int v27; // eax@9
+  //int v27; // eax@9
   int v28; // ebx@12
   signed __int64 v29; // qtt@13
-  int v30; // eax@13
-  int v31; // ST1C_4@13
+  //int v30; // eax@13
+  //int v31; // ST1C_4@13
   double v32; // st7@13
   signed int v33; // eax@13
   int v34; // ecx@13
   float v35; // ST04_4@13
   int v36; // eax@13
   int v37; // esi@15
-  double v39; // [sp+10h] [bp-40h]@2
+  //double v39; // [sp+10h] [bp-40h]@2
   int v40; // [sp+14h] [bp-3Ch]@12
-  int v41; // [sp+1Ch] [bp-34h]@2
-  double v42; // [sp+20h] [bp-30h]@2
-  int v43; // [sp+24h] [bp-2Ch]@5
+  //int v41; // [sp+1Ch] [bp-34h]@2
+  //double v42; // [sp+20h] [bp-30h]@2
+  //int v43; // [sp+24h] [bp-2Ch]@5
   int v44; // [sp+2Ch] [bp-24h]@1
   int v45; // [sp+40h] [bp-10h]@5
   int X_4; // [sp+48h] [bp-8h]@5
-  int v47; // [sp+4Ch] [bp-4h]@5
-  int v48; // [sp+4Ch] [bp-4h]@9
-  int uIDc; // [sp+58h] [bp+8h]@4
-  int uIDd; // [sp+58h] [bp+8h]@4
-  int uIDe; // [sp+58h] [bp+8h]@5
-  int uIDa; // [sp+58h] [bp+8h]@5
-  int uIDf; // [sp+58h] [bp+8h]@8
-  int uIDb; // [sp+58h] [bp+8h]@9
+  //int v47; // [sp+4Ch] [bp-4h]@5
+  //int v48; // [sp+4Ch] [bp-4h]@9
+  //int uIDc; // [sp+58h] [bp+8h]@4
+  //int uIDd; // [sp+58h] [bp+8h]@4
+  //int uIDe; // [sp+58h] [bp+8h]@5
+  //int uIDa; // [sp+58h] [bp+8h]@5
+  //int uIDf; // [sp+58h] [bp+8h]@8
+  //int uIDb; // [sp+58h] [bp+8h]@9
 
-  v2 = this;
   v3 = stru_5C6E00->Cos(pIndoorCamera->sRotationX);
   v44 = stru_5C6E00->Sin(pIndoorCamera->sRotationX);
   v4 = stru_5C6E00->Cos(pIndoorCamera->sRotationY);
   v5 = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
-  v6 = &v2->pParticles[uID];
-  if (v6->type != ParticleType_Invalid)
-  {
-    v7 = v6->x + 6.7553994e15;
-    v41 = LODWORD(v7);
-    v39 = v6->y + 6.7553994e15;
-    v42 = v6->z + 6.7553994e15;
+
+  v6 = &pParticles[uID];
+  if (v6->type == ParticleType_Invalid)
+    return false;
+
+    //v7 = v6->x + 6.7553994e15;
+    //v41 = LODWORD(v7);
+    //v39 = v6->y + 6.7553994e15;
+    //v42 = v6->z + 6.7553994e15;
     if ( v3 )
     {
       if (v6->type & ParticleType_Line)
       {
-        v8 = v6->_x + 6.7553994e15;
-        uIDc = (LODWORD(v8) - pIndoorCamera->pos.x) << 16;
-        v9 = v6->_y + 6.7553994e15;
-        v10 = (LODWORD(v9) - pIndoorCamera->pos.y) << 16;
-        v11 = ((unsigned __int64)(uIDc * (signed __int64)v4) >> 16)
-            + ((unsigned __int64)(v10 * (signed __int64)v5) >> 16);
-        HIDWORD(v8) = (unsigned __int64)(uIDc * (signed __int64)v5) >> 16;
-        v12 = v6->_z + 6.7553994e15;
-        uIDd = (LODWORD(v12) - pIndoorCamera->pos.z) << 16;
-        HIDWORD(v12) = ((unsigned __int64)(v11 * (signed __int64)v3) >> 16)
-                     + ((unsigned __int64)(uIDd * (signed __int64)v44) >> 16);
+        //v8 = v6->_x + 6.7553994e15;
+        //uIDc = (LODWORD(v8) - pIndoorCamera->pos.x) << 16;
+        //v9 = v6->_y + 6.7553994e15;
+        //v10 = (LODWORD(v9) - pIndoorCamera->pos.y) << 16;
+        v11 = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4) + fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
+        //HIDWORD(v8) = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
+        //v12 = v6->_z + 6.7553994e15;
+        //uIDd = (LODWORD(v12) - pIndoorCamera->pos.z) << 16;
+        auto _hidword_v12 = fixpoint_sub0(v11, v3) + fixpoint_mul(v6->z - pIndoorCamera->pos.z, v44);
         LODWORD(v13) = 0;
         HIDWORD(v13) = SLOWORD(pOutdoorCamera->int_fov_rad);
-        v14 = v13 / SHIDWORD(v12);
-        v6->_screenspace_scale = v14;
-        v15 = v6->_screenspace_scale;
+        //v14 = v13 / _hidword_v12;
+        v6->_screenspace_scale = v13 / _hidword_v12;
+        //v15 = v6->_screenspace_scale;
         v6->uScreenSpaceX = pViewport->uScreenCenterX
-                          - ((signed int)((unsigned __int64)(v14
-                                                           * (signed __int64)(signed int)(((unsigned __int64)(v10 * (signed __int64)v4) >> 16)
-                                                                                        - HIDWORD(v8))) >> 16) >> 16);
+                          - ((signed int)((unsigned __int64)(v6->_screenspace_scale
+                                                           * (signed __int64)(fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4)
+                                                                                        - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5))) >> 16) >> 16);
         v6->uScreenSpaceY = pViewport->uScreenCenterY
-                          - ((signed int)((unsigned __int64)(v15
-                                                           * (signed __int64)(signed int)(((unsigned __int64)(uIDd * (signed __int64)v3) >> 16)
+                          - ((signed int)((unsigned __int64)(v6->_screenspace_scale
+                                                           * (signed __int64)(fixpoint_mul(v6->z - pIndoorCamera->pos.z, v3)
                                                                                         - ((unsigned __int64)(v11 * (signed __int64)v44) >> 16))) >> 16) >> 16);
-        v6->sZValue = HIDWORD(v12);
+        v6->sZValue = _hidword_v12;
       }
-      uIDe = (v41 - pIndoorCamera->pos.x) << 16;
-      v47 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
-      v45 = ((unsigned __int64)(uIDe * (signed __int64)v4) >> 16) + ((unsigned __int64)(v47 * (signed __int64)v5) >> 16);
-      HIDWORD(v42) = (unsigned __int64)(uIDe * (signed __int64)v5) >> 16;
-      uIDa = (LODWORD(v42) - pIndoorCamera->pos.z) << 16;
-      X_4 = ((unsigned __int64)(uIDa * (signed __int64)v44) >> 16)
-          + ((unsigned __int64)(v45 * (signed __int64)v3) >> 16);
-      if ( X_4 < 262144 )
+      //uIDe = (v41 - pIndoorCamera->pos.x) << 16;
+      //v47 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
+      v45 = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4) + fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
+      //HIDWORD(v42) = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
+      //uIDa = (LODWORD(v42) - pIndoorCamera->pos.z) << 16;
+      X_4 = fixpoint_mul(v6->z - pIndoorCamera->pos.z, v44) + fixpoint_sub0(v45, v3);
+      if ( X_4 < 0x40000 )
         return 0;
-      v16 = ((unsigned __int64)(v47 * (signed __int64)v4) >> 16); //- v43;Ritor1:it's temporarily
-      v17 = ((unsigned __int64)(uIDa * (signed __int64)v3) >> 16)
-          - ((unsigned __int64)(v45 * (signed __int64)v44) >> 16);
+      v16 = fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4) - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
+      v17 = fixpoint_mul(v6->z - pIndoorCamera->pos.z, v3) - fixpoint_sub0(v45, v44);
     }
     else
     {
       if (v6->type & ParticleType_Line)
       {
-        v18 = v6->_x + 6.7553994e15;
-        uIDf = (LODWORD(v18) - pIndoorCamera->pos.x) << 16;
-        v19 = v6->_y + 6.7553994e15;
-        v20 = (LODWORD(v19) - pIndoorCamera->pos.y) << 16;
-        v21 = v6->_z + 6.7553994e15;
+        //v18 = v6->_x + 6.7553994e15;
+        //uIDf = (LODWORD(v18) - pIndoorCamera->pos.x) << 16;
+        //v19 = v6->_y + 6.7553994e15;
+        //v20 = (LODWORD(v19) - pIndoorCamera->pos.y) << 16;
+        //v21 = v6->_z + 6.7553994e15;
         LODWORD(v22) = 0;
         HIDWORD(v22) = SLOWORD(pOutdoorCamera->int_fov_rad);
-        v23 = v22
-            / (signed int)(((unsigned __int64)(v20 * (signed __int64)v5) >> 16)
-                         + ((unsigned __int64)(uIDf * (signed __int64)v4) >> 16));
-        v6->_screenspace_scale = v23;
-        v24 = v6->_screenspace_scale;
+        auto _var_123 = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4) + fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
+        //v23 = v22 / _var_123;
+        v6->_screenspace_scale = v22 / _var_123;
+        //v24 = v6->_screenspace_scale;
         v6->uScreenSpaceX = pViewport->uScreenCenterX
-                          - ((signed int)((unsigned __int64)(v23
-                                                           * (signed __int64)(signed int)(((unsigned __int64)(v20 * (signed __int64)v4) >> 16)
-                                                                                        - ((unsigned __int64)(uIDf * (signed __int64)v5) >> 16))) >> 16) >> 16);
-        v25 = pViewport->uScreenCenterY
-            - ((signed int)((unsigned __int64)(v24 * (signed __int64)SLODWORD(v21)) >> 16) >> 16);
-        v6->sZValue = ((unsigned __int64)(v20 * (signed __int64)v5) >> 16)
-                     + ((unsigned __int64)(uIDf * (signed __int64)v4) >> 16);
-        v6->uScreenSpaceY = v25;
+                          - ((signed int)((unsigned __int64)(v6->_screenspace_scale
+                                                           * (signed __int64)(fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4)
+                                                                                        - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5))) >> 16) >> 16);
+        v6->uScreenSpaceY = pViewport->uScreenCenterY - (fixpoint_mul(v6->z, v6->_screenspace_scale) >> 16);
+        v6->sZValue = _var_123;
       }
-      uIDb = (v41 - pIndoorCamera->pos.x) << 16;
-      v48 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
-      v26 = (unsigned __int64)(v48 * (signed __int64)v5) >> 16;
-      v27 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
-      X_4 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
-      if ( v27 < 262144 || v27 > (pOutdoorCamera->uPickDepth - 1000) << 16 )
+      //uIDb = (v41 - pIndoorCamera->pos.x) << 16;
+      //v48 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
+      v26 = fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
+      //v27 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
+      X_4 = v26 + fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4);
+      if ( X_4 < 0x40000 || X_4 > (pOutdoorCamera->uPickDepth - 1000) << 16 )
         return 0;
-      v17 = LODWORD(v42);
-      v16 = ((unsigned __int64)(v48 * (signed __int64)v4) >> 16) - ((unsigned __int64)(uIDb * (signed __int64)v5) >> 16);
+      v17 = v6->z;
+      v16 = fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4) - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
     }
     v40 = v17;
     v28 = abs(v16);
@@ -564,13 +559,13 @@
     {
       LODWORD(v29) = 0;
       HIDWORD(v29) = SLOWORD(pOutdoorCamera->int_fov_rad);
-      v30 = v29 / X_4;
-      v6->_screenspace_scale = v30;
-      v31 = v6->_screenspace_scale;
+      //v30 = v29 / X_4;
+      v6->_screenspace_scale = v29 / X_4;
+      //v31 = v6->_screenspace_scale;
       v6->uScreenSpaceX = pViewport->uScreenCenterX
-                        - ((signed int)((unsigned __int64)(v30 * (signed __int64)v16) >> 16) >> 16);
+                        - ((signed int)((unsigned __int64)(v6->_screenspace_scale * (signed __int64)v16) >> 16) >> 16);
       v32 = v6->flt_28;
-      v33 = (signed int)((unsigned __int64)(v31 * (signed __int64)v40) >> 16) >> 16;
+      v33 = (signed int)((unsigned __int64)(v6->_screenspace_scale * (signed __int64)v40) >> 16) >> 16;
       v34 = pViewport->uScreenCenterY - v33;
       v6->uScreenSpaceY = pViewport->uScreenCenterY - v33;
       v35 = v32;
@@ -590,8 +585,7 @@
         }
       }
     }
-  }
-  return 0;
+    return false;
 }
 
 //----- (0048BBA6) --------------------------------------------------------
@@ -612,7 +606,7 @@
     if (p->type == ParticleType_Invalid)
       continue;
 
-    if (!ViewProject_TrueIfStillVisible(i))
+    if (!ViewProject_TrueIfStillVisible_BLV(i))
       continue;
 
     if (p->uScreenSpaceX >= pBLVRenderParams->uViewportX &&
@@ -630,7 +624,7 @@
           v15.uScreenSpaceX = p->uScreenSpaceX;
           v15.uScreenSpaceY = p->uScreenSpaceY;
           v15.sZValue = p->sZValue;
-          pRenderer->MakeParticleBillboardAndPush_BLV(&v15, 0, p->uLightColor, p->_rotation);
+          pRenderer->MakeParticleBillboardAndPush_BLV(&v15, 0, p->uLightColor_bgr, p->angle);
           return;
         }
         if (p->type & ParticleType_Line)
@@ -641,7 +635,7 @@
             pLines.pLineVertices[2 * pLines.uNumLines].pos.y = p->uScreenSpaceY;
             pLines.pLineVertices[2 * pLines.uNumLines].pos.z = 1.0 - 1.0 / ((short)p->sZValue * 0.061758894);
             pLines.pLineVertices[2 * pLines.uNumLines].rhw = 1.0;
-            pLines.pLineVertices[2 * pLines.uNumLines].diffuse = p->uLightColor;
+            pLines.pLineVertices[2 * pLines.uNumLines].diffuse = p->uLightColor_bgr;
             pLines.pLineVertices[2 * pLines.uNumLines].specular = 0;
             pLines.pLineVertices[2 * pLines.uNumLines].texcoord.x = 0.0;
             pLines.pLineVertices[2 * pLines.uNumLines].texcoord.y = 0.0;
@@ -650,7 +644,7 @@
             pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.y = p->uScreenSpaceW;
             pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.z = 1.0 - 1.0 / ((short)p->sZValue2 * 0.061758894);
             pLines.pLineVertices[2 * pLines.uNumLines + 1].rhw = 1.0;
-            pLines.pLineVertices[2 * pLines.uNumLines + 1].diffuse = p->uLightColor;
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].diffuse = p->uLightColor_bgr;
             pLines.pLineVertices[2 * pLines.uNumLines + 1].specular = 0;
             pLines.pLineVertices[2 * pLines.uNumLines + 1].texcoord.x = 0.0;
             pLines.pLineVertices[2 * pLines.uNumLines++ + 1].texcoord.y = 0.0;
@@ -663,9 +657,7 @@
           v15.uScreenSpaceX = p->uScreenSpaceX;
           v15.uScreenSpaceY = p->uScreenSpaceY;
           v15.sZValue = p->sZValue;
-          pRenderer->MakeParticleBillboardAndPush_BLV(&v15, pBitmaps_LOD->pHardwareTextures[p->uTextureID],
-                        p->uLightColor,
-                        p->_rotation);
+          pRenderer->MakeParticleBillboardAndPush_BLV(&v15, pBitmaps_LOD->pHardwareTextures[p->uTextureID], p->uLightColor_bgr, p->angle);
         }
         if (p->type & ParticleType_Sprite)
         {
@@ -674,9 +666,7 @@
           v15.uScreenSpaceX = p->uScreenSpaceX;
           v15.uScreenSpaceY = p->uScreenSpaceY;
           v15.sZValue = p->sZValue;
-          pRenderer->MakeParticleBillboardAndPush_BLV(&v15, pSprites_LOD->pHardwareSprites[p->uTextureID].pTexture,
-                        p->uLightColor,
-                        p->_rotation);
+          pRenderer->MakeParticleBillboardAndPush_BLV(&v15, pSprites_LOD->pHardwareSprites[p->uTextureID].pTexture, p->uLightColor_bgr, p->angle);
         }
       }
       else
@@ -695,7 +685,7 @@
                      }
                      else
                      {
-                       pRenderer->MakeParticleBillboardAndPush_BLV_Software(v13, v12, p->sZValue, p->uLightColor, v11);
+                       pRenderer->MakeParticleBillboardAndPush_BLV_Software(v13, v12, p->sZValue, p->uLightColor_bgr, v11);
                      }
       }
     }
@@ -706,19 +696,19 @@
 void ParticleEngine::DrawParticles_ODM()
 {
   ParticleEngine *pParticleEngine; // esi@1
-  int pParticleNum; // eax@1
+  //int pParticleNum; // eax@1
   unsigned __int8 v3; // zf@1
   char v4; // sf@1
   unsigned __int8 v5; // of@1
-  char *v7; // edi@2
-  int v8; // eax@6
-  signed int pNumLines; // eax@8
+  //char *v7; // edi@2
+  //int v8; // eax@6
+  //signed int pNumLines; // eax@8
   int v10; // eax@14
   int v11; // ecx@16
   int v12; // edx@16
-  Particle *pParticle; // eax@24
+  //Particle *pParticle; // eax@24
   RenderBillboardTransform_local0 pBillboard; // [sp+Ch] [bp-58h]@1
-  int v15; // [sp+5Ch] [bp-8h]@9
+  //int v15; // [sp+5Ch] [bp-8h]@9
   int v16; // [sp+60h] [bp-4h]@1
 
   pBillboard.uParentBillboardID = -1;
@@ -728,92 +718,86 @@
   //v3 = v2 == this->uEndParticle;
   //v4 = v2 - this->uEndParticle < 0;
   //v16 = this->uStartParticle;
-  for (pParticleNum = this->uStartParticle; pParticleNum <= this->uEndParticle; ++pParticleNum)
+  for (uint i = uStartParticle; i <= uEndParticle; ++i)
   {
-    v7 = (char *)&this->pParticles[pParticleNum].sZValue + 2;
-    //do
-    //{
-      if ( *(_DWORD *)(v7 - 82) && pParticleEngine->_48B5B3(pParticleNum) )//*(_DWORD *)(v7 - 82) = this->pParticles[pParticleNum] or this->pParticles[pParticleNum].uType
-      {
+    auto particle = pParticles + i;
+    if (particle->type == ParticleType_Invalid || !ViewProject_TrueIfStillVisible_ODM(i))
+      continue;
+
         if ( pRenderer->pRenderD3D )
         {
-          v8 = *(_DWORD *)(v7 - 82);
-          if ( BYTE1(v8) & 1 )
+          //v8 = *(_DWORD *)(v7 - 82);
+          if (particle->type & ParticleType_Diffuse)
           {
-            pParticle = &pParticleEngine->pParticles[pParticleNum];
-            pBillboard._screenspace_x_scaler_packedfloat = pParticle->_screenspace_scale / 4;
-            pBillboard._screenspace_y_scaler_packedfloat = pParticle->_screenspace_scale / 4;
-            pBillboard.uScreenSpaceX = pParticle->uScreenSpaceX;
-            pBillboard.uScreenSpaceY = pParticle->uScreenSpaceY;
-            pBillboard.sZValue = pParticle->sZValue;
-            pRenderer->MakeParticleBillboardAndPush_ODM(&pBillboard, 0, pParticle->uLightColor, pParticle->_rotation);
+            pBillboard._screenspace_x_scaler_packedfloat = particle->_screenspace_scale / 4;
+            pBillboard._screenspace_y_scaler_packedfloat = particle->_screenspace_scale / 4;
+            pBillboard.uScreenSpaceX = particle->uScreenSpaceX;
+            pBillboard.uScreenSpaceY = particle->uScreenSpaceY;
+            pBillboard.sZValue = particle->sZValue;
+            pRenderer->MakeParticleBillboardAndPush_ODM(&pBillboard, 0, particle->uLightColor_bgr, particle->angle);
             return;
           }
-          if ( BYTE1(v8) & 2 )
+          if (particle->type & ParticleType_Line)
           {
-            pNumLines = pParticleEngine->pLines.uNumLines;
-            if ( pNumLines < 100 )
+            if (pLines.uNumLines < 100)
             {
-              pParticleEngine->pLines.pLineVertices[2 * pNumLines].pos.x = (double)*(signed int *)(v7 - 18);
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines].pos.y = (double)*(signed int *)(v7 - 14);
-              v15 = *(_DWORD *)v7;
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines].pos.z = 1.0 - 1.0 / ((double)v15 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines].rhw = 1.0;
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines].diffuse = *(_DWORD *)(v7 + 18);
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines].specular = 0;
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines].texcoord.x = 0.0;
-              *((float *)&pParticleEngine->pParticles[0].type + 16 * (pParticleEngine->pLines.uNumLines + 813)) = 0.0;
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines + 1].pos.x = (double)*(signed int *)(v7 - 10);
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines + 1].pos.y = (double)*(signed int *)(v7 - 6);
-              v15 = *(_DWORD *)v7;
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines + 1].pos.z = 1.0 - 1.0 / ((double)v15 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines + 1].rhw = 1.0;
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines + 1].diffuse = *(_DWORD *)(v7 + 18);
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines + 1].specular = 0;
-              pParticleEngine->pLines.pLineVertices[2 * pParticleEngine->pLines.uNumLines + 1].texcoord.x = 0.0;
-              __debugbreak();//v1->pLines.pLineVertices[2 * v1->pLines.uNumLines++ + 1].texcoord.y = 0.0;
+              pLines.pLineVertices[2 * pLines.uNumLines].pos.x = particle->uScreenSpaceX;
+              pLines.pLineVertices[2 * pLines.uNumLines].pos.y = particle->uScreenSpaceY;
+              pLines.pLineVertices[2 * pLines.uNumLines].pos.z = 1.0 - 1.0 / ((double)particle->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+              pLines.pLineVertices[2 * pLines.uNumLines].rhw = 1.0;
+              pLines.pLineVertices[2 * pLines.uNumLines].diffuse = particle->uLightColor_bgr;
+              pLines.pLineVertices[2 * pLines.uNumLines].specular = 0;
+              pLines.pLineVertices[2 * pLines.uNumLines].texcoord.x = 0.0;
+              pLines.pLineVertices[2 * pLines.uNumLines].texcoord.y = 0.0;
+
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.x = particle->uScreenSpaceZ;
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.y = particle->uScreenSpaceW;
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.z = 1.0 - 1.0 / ((double)particle->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].rhw = 1.0;
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].diffuse = particle->uLightColor_bgr;
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].specular = 0;
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].texcoord.x = 0.0;
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].texcoord.y = 0.0;
+              pLines.uNumLines++;
             }
           }
-          if ( *(v7 - 81) & 4 )
+          if (particle->type & ParticleType_Bitmap)
           {
-            pBillboard._screenspace_x_scaler_packedfloat = *(_DWORD *)(v7 + 6);
-            pBillboard._screenspace_y_scaler_packedfloat = *(_DWORD *)(v7 + 6);
-            pBillboard.uScreenSpaceX = *(_DWORD *)(v7 - 18);
-            pBillboard.uScreenSpaceY = *(_DWORD *)(v7 - 14);
-            pBillboard.sZValue = *(_DWORD *)(v7 - 2);
-            pRenderer->MakeParticleBillboardAndPush_ODM(&pBillboard, pBitmaps_LOD->pHardwareTextures[*(_DWORD *)(v7 - 46)], *(_DWORD *)(v7 + 18), *(_DWORD *)(v7 - 22));
+            pBillboard._screenspace_x_scaler_packedfloat = particle->_screenspace_scale;
+            pBillboard._screenspace_y_scaler_packedfloat = particle->_screenspace_scale;
+            pBillboard.uScreenSpaceX = particle->uScreenSpaceX;
+            pBillboard.uScreenSpaceY = particle->uScreenSpaceY;
+            pBillboard.sZValue = particle->sZValue;
+            pRenderer->MakeParticleBillboardAndPush_ODM(&pBillboard, pBitmaps_LOD->pHardwareTextures[particle->uTextureID], particle->uLightColor_bgr, particle->angle);
           }
-          if ( *(v7 - 81) & 8 )
+          if (particle->type & ParticleType_Sprite)
           {
-            pBillboard._screenspace_x_scaler_packedfloat = *(_DWORD *)(v7 + 6);
-            pBillboard._screenspace_y_scaler_packedfloat = *(_DWORD *)(v7 + 6);
-            pBillboard.uScreenSpaceX = *(_DWORD *)(v7 - 18);
-            pBillboard.uScreenSpaceY = *(_DWORD *)(v7 - 14);
-            pBillboard.sZValue = *(_DWORD *)(v7 - 2);
-            pRenderer->MakeParticleBillboardAndPush_ODM(&pBillboard, pSprites_LOD->pHardwareSprites[*(_DWORD *)(v7 - 46)].pTexture, *(_DWORD *)(v7 + 18),
-              *(_DWORD *)(v7 - 22));
+            pBillboard._screenspace_x_scaler_packedfloat = particle->_screenspace_scale;
+            pBillboard._screenspace_y_scaler_packedfloat = particle->_screenspace_scale;
+            pBillboard.uScreenSpaceX = particle->uScreenSpaceX;
+            pBillboard.uScreenSpaceY = particle->uScreenSpaceY;
+            pBillboard.sZValue = particle->sZValue;
+            pRenderer->MakeParticleBillboardAndPush_ODM(&pBillboard, pSprites_LOD->pHardwareSprites[particle->uTextureID].pTexture, particle->uLightColor_bgr, particle->angle);
           }
         }
         else
         {
-          v10 = 13 * *(_DWORD *)(v7 + 6) >> 16;
+          v10 = 13 * particle->_screenspace_scale >> 16;
           if ( v10 > 30 )
             v10 = 30;
-          v11 = *(_DWORD *)(v7 - 18) - (v10 >> 1);
-          v12 = *(_DWORD *)(v7 - 14) - v10;
+          v11 = particle->uScreenSpaceX - (v10 >> 1);
+          v12 = particle->uScreenSpaceY - v10;
           if ( v11 + v10 < pViewport->uViewportTL_X
             || v11 >= pViewport->uViewportBR_X
-            || *(_DWORD *)(v7 - 14) < pViewport->uViewportTL_Y
+            || particle->uScreenSpaceY < pViewport->uViewportTL_Y
             || v12 >= (signed int)pViewport->uViewportBR_Y )
           {
             ;
           }
           else
           {
-            pRenderer->MakeParticleBillboardAndPush_BLV_Software(v11, v12, *(_DWORD *)(v7 - 2), *(_DWORD *)(v7 + 18), v10);
+            pRenderer->MakeParticleBillboardAndPush_BLV_Software(v11, v12, particle->sZValue, particle->uLightColor_bgr, v10);
           }
-        }
-      }
-      
+        }      
   }
 }
\ No newline at end of file
--- a/ParticleEngine.h	Thu Mar 28 00:37:58 2013 +0400
+++ b/ParticleEngine.h	Mon Apr 01 13:39:19 2013 +0200
@@ -64,8 +64,8 @@
   float _x;
   float _y;
   float _z;
-  int field_38;
-  int _rotation;
+  int rotation_speed;
+  int angle;
   int uScreenSpaceX;
   int uScreenSpaceY;
   int uScreenSpaceZ;  // line end x
@@ -83,7 +83,7 @@
   int _screenspace_scale;
   float flt_5C;
   float flt_60;
-  int uLightColor;
+  int uLightColor_bgr;
 };
 #pragma pack(pop)
 
@@ -113,8 +113,8 @@
   void AddParticle(Particle_sw *a2);
   void Draw();
   void UpdateParticles();
-  bool ViewProject_TrueIfStillVisible(unsigned int uParticleID);
-  bool _48B5B3(unsigned int uID);
+  bool ViewProject_TrueIfStillVisible_BLV(unsigned int uParticleID);
+  bool ViewProject_TrueIfStillVisible_ODM(unsigned int uID);
   void DrawParticles_BLV();
   void DrawParticles_ODM();
 
--- a/Render.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/Render.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -5597,7 +5597,7 @@
   {
     pDefaultZBuffer = pActiveZBuffer = nullptr;
     pDefaultZBuffer = pActiveZBuffer = (int *)pAllocator->AllocNamedChunk(0, 0x12C000, "Z Buf.");
-    memset32(pActiveZBuffer, 0xFFFF0000u, 0x4B000u);
+    memset32(pActiveZBuffer, 0xFFFF0000, 0x4B000u); //    // inlined Render::ClearActiveZBuffer  (mm8::004A085B)
   }
 }
 
--- a/UiGame.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/UiGame.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -554,7 +554,7 @@
   {
     if ( (signed int)pX > 467 || (signed int)pY > 351 )
       goto _click_on_game_ui;
-    if ( pRenderer->pRenderD3D )
+    if ( pRenderer->pRenderD3D )  // inlined mm8::4C1E01
     {
       v18 = pGame->pVisInstance->get_picked_object_zbuf_val();
       if ( (signed int)pX < (signed int)pViewport->uScreen_TL_X
--- a/Viewport.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/Viewport.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -37,7 +37,7 @@
     this->uScreenHeight = br_y - tl_y + 1;
     this->uScreenCenterX = (signed int)(br_x + tl_x) /2;
     if ( pRenderer->pRenderD3D == 0 )
-        this->uScreenCenterY = this->uScreen_BR_Y - fixpoint_mul(field_30, uScreenHeight);
+        this->uScreenCenterY = this->uScreen_BR_Y - fixpoint_sub0(field_30, uScreenHeight);
     else
         this->uScreenCenterY = uScreenHeight/2;
     SetViewport(this->uScreen_TL_X, this->uScreen_TL_Y, this->uScreen_BR_X, this->uScreen_BR_Y);
--- a/mm7_1.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/mm7_1.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -64,11 +64,16 @@
   return ((__int64)a1 << 16) / a2;
 }
 
+int fixpoint_mul(int a1, int a2)
+{
+  return (((__int64)a1 << 16) * a2) >> 16;
+}
+
 //----- (004453C0) mm6-----------------------------------------------------
 //----- (004A1760) mm6_chinese---------------------------------------------
-int fixpoint_mul(int a1, int a2)
+int fixpoint_sub0(int a1, int a2)
 {
-  return ((__int64)a1 * (__int64)a2) / 65536;
+  return ((__int64)a1 * (__int64)a2) >> 16;
 }
 
 //----- (004196A0) --------------------------------------------------------
--- a/mm7_2.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/mm7_2.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -7148,7 +7148,7 @@
           {
             if (pAsyncMouse)
               goto _def_wnd_proc;
-            v33 = GetPickDepth();
+            v33 = pGame->pIndoorCameraD3D->GetPickDepth();
             pGame->PickMouse(v33, (unsigned __int16)lParam, lParam >> 16, v31, &vis_sprite_filter_2, &vis_door_filter);
           }
           if (!pAsyncMouse)
@@ -7167,7 +7167,7 @@
         {
           if ( pGame && !pAsyncMouse )
           {
-            v34 = GetPickDepth();
+            v34 = pGame->pIndoorCameraD3D->GetPickDepth();
             pGame->PickMouse(v34, (unsigned __int16)lParam, lParam >> 16, 1, &vis_sprite_filter_3, &vis_face_filter);
             return DefWindowProcA(hWnd, Msg, wParam, lParam);
           }
--- a/mm7_3.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/mm7_3.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -7789,7 +7789,7 @@
       v15 = grid_x2 - a1;
       v13 = grid_z1 - a2;
     }
-    return v14 + v8 + fixpoint_mul(v13, (v10 - v8) * 128) + fixpoint_mul(v15, (v9 - v8) * 128);
+    return v14 + v8 + fixpoint_sub0(v13, (v10 - v8) * 128) + fixpoint_sub0(v15, (v9 - v8) * 128);
   }
   else
     return y_x1z1;
--- a/mm7_4.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/mm7_4.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -306,7 +306,7 @@
           else
           {
             auto a_div_b = fixpoint_div(y - word_721390_ys[j], word_721390_ys[j + 1] - word_721390_ys[j]);
-            auto res = fixpoint_mul((signed int)word_721460_xs[j + 1] - (signed int)word_721460_xs[j], a_div_b);
+            auto res = fixpoint_sub0((signed int)word_721460_xs[j + 1] - (signed int)word_721460_xs[j], a_div_b);
 
             if (res + word_721460_xs[j] >= x)
                 ++v53;
@@ -324,7 +324,7 @@
           }
           else
           {
-            v21 = fixpoint_mul(pFloor->zCalc1, x) + fixpoint_mul(pFloor->zCalc2, y) + (short)(pFloor->zCalc3 >> 16);
+            v21 = fixpoint_sub0(pFloor->zCalc1, x) + fixpoint_sub0(pFloor->zCalc2, y) + (short)(pFloor->zCalc3 >> 16);
           }
           blv_floor_level[v55] = v21;
           blv_floor_id[v55] = pSector->pFloors[i];
@@ -377,7 +377,7 @@
                 else
                 {
                   auto a_div_b = fixpoint_div(y - word_721390_ys[j], word_721390_ys[j + 1] - word_721390_ys[j]);
-                  auto res = fixpoint_mul(word_721460_xs[j + 1] - word_721460_xs[j], a_div_b);
+                  auto res = fixpoint_sub0(word_721460_xs[j + 1] - word_721460_xs[j], a_div_b);
                   if (res + word_721460_xs[j] >= x)
                     ++v54;
                 }
--- a/mm7_5.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/mm7_5.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -3960,18 +3960,6 @@
   return result;
 }
 
-//----- (0043643E) --------------------------------------------------------
-double __cdecl GetPickDepth()
-{
-  double result; // st7@2
-
-  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
-    result = (double)pOutdoorCamera->uPickDepth;
-  else
-    result = 16192.0;
-  return result;
-}
-
 //----- (0043648F) --------------------------------------------------------
 void Vec3_short__to_RenderVertexSoft(RenderVertexSoft *_this, Vec3_short_ *a2)
 {
@@ -6281,7 +6269,7 @@
 //LABEL_15:
   pSex = 1;
   return pSex;*/
-  for (uint i = 1; i <= 4; pPlayers[i]) 
+  for (uint i = 1; i <= 4; ++i)
     {
       pRace = pPlayers[i]->GetRace();
       pSex = pPlayers[i]->GetSexByVoice();
--- a/mm7_6.cpp	Thu Mar 28 00:37:58 2013 +0400
+++ b/mm7_6.cpp	Mon Apr 01 13:39:19 2013 +0200
@@ -7382,7 +7382,7 @@
         if ( !pPlayer->CanCastSpell(uRequiredMana) )
           goto play_sound_and_continue;
         pGame->GetIndoorCamera();
-        v623 = (signed __int64)GetPickDepth();
+        v623 = (signed __int64)pGame->pIndoorCameraD3D->GetPickDepth();
         HIDWORD(v733) = sub_46A6AC((int)dword_50BF30, 100, v623);
         v707.x = 0;
         v707.y = 0;
--- a/mm7_data.h	Thu Mar 28 00:37:58 2013 +0400
+++ b/mm7_data.h	Mon Apr 01 13:39:19 2013 +0200
@@ -8,38 +8,6 @@
 
 
 typedef unsigned int uint;
-/*
-#define LOWORD(a) (*((unsigned short *)&a))
-#define SLOWORD(a) (__debugbreak(), *((signed short *)&a))
-#define HIWORD(a) (*((unsigned short *)&a + 1))
-#define SHIWORD(a) (*((short *)&a + 1))
-
-#define LODWORD(a) (*((unsigned int *)&a))
-#define HIDWORD(a) (*((unsigned int *)&a + 1))
-#define SLODWORD(a) (*((int *)&a))
-#define SHIDWORD(a) (*((int *)&a + 1))
-
-#define LOBYTE(a) (*((unsigned char *)&a))
-#define SLOBYTE(a) (*((signed char *)&a))
-
-#define HIBYTE(a) (*((unsigned char *)&a + sizeof(a) - 1))
-
-#define BYTE1(a) (*((unsigned char *)&a + 1))
-#define SBYTE1(a) (*((signed char *)&a + 1))
-
-#define BYTE2(a) (*((unsigned char *)&a + 2))
-#define BYTE3(a) (*((unsigned char *)&a + 3))
-
-#define WORD2(a) (__debugbreak(), *(unsigned short *)((char *)&a + 4))
-
-#define __OFSUB__(a, b) (unsigned __int8)((a) == (b))
-
-
-typedef unsigned __int16 _WORD;
-typedef unsigned __int64 _QWORD;
-*/
-
-
 
 
 
@@ -1749,7 +1717,6 @@
 void __cdecl back_to_game();
 void __cdecl GUI_MainMenuMessageProc();
 double __cdecl get_shading_dist_mist();
-double __cdecl GetPickDepth();
 void Vec3_short__to_RenderVertexSoft(struct RenderVertexSoft *_this, struct Vec3_short_ *a2);
 void __cdecl nullsub_4(); // idb
 void __cdecl nullsub_5(); // idb
@@ -2144,8 +2111,9 @@
 signed int __fastcall SpawnRandomTreasure(struct MapInfo *a1, struct SpawnPointMM7 *a2);
 void DamageMonsterFromParty(signed int a1, unsigned int uActorID_Monster, struct Vec3_int_ *pVelocity);
 
+int fixpoint_sub0(int, int);
+int fixpoint_div(int, int);
 int fixpoint_mul(int, int);
-int fixpoint_div(int, int);
 
 
 #define ErrD3D(hr) do {extern void ErrHR(HRESULT, const char *, const char *, const char *, int); ErrHR(hr, "Direct3D", __FUNCTION__, __FILE__, __LINE__);} while(0)