コード例 #1
0
 private unsafe static void DecodeBlock(byte *input, int blockWidth, int blockHeight, uint *output)
 {
     if (input[0] == 0xfc && (input[1] & 1) == 1)
     {
         uint c = Color(input[9], input[11], input[13], input[15]);
         for (int i = 0; i < blockWidth * blockHeight; i++)
         {
             output[i] = c;
         }
     }
     else
     {
         BlockData blockData = new BlockData();
         blockData.bw = blockWidth;
         blockData.bh = blockHeight;
         BlockData *blockPtr = &blockData;
         DecodeBlockParameters(input, blockPtr);
         DecodeEndpoints(input, blockPtr);
         DecodeWeights(input, blockPtr);
         if (blockData.part_num > 1)
         {
             SelectPartition(input, blockPtr);
         }
         ApplicateColor(blockPtr, output);
     }
 }
コード例 #2
0
 private unsafe static void ApplicateColor(BlockData *block, uint *output)
 {
     if (block->dual_plane != 0)
     {
         int *ps = stackalloc int[] { 0, 0, 0, 0 };
         ps[block->plane_selector] = 1;
         if (block->part_num > 1)
         {
             for (int i = 0; i < block->bw * block->bh; i++)
             {
                 int  p = block->partition[i];
                 byte r = SelectColor(block->endpoints[p * 8 + 0], block->endpoints[p * 8 + 4], block->weights[i * 2 + ps[0]]);
                 byte g = SelectColor(block->endpoints[p * 8 + 1], block->endpoints[p * 8 + 5], block->weights[i * 2 + ps[1]]);
                 byte b = SelectColor(block->endpoints[p * 8 + 2], block->endpoints[p * 8 + 6], block->weights[i * 2 + ps[2]]);
                 byte a = SelectColor(block->endpoints[p * 8 + 3], block->endpoints[p * 8 + 7], block->weights[i * 2 + ps[3]]);
                 output[i] = Color(r, g, b, a);
             }
         }
         else
         {
             for (int i = 0; i < block->bw * block->bh; i++)
             {
                 byte r = SelectColor(block->endpoints[0], block->endpoints[4], block->weights[i * 2 + ps[0]]);
                 byte g = SelectColor(block->endpoints[1], block->endpoints[5], block->weights[i * 2 + ps[1]]);
                 byte b = SelectColor(block->endpoints[2], block->endpoints[6], block->weights[i * 2 + ps[2]]);
                 byte a = SelectColor(block->endpoints[3], block->endpoints[7], block->weights[i * 2 + ps[3]]);
                 output[i] = Color(r, g, b, a);
             }
         }
     }
     else if (block->part_num > 1)
     {
         for (int i = 0; i < block->bw * block->bh; i++)
         {
             int  p = block->partition[i];
             byte r = SelectColor(block->endpoints[p * 8 + 0], block->endpoints[p * 8 + 4], block->weights[i * 2]);
             byte g = SelectColor(block->endpoints[p * 8 + 1], block->endpoints[p * 8 + 5], block->weights[i * 2]);
             byte b = SelectColor(block->endpoints[p * 8 + 2], block->endpoints[p * 8 + 6], block->weights[i * 2]);
             byte a = SelectColor(block->endpoints[p * 8 + 3], block->endpoints[p * 8 + 7], block->weights[i * 2]);
             output[i] = Color(r, g, b, a);
         }
     }
     else
     {
         for (int i = 0; i < block->bw * block->bh; i++)
         {
             byte r = SelectColor(block->endpoints[0], block->endpoints[4], block->weights[i * 2]);
             byte g = SelectColor(block->endpoints[1], block->endpoints[5], block->weights[i * 2]);
             byte b = SelectColor(block->endpoints[2], block->endpoints[6], block->weights[i * 2]);
             byte a = SelectColor(block->endpoints[3], block->endpoints[7], block->weights[i * 2]);
             output[i] = Color(r, g, b, a);
         }
     }
 }
