[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/codenamecpp/GLKeeper/main/src/DK2EngineTextures.cpp [Back]  [Original]

#include "stdafx.h"
#include "DK2EngineTextures.h"

//////////////////////////////////////////////////////////////////////////

#define MAKEDWORD(ch0, ch1, ch2, ch3)                              \
                ((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) > 3;
    //int a = (magic_input_table_6c10c0[i] & 0x0001ffff)  mLength)
        {
            int numAvailableBytes = (mLength - offsetFromOrigin);
            numElementsToRead = numAvailableBytes / Cache_ElementSize;

            cxx_assert((numAvailableBytes % Cache_ElementSize) == 0);
        }

        mCacheSize = cxx::read_some_elements(mStream, mCache, numElementsToRead);
        if (!mStream)
        {
            cxx_assert(false);
            return;
        }
    }

private:
    std::istream& mStream;
    int mOrigin;
    int mLength;
    int mPageIndex;
    int mCache[512];
    int mCacheSize; // in uints
};

//////////////////////////////////////////////////////////////////////////

stream_uint32* bs;
unsigned int bs_index;
unsigned int bs_red = 0;
unsigned int bs_green = 0;
unsigned int bs_blue = 0;
unsigned int bs_alpha = 0;

int decompress2_chunk[256]; /* buffers */
int decompress3_chunk[288];
int decompress4_chunk[512];

//////////////////////////////////////////////////////////////////////////

inline unsigned int bs_read(unsigned int pos, int bits)
{
    unsigned int w1, w2;
    unsigned int word_index;
    unsigned int shamt;
  
    word_index = pos >> 5;
    shamt = pos & 0x1f;
    w1 = bs->get(word_index) get(word_index + 1) >> (32 - shamt) : 0;
    w1 |= w2;
    w1 >>= (32 - bits);

    return w1;
}

