コード例 #1
0
ファイル: PSVita.cs プロジェクト: Cri4Key/Scarlet
 public static int GetBitsPerPixel(SceGxmTextureBaseFormat baseFormat)
 {
     if (!bitsPerPixelMap.ContainsKey(baseFormat))
     {
         throw new Exception(string.Format("No matching bits per pixel known for {0}", baseFormat));
     }
     return(bitsPerPixelMap[baseFormat]);
 }
コード例 #2
0
        public TextureBundle(BinaryReader reader, SceGxtTextureInfo info)
        {
            reader.BaseStream.Seek(info.DataOffset, SeekOrigin.Begin);

            Width         = info.GetWidth();
            Height        = info.GetHeight();
            PaletteIndex  = info.PaletteIndex;
            RawLineSize   = (int)(info.DataSize / info.GetHeightRounded());
            TextureFormat = info.GetTextureFormat();

            RoundedWidth  = Width;  //info.GetWidthRounded();
            RoundedHeight = Height; //info.GetHeightRounded();

            if (!PixelDataProviders.PixelFormatMap.ContainsKey(TextureFormat) || !PixelDataProviders.ProviderFunctions.ContainsKey(TextureFormat))
            {
                throw new FormatNotImplementedException(TextureFormat);
            }

            PixelFormat = PixelDataProviders.PixelFormatMap[TextureFormat];
            PixelData   = PixelDataProviders.ProviderFunctions[TextureFormat](reader, info);

            SceGxmTextureBaseFormat textureBaseFormat = info.GetTextureBaseFormat();

            // TODO: is this right? PVRTC/PVRTC2 doesn't need this, but everything else does?
            if (textureBaseFormat != SceGxmTextureBaseFormat.PVRT2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRT4BPP &&
                textureBaseFormat != SceGxmTextureBaseFormat.PVRTII2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRTII4BPP)
            {
                SceGxmTextureType textureType = info.GetTextureType();
                switch (textureType)
                {
                case SceGxmTextureType.Linear:
                    // Nothing to be done!
                    break;

                case SceGxmTextureType.Tiled:
                    // TODO: verify me!
                    PixelData = PostProcessing.UntileTexture(PixelData, info.GetWidthRounded(), info.GetHeightRounded(), PixelFormat);
                    break;

                case SceGxmTextureType.Swizzled:
                case SceGxmTextureType.Cube:
                    // TODO: is cube really the same as swizzled? seems that way from CS' *env* files...
                    PixelData = PostProcessing.UnswizzleTexture(PixelData, info.GetWidthRounded(), info.GetHeightRounded(), PixelFormat);
                    break;

                case (SceGxmTextureType)0xA0000000:
                    // TODO: mehhhhh
                    PixelData = PostProcessing.UnswizzleTexture(PixelData, info.GetWidthRounded(), info.GetHeightRounded(), PixelFormat);
                    break;

                default:
                    throw new TypeNotImplementedException(textureType);
                }
            }
        }
コード例 #3
0
        private static byte[] DecompressDxtBlock(BinaryReader reader, SceGxmTextureBaseFormat format)
        {
            byte[] outputData = new byte[(4 * 4) * 4];
            byte[] colorData  = null, alphaData = null;

            if (format != SceGxmTextureBaseFormat.UBC1)
            {
                alphaData = DecompressDxtAlpha(reader, format);
            }

            colorData = DecompressDxtColor(reader, format);

            for (int i = 0; i < colorData.Length; i += 4)
            {
                outputData[i]     = colorData[i];
                outputData[i + 1] = colorData[i + 1];
                outputData[i + 2] = colorData[i + 2];
                outputData[i + 3] = (alphaData != null ? alphaData[i + 3] : colorData[i + 3]);
            }

            return(outputData);
        }