コード例 #3
0
        private unsafe static void SelectPartition(byte *input, BlockData *block)
        {
            bool small_block = block->bw * block->bh < 31;
            int  seed        = (*((int *)input) >> 13 & 0x3ff) | (block->part_num - 1) << 10;

            uint rnum;

            unchecked
            {
                rnum  = (uint)seed;
                rnum ^= rnum >> 15;
                rnum -= rnum << 17;
                rnum += rnum << 7;
                rnum += rnum << 4;
                rnum ^= rnum >> 5;
                rnum += rnum << 16;
                rnum ^= rnum >> 7;
                rnum ^= rnum >> 3;
                rnum ^= rnum << 6;
                rnum ^= rnum >> 17;
            }

            int *seeds = stackalloc int[8];

            for (int i = 0; i < 8; i++)
            {
                seeds[i]  = (int)((rnum >> (i * 4)) & 0xF);
                seeds[i] *= seeds[i];
            }


            int *sh = stackalloc int[2];

            sh[0] = (seed & 2) != 0 ? 4 : 5;
            sh[1] = block->part_num == 3 ? 6 : 5;

            if ((seed & 1) != 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    seeds[i] >>= sh[i % 2];
                }
            }
            else
            {
                for (int i = 0; i < 8; i++)
                {
                    seeds[i] >>= sh[1 - i % 2];
                }
            }

            if (small_block)
            {
                for (int t = 0, i = 0; t < block->bh; t++)
                {
                    for (int s = 0; s < block->bw; s++, i++)
                    {
                        int x = s << 1;
                        int y = t << 1;
                        int a = (int)((seeds[0] * x + seeds[1] * y + (rnum >> 14)) & 0x3f);
                        int b = (int)((seeds[2] * x + seeds[3] * y + (rnum >> 10)) & 0x3f);
                        int c = (int)(block->part_num < 3 ? 0 : (seeds[4] * x + seeds[5] * y + (rnum >> 6)) & 0x3f);
                        int d = (int)(block->part_num < 4 ? 0 : (seeds[6] * x + seeds[7] * y + (rnum >> 2)) & 0x3f);
                        block->partition[i] = (a >= b && a >= c && a >= d) ? 0 : (b >= c && b >= d) ? 1 : (c >= d) ? 2 : 3;
                    }
                }
            }
            else
            {
                for (int y = 0, i = 0; y < block->bh; y++)
                {
                    for (int x = 0; x < block->bw; x++, i++)
                    {
                        int a = (int)((seeds[0] * x + seeds[1] * y + (rnum >> 14)) & 0x3f);
                        int b = (int)((seeds[2] * x + seeds[3] * y + (rnum >> 10)) & 0x3f);
                        int c = (int)(block->part_num < 3 ? 0 : (seeds[4] * x + seeds[5] * y + (rnum >> 6)) & 0x3f);
                        int d = (int)(block->part_num < 4 ? 0 : (seeds[6] * x + seeds[7] * y + (rnum >> 2)) & 0x3f);
                        block->partition[i] = (a >= b && a >= c && a >= d) ? 0 : (b >= c && b >= d) ? 1 : (c >= d) ? 2 : 3;
                    }
                }
            }
        }
