예제 #1
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;
                    }
                }
            }
        }
예제 #2
0
        private unsafe static void DecodeIntseq(byte *input, int offset, int a, int b, int count, bool reverse, IntSeqData *_out)
        {
            if (count <= 0)
            {
                return;
            }

            int n = 0;

            if (a == 3)
            {
                int mask             = (1 << b) - 1;
                int block_count      = (count + 4) / 5;
                int last_block_count = (count + 4) % 5 + 1;
                int block_size       = 8 + 5 * b;
                int last_block_size  = (block_size * last_block_count + 4) / 5;

                if (reverse)
                {
                    for (int i = 0, p = offset; i < block_count; i++, p -= block_size)
                    {
                        int   now_size = (i < block_count - 1) ? block_size : last_block_size;
                        ulong d        = BitReverseU64(GetBits64(input, p - now_size, now_size), now_size);
                        int   x        = (int)((d >> b & 3) | (d >> b * 2 & 0xc) | (d >> b * 3 & 0x10) | (d >> b * 4 & 0x60) | (d >> b * 5 & 0x80));
                        for (int j = 0; j < 5 && n < count; j++, n++)
                        {
                            _out[n] = new IntSeqData()
                            {
                                bits    = (int)(d >> (DImt[j] + b * j)) & mask,
                                nonbits = DITritsTable[j * 256 + x],
                            };
                        }
                    }
                }
                else
                {
                    for (int i = 0, p = offset; i < block_count; i++, p += block_size)
                    {
                        ulong d = GetBits64(input, p, (i < block_count - 1) ? block_size : last_block_size);
                        int   x = (int)((d >> b & 3) | (d >> b * 2 & 0xc) | (d >> b * 3 & 0x10) | (d >> b * 4 & 0x60) | (d >> b * 5 & 0x80));
                        for (int j = 0; j < 5 && n < count; j++, n++)
                        {
                            _out[n] = new IntSeqData()
                            {
                                bits    = unchecked ((int)(d >> (DImt[j] + b * j))) & mask,
                                nonbits = DITritsTable[j * 256 + x],
                            };
                        }
                    }
                }
            }
            else if (a == 5)
            {
                int mask             = (1 << b) - 1;
                int block_count      = (count + 2) / 3;
                int last_block_count = (count + 2) % 3 + 1;
                int block_size       = 7 + 3 * b;
                int last_block_size  = (block_size * last_block_count + 2) / 3;

                if (reverse)
                {
                    for (int i = 0, p = offset; i < block_count; i++, p -= block_size)
                    {
                        int   now_size = (i < block_count - 1) ? block_size : last_block_size;
                        ulong d        = BitReverseU64(GetBits64(input, p - now_size, now_size), now_size);
                        int   x        = (int)((d >> b & 7) | (d >> b * 2 & 0x18) | (d >> b * 3 & 0x60));
                        for (int j = 0; j < 3 && n < count; j++, n++)
                        {
                            _out[n] = new IntSeqData()
                            {
                                bits    = (int)d >> (DImq[j] + b * j) & mask,
                                nonbits = DIQuintsTable[j * 128 + x],
                            };
                        }
                    }
                }
                else
                {
                    for (int i = 0, p = offset; i < block_count; i++, p += block_size)
                    {
                        ulong d = GetBits64(input, p, (i < block_count - 1) ? block_size : last_block_size);
                        int   x = (int)((d >> b & 7) | (d >> b * 2 & 0x18) | (d >> b * 3 & 0x60));
                        for (int j = 0; j < 3 && n < count; j++, n++)
                        {
                            _out[n] = new IntSeqData()
                            {
                                bits    = (int)d >> (DImq[j] + b * j) & mask,
                                nonbits = DIQuintsTable[j * 128 + x],
                            };
                        }
                    }
                }
            }
            else
            {
                if (reverse)
                {
                    for (int p = offset - b; n < count; n++, p -= b)
                    {
                        _out[n] = new IntSeqData()
                        {
                            bits    = BitReverseU8((byte)GetBits(input, p, b), b),
                            nonbits = 0,
                        };
                    }
                }
                else
                {
                    for (int p = offset; n < count; n++, p += b)
                    {
                        _out[n] = new IntSeqData()
                        {
                            bits    = GetBits(input, p, b),
                            nonbits = 0,
                        };
                    }
                }
            }
        }
예제 #3
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;
                }
            }
        }