view LOD.cpp @ 117:a64b244da76c

some things lod
author Nomad
date Tue, 13 Nov 2012 17:29:38 +0200
parents 75faebd0a975
children 2546de5c70dd 6d1f537a1346
line wrap: on
line source

#include "LOD.h"
#include "Render.h"
#include "Allocator.h"
#include "PaletteManager.h"
#include "Viewport.h"
#include "Log.h"

#include "mm7_data.h"







LODFile_IconsBitmaps *pEvents_LOD;
LODFile_IconsBitmaps *pIcons_LOD;
LODFile_Sprites *pSprites_LOD;
LODFile_IconsBitmaps *pBitmaps_LOD;

LODWriteableFile *pNew_LOD;
LODWriteableFile *pGames_LOD;




int _6A0CA4_lod_binary_search; // weak
int _6A0CA8_lod_unused; // weak





//----- (004355F7) --------------------------------------------------------
void LODFile_IconsBitmaps::_4355F7()
{
  LODFile_IconsBitmaps *v1; // esi@1
  int v2; // edi@2
  Texture *v3; // ebp@3
  struct IDirect3DTexture2 **v4; // eax@4
  struct IDirect3DTexture2 *v5; // eax@5
  struct IDirectDrawSurface **v6; // eax@7
  struct IDirectDrawSurface *v7; // eax@8
  int v8; // eax@11

  v1 = this;
  if ( this->uTexturePacksCount )
  {
    v2 = this->uNumLoadedFiles - 1;
    if ( v2 >= this->uNumPrevLoadedFiles )
    {
      v3 = &this->pTextures[v2];
      do
      {
        v3->Release();
        v4 = v1->pHardwareTextures;
        if ( v4 )
        {
          v5 = v4[v2];
          if ( v5 )
          {
            v5->Release();
            v1->pHardwareTextures[v2] = 0;
          }
        }
        v6 = v1->pHardwareSurfaces;
        if ( v6 )
        {
          v7 = v6[v2];
          if ( v7 )
          {
            v7->Release();
            v1->pHardwareSurfaces[v2] = 0;
          }
        }
        --v2;
        --v3;
      }
      while ( v2 >= v1->uNumPrevLoadedFiles );
    }
    v8 = v1->uNumPrevLoadedFiles;
    v1->uNumPrevLoadedFiles = 0;
    v1->uNumLoadedFiles = v8;
    v1->uTexturePacksCount = 0;
  }
}

//----- (004114F2) --------------------------------------------------------
void LODFile_IconsBitmaps::_4114F2()
{
  LODFile_IconsBitmaps *v1; // esi@1
  int *pTexturePacksCount; // eax@1
  int v3; // ecx@1
  int v4; // ecx@2
  int v5; // edi@3
  Texture *v6; // ebx@4
  struct IDirect3DTexture2 **v7; // eax@5
  struct IDirect3DTexture2 *v8; // eax@6
  struct IDirectDrawSurface **v9; // eax@8
  struct IDirectDrawSurface *v10; // eax@9
  int v11; // eax@12

  v1 = this;
  pTexturePacksCount = &this->uTexturePacksCount;
  v3 = this->uTexturePacksCount;
  if ( v3 )
  {
    v4 = v3 - 1;
    *pTexturePacksCount = v4;
    if ( !v4 )
    {
      v5 = v1->uNumLoadedFiles - 1;
      if ( v5 >= v1->uNumPrevLoadedFiles )
      {
        v6 = &v1->pTextures[v5];
        do
        {
          v6->Release();
          v7 = v1->pHardwareTextures;
          if ( v7 )
          {
            v8 = v7[v5];
            if ( v8 )
            {
              v8->Release();
              v1->pHardwareTextures[v5] = 0;
            }
          }
          v9 = v1->pHardwareSurfaces;
          if ( v9 )
          {
            v10 = v9[v5];
            if ( v10 )
            {
              v10->Release();
              v1->pHardwareSurfaces[v5] = 0;
            }
          }
          --v5;
          --v6;
        }
        while ( v5 >= v1->uNumPrevLoadedFiles );
      }
      v11 = v1->uNumPrevLoadedFiles;
      v1->uNumPrevLoadedFiles = 0;
      v1->uNumLoadedFiles = v11;
    }
  }
}

//----- (004AC67E) --------------------------------------------------------
int LODFile_Sprites::LoadSpriteFromFile(LODSprite *pSpriteHeader, const char *pContainer)
{
  FILE *v3; // eax@1
  FILE *v4; // ebx@1
  int result; // eax@2
  LODSprite *v6; // esi@3
  LODSprite_stru0 *v7; // eax@3
  size_t v8; // ST10_4@3
  int *v9; // ebx@3
  int v10; // eax@3
  void *v11; // eax@5
  LODSprite_stru0 *v12; // eax@6
  void *v13; // ecx@6
  LODSprite_stru0 *i; // edx@6
  FILE *File; // [sp+4h] [bp-4h]@1
  void *DstBufa; // [sp+10h] [bp+8h]@4
  int Sizea; // [sp+14h] [bp+Ch]@3

  v3 = FindContainer(pContainer, 0);
  v4 = v3;
  File = v3;
  if ( v3 )
  {
    v6 = pSpriteHeader;
    fread(pSpriteHeader, 1u, 0x20u, v3);
    strcpy(pSpriteHeader->pName, pContainer);
    Sizea = pSpriteHeader->uSpriteSize;
    v7 = (LODSprite_stru0 *)pAllocator->AllocNamedChunk(v6->pSpriteLines, 8 * v6->uHeight, v6->pName);
    v8 = 8 * pSpriteHeader->uHeight;
    pSpriteHeader->pSpriteLines = v7;
    fread(v7, 1u, v8, v4);
    v9 = &pSpriteHeader->uDecompressedSize;
    v10 = pSpriteHeader->uDecompressedSize;
    if ( v10 )
    {
      pSpriteHeader->pDecompressedBytes = pAllocator->AllocNamedChunk(
                                            pSpriteHeader->pDecompressedBytes,
                                            v10,
                                            pSpriteHeader->pName);
      DstBufa = pAllocator->AllocNamedChunk(0, Sizea, pSpriteHeader->pName);
      fread(DstBufa, 1u, Sizea, File);
      zlib::MemUnzip(v6->pDecompressedBytes, (unsigned int *)&v6->uDecompressedSize, DstBufa, v6->uSpriteSize);
      v6->uSpriteSize = *v9;
      pAllocator->FreeChunk(DstBufa);
    }
    else
    {
      v11 = pAllocator->AllocNamedChunk(pSpriteHeader->pDecompressedBytes, Sizea, pSpriteHeader->pName);
      pSpriteHeader->pDecompressedBytes = v11;
      fread(v11, 1u, Sizea, File);
    }
    v12 = v6->pSpriteLines;
    v13 = v6->pDecompressedBytes;
    for ( i = &v12[v6->uHeight]; v12 < i; i = &v6->pSpriteLines[v6->uHeight] )
    {
      v12->ptr_4 = (char *)v12->ptr_4 + (unsigned int)v13;
      ++v12;
    }
    result = 1;
  }
  else
  {
    result = -1;
  }
  return result;
}

//----- (004AC795) --------------------------------------------------------
bool LODFile_Sprites::LoadSprites(const char *pFilename)
{
  if (LoadHeader(pFilename, 1))
    return false;
  else
    return LoadSubIndices("sprites08") == 0;
}

//----- (004AC7C0) --------------------------------------------------------
int LODFile_Sprites::LoadSprite(const char *pContainerName, unsigned int uPaletteID)
{  signed int v3; // edi@1
  LODFile_Sprites *v4; // esi@1
  unsigned int v5; // eax@6
  signed int v6; // ecx@10
  Sprite *v7; // eax@11
  FILE *v8; // eax@12
  Sprite *v10; // edx@21
  int v11; // eax@21
  int v12; // eax@22
  unsigned __int8 v13; // zf@23
  unsigned __int8 v14; // sf@23
  LODSprite DstBuf; // [sp+Ch] [bp-3Ch]@12
  char *Str1; // [sp+34h] [bp-14h]@24
  LODSprite *v17; // [sp+38h] [bp-10h]@3
  int v18; // [sp+44h] [bp-4h]@12

  auto a3 = uPaletteID;
  v3 = 0;
  v4 = this;
  if ( pRenderer->pRenderD3D )
  {
    if ( (signed int)this->uNumLoadedSprites > 0 )
    {
      v17 = 0;
      while ( _strcmpi(*(const char **)&v17->pName[(unsigned int)v4->pHardwareSprites], pContainerName) )
      {
        ++v17;
        ++v3;
        if ( v3 >= (signed int)v4->uNumLoadedSprites )
          goto LABEL_6;
      }
      return v3;
    }
  }
  else
  {
    if ( (signed int)this->uNumLoadedSprites > 0 )
    {
      v17 = this->pSpriteHeaders;
      while ( _strcmpi(v17->pName, pContainerName) )
      {
        ++v17;
        ++v3;
        if ( v3 >= (signed int)v4->uNumLoadedSprites )
          goto LABEL_6;
      }
      return v3;
    }
  }
LABEL_6:
  v5 = v4->uNumLoadedSprites;
  if ( v5 == 1500 )
    return -1;
  if ( pRenderer->pRenderD3D && v4->field_ECAC )
  {
    if ( !v4->pHardwareSprites )
    {
      v4->pHardwareSprites = (Sprite *)pAllocator->AllocNamedChunk(0, 0xEA60u, "hardSprites");
      v6 = 0;
      do
      {
        v7 = &v4->pHardwareSprites[v6];
        ++v6;
        v7->pName = 0;
        v7->pTextureSurface = 0;
        v7->pTexture = 0;
      }
      while ( v6 < 1500 );
    }
    DstBuf.uHeight = 0;
    DstBuf.uPaletteId = 0;
    DstBuf.word_1A = 0;
    DstBuf.pSpriteLines = 0;
    DstBuf.pDecompressedBytes = 0;
    v18 = 0;
    v8 = FindContainer(pContainerName, 0);
    if ( !v8 )
    {
      v18 = -1;
      //LODSprite::dtor(&DstBuf);
      return -1;
    }
    fread(&DstBuf, 1u, 0x20u, v8);
    v10 = v4->pHardwareSprites;
    v11 = 5 * v4->uNumLoadedSprites;
    v18 = -1;
    pHardwareSprites[uNumLoadedSprites].uBufferWidth = DstBuf.uWidth;
    pHardwareSprites[uNumLoadedSprites].uBufferHeight = DstBuf.uHeight;
    pSpriteHeaders[uNumLoadedSprites].uWidth = DstBuf.uWidth;
    pSpriteHeaders[uNumLoadedSprites].uHeight = DstBuf.uHeight;
    //LODSprite::dtor(&DstBuf);
    goto LABEL_29;
  }
  v12 = LoadSpriteFromFile( &v4->pSpriteHeaders[v5], pContainerName);
  v4->pSpriteHeaders[v4->uNumLoadedSprites].word_1A = 0;
  if ( v12 != -1 )
  {
LABEL_28:
    v4->pSpriteHeaders[v4->uNumLoadedSprites].uPaletteId = pPaletteManager->LoadPalette(
                                                             v4->pSpriteHeaders[v4->uNumLoadedSprites].uPaletteId);
LABEL_29:
    if ( pRenderer->pRenderD3D )
    {
      v4->pHardwareSprites[v4->uNumLoadedSprites].pName = (const char *)pAllocator->AllocNamedChunk(
                                                                          v4->pHardwareSprites[v4->uNumLoadedSprites].pName,
                                                                          0x14u,
                                                                          pContainerName);
      strcpy((char *)pHardwareSprites[uNumLoadedSprites].pName, pContainerName);
      v4->pHardwareSprites[v4->uNumLoadedSprites].uPaletteID = uPaletteID;
      pRenderer->MoveSpriteToDevice(&pHardwareSprites[uNumLoadedSprites]);
    }
    ++v4->uNumLoadedSprites;
    return v4->uNumLoadedSprites - 1;
  }
  v13 = v4->uNumLoadedSprites == 0;
  v14 = (v4->uNumLoadedSprites & 0x80000000u) != 0;
  v17 = 0;
  if ( v14 | v13 )
  {
LABEL_27:
    if ( LoadSpriteFromFile(&v4->pSpriteHeaders[v4->uNumLoadedSprites], "pending") == -1 )
      return -1;
    goto LABEL_28;
  }
  Str1 = (char *)v4->pSpriteHeaders;
  while ( _strcmpi(Str1, "pending") )
  {
    v17 = (LODSprite *)((char *)v17 + 1);
    Str1 += 40;
    if ( (signed int)v17 >= (signed int)v4->uNumLoadedSprites )
      goto LABEL_27;
  }
  return (int)v17;
}