コード例 #4
0
        private unsafe static void DecodeEndpoints(byte *input, BlockData *pBlock)
        {
            IntSeqData *epSeq = stackalloc IntSeqData[32];

            DecodeIntseq(input, pBlock->part_num == 1 ? 17 : 29, CemTableA[pBlock->cem_range], CemTableB[pBlock->cem_range], pBlock->endpoint_value_num, false, epSeq);

            int *ev = stackalloc int[32];

            switch (CemTableA[pBlock->cem_range])
            {
            case 3:
                for (int i = 0, b = 0, c = DETritsTable[CemTableB[pBlock->cem_range]]; i < pBlock->endpoint_value_num; i++)
                {
                    int a = (epSeq[i].bits & 1) * 0x1ff;
                    int x = epSeq[i].bits >> 1;
                    switch (CemTableB[pBlock->cem_range])
                    {
                    case 1:
                        b = 0;
                        break;

                    case 2:
                        b = 0b100010110 * x;
                        break;

                    case 3:
                        b = x << 7 | x << 2 | x;
                        break;

                    case 4:
                        b = x << 6 | x;
                        break;

                    case 5:
                        b = x << 5 | x >> 2;
                        break;

                    case 6:
                        b = x << 4 | x >> 4;
                        break;
                    }
                    ev[i] = (a & 0x80) | ((epSeq[i].nonbits * c + b) ^ a) >> 2;
                }
                break;

            case 5:
                for (int i = 0, b = 0, c = DEQuintsTable[CemTableB[pBlock->cem_range]]; i < pBlock->endpoint_value_num; i++)
                {
                    int a = (epSeq[i].bits & 1) * 0x1ff;
                    int x = epSeq[i].bits >> 1;
                    switch (CemTableB[pBlock->cem_range])
                    {
                    case 1:
                        b = 0;
                        break;

                    case 2:
                        b = 0b100001100 * x;
                        break;

                    case 3:
                        b = x << 7 | x << 1 | x >> 1;
                        break;

                    case 4:
                        b = x << 6 | x >> 1;
                        break;

                    case 5:
                        b = x << 5 | x >> 3;
                        break;
                    }
                    ev[i] = (a & 0x80) | ((epSeq[i].nonbits * c + b) ^ a) >> 2;
                }
                break;

            default:
                switch (CemTableB[pBlock->cem_range])
                {
                case 1:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits * 0xff;
                    }
                    break;

                case 2:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits * 0x55;
                    }
                    break;

                case 3:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits << 5 | epSeq[i].bits << 2 | epSeq[i].bits >> 1;
                    }
                    break;

                case 4:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits << 4 | epSeq[i].bits;
                    }
                    break;

                case 5:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits << 3 | epSeq[i].bits >> 2;
                    }
                    break;

                case 6:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits << 2 | epSeq[i].bits >> 4;
                    }
                    break;

                case 7:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits << 1 | epSeq[i].bits >> 6;
                    }
                    break;

                case 8:
                    for (int i = 0; i < pBlock->endpoint_value_num; i++)
                    {
                        ev[i] = epSeq[i].bits;
                    }
                    break;
                }
                break;
            }

            int *v = ev;

            for (int cem = 0, cemOff = 0; cem < pBlock->part_num; v += (pBlock->cem[cem] / 4 + 1) * 2, cem++, cemOff += 8)
            {
                switch (pBlock->cem[cem])
                {
                case 0:
                    SetEndpoint(&pBlock->endpoints[cemOff], v[0], v[0], v[0], 255, v[1], v[1], v[1], 255);
                    break;

                case 1:
                {
                    int l0 = (v[0] >> 2) | (v[1] & 0xc0);
                    int l1 = Clamp(l0 + (v[1] & 0x3f));
                    SetEndpoint(&pBlock->endpoints[cemOff], l0, l0, l0, 255, l1, l1, l1, 255);
                }
                break;

                case 4:
                    SetEndpoint(&pBlock->endpoints[cemOff], v[0], v[0], v[0], v[2], v[1], v[1], v[1], v[3]);
                    break;

                case 5:
                    BitTransferSigned(&v[1], &v[0]);
                    BitTransferSigned(&v[3], &v[2]);
                    v[1] += v[0];
                    SetEndpointClamp(&pBlock->endpoints[cemOff], v[0], v[0], v[0], v[2], v[1], v[1], v[1], v[2] + v[3]);
                    break;

                case 6:
                    SetEndpoint(&pBlock->endpoints[cemOff], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, 255, v[0], v[1], v[2], 255);
                    break;

                case 8:
                    if (v[0] + v[2] + v[4] <= v[1] + v[3] + v[5])
                    {
                        SetEndpoint(&pBlock->endpoints[cemOff], v[0], v[2], v[4], 255, v[1], v[3], v[5], 255);
                    }
                    else
                    {
                        SetEndpointBlue(&pBlock->endpoints[cemOff], v[1], v[3], v[5], 255, v[0], v[2], v[4], 255);
                    }
                    break;

                case 9:
                    BitTransferSigned(&v[1], &v[0]);
                    BitTransferSigned(&v[3], &v[2]);
                    BitTransferSigned(&v[5], &v[4]);
                    if (v[1] + v[3] + v[5] >= 0)
                    {
                        SetEndpointClamp(&pBlock->endpoints[cemOff], v[0], v[2], v[4], 255, v[0] + v[1], v[2] + v[3], v[4] + v[5], 255);
                    }
                    else
                    {
                        SetEndpointBlueClamp(&pBlock->endpoints[cemOff], v[0] + v[1], v[2] + v[3], v[4] + v[5], 255, v[0], v[2], v[4], 255);
                    }
                    break;

                case 10:
                    SetEndpoint(&pBlock->endpoints[cemOff], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, v[4], v[0], v[1], v[2], v[5]);
                    break;

                case 12:
                    if (v[0] + v[2] + v[4] <= v[1] + v[3] + v[5])
                    {
                        SetEndpoint(&pBlock->endpoints[cemOff], v[0], v[2], v[4], v[6], v[1], v[3], v[5], v[7]);
                    }
                    else
                    {
                        SetEndpointBlue(&pBlock->endpoints[cemOff], v[1], v[3], v[5], v[7], v[0], v[2], v[4], v[6]);
                    }
                    break;

                case 13:
                    BitTransferSigned(&v[1], &v[0]);
                    BitTransferSigned(&v[3], &v[2]);
                    BitTransferSigned(&v[5], &v[4]);
                    BitTransferSigned(&v[7], &v[6]);
                    if (v[1] + v[3] + v[5] >= 0)
                    {
                        SetEndpointClamp(&pBlock->endpoints[cemOff], v[0], v[2], v[4], v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5], v[6] + v[7]);
                    }
                    else
                    {
                        SetEndpointBlueClamp(&pBlock->endpoints[cemOff], v[0] + v[1], v[2] + v[3], v[4] + v[5], v[6] + v[7], v[0], v[2], v[4], v[6]);
                    }
                    break;
                }
            }
        }