コード例 #4
0
        private Bitmap CreateBitmap(int infoIdx, int forcePaletteIdx = -1)
        {
            SceGxtTextureInfo info = TextureInfos[infoIdx];

            ImageBinary imageBinary = new ImageBinary();

            imageBinary.Width            = info.GetWidth();
            imageBinary.Height           = info.GetHeight();
            imageBinary.InputPixelFormat = PSVita.GetPixelDataFormat(info.GetTextureFormat());
            imageBinary.InputEndianness  = Endian.LittleEndian;
            imageBinary.AddInputPixels(PixelData[infoIdx]);

            // TODO: verify all this crap, GXT conversion wrt image [dimension/format/type] is fragile as all hell

            SceGxmTextureBaseFormat textureBaseFormat = info.GetTextureBaseFormat();
            SceGxmTextureType       textureType       = info.GetTextureType();

            if (textureType == SceGxmTextureType.Linear &&
                textureBaseFormat != SceGxmTextureBaseFormat.UBC1 && textureBaseFormat != SceGxmTextureBaseFormat.UBC2 && textureBaseFormat != SceGxmTextureBaseFormat.UBC3 &&
                textureBaseFormat != SceGxmTextureBaseFormat.PVRT2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRT4BPP &&
                textureBaseFormat != SceGxmTextureBaseFormat.PVRTII2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRTII4BPP)
            {
                imageBinary.PhysicalWidth  = (int)(((info.DataSize / imageBinary.Height) * 8) / PSVita.GetBitsPerPixel(textureBaseFormat));
                imageBinary.PhysicalHeight = info.GetHeight();
            }
            else
            {
                imageBinary.PhysicalWidth  = info.GetWidthRounded();
                imageBinary.PhysicalHeight = info.GetHeightRounded();
            }

            if (textureBaseFormat != SceGxmTextureBaseFormat.PVRT2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRT4BPP)
            {
                switch (textureType)
                {
                case SceGxmTextureType.Linear:
                    // Nothing to be done!
                    break;

                case SceGxmTextureType.Tiled:
                    // TODO: verify me!
                    imageBinary.InputPixelFormat |= PixelDataFormat.PixelOrderingTiled3DS;
                    break;

                case SceGxmTextureType.Swizzled:
                case SceGxmTextureType.Cube:
                    // TODO: is cube really the same as swizzled? seems that way from CS' *env* files...
                    imageBinary.InputPixelFormat |= PixelDataFormat.PixelOrderingSwizzledVita;
                    break;

                case (SceGxmTextureType)0xA0000000:
                    // TODO: this is odd and needs investigation, found ex. in Odin Sphere, Puyo Puyo Tetris, ...
                    imageBinary.InputPixelFormat |= PixelDataFormat.PixelOrderingSwizzledVita;
                    break;
                }
            }

            if (textureBaseFormat == SceGxmTextureBaseFormat.P4 || textureBaseFormat == SceGxmTextureBaseFormat.P8)
            {
                imageBinary.InputPaletteFormat = PSVita.GetPaletteFormat(info.GetTextureFormat());

                if (textureBaseFormat == SceGxmTextureBaseFormat.P4)
                {
                    foreach (byte[] paletteData in P4Palettes)
                    {
                        imageBinary.AddInputPalette(paletteData);
                    }
                }
                else if (textureBaseFormat == SceGxmTextureBaseFormat.P8)
                {
                    foreach (byte[] paletteData in P8Palettes)
                    {
                        imageBinary.AddInputPalette(paletteData);
                    }
                }
            }

            return(imageBinary.GetBitmap(0, forcePaletteIdx != -1 ? forcePaletteIdx : info.PaletteIndex));
        }
コード例 #5
0
        private static byte[] DecompressDxtColor(BinaryReader reader, SceGxmTextureBaseFormat format)
        {
            byte[] colorOut = new byte[(4 * 4) * 4];

            ushort color0 = reader.ReadUInt16();
            ushort color1 = reader.ReadUInt16();
            uint   bits   = reader.ReadUInt32();

            byte c0r, c0g, c0b, c1r, c1g, c1b;

            UnpackRgb565(color0, out c0r, out c0g, out c0b);
            UnpackRgb565(color1, out c1r, out c1g, out c1b);

            byte[] bitsExt = new byte[16];
            for (int i = 0; i < bitsExt.Length; i++)
            {
                bitsExt[i] = (byte)((bits >> (i * 2)) & 0x3);
            }

            for (int y = 0; y < 4; y++)
            {
                for (int x = 0; x < 4; x++)
                {
                    byte code       = bitsExt[(y * 4) + x];
                    int  destOffset = ((y * 4) + x) * 4;

                    // NOTE: Vita DXT1 appears to be RGB-only, thus always opaque
                    colorOut[destOffset + 3] = 0xFF;

                    if (format == SceGxmTextureBaseFormat.UBC1 && color0 <= color1)
                    {
                        switch (code)
                        {
                        case 0x00:
                            colorOut[destOffset + 0] = c0b;
                            colorOut[destOffset + 1] = c0g;
                            colorOut[destOffset + 2] = c0r;
                            break;

                        case 0x01:
                            colorOut[destOffset + 0] = c1b;
                            colorOut[destOffset + 1] = c1g;
                            colorOut[destOffset + 2] = c1r;
                            break;

                        case 0x02:
                            colorOut[destOffset + 0] = (byte)((c0b + c1b) / 2);
                            colorOut[destOffset + 1] = (byte)((c0g + c1g) / 2);
                            colorOut[destOffset + 2] = (byte)((c0r + c1r) / 2);
                            break;

                        case 0x03:
                            colorOut[destOffset + 0] = 0;
                            colorOut[destOffset + 1] = 0;
                            colorOut[destOffset + 2] = 0;
                            break;
                        }
                    }
                    else
                    {
                        switch (code)
                        {
                        case 0x00:
                            colorOut[destOffset + 0] = c0b;
                            colorOut[destOffset + 1] = c0g;
                            colorOut[destOffset + 2] = c0r;
                            break;

                        case 0x01:
                            colorOut[destOffset + 0] = c1b;
                            colorOut[destOffset + 1] = c1g;
                            colorOut[destOffset + 2] = c1r;
                            break;

                        case 0x02:
                            colorOut[destOffset + 0] = (byte)((2 * c0b + c1b) / 3);
                            colorOut[destOffset + 1] = (byte)((2 * c0g + c1g) / 3);
                            colorOut[destOffset + 2] = (byte)((2 * c0r + c1r) / 3);
                            break;

                        case 0x03:
                            colorOut[destOffset + 0] = (byte)((c0b + 2 * c1b) / 3);
                            colorOut[destOffset + 1] = (byte)((c0g + 2 * c1g) / 3);
                            colorOut[destOffset + 2] = (byte)((c0r + 2 * c1r) / 3);
                            break;
                        }
                    }
                }
            }

            return(colorOut);
        }