//----- (004ACADA) --------------------------------------------------------
void LODFile_Sprites::ReleaseLostHardwareSprites()
{
  LODFile_Sprites *v1; // esi@1
  signed int v2; // ebx@2
  int v3; // edi@3
  IDirectDrawSurface *v4; // eax@4
  IDirect3DTexture2 *v5; // eax@6
  IDirectDrawSurface *v6; // ST00_4@8

  v1 = this;
  if ( this->pHardwareSprites )
  {
    v2 = 0;
    if ( (signed int)this->uNumLoadedSprites > 0 )
    {
      v3 = 0;
      do
      {
        v4 = (IDirectDrawSurface *)v1->pHardwareSprites[v3].pTextureSurface;
        if ( v4 && v4->IsLost() == DDERR_SURFACELOST )
        {
          v5 = v1->pHardwareSprites[v3].pTexture;
          if ( v5 )
          {
            v5->Release();
            v1->pHardwareSprites[v3].pTexture = 0;
          }
          v6 = (IDirectDrawSurface *)v1->pHardwareSprites[v3].pTextureSurface;
          v6->Release();
          v1->pHardwareSprites[v3].pTextureSurface = 0;
          pRenderer->MoveSpriteToDevice(&v1->pHardwareSprites[v3]);
        }
        ++v2;
        ++v3;
      }
      while ( v2 < (signed int)v1->uNumLoadedSprites );
    }
  }
}

//----- (004ACB70) --------------------------------------------------------
void LODFile_Sprites::ReleaseAll()
{
  LODFile_Sprites *v1; // esi@1
  signed int v2; // ebx@2
  int v3; // edi@3
  Sprite *v4; // eax@4
  IDirect3DTexture2 *v5; // eax@5
  Sprite *v6; // eax@7
  IDirectDrawSurface *v7; // eax@8

  v1 = this;
  if ( this->pHardwareSprites )
  {
    v2 = 0;
    if ( (signed int)this->uNumLoadedSprites > 0 )
    {
      v3 = 0;
      do
      {
        v4 = v1->pHardwareSprites;
        if ( v4 )
        {
          v5 = v4[v3].pTexture;
          if ( v5 )
          {
            v5->Release();
            v1->pHardwareSprites[v3].pTexture = 0;
          }
          v6 = v1->pHardwareSprites;
          if ( v6 )
          {
            v7 = (IDirectDrawSurface *)v6[v3].pTextureSurface;
            if ( v7 )
            {
              v7->Release();
              v1->pHardwareSprites[v3].pTextureSurface = 0;
            }
          }
        }
        ++v2;
        ++v3;
      }
      while ( v2 < (signed int)v1->uNumLoadedSprites );
    }
  }
}

//----- (004ACBE0) --------------------------------------------------------
void LODFile_Sprites::MoveSpritesToVideoMemory()
{
  LODFile_Sprites *v1; // esi@1
  int v2; // ebx@1
  signed int v3; // edi@2

  v1 = this;
  v2 = 0;
  if ( this->pHardwareSprites )
  {
    v3 = 0;
    if ( (signed int)this->uNumLoadedSprites > 0 )
    {
      do
      {
        pRenderer->MoveSpriteToDevice(&v1->pHardwareSprites[v2]);
        ++v3;
        ++v2;
      }
      while ( v3 < (signed int)v1->uNumLoadedSprites );
    }
  }
}

//----- (004ACC38) --------------------------------------------------------
int LODSprite::_4ACC38(RenderBillboardTransform_local0 *a2, char a3)
{
  RenderBillboardTransform_local0 *v3; // edi@1
  int result; // eax@1
  int v5; // esi@2
  int v6; // ST18_4@2
  signed int v7; // eax@2
  signed int v8; // ebx@2
  int v9; // ebx@2
  int *v10; // ecx@2
  int v11; // esi@2
  unsigned int v12; // edx@4
  int v13; // esi@13
  int v14; // esi@17
  int v15; // ecx@17
  char *v16; // edx@17
  int v17; // esi@17
  int v18; // ecx@18
  int v19; // esi@18
  LODSprite_stru0 *v20; // edx@21
  int v21; // eax@22
  int v22; // esi@22
  int v23; // eax@25
  int v24; // ecx@25
  signed __int64 v25; // qtt@27
  int v26; // eax@27
  unsigned __int16 *v27; // eax@29
  LODSprite_stru0 *v28; // edx@29
  signed int v29; // ecx@30
  int v30; // ecx@37
  int v31; // ecx@38
  signed int v32; // ecx@41
  int v33; // ecx@47
  int v34; // ecx@56
  int v35; // esi@58
  __int16 v36; // ax@58
  int v37; // ecx@59
  int v38; // eax@59
  int v39; // ecx@62
  signed int v40; // ST30_4@64
  signed __int64 v41; // qtt@64
  int v42; // ecx@64
  unsigned __int16 *v43; // eax@66
  LODSprite_stru0 *v44; // ecx@66
  int v45; // edx@69
  int v46; // edx@77
  unsigned __int16 *pTarget; // [sp+Ch] [bp-50h]@2
  signed int v48; // [sp+10h] [bp-4Ch]@2
  signed int v49; // [sp+14h] [bp-48h]@2
  int v50; // [sp+14h] [bp-48h]@19
  int v51; // [sp+14h] [bp-48h]@57
  int v52; // [sp+18h] [bp-44h]@13
  int v53; // [sp+1Ch] [bp-40h]@2
  int v54; // [sp+1Ch] [bp-40h]@22
  int v55; // [sp+1Ch] [bp-40h]@32
  int v56; // [sp+1Ch] [bp-40h]@69
  int v57; // [sp+20h] [bp-3Ch]@2
  int v58; // [sp+24h] [bp-38h]@1
  int v59; // [sp+28h] [bp-34h]@2
  int v60; // [sp+28h] [bp-34h]@13
  unsigned __int16 *v61; // [sp+2Ch] [bp-30h]@2
  int v62; // [sp+30h] [bp-2Ch]@2
  void *v63; // [sp+30h] [bp-2Ch]@29
  void *v64; // [sp+30h] [bp-2Ch]@66
  int v65; // [sp+34h] [bp-28h]@2
  int v66; // [sp+34h] [bp-28h]@22
  int v67; // [sp+34h] [bp-28h]@59
  int v68; // [sp+38h] [bp-24h]@13
  unsigned int v69; // [sp+3Ch] [bp-20h]@2
  int v70; // [sp+40h] [bp-1Ch]@2
  signed int v71; // [sp+40h] [bp-1Ch]@15
  int v72; // [sp+44h] [bp-18h]@2
  unsigned __int16 *v73; // [sp+44h] [bp-18h]@29
  unsigned __int16 *v74; // [sp+44h] [bp-18h]@66
  int v75; // [sp+48h] [bp-14h]@4
  int v76; // [sp+48h] [bp-14h]@22
  int v77; // [sp+48h] [bp-14h]@59
  LODSprite *v78; // [sp+4Ch] [bp-10h]@1
  int v79; // [sp+50h] [bp-Ch]@4
  int v80; // [sp+50h] [bp-Ch]@21
  int v81; // [sp+50h] [bp-Ch]@62
  int v82; // [sp+50h] [bp-Ch]@67
  int v83; // [sp+50h] [bp-Ch]@75
  int *pTargetZ; // [sp+54h] [bp-8h]@4
  int v85; // [sp+58h] [bp-4h]@18
  int v86; // [sp+58h] [bp-4h]@56
  signed int v87; // [sp+64h] [bp+8h]@2
  int v88; // [sp+68h] [bp+Ch]@18
  int v89; // [sp+68h] [bp+Ch]@56

  v3 = a2;
  v78 = this;
  result = a2->field_10;
  v58 = a2->field_10;
  if ( result <= 0 )
    return result;
  v5 = a2->field_14;
  v6 = a2->field_10;
  v87 = (signed __int64)0x100000000ui64 / result;
  v48 = (signed __int64)0x100000000ui64 / result;
  v62 = (signed __int64)0x100000000ui64 / v5;
  v7 = this->uHeight;
  v8 = (signed int)((signed __int64)0x100000000ui64 / v5) >> 1;
  v53 = v8;
  v70 = (this->uHeight << 16) - v8;
  v49 = v7;
  v69 = v3->uTargetPitch;
  pTarget = v3->pTarget;
  v57 = v3->sZValue;
  v61 = v3->pPalette;
  v9 = (v6 * this->uWidth + 32768) >> 16;
  v72 = v3->uScreenSpaceY;
  result = (v5 * v7 + 32768) >> 16;
  v10 = (int *)(v72 - result + 1);
  v11 = v3->uScreenSpaceX - (v9 >> 1) + 1;
  v65 = v72 - result + 1;
  v59 = v11 + v9 - 1;
  if ( BYTE1(v3->uFlags) & 8 )
  {
    v10 = (int *)((char *)v10 + (v49 >> 1));
    v72 += v49 >> 1;
    v65 = (int)v10;
  }
  v12 = v72;
  pTargetZ = v10;
  v75 = v3->uScreenSpaceX - (v9 >> 1) + 1;
  v79 = v11 + v9 - 1;
  if ( !(v3->uFlags & 8) )
  {
    if ( v65 < (signed int)v3->uViewportY )
      pTargetZ = (int *)v3->uViewportY;
    if ( v72 > (signed int)v3->uViewportW )
      v12 = v3->uViewportW;
    if ( v11 < (signed int)v3->uViewportX )
      v75 = v3->uViewportX;
    if ( v59 > (signed int)v3->uViewportZ )
      v79 = v3->uViewportZ;
  }
  v68 = v75 - v11;
  v13 = -v62;
  v60 = v59 - v79;
  v52 = -v62;
  if ( v3->uFlags & 1 )
  {
    v13 = v62;
    v70 = v53;
    v52 = v62;
  }
  v71 = v13 * (v72 - v12) + v70;
  if ( LOBYTE(viewparams->field_20) )
  {
    if ( a3 )
      return result;
  }
  v14 = 5 * v12;
  v15 = v69 * v12;
  result = v12 - v72 + result - 1;
  v16 = (char *)pTargetZ - v65;
  v17 = v14 << 7;
  if ( v3->uFlags & 4 )
  {
    v34 = v79 + v15;
    v89 = v34;
    v86 = v79 + v17;
    if ( result < (signed int)v16 )
      return result;
    v51 = result - (int)v16 + 1;
    while ( 1 )
    {
      v35 = v71 >> 16;
      v36 = LOWORD(v78->pSpriteLines[v35].dword_0);
      if ( v36 == -1 )
      {
        v34 -= v69;
        v89 = v34;
        goto LABEL_84;
      }
      v37 = v9 - ((unsigned __int64)(v36 * (signed __int64)v58) >> 16);
      v67 = v87 * ((unsigned __int64)(LOWORD(v78->pSpriteLines[v35].dword_0) * (signed __int64)v58) >> 16);
      v38 = v9 - v60;
      v77 = v9 - v60;
      if ( v9 - v60 <= (signed int)(v9
                                  - ((unsigned __int64)(HIWORD(v78->pSpriteLines[v35].dword_0) * (signed __int64)v58) >> 16))
        || v68 >= v37 )
      {
        v89 -= v69;
        v34 = v89;
LABEL_84:
        v86 -= 640;
        goto LABEL_85;
      }
      if ( v38 < v37 )
      {
        v81 = (v87 >> 1) + v87 * (v37 - v38);
      }
      else
      {
        v77 = v37;
        v81 = v87 >> 1;
        v39 = v37 - v9;
        v89 += v39 + v60;
        v86 += v60 + v39;
      }
      v40 = ((HIWORD(v78->pSpriteLines[v35].dword_0) + 1) << 16) - v81 - v67;
      LODWORD(v41) = v40 << 16;
      HIDWORD(v41) = v40 >> 16;
      v42 = v77 - (((signed int)((unsigned __int64)(v41 / v48) - 32768) >> 16) + 1);
      if ( v68 >= v42 )
        v42 = v68;
      v43 = &pTarget[v89];
      v74 = &v43[v42 - v77 + 1];
      v44 = &v78->pSpriteLines[v35];
      v64 = v44->ptr_4;
      if ( !v57 )
      {
        v83 = v67 + v81;
        if ( ((v83 - (LOWORD(v44->dword_0) << 16)) & 0xFFFF0000) < 0 )
        {
          v83 += v87;
          --v43;
          --pTargetZ;
        }
        while ( v43 >= v74 )
        {
          v46 = (v83 - ((signed int)LOWORD(v78->pSpriteLines[v35].dword_0) << 16)) >> 16;
          if ( *((char *)v64 + v46) )
            *v43 = v61[*((char *)v64 + v46)];
          v83 += v87;
          --v43;
        }
        goto LABEL_81;
      }
      pTargetZ = &v3->pTargetZ[v86];
      v82 = v67 + v81;
      if ( ((v82 - (LOWORD(v44->dword_0) << 16)) & 0xFFFF0000) < 0 )
        goto LABEL_72;
LABEL_73:
      if ( v43 >= v74 )
        break;
LABEL_81:
      v89 += v9 - v77 - v60 - v69;
      v34 = v89;
      v86 = v86 + v9 - v77 - v60 - 640;
LABEL_85:
      result = v52;
      v71 += v52;
      --v51;
      if ( !v51 )
        return result;
    }
    v45 = (v82 - ((signed int)LOWORD(v78->pSpriteLines[v35].dword_0) << 16)) >> 16;
    v56 = *((char *)v64 + v45);
    if ( *((char *)v64 + v45) && v57 <= (unsigned int)*pTargetZ )
    {
      *pTargetZ = v57;
      *v43 = v61[v56];
    }
LABEL_72:
    v82 += v87;
    --v43;
    --pTargetZ;
    goto LABEL_73;
  }
  v18 = v75 + v15;
  v19 = v75 + v17;
  v88 = v18;
  v85 = v19;
  if ( result >= (signed int)v16 )
  {
    v50 = result - (int)v16 + 1;
    while ( 1 )
    {
      v20 = &v78->pSpriteLines[v71 >> 16];
      v80 = v71 >> 16;
      if ( LOWORD(v20->dword_0) != -1 )
        break;
      v18 -= v69;
      v85 = v19 - 640;
      v88 = v18;
LABEL_54:
      result = v52;
      v71 += v52;
      --v50;
      if ( !v50 )
        return result;
      v19 = v85;
    }
    v21 = (v58 * LOWORD(v20->dword_0) + 32768) >> 16;
    v66 = v21 * v87;
    v76 = v68;
    v54 = HIWORD(v20->dword_0);
    v22 = v9 - v60;
    if ( v68 >= (v58 * v54 + 32768) >> 16 || v22 <= v21 )
    {
      v88 -= v69;
      v85 -= 640;
      goto LABEL_51;
    }
    if ( v68 > v21 )
    {
      v24 = (v87 >> 1) + v87 * (v68 - v21);
    }
    else
    {
      v76 = (v58 * LOWORD(v20->dword_0) + 32768) >> 16;
      v23 = v21 - v68;
      v88 += v23;
      v24 = v87 >> 1;
      v85 += v23;
    }
    LODWORD(v25) = (((v54 + 1) << 16) - v24 - v66) << 16;
    HIDWORD(v25) = (((v54 + 1) << 16) - v24 - v66) >> 16;
    v26 = v76 + ((signed int)(v25 / v48) >> 16) + 1;
    if ( v22 > v26 )
      v22 = v26;
    v27 = &pTarget[v88];
    v73 = &v27[v22 - v76 - 1];
    v28 = &v78->pSpriteLines[v80];
    v63 = v28->ptr_4;
    if ( v57 )
    {
      pTargetZ = &v3->pTargetZ[v85];
      v29 = v66 - (LOWORD(v28->dword_0) << 16) + v24;
      if ( (v29 & 0xFFFF0000) >= 0 )
        goto LABEL_36;
      while ( 1 )
      {
        v29 += v87;
        ++v27;
        ++pTargetZ;
LABEL_36:
        if ( v27 >= v73 )
          break;
        v55 = *((char *)v63 + (v29 >> 16));
        if ( *((char *)v63 + (v29 >> 16)) && v57 <= (unsigned int)*pTargetZ )
        {
          *pTargetZ = v57;
          *v27 = v61[v55];
        }
      }
      v30 = v29 >> 16;
      if ( v30 > HIWORD(v78->pSpriteLines[v80].dword_0) - (signed int)LOWORD(v78->pSpriteLines[v80].dword_0)
        || (v31 = *((char *)v63 + v30)) == 0
        || v57 > (unsigned int)*pTargetZ )
        goto LABEL_50;
      *pTargetZ = v57;
    }
    else
    {
      v32 = v66 - (LOWORD(v28->dword_0) << 16) + v24;
      if ( (v32 & 0xFFFF0000) < 0 )
      {
        v32 += v87;
        ++v27;
        ++pTargetZ;
      }
      while ( v27 < v73 )
      {
        if ( *((char *)v63 + (v32 >> 16)) )
          *v27 = v61[*((char *)v63 + (v32 >> 16))];
        v32 += v87;
        ++v27;
      }
      v33 = v32 >> 16;
      if ( v33 > HIWORD(v78->pSpriteLines[v80].dword_0) - (signed int)LOWORD(v78->pSpriteLines[v80].dword_0)
        || (v31 = *((char *)v63 + v33)) == 0 )
        goto LABEL_50;
    }
    *v27 = v61[v31];
LABEL_50:
    v88 += v68 - v76 - v69;
    v85 = v85 + v68 - v76 - 640;
LABEL_51:
    v18 = v88;
    goto LABEL_54;
  }
  return result;
}