コード例 #5
0
        private unsafe static void DecodeWeights(byte *input, BlockData *block)
        {
            IntSeqData *wSeq = stackalloc IntSeqData[128];

            DecodeIntseq(input, 128, WeightPrecTableA[block->weight_range], WeightPrecTableB[block->weight_range], block->weight_num, true, wSeq);

            int *wv = stackalloc int[128];

            if (WeightPrecTableA[block->weight_range] == 0)
            {
                switch (WeightPrecTableB[block->weight_range])
                {
                case 1:
                    for (int i = 0; i < block->weight_num; i++)
                    {
                        wv[i] = wSeq[i].bits != 0 ? 63 : 0;
                    }
                    break;

                case 2:
                    for (int i = 0; i < block->weight_num; i++)
                    {
                        wv[i] = wSeq[i].bits << 4 | wSeq[i].bits << 2 | wSeq[i].bits;
                    }
                    break;

                case 3:
                    for (int i = 0; i < block->weight_num; i++)
                    {
                        wv[i] = wSeq[i].bits << 3 | wSeq[i].bits;
                    }
                    break;

                case 4:
                    for (int i = 0; i < block->weight_num; i++)
                    {
                        wv[i] = wSeq[i].bits << 2 | wSeq[i].bits >> 2;
                    }
                    break;

                case 5:
                    for (int i = 0; i < block->weight_num; i++)
                    {
                        wv[i] = wSeq[i].bits << 1 | wSeq[i].bits >> 4;
                    }
                    break;
                }
                for (int i = 0; i < block->weight_num; i++)
                {
                    if (wv[i] > 32)
                    {
                        ++wv[i];
                    }
                }
            }
            else if (WeightPrecTableB[block->weight_range] == 0)
            {
                int s = WeightPrecTableA[block->weight_range] == 3 ? 32 : 16;
                for (int i = 0; i < block->weight_num; i++)
                {
                    wv[i] = wSeq[i].nonbits * s;
                }
            }
            else
            {
                if (WeightPrecTableA[block->weight_range] == 3)
                {
                    switch (WeightPrecTableB[block->weight_range])
                    {
                    case 1:
                        for (int i = 0; i < block->weight_num; i++)
                        {
                            wv[i] = wSeq[i].nonbits * 50;
                        }
                        break;

                    case 2:
                        for (int i = 0; i < block->weight_num; i++)
                        {
                            wv[i] = wSeq[i].nonbits * 23;
                            if ((wSeq[i].bits & 2) != 0)
                            {
                                wv[i] += 0b1000101;
                            }
                        }
                        break;

                    case 3:
                        for (int i = 0; i < block->weight_num; i++)
                        {
                            wv[i] = wSeq[i].nonbits * 11 + ((wSeq[i].bits << 4 | wSeq[i].bits >> 1) & 0b1100011);
                        }
                        break;
                    }
                }
                else if (WeightPrecTableA[block->weight_range] == 5)
                {
                    switch (WeightPrecTableB[block->weight_range])
                    {
                    case 1:
                        for (int i = 0; i < block->weight_num; i++)
                        {
                            wv[i] = wSeq[i].nonbits * 28;
                        }
                        break;

                    case 2:
                        for (int i = 0; i < block->weight_num; i++)
                        {
                            wv[i] = wSeq[i].nonbits * 13;
                            if ((wSeq[i].bits & 2) != 0)
                            {
                                wv[i] += 0b1000010;
                            }
                        }
                        break;
                    }
                }
                for (int i = 0; i < block->weight_num; i++)
                {
                    int a = (wSeq[i].bits & 1) * 0x7f;
                    wv[i] = (a & 0x20) | ((wv[i] ^ a) >> 2);
                    if (wv[i] > 32)
                    {
                        ++wv[i];
                    }
                }
            }

            int ds = (1024 + block->bw / 2) / (block->bw - 1);
            int dt = (1024 + block->bh / 2) / (block->bh - 1);
            int pn = block->dual_plane != 0 ? 2 : 1;

            for (int t = 0, i = 0; t < block->bh; t++)
            {
                for (int s = 0; s < block->bw; s++, i++)
                {
                    int gs  = (ds * s * (block->width - 1) + 32) >> 6;
                    int gt  = (dt * t * (block->height - 1) + 32) >> 6;
                    int fs  = gs & 0xf;
                    int ft  = gt & 0xf;
                    int v   = (gs >> 4) + (gt >> 4) * block->width;
                    int w11 = (fs * ft + 8) >> 4;
                    int w10 = ft - w11;
                    int w01 = fs - w11;
                    int w00 = 16 - fs - ft + w11;

                    for (int p = 0; p < pn; p++)
                    {
                        int p00 = wv[v * pn + p];
                        int p01 = wv[(v + 1) * pn + p];
                        int p10 = wv[(v + block->width) * pn + p];
                        int p11 = wv[(v + block->width + 1) * pn + p];
                        block->weights[i * 2 + p] = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4;
                    }
                }
            }
        }