static unsigned int prepare_decompress(unsigned int value, unsigned int pos)
{
    int xindex, index, control_word = 0;
    unsigned char magic_index = 0x3f;

    decompress2_chunk[0] = value * magic_output_table[0];
    memset(&decompress2_chunk[1], 0,
            sizeof(decompress2_chunk) - sizeof(unsigned int));

    for (;;)
    {
        xindex = index = bs_read(pos, 17);
        if (index >= 0x8000) 
        {
            index >>= 13;
            control_word = dc_control_table_7af0e0[60 + index];
        } 
        else if (index >= 0x800) 
        {
            index >>= 9;
            control_word = dc_control_table_7af0e0[72 + index];
        } 
        else if (index >= 0x400) 
        {
            index >>= 7;
            control_word = dc_control_table_7af0e0[128 + index];
        } 
        else if (index >= 0x200) 
        {
            index >>= 5;
            control_word = dc_control_table_7af0e0[128 + index];
        } 
        else if (index >= 0x100) 
        {
            index >>= 4;
            control_word = dc_control_table_7af0e0[144 + index];
        } 
        else if (index >= 0x80) 
        {
            index >>= 3;
            control_word = dc_control_table_7af0e0[160 + index];
        } 
        else if (index >= 0x40) 
        {
            index >>= 2;
            control_word = dc_control_table_7af0e0[176 + index];
        } 
        else if (index >= 0x20) 
        {
            index >>= 1;
            control_word = dc_control_table_7af0e0[192 + index];
        }

        if ((control_word & 0xff00) == 0x4100)
        {
            break;
        }

        if ((control_word & 0xff00) > 0x4100) 
        {
            unsigned short unk14;
            // read next control 
            pos += control_word >> 16;
            unk14 = bs_read(pos, 14);
            pos += 14;
            magic_index -= (unk14 & 0xff00) >> 8;
            unk14 &= 0xff;
            if (unk14) 
            {
                if (unk14 != 0x80) 
                {
                    if(unk14 > 0x80) 
                        unk14 -= 0x100;
                    magic_index--;
                } 
                else 
                {
                    unk14 = bs_read(pos, 8);
                    pos += 8;
                    unk14 -= 0x100;
                }
            } 
            else 
            {
                unk14 = bs_read(pos, 8);
                pos += 8;
            }
            control_word = unk14;
        } 
        else 
        {
            int bit_to_test;
            unsigned int rem = control_word >> 16;
            unsigned int xoramt = 0;
            magic_index -= (control_word & 0xff00) >> 8;
            bit_to_test = 16 - rem;
            if (xindex & (1 > 16);
}

static void decompress_func1(int *in, int *out)
{
    int64_t rx;
    int sa;
    int b, a, c, d, i, p, s;
    unsigned int sc, sd, si;
    double rxf, rxg, rxs;
    double xf, xg;

    if(!(in[1] | in[2] | in[3] | in[4] | in[6] | in[7])) 
    {
        a = in[0];
        out[0] = a;
        out[9] = a;
        out[18] = a;
        out[27] = a;
        out[36] = a;
        out[45] = a;
        out[54] = a;
        out[63] = a;
        return;
    }

    b = in[5] - in[3];
    c = in[1] - in[7];
    i = in[3] + in[5];
    a = in[7] + in[1];
    xf = b;
    xg = c;
    p = i + a;
    a -= i;

    rxs = xg + xf;
    rxf = xf * float_7af03c + float_7af044 * rxs;
    rxg = xg * float_7af040 - float_7af044 * rxs;
    int ra = (int)(rxf + (rxf > 0 ? 0.5f : -0.5f));
    int rb = (int)(rxg + (rxg > 0 ? 0.5f : -0.5f));

    sa = a;
    rx = sa;
    rx *= norm_7af038;
    a = (int)rx;
    d = rx >> 32;

    b = in[6];
    d += d;
    a = in[2];

    c = ra;
    i = rb;
    c += d;
    d += i;
    i += p;
    sc = c;
    sd = d;
    si = i;
    c = in[0];
    d = in[4];
    s = b + a;
    a -= b;
    b = d + c;
    c -= d;

    sa = a;
    rx = sa;
    rx *= norm_7af038;
    a = (int)rx;
    d = rx >> 32;

    d += d;
    out[18] = (c - d) + sc;
    out[45] = (c - d) - sc;
    out[27] = (b - (s + d)) + ra;
    out[36] = (b - (s + d)) - ra;
    out[0] = (s + d) + b + si;
    out[9] = sd + d + c;
    out[54] = d + c - sd;
    out[63] = (s + d) + b - si;
}

static void decompress_func2(int *in, int *out)
{
    int64_t rx;
    int sa;
    int b, a, c, d, i, p, s;
    unsigned int sc, sd, si;
    int ra, rb;
    double rxf, rxg, rxs;
    double xf, xg;

    b = in[5] - in[3];
    c = in[1] - in[7];
    i = in[3] + in[5];
    a = in[7] + in[1];
    xf = b;
    xg = c;
    p = i + a;
    a -= i;

    rxs = xg + xf;
    rxf = xf * float_7af03c + float_7af044 * rxs;
    rxg = xg * float_7af040 - float_7af044 * rxs;
    ra = (int)(rxf + (rxf > 0 ? 0.5f : -0.5f));
    rb = (int)(rxg + (rxg > 0 ? 0.5f : -0.5f));

    sa = a;
    rx = sa;
    rx *= norm_7af038;
    a = (int)rx;
    d = rx >> 32;

    b = in[6];
    d += d;
    a = in[2];

    c = ra;
    i = rb;
    c += d;
    d += i;
    i += p;
    sc = c;
    sd = d;
    si = i;
    c = in[0];
    d = in[4];
    s = b + a;
    a -= b;
    b = d + c;
    c -= d;

    sa = a;
    rx = sa;
    rx *= norm_7af038;
    a = (int)rx;
    d = rx >> 32;

    d += d;
    p = sc;
    s += d;
    a = d + c;
    c -= d;
    d = s + b;
    b -= s;
    s = c + p;
    c -= p;
    p = ra;
    out[2] = s;
    s = sd;
    out[5] = c;
    c = b + p;
    b -= p;
    p = si;
    out[3] = c;
    out[4] = b;
    b = s + a;
    a -= s;
    c = d + p;
    d -= p;
    out[0] = c;
    out[1] = b;
    out[6] = a;
    out[7] = d;
}

static void decompress(bool hasAlpha)
{
  unsigned char jt_index, jt_value;
  unsigned int bs_pos = bs_index;
  int value;
  unsigned char blanket_fill;
  
  /* red */
  value = 0;
  jt_index = bs_read(bs_pos, 8);

  jt_value = jump_table_7af4e0[jt_index];
  bs_pos += jt_value & 0xf;
  jt_value >>= 4;
  if( jt_value ) {
    /* value is signed */
    value = bs_read(bs_pos, jt_value);
    if( (value & (1  16, 0, 255);
            out[i * 4 + 3] = hasAlpha ? clamp(a >> 16, 0, 255) : 255;
        }
        out += stride;
        inp += 64;
    }
}

inline void initialize_dd(stream_uint32 *buf)
{
    bs = buf;
    bs_index = 0;
    bs_red = 0;
    bs_blue = 0;
    bs_green = 0;
    bs_alpha = 0;
}

static void dd_texture(stream_uint32 *buf, unsigned char *outp, unsigned int stride, unsigned short width, unsigned short height, bool hasAlpha)
{
    initialize_dd(buf);

    for(unsigned short y = 0; y < height; y += 8)
    for(unsigned short x = 0; x < width; x += 8) 
    {
        decompress_block(&outp[y * stride + x * 4], stride, hasAlpha);
    }
}

//////////////////////////////////////////////////////////////////////////

static void decompress_block_444(unsigned char *out, unsigned short stride, bool hasAlpha)
{
    unsigned int bs_pos = bs_index;
    unsigned int red = bs_read(bs_pos, 8);
    bs_index = prepare_decompress(red, bs_pos + 8);
    for (int i = 0; i < 8; i++) 
    {
        decompress_func1(&decompress2_chunk[i * 8], &decompress3_chunk[i]);
    }
    for (int i = 0; i < 8; i++) 
    {
        decompress_func2(&decompress3_chunk[i * 9], &decompress4_chunk[i * 64]);
    }
    bs_pos = bs_index;

    unsigned int green = bs_read(bs_pos, 8);
    bs_index = prepare_decompress(green, bs_pos + 8);
    for (int i = 0; i < 8; i++) 
    {
        decompress_func1(&decompress2_chunk[i * 8], &decompress3_chunk[i]);
    }
    for (int i = 0; i < 8; i++) 
    {
        decompress_func2(&decompress3_chunk[i * 9], &decompress4_chunk[i * 64 + 9]);
    }
    bs_pos = bs_index;

    unsigned int blue = bs_read(bs_pos, 8);
    bs_index = prepare_decompress(blue, bs_pos + 8);
    for (int i = 0; i < 8; i++) 
    {
        decompress_func1(&decompress2_chunk[i * 8], &decompress3_chunk[i]);
    }
    for (int i = 0; i < 8; i++) 
    {
        decompress_func2(&decompress3_chunk[i * 9], &decompress4_chunk[i * 64 + 18]);
    }
    bs_pos = bs_index;

    if (hasAlpha)
    {
        unsigned int alpha = bs_read(bs_pos, 8);
        bs_index = prepare_decompress(alpha, bs_pos + 8);
        for (int i = 0; i < 8; i++) 
        {
            decompress_func1(&decompress2_chunk[i * 8], &decompress3_chunk[i]);
        }
        for (int i = 0; i < 8; i++) 
        {
            decompress_func2(&decompress3_chunk[i * 9], &decompress4_chunk[i * 64 + 27]);
        }
        bs_pos = bs_index;
    }

    /* another check for a flag at 668dc7, set in the master routine */
    /* dword_7af600 = dest */

    const int* inp = decompress4_chunk;
    if (hasAlpha) 
    {
        cxx_assert(false);
    } 
    else 
    {
        const int* inp = decompress4_chunk;
        for (int j = 0; j < 8; ++j) 
        {
            for(int i = 0; i < 8; ++i) 
            {
                int r = inp[i +  0];
                int g = inp[i + 18];
                int b = inp[i +  9];

                out[i * 4 + 0] = clamp(r >> 16, 0, 255);
                out[i * 4 + 1] = clamp(b >> 16, 0, 255);
                out[i * 4 + 2] = clamp(g >> 16, 0, 255);
                out[i * 4 + 3] = 255;
            }
            out += stride;
            inp += 64;
        }
    }
}

static void dd_texture_444(stream_uint32 *buf, unsigned char *outp, unsigned int stride, unsigned short width, unsigned short height, bool hasAlpha)
{
    initialize_dd(buf);

    for(unsigned short y = 0; y < height; y += 8)
    {
        for(unsigned short x = 0; x < width; x += 8) 
        {
            decompress_block_444(&outp[y * stride + x * 4], stride, hasAlpha);
        }
    }
}

//////////////////////////////////////////////////////////////////////////

struct DK2EngineTextureEntry
{
    DK2EngineTextureEntry()
        : mName()
        , mSizeX()
        , mSizeY()
        , mSizeX2()
        , mSizeY2()
        , mDataLength()
        , mDataStartLocation()
        , mHasAlpha()
    {}
    
    // data
    const char* mName;
    int mSizeX;
    int mSizeY;
    int mSizeX2;
    int mSizeY2;
    int mDataLength;
    int mDataStartLocation;
    bool mHasAlpha;
};

typedef std::vector DK2EngineTextureEntries;
struct DK2EngineTexturesCacheDir
{
public:
    std::ifstream           mDatStream;
    ByteArray               mDirContent;
    DK2EngineTextureEntries mEntries;
};
static DK2EngineTexturesCacheDir* gCacheDir = nullptr;

//////////////////////////////////////////////////////////////////////////
static bool dk2_read_dir_content(const char* theDirFilepath, const char* theDatFilename)
{

    struct dk2_dir_header
    {
        unsigned int mSignature; // TCHC
        int mDataLength;
        int mVersion;
        int mEntriesCount;
    };

    int numEntries = 0;
    { std::ifstream fileStream {theDirFilepath, std::ios::in | std::ios::binary};
        if (!fileStream.is_open())
            return false;

        // read header
        dk2_dir_header dirHeader {};
        cxx::read_elements(fileStream, &dirHeader, 1);
        if (dirHeader.mSignature != MAKEDWORD('T','C','H','C'))
            return false;

        // read dir content
        const int dirLength = dirHeader.mDataLength - sizeof(dk2_dir_header);
        gCacheDir->mDirContent.resize(dirLength);
        if(!fileStream.read((char*) &gCacheDir->mDirContent[0], dirLength))
            return false;

        numEntries = dirHeader.mEntriesCount;
    }

    // scan dir entities
    gCacheDir->mDatStream.open(theDatFilename, std::ios::in | std::ios::binary);
    if (!gCacheDir->mDatStream.is_open())
        return false;

    // allocate entries
    gCacheDir->mEntries.resize(numEntries);

    // read entries
    unsigned char* cursorPos = &gCacheDir->mDirContent[0];
    for (int i = 0; i < numEntries; ++i)
    {
        // read name
        gCacheDir->mEntries[i].mName = (const char*)cursorPos;
        for (;;) {
            if (*(cursorPos++) == 0)
                break;
        }
        // read data offset ot dat file
        int offset = cursorPos[0] | 
            (cursorPos[1] mDatStream, &sizeY, 1);
        cxx::read_elements(gCacheDir->mDatStream, &dataSize, 1);  // need correction

        unsigned short shortDataX = 0;
        unsigned short shortDataY = 0;
        cxx::read_elements(gCacheDir->mDatStream, &shortDataX, 1);
        cxx::read_elements(gCacheDir->mDatStream, &shortDataY, 1);

        unsigned int someFlags = 0;
        cxx::read_elements(gCacheDir->mDatStream, &someFlags, 1);

        gCacheDir->mEntries[i].mSizeX = sizeX;
        gCacheDir->mEntries[i].mSizeY = sizeY;
        gCacheDir->mEntries[i].mDataLength = dataSize - 8;
        gCacheDir->mEntries[i].mSizeX2 = shortDataX;
        gCacheDir->mEntries[i].mSizeY2 = shortDataY;
        gCacheDir->mEntries[i].mHasAlpha = (someFlags >> 7) > 0;
        gCacheDir->mEntries[i].mDataStartLocation = offset + 20;
    }

    return true;
}

static bool DK2_GetEngineTextureDesc(int theIndex, DK2EngineTextureEntry* theOutput)
{
    int numEntries = gCacheDir->mEntries.size();
    if (gCacheDir && theIndex < numEntries)
    {
        theOutput[0] = gCacheDir->mEntries[theIndex];
        return true;
    }
    return false;
}

static bool DK2_ExtractEngineTexturePixels(int theIndex, unsigned char* theOutputBuffer)
{
    int numEntries = gCacheDir->mEntries.size();
    if (gCacheDir && theIndex < numEntries)
    {
        stream_uint32 uint32stream (gCacheDir->mDatStream, 
            gCacheDir->mEntries[theIndex].mDataStartLocation, 
            gCacheDir->mEntries[theIndex].mDataLength);

        dd_texture(&uint32stream, theOutputBuffer, 
            gCacheDir->mEntries[theIndex].mSizeX * 4,
            gCacheDir->mEntries[theIndex].mSizeX,
            gCacheDir->mEntries[theIndex].mSizeY, gCacheDir->mEntries[theIndex].mHasAlpha);
        return true;
    }
    return false;
}

static bool DK2_OpenEngineTexturesCache(const char* theCacheLocation)
{
    cxx_assert(gCacheDir == nullptr);
    if (gCacheDir)
    {
        return true;
    }

    std::string pathDat = cxx::va("%s/EngineTextures.dat", theCacheLocation);
    std::string pathDir = cxx::va("%s/EngineTextures.dir", theCacheLocation);

    gCacheDir = new DK2EngineTexturesCacheDir;

    // read dir content
    if (!dk2_read_dir_content(pathDir.c_str(), pathDat.c_str()))
    {
        SafeDelete(gCacheDir);
        return false;
    }
    return true;
}

static void DK2_CloseEngineTexturesCache()
{
    SafeDelete(gCacheDir);
}

static bool DK2_GetEngineTexturesCount(int* theOutput)
{
    if (!gCacheDir)
    {
        return false;
    }
    *theOutput = gCacheDir->mEntries.size();
    return true;
}

//////////////////////////////////////////////////////////////////////////

inline int GetMipmapLevelFromName(const std::string& theString)
{
    const int stringLength = theString.length();
    if (stringLength < 3)
    {
        return -1;
    }
    bool isMipmap = (theString[stringLength - 3] == 'M') && (theString[stringLength - 2] == 'M');
    if (!isMipmap)
    {
        return -1;
    }

    char mchar = theString[stringLength - 1];
    if (mchar < '0' || mchar > '9')
    {
        return -1;
    }
    return mchar - '0';
}

//////////////////////////////////////////////////////////////////////////

DK2EngineTexturesCache::DK2EngineTexturesCache()
{}

DK2EngineTexturesCache::~DK2EngineTexturesCache()
{
    Shutdown();
}

bool DK2EngineTexturesCache::ScanDungeonKeeperTexturesCache(const std::string& theTexturesCachePath)
{
    DK2_CloseEngineTexturesCache();
    if (!DK2_OpenEngineTexturesCache(theTexturesCachePath.c_str()))
    {
        gConsole.LogMessage(eLogLevel_Warning, "Cannot open engine textures cache");
        return false;
    }
    int numEntries;
    if (!DK2_GetEngineTexturesCount(&numEntries))
    {
        gConsole.LogMessage(eLogLevel_Warning, "Cannot query engine textures cache entries");
        return false;
    }
    gConsole.LogMessage(eLogLevel_Info, "Found %d entries in engine textures cache", numEntries);

    mEntries.reserve(2048);
    for (int ientry = 0; ientry < numEntries; ++ientry)
    {
        DK2EngineTextureEntry engineTextureDesc;
        if (!DK2_GetEngineTextureDesc(ientry, &engineTextureDesc))
        {
            gConsole.LogMessage(eLogLevel_Warning, "Cannot query information of %d entry", ientry);
            continue;
        }
        std::string textureName = engineTextureDesc.mName;

        const int iMip = GetMipmapLevelFromName(textureName);
        if ((iMip < 0) || (iMip > MAX_ENGINE_TEXTURE_MIPS - 1))
        {
            cxx_assert(false);

            gConsole.LogMessage(eLogLevel_Warning, "Ignore texture '%s'", engineTextureDesc.mName);
            continue;
        }
        // remove MMn suffix
        textureName.erase(
            textureName.begin() + textureName.length() - 3,
            textureName.end());

        DK2EngineTextureID textureID;

        auto entry_iterator = mIndices.find(textureName);
        if (entry_iterator == mIndices.end())
        {
            textureID = mEntries.size();
            mIndices.emplace(textureName, textureID);
            mEntries.push_back({});
        }
        else
        {
            textureID = entry_iterator->second;
        }

        DK2EngineTextureDesc& textureEntry = mEntries[textureID];
        textureEntry.mHasAlpha = textureEntry.mHasAlpha || engineTextureDesc.mHasAlpha;
        textureEntry.mMips[iMip].mDimX = engineTextureDesc.mSizeX;
        textureEntry.mMips[iMip].mDimY = engineTextureDesc.mSizeY;
        textureEntry.mMips[iMip].mEntryIndex = ientry;
        ++textureEntry.mMipsCount;
    }
    gConsole.LogMessage(eLogLevel_Info, "Found %d unique entries in textures cache", mEntries.size());
    return true;
}

void DK2EngineTexturesCache::Shutdown()
{
    DK2_CloseEngineTexturesCache();
    mIndices.clear();
    mEntries.clear();
}

bool DK2EngineTexturesCache::ExtractTexture(DK2EngineTextureID theTextureID, BitmapImage& outputBitmap) const
{
    bool isTextureID = theTextureID < mEntries.size();

    cxx_assert(isTextureID);
    if (!isTextureID)
    {
        gConsole.LogMessage(eLogLevel_Warning, "Invalid engine texture id %d", theTextureID);
        return false;
    }

    const DK2EngineTextureDesc& texEntry = mEntries[theTextureID];
    
    if (texEntry.mMips[0].mEntryIndex < 0)
    {
        gConsole.LogMessage(eLogLevel_Warning, "Engine texture mip #0 is not defined for %d", theTextureID);
        return false;
    }

    // create image
    Point2D dims {texEntry.mMips[0].mDimX, texEntry.mMips[0].mDimY};
    outputBitmap.Clear();
    if (!outputBitmap.Create(ePixelFormat_RGBA8, dims, nullptr))
    {
        gConsole.LogMessage(eLogLevel_Warning, "Cannot create memory bitmap for %d", theTextureID);
        return false;
    }

    unsigned char* pixels = outputBitmap.GetMipPixels(0);
    if (!DK2_ExtractEngineTexturePixels(texEntry.mMips[0].mEntryIndex, pixels))
    {
        gConsole.LogMessage(eLogLevel_Warning, "Cannot extract texture pixels for %d", theTextureID);
        return false;
    }

    // extract mipmaps
    for (int imip = 1; imip < MAX_ENGINE_TEXTURE_MIPS; ++imip)
    {
        const int texindex = texEntry.mMips[imip].mEntryIndex;
        if (texindex < 0)
        {
            continue;
        }

        DK2EngineTextureEntry desc;
        if (!DK2_GetEngineTextureDesc(texindex, &desc))
        {
            gConsole.LogMessage(eLogLevel_Warning, "Cannot query texture desc mipmap %d for %d", imip, theTextureID);
            continue;
        }
        Point2D mipDims {desc.mSizeX, desc.mSizeY};
        outputBitmap.AddMipLevel(mipDims, &pixels);
        if (!DK2_ExtractEngineTexturePixels(texindex, pixels))
        {
            gConsole.LogMessage(eLogLevel_Warning, "Cannot extract texture mipmap %d for %d", imip, theTextureID);
            continue;
        }
    }

    outputBitmap.SetHasAlphaHint(texEntry.mHasAlpha);
    return true;
}


bool DK2EngineTexturesCache::Decompress444(const ByteArray& textureData, BitmapImage& outputImage)
{
    outputImage.Clear();

    unsigned short sizex;
    unsigned short sizey;
    unsigned int flags;

    // read metadata
    {
        cxx::memory_istream memorystream((char*)textureData.data(), (char*)textureData.data() + textureData.size());
        std::istream instream(&memorystream);
        if (!instream.read((char*)&sizex, sizeof(sizex)) || 
            !instream.read((char*)&sizey, sizeof(sizey)) || 
            !instream.read((char*)&flags, sizeof(flags)))
        {
            cxx_assert(false);
            return false;
        }
    }

    bool hasAlpha = (flags & 0x80) > 0;

    unsigned int metadataLength = sizeof(sizex) + sizeof(sizey) + sizeof(flags);
    unsigned int dataLength = textureData.size() - metadataLength;

    if (!outputImage.Create(ePixelFormat_RGBA8, {sizex, sizey}, COLOR_BLACK))
    {
        cxx_assert(false);
        return false;
    }

    cxx::memory_istream memorystream((char*)&textureData[0], (char*) &textureData[0] + textureData.size());
    std::istream instream(&memorystream);
    stream_uint32 uint32stream (instream, metadataLength, dataLength);

    dd_texture_444(&uint32stream, outputImage.GetMipPixels(0), sizex * 4, sizex, sizey, hasAlpha);

    outputImage.SetHasAlphaHint(hasAlpha);
    return true;
}

bool DK2EngineTexturesCache::FindTextureByName(const std::string& theTextureName, DK2EngineTextureID& theTextureID) const
{
    auto found_iterator = mIndices.find(theTextureName);
    if (found_iterator != mIndices.end())
    {
        theTextureID = found_iterator->second;
        return true;
    }
    return false;
}

bool DK2EngineTexturesCache::ExtractTextureInfo(DK2EngineTextureID theTextuteID, DK2EngineTextureDesc& outputInfo) const
{
    cxx_assert(theTextuteID < mEntries.size());
    if (theTextuteID < mEntries.size())
    {
        outputInfo = mEntries[theTextuteID];
        return true;
    }
    gConsole.LogMessage(eLogLevel_Warning, "Invalid engine texture id %d", theTextuteID);
    return false;
}

bool DK2EngineTexturesCache::GetTextureNameByID(DK2EngineTextureID theTextureID, std::string& textureName) const
{
    textureName.clear();
    for (const auto& roller: mIndices)
    {
        if (roller.second == theTextureID)
        {
            textureName = roller.first;
            return true;
        }
    }
    return false;
}

Web Proxy Viewer  |  New URL  |  Original Page