//----- (004AD2D1) --------------------------------------------------------
int LODSprite::_4AD2D1(struct RenderBillboardTransform_local0 *a2, int a3)
{
  int result; // eax@1
  unsigned int v4; // esi@1
  int v5; // edi@1
  LODSprite_stru0 *v6; // edx@2
  __int16 v7; // bx@2
  int v8; // ecx@3
  unsigned __int16 *v9; // esi@3
  int v10; // ebx@3
  void *v11; // edx@3
  unsigned __int16 *v12; // ecx@3
  int v13; // ebx@4
  LODSprite *v14; // [sp+8h] [bp-10h]@1
  unsigned __int16 *v15; // [sp+10h] [bp-8h]@1
  unsigned __int16 *v16; // [sp+14h] [bp-4h]@1
  int i; // [sp+20h] [bp+8h]@1

  result = (int)a2;
  v14 = this;
  v4 = a2->uTargetPitch;
  v16 = a2->pTarget;
  v15 = a2->pPalette;
  v5 = this->uHeight - 1;
  for ( i = v4 * a2->uScreenSpaceY - (this->uWidth >> 1) + a2->uScreenSpaceX + 1; v5 >= 0; --v5 )
  {
    v6 = &this->pSpriteLines[v5];
    v7 = LOWORD(v6->dword_0);
    if ( LOWORD(v6->dword_0) != -1 )
    {
      v8 = v7;
      v9 = &v16[v7 + i];
      v10 = HIWORD(v6->dword_0);
      v11 = v6->ptr_4;
      v12 = &v9[v10 - v8];
      while ( v9 <= v12 )
      {
        v13 = *(char *)v11;
        v11 = (char *)v11 + 1;
        if ( v13 )
          *v9 = v15[v13];
        ++v9;
      }
      v4 = *(int *)(result + 48);
      //this = v14;
    }
    i -= v4;
  }
  return result;
}

//----- (0046454B) --------------------------------------------------------
void LODFile_IconsBitmaps::ReleaseAll2()
{
  LODFile_IconsBitmaps *v1; // esi@1
  int v2; // edi@1
  Texture *v3; // ebx@2
  struct IDirect3DTexture2 **v4; // eax@3
  struct IDirect3DTexture2 *v5; // eax@4
  struct IDirectDrawSurface **v6; // eax@6
  struct IDirectDrawSurface *v7; // eax@7
  int v8; // eax@10

  v1 = this;
  v2 = this->uNumLoadedFiles - 1;
  if ( v2 >= this->dword_11B84 )
  {
    v3 = &this->pTextures[v2];
    do
    {
      v3->Release();
      v4 = v1->pHardwareTextures;
      if ( v4 )
      {
        v5 = v4[v2];
        if ( v5 )
        {
          v5->Release();
          v1->pHardwareTextures[v2] = 0;
        }
      }
      v6 = v1->pHardwareSurfaces;
      if ( v6 )
      {
        v7 = v6[v2];
        if ( v7 )
        {
          v7->Release();
          v1->pHardwareSurfaces[v2] = 0;
        }
      }
      --v2;
      --v3;
    }
    while ( v2 >= v1->dword_11B84 );
  }
  v8 = v1->dword_11B84;
  v1->uTexturePacksCount = 0;
  v1->uNumPrevLoadedFiles = 0;
  v1->uNumLoadedFiles = v8;
}

//----- (004645DC) --------------------------------------------------------
void LODFile_Sprites::DeleteSomeOtherSprites()
{
  int *v1; // esi@1
  int *v2; // edi@1

  v1 = (int *)&this->uNumLoadedSprites;
  v2 = &this->field_ECA0;
  DeleteSpritesRange(field_ECA0, uNumLoadedSprites);
  *v1 = *v2;
}


//----- (00461431) --------------------------------------------------------
void LOD::File::Close()
{
  LOD::File *v1; // esi@1
  LOD::Directory **v2; // edi@2
  FILE *v3; // ST00_4@2

  v1 = this;
  if ( this->isFileOpened )
  {
    this->pContainerName[0] = 0;
    this->uCurrentIndexDir = 0;
    v2 = &this->pSubIndices;
    pAllocator->FreeChunk(this->pSubIndices);
    pAllocator->FreeChunk(v1->pRoot);
    v3 = v1->pFile;
    *v2 = 0;
    v1->pRoot = 0;
    fclose(v3);
    v1->isFileOpened = 0;
    _6A0CA8_lod_unused = 0;
  }
}



//----- (00461492) --------------------------------------------------------
int LODWriteableFile::_461492(LOD::FileHeader *pHeader, LOD::Directory *pDir, const char *Source)
{
  if (isFileOpened)
    return 1;
  if ( !pDir->pFilename[0] )
    return 2;
  strcpy(pHeader->pSignature, "LOD");
  pHeader->dword_0000A4 = 100;
  pHeader->uNumIndices = 1;
  pDir->pFilename[15] = 0;
  pDir->uDataSize = 0;
  pDir->uOfsetFromSubindicesStart = 288;
  strcpy(pLODName, Source);

  pFile = fopen(pLODName, "wb+");
  if (!pFile)
    return 3;

  fwrite(pHeader, 0x100, 1, pFile);
  fwrite(pDir, 0x20, 1, pFile);
  fclose(pFile);
  pFile = 0;
  return 0;
}

//----- (0046153F) --------------------------------------------------------
void LOD::File::ResetSubIndices()
{
  LOD::Directory **pSubIndices_dup2; // esi@2
  LOD::Directory *pSubIndices_dup; // ST00_4@2

  if ( this->isFileOpened )
  {
    pSubIndices_dup2 = &this->pSubIndices;
    this->pContainerName[0] = 0;
    this->uCurrentIndexDir = 0;
    pSubIndices_dup = this->pSubIndices;
    this->uOffsetToSubIndex = 0;
    this->uNumSubIndices = 0;
    this->uLODDataSize = 0;
    pAllocator->FreeChunk(pSubIndices_dup);
    *pSubIndices_dup2 = 0;
  }
}







//----- (00450C8B) --------------------------------------------------------
void LODFile_Sprites::DeleteSomeSprites()
{
  int *v1; // esi@1
  int *v2; // edi@1

  v1 = (int *)&this->uNumLoadedSprites;
  v2 = &this->field_ECA8;
  DeleteSpritesRange(this->field_ECA8, this->uNumLoadedSprites);
  *v1 = *v2;
}

//----- (00450CA9) --------------------------------------------------------
void LODFile_Sprites::DeleteSpritesRange(int uStartIndex, int uStopIndex)
{
  LODFile_Sprites *v3; // edi@1
  int v4; // esi@3
  LODSprite *v5; // ebx@3
  LODSprite *v6; // esi@7
  int v7; // edi@7
  int a2a; // [sp+10h] [bp+8h]@3

  v3 = this;
  if ( this->pHardwareSprites )
  {
    if ( uStartIndex < uStopIndex )
    {
      v4 = uStartIndex;
      v5 = &this->pSpriteHeaders[uStartIndex];
      a2a = uStopIndex - uStartIndex;
      do
      {
        v5->Release();
        pHardwareSprites[v4].Release();
        ++v4;
        ++v5;
        --a2a;
      }
      while ( a2a );
    }
  }
  else
  {
    if ( uStartIndex < uStopIndex )
    {
      v6 = &this->pSpriteHeaders[uStartIndex];
      v7 = uStopIndex - uStartIndex;
      do
      {
        v6->Release();
        ++v6;
        --v7;
      }
      while ( v7 );
    }
  }
}

//----- (00450D1D) --------------------------------------------------------
void LODSprite::Release()
{
  LODSprite *v1; // esi@1

  v1 = this;
  if ( !(HIBYTE(this->word_1A) & 4) )
  {
    pAllocator->FreeChunk(this->pDecompressedBytes);
    pAllocator->FreeChunk(v1->pSpriteLines);
  }
  v1->word_1A = 0;
  v1->pDecompressedBytes = 0;
  v1->pSpriteLines = 0;
  v1->pName[0] = 0;
  v1->word_16 = 0;
  v1->uPaletteId = 0;
  v1->uTexturePitch = 0;
  v1->uHeight = 0;
  v1->uWidth = 0;
  v1->uSpriteSize = 0;
}

//----- (00450D68) --------------------------------------------------------
void Sprite::Release()
{
  if (pName)
    pAllocator->FreeChunk((void *)pName);
  pName = nullptr;

  if (pTextureSurface)
    pTextureSurface->Release();
  pTextureSurface = nullptr;

  if (pTexture)
    pTexture->Release();
  pTexture = nullptr;
}




//----- (0040FA2E) --------------------------------------------------------
bool LODFile_IconsBitmaps::LoadBitmaps(const char *pFilename)
{
  ReleaseAll();
  if (LoadHeader(pFilename, 1))
    return false;
  else
    return LoadSubIndices("bitmaps") == 0;
}


//----- (0040FAEE) --------------------------------------------------------
bool LODFile_IconsBitmaps::LoadIconsOrEvents(const char *pLODFilename)
{
  ReleaseAll();

  if (LoadHeader(pLODFilename, 1))
    return false;
  else
    return LoadSubIndices("icons") == 0;
}