コード例 #6
0
        private unsafe static void DecodeBlockParameters(byte *input, BlockData *pBlock)
        {
            pBlock->dual_plane   = (input[1] & 4) >> 2;
            pBlock->weight_range = (input[0] >> 4 & 1) | (input[1] << 2 & 8);

            if ((input[0] & 3) != 0)
            {
                pBlock->weight_range |= input[0] << 1 & 6;
                switch (input[0] & 0xc)
                {
                case 0:
                    pBlock->width  = (*((int *)input) >> 7 & 3) + 4;
                    pBlock->height = (input[0] >> 5 & 3) + 2;
                    break;

                case 4:
                    pBlock->width  = (*((int *)input) >> 7 & 3) + 8;
                    pBlock->height = (input[0] >> 5 & 3) + 2;
                    break;

                case 8:
                    pBlock->width  = (input[0] >> 5 & 3) + 2;
                    pBlock->height = (*((int *)input) >> 7 & 3) + 8;
                    break;

                case 12:
                    if ((input[1] & 1) != 0)
                    {
                        pBlock->width  = (input[0] >> 7 & 1) + 2;
                        pBlock->height = (input[0] >> 5 & 3) + 2;
                    }
                    else
                    {
                        pBlock->width  = (input[0] >> 5 & 3) + 2;
                        pBlock->height = (input[0] >> 7 & 1) + 6;
                    }
                    break;
                }
            }
            else
            {
                pBlock->weight_range |= input[0] >> 1 & 6;
                switch ((*((int *)input)) & 0x180)
                {
                case 0:
                    pBlock->width  = 12;
                    pBlock->height = (input[0] >> 5 & 3) + 2;
                    break;

                case 0x80:
                    pBlock->width  = (input[0] >> 5 & 3) + 2;
                    pBlock->height = 12;
                    break;

                case 0x100:
                    pBlock->width         = (input[0] >> 5 & 3) + 6;
                    pBlock->height        = (input[1] >> 1 & 3) + 6;
                    pBlock->dual_plane    = 0;
                    pBlock->weight_range &= 7;
                    break;

                case 0x180:
                    pBlock->width  = (input[0] & 0x20) != 0 ? 10 : 6;
                    pBlock->height = (input[0] & 0x20) != 0 ? 6 : 10;
                    break;
                }
            }

            pBlock->part_num = (input[1] >> 3 & 3) + 1;

            pBlock->weight_num = pBlock->width * pBlock->height;
            if (pBlock->dual_plane != 0)
            {
                pBlock->weight_num *= 2;
            }

            int weight_bits, config_bits, cem_base = 0;

            switch (WeightPrecTableA[pBlock->weight_range])
            {
            case 3:
                weight_bits = pBlock->weight_num * WeightPrecTableB[pBlock->weight_range] + (pBlock->weight_num * 8 + 4) / 5;
                break;

            case 5:
                weight_bits = pBlock->weight_num * WeightPrecTableB[pBlock->weight_range] + (pBlock->weight_num * 7 + 2) / 3;
                break;

            default:
                weight_bits = pBlock->weight_num * WeightPrecTableB[pBlock->weight_range];
                break;
            }

            if (pBlock->part_num == 1)
            {
                pBlock->cem[0] = *((int *)(input + 1)) >> 5 & 0xf;
                config_bits    = 17;
            }
            else
            {
                cem_base = *((int *)(input + 2)) >> 7 & 3;
                if (cem_base == 0)
                {
                    int cem = input[3] >> 1 & 0xf;
                    for (int i = 0; i < pBlock->part_num; i++)
                    {
                        pBlock->cem[i] = cem;
                    }
                    config_bits = 29;
                }
                else
                {
                    for (int i = 0; i < pBlock->part_num; i++)
                    {
                        pBlock->cem[i] = ((input[3] >> (i + 1) & 1) + cem_base - 1) << 2;
                    }
                    switch (pBlock->part_num)
                    {
                    case 2:
                        pBlock->cem[0] |= input[3] >> 3 & 3;
                        pBlock->cem[1] |= GetBits(input, 126 - weight_bits, 2);
                        break;

                    case 3:
                        pBlock->cem[0] |= input[3] >> 4 & 1;
                        pBlock->cem[0] |= GetBits(input, 122 - weight_bits, 2) & 2;
                        pBlock->cem[1] |= GetBits(input, 124 - weight_bits, 2);
                        pBlock->cem[2] |= GetBits(input, 126 - weight_bits, 2);
                        break;

                    case 4:
                        for (int i = 0; i < 4; i++)
                        {
                            pBlock->cem[i] |= GetBits(input, 120 + i * 2 - weight_bits, 2);
                        }
                        break;
                    }
                    config_bits = 25 + pBlock->part_num * 3;
                }
            }

            if (pBlock->dual_plane != 0)
            {
                config_bits           += 2;
                pBlock->plane_selector = GetBits(input, cem_base != 0 ? 130 - weight_bits - pBlock->part_num * 3 : 126 - weight_bits, 2);
            }

            int remain_bits = 128 - config_bits - weight_bits;

            pBlock->endpoint_value_num = 0;
            for (int i = 0; i < pBlock->part_num; i++)
            {
                pBlock->endpoint_value_num += (pBlock->cem[i] >> 1 & 6) + 2;
            }

            for (int i = 0, endpoint_bits; i < CemTableA.Length; i++)
            {
                switch (CemTableA[i])
                {
                case 3:
                    endpoint_bits = pBlock->endpoint_value_num * CemTableB[i] + (pBlock->endpoint_value_num * 8 + 4) / 5;
                    break;

                case 5:
                    endpoint_bits = pBlock->endpoint_value_num * CemTableB[i] + (pBlock->endpoint_value_num * 7 + 2) / 3;
                    break;

                default:
                    endpoint_bits = pBlock->endpoint_value_num * CemTableB[i];
                    break;
                }

                if (endpoint_bits <= remain_bits)
                {
                    pBlock->cem_range = i;
                    break;
                }
            }
        }