コード例 #6
0
        private static void DecodeDxtTile(BinaryReader reader, byte[] targetData, int x, int y, int width, int height, SceGxmTextureBaseFormat format)
        {
            for (int by = 0; by < 8; by += 4)
            {
                for (int bx = 0; bx < 8; bx += 4)
                {
                    using (BinaryReader decodedReader = new BinaryReader(new MemoryStream(DecompressDxtBlock(reader, format))))
                    {
                        for (int px = 0; px < 4; px++)
                        {
                            for (int py = 0; py < 4; py++)
                            {
                                int ix = (x + bx + px);
                                int iy = (y + by + py);
                                if (ix >= width || iy >= height)
                                {
                                    continue;
                                }

                                int pixelOffset = (int)(((iy * width) + ix) * 4);
                                Buffer.BlockCopy(decodedReader.ReadBytes(4), 0, targetData, pixelOffset, 4);
                            }
                        }
                    }
                }
            }
        }
コード例 #7
0
        private static byte[] DecompressDxtAlpha(BinaryReader reader, SceGxmTextureBaseFormat format)
        {
            byte[] alphaOut = new byte[(4 * 4) * 4];

            if (format == SceGxmTextureBaseFormat.UBC2)
            {
                ulong alpha = reader.ReadUInt64();
                for (int i = 0; i < alphaOut.Length; i += 4)
                {
                    alphaOut[i + 3] = (byte)(((alpha & 0xF) << 4) | (alpha & 0xF));
                    alpha         >>= 4;
                }
            }
            else if (format == SceGxmTextureBaseFormat.UBC3)
            {
                byte alpha0 = reader.ReadByte();
                byte alpha1 = reader.ReadByte();
                byte bits_5 = reader.ReadByte();
                byte bits_4 = reader.ReadByte();
                byte bits_3 = reader.ReadByte();
                byte bits_2 = reader.ReadByte();
                byte bits_1 = reader.ReadByte();
                byte bits_0 = reader.ReadByte();

                ulong bits = (ulong)(((ulong)bits_0 << 40) | ((ulong)bits_1 << 32) | ((ulong)bits_2 << 24) | ((ulong)bits_3 << 16) | ((ulong)bits_4 << 8) | (ulong)bits_5);

                byte[] bitsExt = new byte[16];
                for (int i = 0; i < bitsExt.Length; i++)
                {
                    bitsExt[i] = (byte)((bits >> (i * 3)) & 0x7);
                }

                for (int y = 0; y < 4; y++)
                {
                    for (int x = 0; x < 4; x++)
                    {
                        byte code       = bitsExt[(y * 4) + x];
                        int  destOffset = (((y * 4) + x) * 4) + 3;

                        if (alpha0 > alpha1)
                        {
                            switch (code)
                            {
                            case 0x00: alphaOut[destOffset] = alpha0; break;

                            case 0x01: alphaOut[destOffset] = alpha1; break;

                            case 0x02: alphaOut[destOffset] = (byte)((6 * alpha0 + 1 * alpha1) / 7); break;

                            case 0x03: alphaOut[destOffset] = (byte)((5 * alpha0 + 2 * alpha1) / 7); break;

                            case 0x04: alphaOut[destOffset] = (byte)((4 * alpha0 + 3 * alpha1) / 7); break;

                            case 0x05: alphaOut[destOffset] = (byte)((3 * alpha0 + 4 * alpha1) / 7); break;

                            case 0x06: alphaOut[destOffset] = (byte)((2 * alpha0 + 5 * alpha1) / 7); break;

                            case 0x07: alphaOut[destOffset] = (byte)((1 * alpha0 + 6 * alpha1) / 7); break;
                            }
                        }
                        else
                        {
                            switch (code)
                            {
                            case 0x00: alphaOut[destOffset] = alpha0; break;

                            case 0x01: alphaOut[destOffset] = alpha1; break;

                            case 0x02: alphaOut[destOffset] = (byte)((4 * alpha0 + 1 * alpha1) / 5); break;

                            case 0x03: alphaOut[destOffset] = (byte)((3 * alpha0 + 2 * alpha1) / 5); break;

                            case 0x04: alphaOut[destOffset] = (byte)((2 * alpha0 + 3 * alpha1) / 5); break;

                            case 0x05: alphaOut[destOffset] = (byte)((1 * alpha0 + 4 * alpha1) / 5); break;

                            case 0x06: alphaOut[destOffset] = 0x00; break;

                            case 0x07: alphaOut[destOffset] = 0xFF; break;
                            }
                        }
                    }
                }
            }

            return(alphaOut);
        }