//----- (0040FA60) --------------------------------------------------------
void LODFile_IconsBitmaps::ReleaseAll()
{
  LODFile_IconsBitmaps *v1; // esi@1
  unsigned int v2; // edi@1
  Texture *v3; // ebp@2
  struct IDirect3DTexture2 **v4; // eax@3
  struct IDirect3DTexture2 *v5; // eax@4
  struct IDirectDrawSurface **v6; // eax@6
  struct IDirectDrawSurface *v7; // eax@7

  v1 = this;
  v2 = this->uNumLoadedFiles - 1;
  if ( (v2 & 0x80000000u) == 0 )
  {
    v3 = &this->pTextures[v2];
    do
    {
      v3->Release();
      v4 = v1->pHardwareTextures;
      if ( v4 )
      {
        v5 = v4[v2];
        if ( v5 )
        {
          v5->Release();
          v1->pHardwareTextures[v2] = 0;
        }
      }
      v6 = v1->pHardwareSurfaces;
      if ( v6 )
      {
        v7 = v6[v2];
        if ( v7 )
        {
          v7->Release();
          v1->pHardwareSurfaces[v2] = 0;
        }
      }
      --v2;
      --v3;
    }
    while ( (v2 & 0x80000000u) == 0 );
  }
  v1->uTexturePacksCount = 0;
  v1->uNumPrevLoadedFiles = 0;
  v1->dword_11B84 = 0;
  v1->dword_11B80 = 0;
  v1->uNumLoadedFiles = 0;
}

//----- (0040F9F0) --------------------------------------------------------
unsigned int LODFile_IconsBitmaps::FindTextureByName(const char *pName)
{
  LODFile_IconsBitmaps *v2; // esi@1
  unsigned int v3; // edi@1
  Texture *v4; // ebx@2
  unsigned int result; // eax@5

  v2 = this;
  v3 = 0;
  if ( (signed int)this->uNumLoadedFiles <= 0 )
  {
LABEL_5:
    result = -1;
  }
  else
  {
    v4 = this->pTextures;
    while ( _strcmpi(v4->pName, pName) )
    {
      ++v3;
      ++v4;
      if ( (signed int)v3 >= (signed int)v2->uNumLoadedFiles )
        goto LABEL_5;
    }
    result = v3;
  }
  return result;
}

//----- (0040F9C5) --------------------------------------------------------
int LODFile_IconsBitmaps::_40F9C5()
{
  signed int result; // eax@1
  Texture *pTex; // edx@1

  result = this->uNumLoadedFiles;
  for ( pTex = &this->pTextures[result]; !pTex->pName[0]; --pTex )
    --result;
  if ( result < (signed int)this->uNumLoadedFiles )
  {
    ++result;
    this->uNumLoadedFiles = result;
  }
  return result;
}



//----- (0046249B) --------------------------------------------------------
LODFile_Sprites::~LODFile_Sprites()
{
  LODFile_Sprites *v1; // esi@1
  signed int v2; // ebx@1
  LODSprite *v3; // edi@3
  char *v4; // edi@6
  int thisa; // [sp+4h] [bp-10h]@3
  LODSprite *thisb; // [sp+4h] [bp-10h]@7

  v1 = this;
  v2 = 0;
  if ( this->pHardwareSprites )
  {
    if ( (signed int)this->uNumLoadedSprites > 0 )
    {
      thisa = 0;
      v3 = this->pSpriteHeaders;
      do
      {
        v3->Release();
        v1->pHardwareSprites[thisa].Release();
        ++thisa;
        ++v2;
        ++v3;
      }
      while ( v2 < (signed int)v1->uNumLoadedSprites );
    }
  }
  else
  {
    v4 = (char *)&this->uNumLoadedSprites;
    if ( (signed int)this->uNumLoadedSprites > 0 )
    {
      thisb = this->pSpriteHeaders;
      do
      {
        thisb->Release();
        ++thisb;
        ++v2;
      }
      while ( v2 < *(int *)v4 );
    }
  }
  //_eh_vector_destructor_iterator_(v1->pSpriteHeaders, 40, 1500, LODSprite::dtor);
  //LOD::File::vdtor((LOD::File *)v1);
}
// 4CC2B4: using guessed type int __stdcall _eh vector destructor iterator_(int, int, int, int);


//----- (00462463) --------------------------------------------------------
LODSprite::~LODSprite()
{
  LODSprite *v1; // esi@1

  v1 = this;
  if ( !(HIBYTE(this->word_1A) & 4) )
  {
    pAllocator->FreeChunk(this->pDecompressedBytes);
    pAllocator->FreeChunk(v1->pSpriteLines);
  }
  v1->pDecompressedBytes = 0;
  v1->pSpriteLines = 0;
}

//----- (004623E5) --------------------------------------------------------
LODFile_Sprites::LODFile_Sprites():
  LOD::File()
{
  /*_eh_vector_constructor_iterator_(
    v1->pSpriteHeaders,
    40,
    1500,
    (void (__thiscall *)(void *))LODSprite::LODSprite,
    (void (__thiscall *)(void *))LODSprite::dtor);*/
  field_ECA4 = 0;
  field_ECA0 = 0;
  pHardwareSprites = 0;
  field_ECAC = 0;
  field_ECB4 = 0;
  uNumLoadedSprites = 0;
}

//----- (00462303) --------------------------------------------------------
LODFile_IconsBitmaps::~LODFile_IconsBitmaps()
{
  LODFile_IconsBitmaps *v1; // esi@1
  unsigned int v2; // edi@1
  struct IDirect3DTexture2 **v3; // eax@3
  struct IDirect3DTexture2 *v4; // eax@4
  struct IDirectDrawSurface **v5; // eax@6
  struct IDirectDrawSurface *v6; // eax@7
  Texture *thisa; // [sp+4h] [bp-10h]@2

  v1 = this;
  v2 = this->uNumLoadedFiles - 1;
  if ( (v2 & 0x80000000u) == 0 )
  {
    thisa = &this->pTextures[v2];
    do
    {
      thisa->Release();
      v3 = v1->pHardwareTextures;
      if ( v3 )
      {
        v4 = v3[v2];
        if ( v4 )
        {
          v4->Release();
          v1->pHardwareTextures[v2] = 0;
        }
      }
      v5 = v1->pHardwareSurfaces;
      if ( v5 )
      {
        v6 = v5[v2];
        if ( v6 )
        {
          v6->Release();
          v1->pHardwareSurfaces[v2] = 0;
        }
      }
      --thisa;
      --v2;
    }
    while ( (v2 & 0x80000000u) == 0 );
  }
  if ( v1->pHardwareSurfaces )
    free(v1->pHardwareSurfaces);
  if ( v1->pHardwareTextures )
    free(v1->pHardwareTextures);
  if ( v1->ptr_011BB4 )
    free(v1->ptr_011BB4);
  //LOD::File::vdtor((LOD::File *)v1);
}

//----- (00462272) --------------------------------------------------------
LODFile_IconsBitmaps::LODFile_IconsBitmaps():
  LOD::File()
{
  LODFile_IconsBitmaps *v1; // esi@1
  Texture *v2; // ebx@1
  signed int v3; // [sp+4h] [bp-10h]@1

  v1 = this;
  /*v2 = v1->pTextures;
  v3 = 1000;
  do
  {
    Texture::Texture(v2);
    ++v2;
    --v3;
  }
  while ( v3 );*/
  v1->uTexturePacksCount = 0;
  v1->uNumPrevLoadedFiles = 0;
  v1->dword_11B84 = 0;
  v1->dword_11B80 = 0;
  v1->uNumLoadedFiles = 0;
  v1->dword_011BA4 = 0;
  v1->dword_011BA8 = 0;
  v1->pHardwareSurfaces = 0;
  v1->pHardwareTextures = 0;
  v1->ptr_011BB4 = 0;
}


//----- (004621A7) --------------------------------------------------------
bool LODWriteableFile::_4621A7()
{
  CloseWriteFile();
  return LoadFile(pLODName, 0);
}


//----- (00461FD4) --------------------------------------------------------
int LODWriteableFile::Save()
{
  LODWriteableFile *v1; // esi@1
  int v2; // edi@1
  unsigned int v3; // edx@1
  LOD::Directory *v4; // eax@2
  unsigned int v5; // ecx@2
  int v6; // eax@2
  signed int v7; // ebx@5
  int v8; // ecx@5
  LOD::Directory **v9; // edi@6
  int v10; // edx@6
  LOD::Directory *v11; // eax@6
  FILE *v12; // eax@9
  FILE *v13; // ebx@9
  signed int result; // eax@10
  unsigned int v15; // eax@11
  FILE *v16; // ST00_4@11
  size_t v17; // edi@12
  char OldFilename[256]; // [sp+Ch] [bp-228h]@9
  char NewFilename[256]; // [sp+10Ch] [bp-128h]@15
  //LOD::Directory v0; // [sp+20Ch] [bp-28h]@11
  unsigned int v21; // [sp+22Ch] [bp-8h]@5
  int v22; // [sp+230h] [bp-4h]@1

  v1 = this;
  v2 = 0;
  v3 = this->uNumSubIndices;
  v22 = 0;
  if ( (signed int)v3 > 0 )
  {
    v4 = this->pSubIndices;
    v5 = v3;
    v6 = (int)&v4->uDataSize;
    do
    {
      v2 += *(int *)v6;
      v6 += 32;
      --v5;
    }
    while ( v5 );
    v22 = v2;
  }
  v7 = 0;
  v21 = 32 * v3 + v2;
  v8 = 32 * v3;
  if ( (signed int)v3 > 0 )
  {
    v9 = &v1->pSubIndices;
    v10 = 0;
    v11 = v1->pSubIndices;
    do
    {
      v11[v10].uOfsetFromSubindicesStart = v8;
      v11 = *v9;
      v8 += (*v9)[v10].uDataSize;
      ++v7;
      ++v10;
    }
    while ( v7 < (signed int)v1->uNumSubIndices );
    v2 = v22;
  }
  strcpy(OldFilename, "lod.tmp");
  v12 = fopen(OldFilename, "wb+");
  v13 = v12;
  if ( v12 )
  {
    fwrite(&v1->header, 0x100, 1, v12);

    LOD::Directory v0; // [sp+20Ch] [bp-28h]@11
    //LOD::Directory::LOD::Directory(&v0);

    strcpy((char *)&v0, "chapter");
    v15 = v1->uOffsetToSubIndex;
    v0.dword_000018 = 0;
    v0.uOfsetFromSubindicesStart = v15;
    v0.word_00001E = 0;
    v0.uDataSize = v21;
    v0.uNumSubIndices = LOWORD(v1->uNumSubIndices);
    fwrite(&v0, 0x20, 1, v13);
    fwrite(v1->pSubIndices, 0x20, v1->uNumSubIndices, v13);
    v16 = v1->pOutputFileHandle;
    v22 = v2;
    fseek(v16, 0, 0);
    if ( v2 > 0 )
    {
      do
      {
        v17 = v1->uIOBufferSize;
        if ( v22 <= (signed int)v17 )
          v17 = v22;
        fread(v1->pIOBuffer, 1, v17, v1->pOutputFileHandle);
        fwrite(v1->pIOBuffer, 1, v17, v13);
        v22 -= v17;
      }
      while ( v22 > 0 );
    }
    strcpy(NewFilename, (const char *)v1->pLODName);
    fclose(v13);
    fclose(v1->pOutputFileHandle);
    v1->CloseWriteFile();
    remove("lodapp.tmp");
    remove(NewFilename);
    rename(OldFilename, NewFilename);
    v1->CloseWriteFile();
    v1->LoadFile(v1->pLODName, 0);
    result = 0;
  }
  else
  {
    result = 5;
  }
  return result;
}


//----- (00461F71) --------------------------------------------------------
bool LOD::File::AppendDirectory(LOD::Directory *pDir, const void *pData)
{
  unsigned int v3; // edi@1
  bool result; // eax@2
  FILE *v5; // ST0C_4@3

  v3 = this->uNumSubIndices;
  if ( (signed int)v3 < 299 )
  {
    memcpy(&this->pSubIndices[v3], pDir, sizeof(this->pSubIndices[v3]));
    v5 = this->pOutputFileHandle;
    ++this->uNumSubIndices;
    fwrite(pData, 1u, pDir->uDataSize, v5);
    result = 1;
  }
  else
  {
    MessageBoxA(0, "Unable to append item!", "LOD::File", 0x30u);
    result = 0;
  }
  return result;
}


//----- (00461F1E) --------------------------------------------------------
int LODWriteableFile::CreateTempFile()
{
  LODWriteableFile *v1; // esi@1
  int result; // eax@2
  FILE *pFile; // eax@5
  int v4; // eax@5

  v1 = this;
  if ( this->isFileOpened )
  {
    if ( this->pIOBuffer && this->uIOBufferSize )
    {
      this->uCurrentIndexDir = 0;
      this->uNumSubIndices = 0;
      pFile = fopen("lodapp.tmp", "wb+");
      v1->pOutputFileHandle = pFile;
      v4 = -(pFile != 0);
      LOBYTE(v4) = v4 & 0xF9;
      result = v4 + 7;
    }
    else
    {
      result = 5;
    }
  }
  else
  {
    result = 1;
  }
  return result;
}