コード例 #7
0
 internal static void Release(BlockData *data)
 {
     Marshal.FreeHGlobal((IntPtr)data);
 }
コード例 #8
0
ファイル: Save.cs プロジェクト: takaaptech/Voxelmetric
        public bool DoDecompression()
        {
            var pools    = Globals.WorkPool.GetPool(Chunk.ThreadID);
            var provider = Chunk.world.blockProvider;

            if (IsDifferential)
            {
                int blockPosSize  = StructSerialization.TSSize <BlockPos> .ValueSize;
                int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize;

                m_positionsModified = new BlockPos[m_positionsBytes.Length / blockPosSize];
                m_blocksModified    = new BlockData[m_blocksBytes.Length / blockDataSize];

                int i, j;
                unsafe
                {
                    // Extract positions
                    fixed(byte *pSrc = m_positionsBytes)
                    {
                        for (i = 0, j = 0; j < m_positionsModified.Length; i += blockPosSize, j++)
                        {
                            m_positionsModified[j] = *(BlockPos *)&pSrc[i];
                        }
                    }

                    // Extract block data
                    fixed(byte *pSrc = m_blocksBytes)
                    {
                        for (i = 0, j = 0; j < m_blocksModified.Length; i += blockDataSize, j++)
                        {
                            BlockData *bd = (BlockData *)&pSrc[i];
                            // Convert global block types into internal optimized version
                            ushort type = provider.GetTypeFromTypeInConfig(bd->Type);

                            m_blocksModified[j] = new BlockData(type, bd->Solid);
                        }
                    }
                }
            }
            else
            {
                int blockDataSize     = StructSerialization.TSSize <BlockData> .ValueSize;
                int requestedByteSize = Env.ChunkSizePow3 * blockDataSize;

                // Pop a large enough buffers from the pool
                var bytes = pools.ByteArrayPool.Pop(requestedByteSize);
                {
                    // Decompress data
                    int decompressedLength = CLZF2.lzf_decompress(m_blocksBytes, m_blocksBytes.Length, ref bytes);
                    if (decompressedLength != Env.ChunkSizePow3 * blockDataSize)
                    {
                        m_blocksBytes = null;
                        return(false);
                    }

                    // Fill chunk with decompressed data
                    ChunkBlocks blocks = Chunk.Blocks;
                    int         i      = 0;
                    unsafe
                    {
                        fixed(byte *pSrc = bytes)
                        {
                            int index   = Helpers.ZeroChunkIndex;
                            int yOffset = Env.ChunkSizeWithPaddingPow2 - Env.ChunkSize * Env.ChunkSizeWithPadding;
                            int zOffset = Env.ChunkSizeWithPadding - Env.ChunkSize;

                            for (int y = 0; y < Env.ChunkSize; ++y, index += yOffset)
                            {
                                for (int z = 0; z < Env.ChunkSize; ++z, index += zOffset)
                                {
                                    for (int x = 0; x < Env.ChunkSize; ++x, i += blockDataSize, ++index)
                                    {
                                        BlockData *bd = (BlockData *)&pSrc[i];

                                        // Convert global block type into internal optimized version
                                        ushort type = provider.GetTypeFromTypeInConfig(bd->Type);

                                        blocks.SetRaw(index, new BlockData(type, bd->Solid));
                                    }
                                }
                            }
                        }
                    }
                }
                // Return our temporary buffer back to the pool
                pools.ByteArrayPool.Push(bytes);
            }

            ResetTemporary();
            return(true);
        }