//----- (00461EE9) --------------------------------------------------------
void LODWriteableFile::CloseWriteFile()
{
  if (isFileOpened)
  {
    pContainerName[0] = 0;
    uCurrentIndexDir = 0;
    _6A0CA8_lod_unused = 0;
    
    isFileOpened = false;
    fflush(pFile);
    fclose(pFile);
    pFile = 0;
  }
}
// 6A0CA8: using guessed type int 6A0CA8_lod_unused;


//----- (00461B48) --------------------------------------------------------
unsigned int LODWriteableFile::Write(const LOD::Directory *pDir, const void *pDirData, int a4)
{
  //LODWriteableFile *v4; // ebx@1
  int v5; // esi@1
  //unsigned __int8 v7; // zf@7
  //unsigned __int8 v8; // sf@7
  const LOD::Directory *v9; // edi@9
  int v10; // eax@9
  //unsigned __int8 v11; // of@15
  unsigned __int16 v12; // dx@17
  LOD::Directory *v13; // eax@17
  unsigned __int16 v14; // cx@17
  int v15; // edi@27
  unsigned int v16; // eax@27
  int v17; // eax@29
  int v18; // edx@31
  int v19; // eax@31
  void *v20; // edi@32
  LOD::Directory *v21; // edi@34
  signed int v22; // esi@34
  int v23; // eax@34
  LOD::Directory *v24; // ecx@35
  int v25; // edx@35
  __int32 v26; // eax@37
  int i; // esi@39
  __int32 v28; // esi@46
  char pFilename[256]; // [sp+Ch] [bp-230h]@22
  char NewFilename[256]; // [sp+10Ch] [bp-130h]@51
  //LOD::Directory Str; // [sp+20Ch] [bp-30h]@27
  size_t v33; // [sp+22Ch] [bp-10h]@27
  //int v34; // [sp+230h] [bp-Ch]@7
  __int32 v35; // [sp+234h] [bp-8h]@8
  int v36; // [sp+238h] [bp-4h]@7
  size_t Count; // [sp+244h] [bp+8h]@40
  __int32 Countc; // [sp+244h] [bp+8h]@46
  size_t Countb; // [sp+244h] [bp+8h]@47
  FILE *pFile; // [sp+24Ch] [bp+10h]@22

  //v4 = this;
  //v5 = 0;

  if (!isFileOpened)
    return 1;
  if (!pSubIndices)
    return 2;
  if (!pIOBuffer || !uIOBufferSize)
    return 3;

  //v7 = this->uNumSubIndices == 0;
  //v8 = (this->uNumSubIndices & 0x80000000u) != 0;
  v35 = 0;
  v36 = 0;
  //v34 = 0;
  for (v5 = 0; v5 < uNumSubIndices; ++v5)
  /*if ( v8 | v7 )
  {
    v9 = pDir;
    goto LABEL_22;
  }
  while ( 1 )*/
  {
    v9 = pDir;
    v10 = _strcmpi(pSubIndices[v5].pFilename, pDir->pFilename);
    if (v10 > 0)
      break;
    else if (v10 < 0)
      continue;
    /*if ( v10 )
    {
      if ( v10 > 0 )
        goto LABEL_22;
      goto LABEL_15;
    }*/
    if ( !a4 )
    {
      v36 = 1;
      break;
    }
    if ( a4 == 1 )
    {
      v12 = pDir->uNumSubIndices;
      v13 = &pSubIndices[v5];
      v14 = v13->uNumSubIndices;
      if ( v14 >= v12 && (v14 != v12 || (unsigned __int16)v13->word_00001E >= pDir->word_00001E) )
        return 4;
      v36 = 1;
      break;
    }
    if ( a4 == 2 )
      return 4;
//LABEL_15:
    //v35 += 32;
    //++v5;
    //v11 = __OFSUB__(v5, v4->uNumSubIndices);
    //v8 = ((v5 - v4->uNumSubIndices) & 0x80000000u) != 0;
    //v34 = v5;
    //if ( !(v8 ^ v11) )
      //goto LABEL_22;
  }
/*  v12 = pDir->uNumSubIndices;
  v13 = &v4->pSubIndices[v5];
  v14 = v13->uNumSubIndices;
  if ( v14 >= v12 && (v14 != v12 || (unsigned __int16)v13->word_00001E >= pDir->word_00001E) )
    return 4;
LABEL_20:
  v36 = 1;
LABEL_22:*/
  strcpy(pFilename, "lod.tmp");
  pFile = fopen(pFilename, "wb+");
  if ( !pFile )
    return 5;
  if ( v36 )
    v35 = pSubIndices[v5].uDataSize;
  else
    v35 = 0;
  v33 = v9->uDataSize;
  v15 = v33 - v35;

  LOD::Directory Str; // [sp+20Ch] [bp-30h]@27
  //LOD::Directory::LOD::Directory(&Str);

  strcpy(Str.pFilename, "chapter");
  v16 = uLODDataSize;
  Str.uNumSubIndices = uNumSubIndices;
  Str.dword_000018 = 0;
  Str.word_00001E = 0;
  if ( !v36 )
  {
    ++Str.uNumSubIndices;
    v15 += 32;
  }
  //v7 = v36 == 0;
  Str.uDataSize = v15 + v16;
  Str.uOfsetFromSubindicesStart = 288;
  v17 = (signed __int16)Str.uNumSubIndices;
  uNumSubIndices = (signed __int16)Str.uNumSubIndices;
  if ( !v36 && v17 > v5 )
  {
    v18 = v17;
    v19 = v17 - v5;
    do
    {
      v20 = &pSubIndices[v18];
      --v18;
      --v19;
      memcpy(v20, (char *)v20 - 32, 0x20u);
    }
    while ( v19 );
    //v5 = v34;
  }
  //v34 = 32 * v5;
  memcpy(&pSubIndices[v5], pDir, sizeof(LOD::Directory));
  v23 = 32 * uNumSubIndices;
  if ( (signed int)uNumSubIndices > 0 )
  {
    for (int i =  0; i < (signed int)uNumSubIndices; ++i)
    {
      pSubIndices[i].uOfsetFromSubindicesStart = v23;
      v23 += pSubIndices[i].uDataSize;
    }
  }
  fwrite(&header, 0x100, 1, pFile);
  fwrite(&Str, 0x20, 1, pFile);
  fseek(pFile, Str.uOfsetFromSubindicesStart, 0);
  fwrite(pSubIndices, 0x20u, uNumSubIndices, pFile);
  v26 = 32 * uNumSubIndices;
  if ( !v36 )
    v26 -= 32;
  fseek(pFile, v26, 1);
  for ( i = pSubIndices[v5].uOfsetFromSubindicesStart
          - pSubIndices->uOfsetFromSubindicesStart; i > 0; i -= Count )
  {
    Count = uIOBufferSize;
    if ( i <= (signed int)uIOBufferSize )
      Count = i;
    fread(pIOBuffer, 1u, Count, pFile);
    fwrite(pIOBuffer, 1u, Count, pFile);
  }
  fwrite(pDirData, 1u, v33, pFile);
  if ( v36 )
    fseek(pFile, v35, 1);
  Countc = ftell(pFile);
  fseek(pFile, 0, 2);
  v28 = ftell(pFile) - Countc;
  fseek(pFile, Countc, 0);
  while ( v28 > 0 )
  {
    Countb = uIOBufferSize;
    if ( v28 <= (signed int)uIOBufferSize )
      Countb = v28;
    fread(pIOBuffer, 1u, Countb, pFile);
    fwrite(pIOBuffer, 1u, Countb, pFile);
    v28 -= Countb;
  }
  strcpy(NewFilename, (const char *)pLODName);
  fclose(pFile);
  CloseWriteFile();
  remove(NewFilename);
  rename(pFilename, NewFilename);
  CloseWriteFile();
  LoadFile(pLODName, 0);
  return 0;
}


//----- (00461A43) --------------------------------------------------------
bool LODWriteableFile::LoadFile(const char *pFilename, bool bWriting)
{
  LODWriteableFile *v3; // esi@1
  FILE *pFile_dup; // eax@4
  unsigned int v5; // ecx@5
  __int32 v6; // eax@5
  FILE *v7; // ST00_4@5
  size_t v8; // edi@5
  const char *v10; // [sp-4h] [bp-30h]@2

  v3 = this;
  if ( bWriting & 1 )
    v10 = "rb";
  else
    v10 = "rb+";
  pFile_dup = fopen(pFilename, v10);
  v3->pFile = pFile_dup;
  if ( !pFile_dup )
  {
    isFileOpened = false;
    return 0;
  }
  strcpy(pLODName, pFilename);
  fread(&header, 0x100u, 1u, v3->pFile);
  
  LOD::Directory dir; // [sp+Ch] [bp-20h]@5
  //LOD::Directory::LOD::Directory(&dir);

  fread(&dir, 0x20u, 1u, v3->pFile);
  fseek(v3->pFile, 0, 0);
  isFileOpened = 1;
  strcpy((char *)v3->pContainerName, "chapter");
  v5 = (signed __int16)dir.uNumSubIndices;
  v6 = dir.uOfsetFromSubindicesStart;
  v3->uCurrentIndexDir = 0;
  v3->uOffsetToSubIndex = v6;
  v7 = v3->pFile;
  v3->uNumSubIndices = v5;
  v3->uLODDataSize = dir.uDataSize;
  fseek(v7, v6, SEEK_SET);
  v8 = v3->uNumSubIndices;
  if ( (signed int)v8 > 300 )
  {
    MessageBoxA(0, "LODchapterPages exceed 300", "LOD::File", MB_ICONEXCLAMATION);
    fclose(v3->pFile);
    return 0;
  }
  fread(pSubIndices, 0x20u, v8, v3->pFile);
  return 1;
}


//----- (00461A11) --------------------------------------------------------
void LOD::File::FreeSubIndexAndIO()
{
  void *v1; // edi@1
  LOD::Directory **v2; // esi@1

  v1 = this;
  v2 = &this->pSubIndices;
  pAllocator->FreeChunk(this->pSubIndices);
  v1 = (char *)v1 + 264;
  pAllocator->FreeChunk(pIOBuffer);// delete [] pIOBuffer;
  pIOBuffer = nullptr;
  pSubIndices = nullptr;
}


//----- (00461954) --------------------------------------------------------
void LOD::File::AllocSubIndicesAndIO(unsigned int uNumSubIndices, unsigned int uBufferSize)
{
  //LOD::File *v3; // esi@1
  LOD::Directory *pSubIndices_dup; // eax@3
  char v5; // zf@3

  //v3 = this;
  if (pSubIndices)
  {
    MessageBoxA(0, "Attempt to reset a LOD subindex!", "MM6", MB_ICONEXCLAMATION);
    pAllocator->FreeChunk(pSubIndices);
    pSubIndices = nullptr;
  }
  pSubIndices_dup = (LOD::Directory *)pAllocator->AllocNamedChunk(
                                      pSubIndices,
                                      32 * uNumSubIndices,
                                      "LODsub");
  v5 = pIOBuffer == 0;
  pSubIndices = pSubIndices_dup;
  if ( !v5 )
  {
    MessageBoxA(0, "Attempt to reset a LOD IObuffer!", "MM6", MB_ICONEXCLAMATION);
    pAllocator->FreeChunk(pIOBuffer);
    pIOBuffer = 0;
    uIOBufferSize = 0;
  }
  if ( uBufferSize )
  {
    pIOBuffer = (unsigned __int8 *)pAllocator->AllocNamedChunk(pIOBuffer, uBufferSize, "LODio");
    uIOBufferSize = uBufferSize;
  }
}



//----- (0046188A) --------------------------------------------------------
int LOD::File::LoadSubIndices(const char *pContainer)
{
  LOD::File *v2; // esi@1
  unsigned int uDir; // edi@1
  int uDir_dup; // ebx@2
  int result; // eax@5
  LOD::Directory *v6; // eax@7
  LOD::Directory *v7; // eax@7
  __int32 v8; // edx@7
  FILE *v9; // ST00_4@7
  LOD::Directory *pSubIndices_dup; // eax@7

  v2 = this;
  ResetSubIndices();
  uDir = 0;
  if ( (signed int)v2->header.uNumIndices <= 0 )
  {
LABEL_5:
    result = 3;
  }
  else
  {
    uDir_dup = 0;
    while ( _strcmpi(pContainer, (const char *)&v2->pRoot[uDir_dup]) )
    {
      ++uDir;
      ++uDir_dup;
      if ( (signed int)uDir >= (signed int)v2->header.uNumIndices )
        goto LABEL_5;
    }
    strcpy((char *)v2->pContainerName, pContainer);
    v6 = v2->pRoot;
    v2->uCurrentIndexDir = uDir;
    v7 = &v6[uDir];
    v8 = v7->uOfsetFromSubindicesStart;
    v2->uOffsetToSubIndex = v8;
    v9 = v2->pFile;
    v2->uNumSubIndices = v7->uNumSubIndices;
    fseek(v9, v8, 0);
    pSubIndices_dup = (LOD::Directory *)pAllocator->AllocNamedChunk(
                                        v2->pSubIndices,
                                        32 * (v2->uNumSubIndices + 5),
                                        "LOD Index");
    v2->pSubIndices = pSubIndices_dup;
    if ( pSubIndices_dup )
      fread(pSubIndices_dup, 0x20u, v2->uNumSubIndices, v2->pFile);
    result = 0;
  }
  return result;
}

//----- (004617D5) --------------------------------------------------------
bool LOD::File::LoadHeader(const char *pFilename, bool bWriting)
{
  LOD::File *this_dup; // esi@1
  FILE *pFile_dup; // eax@6
  void *pRoot_dup; // eax@7
  const char *v6; // [sp-4h] [bp-Ch]@4
  FILE *v7; // [sp-4h] [bp-Ch]@7

  this_dup = this;
  if ( this->isFileOpened )
    Close();
  if ( bWriting & 1 )
    v6 = "rb";
  else
    v6 = "rb+";
  pFile_dup = fopen(pFilename, v6);
  this_dup->pFile = pFile_dup;
  if ( pFile_dup )
  {
    strcpy(this_dup->pLODName, pFilename);
    fread(&this_dup->header, 0x100u, 1u, this_dup->pFile);
    pRoot_dup = pAllocator->AllocNamedChunk(this_dup->pRoot, 0xA0u, "LOD CArray");
    this_dup->pRoot = (LOD::Directory *)pRoot_dup;
    v7 = this_dup->pFile;
    if ( pRoot_dup )
    {
      fread(pRoot_dup, 0x20u, this_dup->header.uNumIndices, v7);
      fseek(this_dup->pFile, 0, 0);
      this_dup->isFileOpened = 1;
      return false;
    }
    else
    {
      fclose(v7);
      return true;
    }
  }
  return true;
}


//----- (004617B6) --------------------------------------------------------
void LOD::FileHeader::Reset()
{
  this->pSignature[0] = 0;
  this->LodVersion[0] = 0;
  this->LodDescription[0] = 0;
  this->dword_0000A4 = 0;
  this->dword_0000A8 = 0;
  this->uNumIndices = 0;
}

//----- (00461790) --------------------------------------------------------
LOD::File::~File()
{
  LOD::File *v1; // esi@1

  v1 = this;
  if ( this->isFileOpened )
  {
    fclose(this->pFile);
    pAllocator->FreeChunk(v1->pSubIndices);
  }
}


//----- (0046175B) --------------------------------------------------------
LOD::File::File():
  pRoot(nullptr),
  isFileOpened(false)
{
  LOD::File *v1; // esi@1

  v1 = this;
  v1->pFile = 0;
  v1->pSubIndices = 0;
  v1->pIOBuffer = 0;
  v1->isFileOpened = 0;
  v1->uIOBufferSize = 0;
  Close();
}


//----- (00461743) --------------------------------------------------------
LOD::Directory *LOD::Directory::Reset()
{
  LOD::Directory *result; // eax@1

  result = this;
  this->pFilename[0] = 0;
  this->uOfsetFromSubindicesStart = 0;
  this->uDataSize = 0;
  this->dword_000018 = 0;
  this->uNumSubIndices = 0;
  this->word_00001E = 0;
  return result;
}


//----- (0046172B) --------------------------------------------------------
LOD::Directory::Directory()
{
  this->pFilename[0] = 0;
  this->uOfsetFromSubindicesStart = 0;
  this->uDataSize = 0;
  this->uNumSubIndices = 0;
  this->dword_000018 = 0;
  this->word_00001E = 0;
}

//----- (0046165E) --------------------------------------------------------
int LOD::File::CalcIndexFast(int startIndex, int maxIndex, const char *pContainerName)
{
  int v4; // esi@1
  int v5; // ebx@2
  int result; // eax@2
  int v7; // edi@10
  int v8; // esi@11
  int v9; // esi@17
  LOD::File *v10; // [sp+Ch] [bp-4h]@1

  v4 = startIndex;
  v10 = this;
  while ( 1 )                                   // binary search in LOD indices
  {
    while ( 1 )
    {
      v5 = maxIndex - v4;
      result = _strcmpi((const char *)pContainerName, (const char *)(&v10->pSubIndices[(maxIndex - v4) / 2] + v4));
      if ( !result )
        _6A0CA4_lod_binary_search = (maxIndex - v4) / 2 + v4;
      if ( v4 == maxIndex )
        goto LABEL_14;
      if ( result < 0 )
        break;
      if ( v5 <= 4 )
      {
        v7 = v4;
        if ( v4 < maxIndex )
        {
          v9 = v4;
          do
          {
            result = _strcmpi((const char *)pContainerName, (const char *)&v10->pSubIndices[v9]);
            if ( !result )
              goto LABEL_21;
            ++v7;
            ++v9;
          }
          while ( v7 < maxIndex );
        }
LABEL_14:
        _6A0CA4_lod_binary_search = -1;
        return result;
      }
      v4 += (maxIndex - v4) / 2;
    }
    if ( v5 <= 4 )
      break;
    maxIndex = (maxIndex - v4) / 2 + v4;
  }
  v7 = v4;
  if ( v4 >= maxIndex )
    goto LABEL_14;
  v8 = v4;
  while ( 1 )
  {
    result = _strcmpi((const char *)pContainerName, (const char *)&v10->pSubIndices[v8]);
    if ( !result )
      break;
    ++v7;
    ++v8;
    if ( v7 >= maxIndex )
      goto LABEL_14;
  }
LABEL_21:
  _6A0CA4_lod_binary_search = v7;
  return result;
}
// 6A0CA4: using guessed type int _6A0CA4_lod_binary_search;


//----- (0046161C) --------------------------------------------------------
bool LOD::File::DoesContainerExist(const char *pContainer)
{
  LOD::File *this_dup; // esi@1
  int i; // ebx@1
  signed int i_dup; // edi@1
  bool result; // eax@4

  this_dup = this;
  i = 0;
  i_dup = 0;
  if ( (signed int)this->uNumSubIndices <= 0 )
  {
LABEL_4:
    result = 0;
  }
  else
  {
    while ( _strcmpi((const char *)pContainer, (const char *)&this_dup->pSubIndices[i]) )
    {
      ++i_dup;
      ++i;
      if ( i_dup >= (signed int)this_dup->uNumSubIndices )
        goto LABEL_4;
    }
    result = 1;
  }
  return result;
}


//----- (00461397) --------------------------------------------------------
int LODFile_Sprites::_461397()
{
  int result; // eax@1
  int *pfield_ECA0; // edi@1
  int v3; // esi@1
  int v4; // ecx@3

  result = this->uNumLoadedSprites;
  pfield_ECA0 = &this->field_ECA0;
  v3 = this->field_ECA0;
  this->field_ECA8 = result;
  if ( result < v3 )
    this->field_ECA8 = v3;
  v4 = this->field_ECA4;
  if ( v3 < v4 )
    *pfield_ECA0 = v4;
  return result;
}

//----- (00461580) --------------------------------------------------------
FILE *LOD::File::FindContainer(const char *pContainerName, bool bLinearSearch)
{
  unsigned int v4; // eax@4
  if (!isFileOpened)
    return 0;


  if (bLinearSearch)
  {
    for (uint i = 0; i < uNumSubIndices; ++i)
      if (!strcmpi(pContainerName, pSubIndices[i].pFilename))
      {
        v4 = pSubIndices[i].uOfsetFromSubindicesStart;
        fseek(pFile, uOffsetToSubIndex + v4, SEEK_SET);
        return pFile;
      }

    return nullptr;
  }
  else
  {
    CalcIndexFast(0, uNumSubIndices, pContainerName);
    if ( _6A0CA4_lod_binary_search < 0 )
      return 0;
    v4 = pSubIndices[_6A0CA4_lod_binary_search].uOfsetFromSubindicesStart;
    fseek(pFile, uOffsetToSubIndex + v4, SEEK_SET);
    return pFile;
  }
}

//----- (0041097D) --------------------------------------------------------
void LODFile_IconsBitmaps::SetupPalettes(unsigned int uTargetRBits, unsigned int uTargetGBits, unsigned int uTargetBBits)
{
  int v4; // edx@1
  LODFile_IconsBitmaps *v5; // esi@1
  int v6; // ecx@1
  unsigned __int8 v7; // zf@4
  unsigned __int8 v8; // sf@4
  unsigned __int16 **v9; // edi@5
  FILE *v10; // eax@7
  FILE *v11; // ebx@7
  signed int v12; // ebx@8
  int v13; // eax@9
  int v14; // edx@9
  int v16; // [sp+4Ch] [bp-8h]@4
  FILE *File; // [sp+50h] [bp-4h]@7

  v4 = uTargetGBits;
  v5 = this;
  v6 = uTargetBBits;
  if ( v5->uTextureRedBits != uTargetRBits
    || v5->uTextureGreenBits != uTargetGBits
    || v5->uTextureBlueBits != uTargetBBits )
  {
    v16 = 0;
    v7 = v5->uNumLoadedFiles == 0;
    v8 = (v5->uNumLoadedFiles & 0x80000000u) != 0;
    v5->uTextureRedBits = uTargetRBits;
    v5->uTextureGreenBits = v4;
    v5->uTextureBlueBits = v6;
    if ( !(v8 | v7) )
    {
      v9 = &v5->pTextures[0].pPalette16;
      do
      {
        Texture DstBuf; // [sp+4h] [bp-50h]@6
        //Texture::Texture(&DstBuf);

        if ( *v9 )
        {
          v10 = FindContainer((const char *)v9 - 64, 0);
          v11 = v10;
          File = v10;
          if ( v10 )
          {
            fread(&DstBuf, 1u, 0x30u, v10);
            fseek(v11, DstBuf.uTextureSize, 1);
            v12 = 0;
            do
            {
              fread((char *)&uTargetRBits + 3, 1u, 1u, File);
              fread((char *)&uTargetBBits + 3, 1u, 1u, File);
              v13 = fread((char *)&uTargetGBits + 3, 1u, 1u, File);
              LOWORD(v13) = (unsigned __int8)(BYTE3(uTargetRBits) >> (8 - LOBYTE(v5->uTextureRedBits)));
              (*v9)[v12] = v13 << (LOBYTE(v5->uTextureGreenBits) + LOBYTE(v5->uTextureBlueBits));
              LOWORD(v14) = (unsigned __int8)(BYTE3(uTargetBBits) >> (8 - LOBYTE(v5->uTextureGreenBits)));
              (*v9)[v12] |= v14 << v5->uTextureBlueBits;
              (*v9)[v12] |= BYTE3(uTargetGBits) >> (8 - LOBYTE(v5->uTextureBlueBits));
              ++v12;
            }
            while ( v12 < 256 );
          }
        }
        ++v16;
        v9 += 18;
      }
      while ( v16 < (signed int)v5->uNumLoadedFiles );
    }
  }
}



//----- (0041088B) --------------------------------------------------------
void *LOD::File::LoadRaw(const char *pContainer, int a3)
{
  LOD::File *v3; // esi@1
  FILE *v4; // eax@1
  FILE *v5; // esi@1
  void *v6; // eax@5
  void *v7; // ebx@7
  void *v8; // edi@7
  void *v9; // eax@9
  Texture DstBuf; // [sp+Ch] [bp-4Ch]@1
  FILE *File; // [sp+54h] [bp-4h]@1
  unsigned int Argsa; // [sp+60h] [bp+8h]@3

  v3 = this;
  v4 = FindContainer(pContainer, 0);
  v5 = v4;
  File = v4;
  if ( !v4 )
    Abortf("Unable to load %s", pContainer);
  fread(&DstBuf, 1u, 0x30u, v4);
  Argsa = DstBuf.uTextureSize;
  if ( DstBuf.uDecompressedSize )
  {
    if ( a3 )
      v6 = malloc(DstBuf.uDecompressedSize);
    else
      v6 = pAllocator->AllocNamedChunk(0, DstBuf.uDecompressedSize, DstBuf.pName);
    v7 = v6;
    v8 = pAllocator->AllocNamedChunk(0, DstBuf.uTextureSize, DstBuf.pName);
    fread(v8, 1u, Argsa, File);
    zlib::MemUnzip(v7, &DstBuf.uDecompressedSize, v8, DstBuf.uTextureSize);
    DstBuf.uTextureSize = DstBuf.uDecompressedSize;
    pAllocator->FreeChunk(v8);
  }
  else
  {
    if ( a3 )
      v9 = malloc(DstBuf.uTextureSize);
    else
      v9 = pAllocator->AllocNamedChunk(0, DstBuf.uTextureSize, DstBuf.pName);
    v7 = v9;
    fread(v9, 1u, Argsa, v5);
  }
  return v7;
}