コード例 #9
0
ファイル: Save.cs プロジェクト: takaaptech/Voxelmetric
        public bool DoCompression()
        {
            if (Features.UseDifferentialSerialization)
            {
                var provider      = Chunk.world.blockProvider;
                int blockPosSize  = StructSerialization.TSSize <BlockPos> .ValueSize;
                int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize;

                int posLenBytes = m_blocksModified.Length * blockPosSize;
                int blkLenBytes = m_blocksModified.Length * blockDataSize;
                m_positionsBytes = new byte[posLenBytes];
                m_blocksBytes    = new byte[blkLenBytes];

                unsafe
                {
                    // Pack positions to a byte array
                    fixed(byte *pDst = m_positionsBytes)
                    {
                        for (int i = 0, j = 0; i < m_blocksModified.Length; i++, j += blockPosSize)
                        {
                            *(BlockPos *)&pDst[j] = m_positionsModified[i];
                        }
                    }

                    // Pack block data to a byte array
                    fixed(BlockData *pBD = m_blocksModified)
                    fixed(byte *pDst = m_blocksBytes)
                    {
                        for (int i = 0, j = 0; i < m_blocksModified.Length; i++, j += blockDataSize)
                        {
                            BlockData *bd = &pBD[i];
                            // Convert block types from internal optimized version into global types
                            ushort typeInConfig = provider.GetConfig(bd->Type).typeInConfig;

                            *(BlockData *)&pDst[j] = new BlockData(typeInConfig, bd->Solid);
                        }
                    }
                }
            }
            else
            {
                var pools    = Globals.WorkPool.GetPool(Chunk.ThreadID);
                var provider = Chunk.world.blockProvider;

                int blockDataSize     = StructSerialization.TSSize <BlockData> .ValueSize;
                int requestedByteSize = Env.ChunkSizePow3 * blockDataSize;

                // Pop large enough buffers from the pool
                byte[] tmp             = pools.ByteArrayPool.Pop(requestedByteSize);
                byte[] bytesCompressed = pools.ByteArrayPool.Pop(requestedByteSize);
                {
                    ChunkBlocks blocks = Chunk.Blocks;
                    int         i      = 0;

                    int index   = Helpers.ZeroChunkIndex;
                    int yOffset = Env.ChunkSizeWithPaddingPow2 - Env.ChunkSize * Env.ChunkSizeWithPadding;
                    int zOffset = Env.ChunkSizeWithPadding - Env.ChunkSize;

                    for (int y = 0; y < Env.ChunkSize; ++y, index += yOffset)
                    {
                        for (int z = 0; z < Env.ChunkSize; ++z, index += zOffset)
                        {
                            for (int x = 0; x < Env.ChunkSize; ++x, i += blockDataSize, ++index)
                            {
                                BlockData bd = blocks.Get(index);

                                // Convert block types from internal optimized version into global types
                                ushort typeInConfig = provider.GetConfig(bd.Type).typeInConfig;

                                // Write updated block data to destination buffer
                                unsafe
                                {
                                    fixed(byte *pDst = tmp)
                                    {
                                        *(BlockData *)&pDst[i] = new BlockData(typeInConfig, bd.Solid);
                                    }
                                }
                            }
                        }
                    }

                    // Compress bytes
                    int blkLenBytes = CLZF2.lzf_compress(tmp, requestedByteSize, ref bytesCompressed);
                    m_blocksBytes = new byte[blkLenBytes];

                    // Copy data from a temporary buffer to block buffer
                    Array.Copy(bytesCompressed, 0, m_blocksBytes, 0, blkLenBytes);
                }

                // Return our temporary buffer back to the pool
                pools.ByteArrayPool.Push(bytesCompressed);
                pools.ByteArrayPool.Push(tmp);
            }

            return(true);
        }