//----- (00410522) --------------------------------------------------------
int LODFile_IconsBitmaps::_410522(Texture *pDst, const char *pContainer, unsigned int uTextureType)
{
  LODFile_IconsBitmaps *v4; // edi@1
  Texture *v5; // esi@5
  unsigned int v6; // eax@5
  void *v7; // eax@6
  unsigned int v8; // ST28_4@6
  void *v9; // ST2C_4@6
  unsigned __int8 *v10; // eax@7
  FILE *v11; // ST28_4@7
  void *v12; // eax@9
  FILE *v13; // ST28_4@9
  signed int v14; // eax@12
  int v15; // ecx@12
  int v16; // ecx@12
  int v17; // eax@12
  signed int v18; // ebx@14
  int v19; // eax@15
  int v20; // edx@15
  signed int v21; // ecx@18
  signed int v22; // ecx@23
  char Args[100]; // [sp+4h] [bp-68h]@3
  FILE *File; // [sp+68h] [bp-4h]@1

  v4 = this;
  File = FindContainer(pContainer, 0);
  if ( !File )
  {
    File = FindContainer("pending", 0);
    if ( !File )
    {
      sprintf(Args, "Can't find %s!", pContainer);
      Abortf(Args);
    }
  }
  v5 = pDst;
  fread(pDst, 1u, 0x30u, File);
  strcpy(v5->pName, pContainer);
  pDst = (Texture *)v5->uTextureSize;
  v6 = v5->uDecompressedSize;
  v5->pLevelOfDetail0 = 0;
  if ( v6 )
  {
    v7 = operator new(v6);
    v8 = v5->uTextureSize;
    v5->pLevelOfDetail0 = (unsigned __int8 *)v7;
    pContainer = (const char *)operator new(v8);
    fread((void *)pContainer, 1u, (size_t)pDst, File);
    zlib::MemUnzip(v5->pLevelOfDetail0, &v5->uDecompressedSize, pContainer, v5->uTextureSize);
    v9 = (void *)pContainer;
    v5->uTextureSize = v5->uDecompressedSize;
    free(v9);
  }
  else
  {
    v10 = (unsigned __int8 *)operator new(0);
    v11 = File;
    v5->pLevelOfDetail0 = v10;
    fread(v10, 1u, (size_t)pDst, v11);
  }
  v5->pPalette24 = 0;
  if ( uTextureType == 1 )
  {
    v12 = operator new(0x300u);
    v13 = File;
    v5->pPalette24 = (unsigned __int8 *)v12;
    fread(v12, 1u, 0x300u, v13);
LABEL_10:
    v5->pPalette16 = 0;
    goto LABEL_11;
  }
  if ( uTextureType != 2 )
    goto LABEL_10;
  v18 = 0;
  v5->pPalette16 = 0;
  v5->pPalette16 = (unsigned __int16 *)operator new(0x400u);
  do
  {
    fread((char *)&pContainer + 3, 1u, 1u, File);
    fread((char *)&uTextureType + 3, 1u, 1u, File);
    v19 = fread((char *)&pDst + 3, 1u, 1u, File);
    LOWORD(v19) = (unsigned __int8)(BYTE3(pContainer) >> (8 - LOBYTE(v4->uTextureRedBits)));
    v5->pPalette16[v18] = v19 << (LOBYTE(v4->uTextureBlueBits) + LOBYTE(v4->uTextureGreenBits));
    LOWORD(v20) = (unsigned __int8)(BYTE3(uTextureType) >> (8 - LOBYTE(v4->uTextureGreenBits)));
    v5->pPalette16[v18] += v20 << v4->uTextureBlueBits;
    v5->pPalette16[v18] += (unsigned __int8)(BYTE3(pDst) >> (8 - LOBYTE(v4->uTextureBlueBits)));
    ++v18;
  }
  while ( v18 < 256 );
LABEL_11:
  if ( v5->pBits & 2 )
  {
    v14 = v5->uSizeOfMaxLevelOfDetail;
    v15 = (int)&v5->pLevelOfDetail0[v14];
    v5->pLevelOfDetail1 = (unsigned __int8 *)v15;
    v16 = (v14 >> 2) + v15;
    v5->pLevelOfDetail2 = (unsigned __int8 *)v16;
    v17 = v16 + (v14 >> 4);
  }
  else
  {
    v17 = 0;
    v5->pLevelOfDetail2 = 0;
    v5->pLevelOfDetail1 = 0;
  }
  v5->pLevelOfDetail3 = (unsigned __int8 *)v17;
  v21 = 1;
  while ( 1 << v21 != v5->uTextureWidth )
  {
    ++v21;
    if ( v21 >= 15 )
      goto LABEL_23;
  }
  v5->uWidthLn2 = v21;
LABEL_23:
  v22 = 1;
  while ( 1 << v22 != v5->uTextureHeight )
  {
    ++v22;
    if ( v22 >= 15 )
      goto LABEL_28;
  }
  v5->uHeightLn2 = v22;
LABEL_28:
  switch ( v5->uWidthLn2 )
  {
    case 2:
      v5->uWidthMinus1 = 3;
      break;
    case 3:
      v5->uWidthMinus1 = 7;
      break;
    case 4:
      v5->uWidthMinus1 = 15;
      break;
    case 5:
      v5->uWidthMinus1 = 31;
      break;
    case 6:
      v5->uWidthMinus1 = 63;
      break;
    case 7:
      v5->uWidthMinus1 = 127;
      break;
    case 8:
      v5->uWidthMinus1 = 255;
      break;
    case 9:
      v5->uWidthMinus1 = 511;
      break;
    case 10:
      v5->uWidthMinus1 = 1023;
      break;
    case 11:
      v5->uWidthMinus1 = 2047;
      break;
    case 12:
      v5->uWidthMinus1 = 4095;
      break;
    default:
      break;
  }
  switch ( v5->uHeightLn2 )
  {
    case 2:
      v5->uHeightMinus1 = 3;
      break;
    case 3:
      v5->uHeightMinus1 = 7;
      break;
    case 4:
      v5->uHeightMinus1 = 15;
      break;
    case 5:
      v5->uHeightMinus1 = 31;
      break;
    case 6:
      v5->uHeightMinus1 = 63;
      break;
    case 7:
      v5->uHeightMinus1 = 127;
      break;
    case 8:
      v5->uHeightMinus1 = 255;
      break;
    case 9:
      v5->uHeightMinus1 = 511;
      break;
    case 10:
      v5->uHeightMinus1 = 1023;
      break;
    case 11:
      v5->uHeightMinus1 = 2047;
      break;
    case 12:
      v5->uHeightMinus1 = 4095;
      break;
    default:
      return 1;
  }
  return 1;
}


//----- (00410423) --------------------------------------------------------
void LODFile_IconsBitmaps::_410423_move_textures_to_device()
{
  LODFile_IconsBitmaps *v1; // esi@1
  unsigned int v2; // edi@1
  char *v3; // ebx@2
  size_t v4; // eax@9
  char *v5; // ST1C_4@9
  void *v6; // eax@12
  signed int v7; // esi@13

  v1 = this;
  v2 = this->uNumLoadedFiles - 1;
  if ( (v2 & 0x80000000u) == 0 )
  {
    v3 = &this->pTextures[v2].pName[2];
    do
    {
      if ( v1->ptr_011BB4[v2] )
      {
        if ( *(v3 - 2) != 'w' || *(v3 - 1) != 't' || *v3 != 'r' || v3[1] != 'd' || v3[2] != 'r' )
        {
          pRenderer->LoadTexture(
            v3 - 2,
            *((short *)v3 + 17),
            (IDirectDrawSurface4 **)&v1->pHardwareSurfaces[v2],
            &v1->pHardwareTextures[v2]);
        }
        else
        {
          v4 = strlen(v3 - 2);
          v5 = (char *)operator new(v4 + 2);
          *v5 = 'h';
          strcpy(v5 + 1, v3 - 2);
          pRenderer->LoadTexture(
            v5,
            *((short *)v3 + 17),
            (IDirectDrawSurface4 **)&v1->pHardwareSurfaces[v2],
            &v1->pHardwareTextures[v2]);
          free(v5);
        }
      }
      --v2;
      v3 -= 72;
    }
    while ( (v2 & 0x80000000u) == 0 );
  }
  v6 = v1->ptr_011BB4;
  if ( v6 )
  {
    v7 = v1->uNumLoadedFiles;
    if ( v7 > 1 )
      memset(v6, 0, v7 - 1);
  }
}


//----- (004103BB) --------------------------------------------------------
void LODFile_IconsBitmaps::ReleaseHardwareTextures()
{
  LODFile_IconsBitmaps *v1; // esi@1
  unsigned int v2; // edi@1
  struct IDirect3DTexture2 **v3; // eax@2
  struct IDirect3DTexture2 *v4; // eax@3
  struct IDirectDrawSurface **v5; // eax@5
  struct IDirectDrawSurface *v6; // eax@6

  v1 = this;
  v2 = this->uNumLoadedFiles;
  while ( 1 )
  {
    --v2;
    if ( (v2 & 0x80000000u) != 0 )
      break;
    v3 = v1->pHardwareTextures;
    if ( v3 )
    {
      v4 = v3[v2];
      if ( v4 )
      {
        v4->Release();
        v1->pHardwareTextures[v2] = 0;
        v1->ptr_011BB4[v2] = 1;
      }
    }
    v5 = v1->pHardwareSurfaces;
    if ( v5 )
    {
      v6 = v5[v2];
      if ( v6 )
      {
        v6->Release();
        v1->pHardwareSurfaces[v2] = 0;
        v1->ptr_011BB4[v2] = 1;
      }
    }
  }
}


//----- (0041033D) --------------------------------------------------------
void LODFile_IconsBitmaps::ReleaseLostHardwareTextures()
{
  LODFile_IconsBitmaps *v1; // edi@1
  unsigned int i; // ebx@1
  struct IDirectDrawSurface **pHardwareSurfaces; // eax@2
  int v4; // esi@3
  struct IDirectDrawSurface *pSurface; // eax@3
  struct IDirect3DTexture2 **v6; // eax@5
  struct IDirect3DTexture2 *v7; // eax@6

  v1 = this;
  for ( i = this->uNumLoadedFiles - 1; (i & 0x80000000u) == 0; --i )
  {
    pHardwareSurfaces = v1->pHardwareSurfaces;
    if ( pHardwareSurfaces )
    {
      v4 = i;
      pSurface = pHardwareSurfaces[i];
      if ( pSurface )
      {
        if ( pSurface->IsLost() == DDERR_SURFACELOST )
        {
          v6 = v1->pHardwareTextures;
          if ( v6 )
          {
            v7 = v6[v4];
            if ( v7 )
            {
              v7->Release();
              v1->pHardwareTextures[v4] = 0;
            }
          }
          v1->pHardwareSurfaces[v4]->Release();
          v1->pHardwareSurfaces[v4] = 0;
          v1->ptr_011BB4[i] = 1;
        }
      }
    }
  }
}

//----- (004101B1) --------------------------------------------------------
int LODFile_IconsBitmaps::ReloadTexture(Texture *pDst, const char *pContainer, int mode)
{
  LODFile_IconsBitmaps *v4; // edi@1
  FILE *v5; // eax@1
  Texture *v6; // esi@2
  unsigned int v7; // ebx@6
  unsigned int v8; // ecx@6
  signed int result; // eax@7
  size_t *v10; // ebx@8
  signed int v11; // ebx@12
  int v12; // eax@13
  int v13; // edx@13
  FILE *File; // [sp+Ch] [bp-8h]@1
  unsigned __int8 v15; // [sp+11h] [bp-3h]@13
  unsigned __int8 v16; // [sp+12h] [bp-2h]@13
  unsigned __int8 DstBuf; // [sp+13h] [bp-1h]@13
  void *DstBufa; // [sp+1Ch] [bp+8h]@10
  void *Sourcea; // [sp+20h] [bp+Ch]@10
  unsigned int Counta; // [sp+24h] [bp+10h]@6

  v4 = this;
  v5 = FindContainer(pContainer, 0);
  File = v5;
  if ( v5
    && (v6 = pDst, pDst->pLevelOfDetail0)
    && mode == 2
    && pDst->pPalette16
    && !pDst->pPalette24
    && (v7 = pDst->uTextureSize,
        fread(pDst, 1u, 0x30u, v5),
        strcpy(pDst->pName, pContainer),
        v8 = pDst->uTextureSize,
        Counta = pDst->uTextureSize,
        (signed int)v8 <= (signed int)v7) )
  {
    v10 = &pDst->uDecompressedSize;
    if ( !pDst->uDecompressedSize || v4->dword_011BA4 )
    {
      fread(pDst->pLevelOfDetail0, 1u, v8, File);
    }
    else
    {
      Sourcea = malloc(pDst->uDecompressedSize);
      DstBufa = malloc(pDst->uTextureSize);
      fread(DstBufa, 1u, Counta, File);
      zlib::MemUnzip(Sourcea, &v6->uDecompressedSize, DstBufa, v6->uTextureSize);
      v6->uTextureSize = *v10;
      free(DstBufa);
      memcpy(v6->pLevelOfDetail0, Sourcea, *v10);
      free(Sourcea);
    }
    v11 = 0;
    do
    {
      fread(&DstBuf, 1u, 1u, File);
      fread(&v16, 1u, 1u, File);
      v12 = fread(&v15, 1u, 1u, File);
      LOWORD(v12) = (unsigned __int8)(DstBuf >> (8 - LOBYTE(v4->uTextureRedBits)));
      v6->pPalette16[v11] = v12 << (LOBYTE(v4->uTextureBlueBits) + LOBYTE(v4->uTextureGreenBits));
      LOWORD(v13) = (unsigned __int8)(v16 >> (8 - LOBYTE(v4->uTextureGreenBits)));
      v6->pPalette16[v11] += v13 << v4->uTextureBlueBits;
      v6->pPalette16[v11] += (unsigned __int8)(v15 >> (8 - LOBYTE(v4->uTextureBlueBits)));
      ++v11;
    }
    while ( v11 < 256 );
    result = 1;
  }
  else
  {
    result = -1;
  }
  return result;
}


//----- (0040FC08) --------------------------------------------------------
int LODFile_IconsBitmaps::LoadTextureFromLOD(Texture *pOutTex, const char *pContainer, enum TEXTURE_TYPE eTextureType)
{
  Texture *v8; // esi@3
  size_t v11; // eax@14
  enum TEXTURE_TYPE v12; // eax@14
  signed int v13; // esi@14
  unsigned int v14; // eax@21
  unsigned int v15; // ecx@25
  unsigned int *v16; // ebx@25
  void *v17; // eax@27
  unsigned int v18; // ST28_4@27
  void *v19; // ST3C_4@27
  Allocator *v20; // ebx@29
  void *v21; // eax@29
  size_t v22; // ST2C_4@29
  const void *v23; // ecx@29
  unsigned __int16 v24; // ax@29
  unsigned __int16 v25; // cx@29
  __int16 v26; // dx@29
  unsigned int v27; // ecx@29
  Texture *v28; // eax@29
  unsigned int v29; // ST28_4@30
  void *v30; // eax@30
  unsigned int v31; // ST2C_4@30
  void *v32; // eax@32
  void *v33; // eax@34
  signed int v34; // eax@37
  unsigned __int8 *v35; // ecx@37
  unsigned __int8 *v36; // ecx@37
  unsigned __int8 *v37; // eax@37
  signed int v38; // ebx@39
  int v39; // eax@40
  int v40; // edx@40
  signed int v41; // ecx@43
  signed int v42; // ecx@48

  //v4 = pContainer;
  //v5 = this;
  //v6 = FindContainer(pContainer, 0);
  //File = v6;
  auto pFile = FindContainer(pContainer, false);
  if (!pFile)
    return -1;
  v8 = pOutTex;
  fread(pOutTex, 1u, 0x30u, pFile);
  strcpy(v8->pName, pContainer);
  if (pRenderer->pRenderD3D && v8->pBits & 2 && dword_011BA8)
  {
    if (!pHardwareSurfaces || !pHardwareTextures)
    {
      pHardwareSurfaces = new IDirectDrawSurface *[1000];
      memset(pHardwareSurfaces, 0, 1000 * sizeof(IDirectDrawSurface4 *));

      pHardwareTextures = new IDirect3DTexture2 *[1000];
      memset(pHardwareTextures, 0, 1000 * sizeof(IDirect3DTexture2 *));

      ptr_011BB4 = new char[1000];
      memset(ptr_011BB4, 0, 1000);
    }
    if (strcmp(pContainer, "wtrdr"))//*v4 != 'w' || v4[1] != 't' || v4[2] != 'r' || v4[3] != 'd' || v4[4] != 'r' )
    {
      if (strcmp(pContainer, "WtrTyl"))//if ( *v4 != 'W' || v4[1] != 't' || v4[2] != 'r' || v4[3] != 'T' || v4[4] != 'y' || v4[5] != 'l' )
      {
        v14 = uNumLoadedFiles;
      }
      else
      {
        pRenderer->field_1036AC_bitmapid = uNumLoadedFiles;
        v14 = uNumLoadedFiles;
      }
      v13 = pRenderer->LoadTexture(
              pContainer,
              v8->palette_id1,
              (IDirectDrawSurface4 **)&pHardwareSurfaces[v14],
              &pHardwareTextures[v14]);
    }
    else
    {
      v11 = strlen(pContainer);
      v12 = (enum TEXTURE_TYPE)(int)operator new(v11 + 2);
      eTextureType = v12;
      *(char *)v12 = 104;
      strcpy((char *)(v12 + 1), pContainer);
      v13 = pRenderer->LoadTexture(
              (const char *)eTextureType,
              v8->palette_id1,
              (IDirectDrawSurface4 **)&pHardwareSurfaces[uNumLoadedFiles],
              &pHardwareTextures[uNumLoadedFiles]);
      free((void *)eTextureType);
    }
    return v13;
  }
  v15 = v8->uTextureSize;
  v16 = &v8->uDecompressedSize;
  pOutTex = (Texture *)v8->uTextureSize;
  if ( !v8->uDecompressedSize || dword_011BA4 )
  {
    v20 = pAllocator;
    v32 = pAllocator->AllocNamedChunk(v8->pLevelOfDetail0, v15, v8->pName);
    v8->pLevelOfDetail0 = (unsigned __int8 *)v32;
    fread(v32, 1u, (size_t)pOutTex, pFile);
  }
  else
  {
    v17 = malloc(v8->uDecompressedSize);
    v18 = v8->uTextureSize;
    pContainer = (const char *)v17;
    v19 = malloc(v18);
    fread(v19, 1u, (size_t)pOutTex, pFile);
    zlib::MemUnzip((void *)pContainer, &v8->uDecompressedSize, v19, v8->uTextureSize);
    v8->uTextureSize = *v16;
    free(v19);
    if ( bUseLoResSprites && v8->pBits & 2 )
    {
      v20 = pAllocator;
      pOutTex = (Texture *)(((signed int)v8->uSizeOfMaxLevelOfDetail >> 2)
                          + ((signed int)v8->uSizeOfMaxLevelOfDetail >> 4)
                          + ((signed int)v8->uSizeOfMaxLevelOfDetail >> 6));
      v21 = pAllocator->AllocNamedChunk(v8->pLevelOfDetail0, (unsigned int)pOutTex, v8->pName);
      v22 = (size_t)pOutTex;
      v23 = &pContainer[v8->uTextureWidth * v8->uTextureHeight];
      v8->pLevelOfDetail0 = (unsigned __int8 *)v21;
      memcpy(v21, v23, v22);
      v8->uTextureWidth = (signed __int16)v8->uTextureWidth >> 1;
      v24 = v8->uTextureWidth;
      v8->uTextureHeight = (signed __int16)v8->uTextureHeight >> 1;
      v25 = v8->uTextureHeight;
      --v8->uWidthLn2;
      --v8->uHeightLn2;
      v8->uWidthMinus1 = v24 - 1;
      v26 = v25 - 1;
      v27 = (signed __int16)v24 * (signed __int16)v25;
      v28 = pOutTex;
      v8->uHeightMinus1 = v26;
      v8->uSizeOfMaxLevelOfDetail = v27;
      v8->uTextureSize = (unsigned int)v28;
    }
    else
    {
      v29 = *v16;
      v20 = pAllocator;
      v30 = pAllocator->AllocNamedChunk(v8->pLevelOfDetail0, v29, v8->pName);
      v31 = v8->uDecompressedSize;
      v8->pLevelOfDetail0 = (unsigned __int8 *)v30;
      memcpy(v30, pContainer, v31);
    }
    free((void *)pContainer);
  }
  pAllocator->FreeChunk(v8->pPalette16);
  pAllocator->FreeChunk(v8->pPalette24);
  if ( eTextureType == TEXTURE_24BIT_PALETTE )
  {
    v33 = pAllocator->AllocNamedChunk(v8->pPalette24, 0x300u, v8->pName);
    v8->pPalette24 = (unsigned __int8 *)v33;
    fread(v33, 1u, 0x300u, pFile);
  }
  else
  {
    v8->pPalette24 = 0;
    if ( eTextureType == TEXTURE_16BIT_PALETTE )
    {
      v8->pPalette16 = (unsigned __int16 *)pAllocator->AllocNamedChunk(v8->pPalette16, 0x200u, v8->pName);
      v38 = 0;
      do
      {
        fread((char *)&eTextureType + 3, 1u, 1u, pFile);
        fread((char *)&pContainer + 3, 1u, 1u, pFile);
        v39 = fread((char *)&pOutTex + 3, 1u, 1u, pFile);
        LOWORD(v39) = (unsigned __int8)(BYTE3(eTextureType) >> (8 - LOBYTE(uTextureRedBits)));
        v8->pPalette16[v38] = v39 << (LOBYTE(uTextureBlueBits) + LOBYTE(uTextureGreenBits));
        LOWORD(v40) = (unsigned __int8)(BYTE3(pContainer) >> (8 - LOBYTE(uTextureGreenBits)));
        v8->pPalette16[v38] += v40 << uTextureBlueBits;
        v8->pPalette16[v38] += (unsigned __int8)(BYTE3(pOutTex) >> (8 - LOBYTE(uTextureBlueBits)));
        ++v38;
      }
      while ( v38 < 256 );
      goto LABEL_36;
    }
  }
  v8->pPalette16 = 0;
LABEL_36:
  if ( v8->pBits & 2 )
  {
    v34 = v8->uSizeOfMaxLevelOfDetail;
    v35 = &v8->pLevelOfDetail0[v34];
    v8->pLevelOfDetail1 = v35;
    v36 = &v35[v34 >> 2];
    v8->pLevelOfDetail2 = v36;
    v37 = &v36[v34 >> 4];
  }
  else
  {
    v37 = 0;
    v8->pLevelOfDetail2 = 0;
    v8->pLevelOfDetail1 = 0;
  }
  v8->pLevelOfDetail3 = v37;
  v41 = 1;
  while ( 1 << v41 != v8->uTextureWidth )
  {
    ++v41;
    if ( v41 >= 15 )
      goto LABEL_48;
  }
  v8->uWidthLn2 = v41;
LABEL_48:
  v42 = 1;
  while ( 1 << v42 != v8->uTextureHeight )
  {
    ++v42;
    if ( v42 >= 15 )
      goto LABEL_53;
  }
  v8->uHeightLn2 = v42;
LABEL_53:
  switch ( v8->uWidthLn2 )
  {
    case 2:
      v8->uWidthMinus1 = 3;
      break;
    case 3:
      v8->uWidthMinus1 = 7;
      break;
    case 4:
      v8->uWidthMinus1 = 15;
      break;
    case 5:
      v8->uWidthMinus1 = 31;
      break;
    case 6:
      v8->uWidthMinus1 = 63;
      break;
    case 7:
      v8->uWidthMinus1 = 127;
      break;
    case 8:
      v8->uWidthMinus1 = 255;
      break;
    case 9:
      v8->uWidthMinus1 = 511;
      break;
    case 10:
      v8->uWidthMinus1 = 1023;
      break;
    case 11:
      v8->uWidthMinus1 = 2047;
      break;
    case 12:
      v8->uWidthMinus1 = 4095;
      break;
    default:
      break;
  }
  switch ( v8->uHeightLn2 )
  {
    case 2:
      v8->uHeightMinus1 = 3;
      break;
    case 3:
      v8->uHeightMinus1 = 7;
      break;
    case 4:
      v8->uHeightMinus1 = 15;
      break;
    case 5:
      v8->uHeightMinus1 = 31;
      break;
    case 6:
      v8->uHeightMinus1 = 63;
      break;
    case 7:
      v8->uHeightMinus1 = 127;
      break;
    case 8:
      v8->uHeightMinus1 = 255;
      break;
    case 9:
      v8->uHeightMinus1 = 511;
      break;
    case 10:
      v8->uHeightMinus1 = 1023;
      break;
    case 11:
      v8->uHeightMinus1 = 2047;
      break;
    case 12:
      v8->uHeightMinus1 = 4095;
      break;
    default:
      return 1;
  }
  return 1;
}


Texture *LODFile_IconsBitmaps::LoadTexturePtr(const char *pContainer, enum TEXTURE_TYPE uTextureType)
{
  uint id = LoadTexture(pContainer, uTextureType);
  if (id == -1)
  {
    Log::Warning(L"LOD error\\no container: \"%S\"", pContainer);
    return nullptr;
  }
  return &pTextures[id];
}

//----- (0040FB20) --------------------------------------------------------
unsigned int LODFile_IconsBitmaps::LoadTexture(const char *pContainer, enum TEXTURE_TYPE uTextureType)
{
  //LODFile_IconsBitmaps *v3; // esi@1
  //unsigned int v4; // edi@1
  //Texture *v5; // ebx@2
  unsigned int v6; // ebx@8
  const char *Sourcea; // [sp+14h] [bp+8h]@9

  //v3 = this;
  //v4 = 0;
  areWeLoadingTexture = 1;

  for (uint i = 0; i < uNumLoadedFiles; ++i)
    if (!strcmpi(pContainer, pTextures[i].pName))
      return i;

//  if (!uNumLoadedFiles)
//  {
//LABEL_5:
    if (uNumLoadedFiles >= 1000)
    {
      Log::Warning(L"Maximum texture number exceeded");
      AbortWithError();
    }
    if (LoadTextureFromLOD(&pTextures[uNumLoadedFiles], pContainer, uTextureType) == -1)
    {
      v6 = 0;
      if (uNumLoadedFiles > 0)
      {
        Sourcea = (const char *)pTextures;
        while ( _strcmpi(Sourcea, "pending") )
        {
          Sourcea += 72;
          ++v6;
          if (v6 >= uNumLoadedFiles)
            goto LABEL_15;
        }
        return v6;
      }
LABEL_15:
      LoadTextureFromLOD(&pTextures[uNumLoadedFiles], "pending", uTextureType);
    }
    areWeLoadingTexture = 0;
    ++uNumLoadedFiles;
    return uNumLoadedFiles - 1;
//  }
//  v5 = pTextures;
//  while ( _strcmpi(v5->pName, pContainer) )
//  {
//    ++v4;
//    ++v5;
//    if (v4 >= uNumLoadedFiles )
//      goto LABEL_5;
//  }
//  return v4;
}