コード例 #10
0
        public bool DoDecompression()
        {
            LocalPools    pools    = Globals.WorkPool.GetPool(Chunk.ThreadID);
            BlockProvider provider = Chunk.World.blockProvider;

            if (IsDifferential)
            {
                int blockPosSize  = StructSerialization.TSSize <BlockPos> .ValueSize;
                int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize;

                positionsModified = new BlockPos[positionsBytes.Length / blockPosSize];
                blocksModified    = new BlockData[blocksBytes.Length / blockDataSize];

                int i, j;
                unsafe
                {
                    // Extract positions
                    fixed(byte *pSrc = positionsBytes)
                    {
                        for (i = 0, j = 0; j < positionsModified.Length; i += blockPosSize, j++)
                        {
                            positionsModified[j] = *(BlockPos *)&pSrc[i];
                            Chunk.Blocks.modifiedBlocks.Add(positionsModified[j]);
                        }
                    }

                    // Extract block data
                    fixed(byte *pSrc = blocksBytes)
                    {
                        for (i = 0, j = 0; j < blocksModified.Length; i += blockDataSize, j++)
                        {
                            BlockData *bd = (BlockData *)&pSrc[i];
                            // Convert global block types into internal optimized version
                            ushort type = provider.GetTypeFromTypeInConfig(bd->Type);

                            blocksModified[j] = new BlockData(type, bd->Solid);
                        }
                    }
                }
            }
            else
            {
                int blockDataSize     = StructSerialization.TSSize <BlockData> .ValueSize;
                int requestedByteSize = Env.CHUNK_SIZE_POW_3 * blockDataSize;

                // Pop a large enough buffers from the pool
                byte[] bytes = pools.byteArrayPool.Pop(requestedByteSize);
                {
                    // Decompress data
                    int decompressedLength = CLZF2.lzf_decompress(blocksBytes, blocksBytes.Length, ref bytes);
                    if (decompressedLength != Env.CHUNK_SIZE_POW_3 * blockDataSize)
                    {
                        blocksBytes = null;
                        return(false);
                    }

                    // Fill chunk with decompressed data
                    ChunkBlocks blocks = Chunk.Blocks;
                    int         i      = 0;
                    unsafe
                    {
                        fixed(byte *pSrc = bytes)
                        {
                            int index   = Helpers.ZERO_CHUNK_INDEX;
                            int yOffset = Env.CHUNK_SIZE_WITH_PADDING_POW_2 - Env.CHUNK_SIZE * Env.CHUNK_SIZE_WITH_PADDING;
                            int zOffset = Env.CHUNK_SIZE_WITH_PADDING - Env.CHUNK_SIZE;

                            for (int y = 0; y < Env.CHUNK_SIZE; ++y, index += yOffset)
                            {
                                for (int z = 0; z < Env.CHUNK_SIZE; ++z, index += zOffset)
                                {
                                    for (int x = 0; x < Env.CHUNK_SIZE; ++x, i += blockDataSize, ++index)
                                    {
                                        BlockData *bd = (BlockData *)&pSrc[i];

                                        // Convert global block type into internal optimized version
                                        ushort type = provider.GetTypeFromTypeInConfig(bd->Type);

                                        blocks.SetRaw(index, new BlockData(type, bd->Solid));
                                    }
                                }
                            }
                        }
                    }
                }
                // Return our temporary buffer back to the pool
                pools.byteArrayPool.Push(bytes);
            }

            ResetTemporary();
            return(true);
        }