Ejemplo n.º 1
0
        public Texture Get(TextureStateStruct* TextureState, ClutStateStruct* ClutState)
        {
            Texture Texture;
            //GC.Collect();
            bool Swizzled = TextureState->Swizzled;
            uint TextureAddress = TextureState->Mipmap0.Address;
            uint ClutAddress = ClutState->Address;
            var ClutFormat = ClutState->PixelFormat;
            var ClutStart = ClutState->Start;
            var ClutDataStart = PixelFormatDecoder.GetPixelsSize(ClutFormat, ClutStart);

            ulong Hash1 = TextureAddress | (ulong)((ClutAddress + ClutDataStart) << 32);
            bool Recheck = false;
            if (Cache.TryGetValue(Hash1, out Texture))
            {
                if (Texture.RecheckTimestamp != RecheckTimestamp)
                {
                    Recheck = true;
                }
            }
            else
            {
                Recheck = true;
            }

            if (Recheck)
            {
                //Console.Write(".");

                //Console.WriteLine("{0:X}", ClutAddress);
                var TexturePointer = (byte*)PspMemory.PspAddressToPointerSafe(TextureAddress);
                var ClutPointer = (byte *)PspMemory.PspAddressToPointerSafe(ClutAddress);
                var TextureFormat = TextureState->PixelFormat;
                //var Width = TextureState->Mipmap0.TextureWidth;
                int BufferWidth = TextureState->Mipmap0.BufferWidth;
                var Height = TextureState->Mipmap0.TextureHeight;
                var TextureDataSize = PixelFormatDecoder.GetPixelsSize(TextureFormat, BufferWidth * Height);
                if (ClutState->NumberOfColors > 256)
                {
                    ClutState->NumberOfColors = 256;
                }
                var ClutDataSize = PixelFormatDecoder.GetPixelsSize(ClutFormat, ClutState->NumberOfColors);
                var ClutCount = ClutState->NumberOfColors;
                var ClutShift = ClutState->Shift;
                var ClutMask = ClutState->Mask;

                //Console.WriteLine(TextureFormat);

                if (TextureDataSize > 2048 * 2048 * 4)
                {
                    Console.Error.WriteLine("UPDATE_TEXTURE(TEX={0},CLUT={1}:{2}:{3}:{4}:0x{5:X},SIZE={6}x{7},{8},Swizzled={9})", TextureFormat, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, BufferWidth, Height, BufferWidth, Swizzled);
                    Console.Error.WriteLine("Invalid TEXTURE!");
                    return new Texture();
                }

                TextureCacheKey TextureCacheKey = new TextureCacheKey()
                {
                    TextureAddress = TextureAddress,
                    TextureFormat = TextureFormat,
                    TextureHash = FastHash((uint*)TexturePointer, TextureDataSize),

                    ClutHash = FastHash((uint*)&(ClutPointer[ClutDataStart]), ClutDataSize),
                    ClutAddress = ClutAddress,
                    ClutFormat = ClutFormat,
                    ClutStart = ClutStart,
                    ClutShift = ClutShift,
                    ClutMask = ClutMask,
                    Swizzled = Swizzled,
                };

                if (Texture == null || (!Texture.TextureCacheKey.Equals(TextureCacheKey)))
                {
            #if DEBUG_TEXTURE_CACHE
                    string TextureName = "texture_" + TextureCacheKey.TextureHash + "_" + TextureCacheKey.ClutHash + "_" + TextureFormat + "_" + ClutFormat + "_" + BufferWidth + "x" + Height;

                    Console.Error.WriteLine("UPDATE_TEXTURE(TEX={0},CLUT={1}:{2}:{3}:{4}:0x{5:X},SIZE={6}x{7},{8},Swizzled={9})", TextureFormat, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, BufferWidth, Height, BufferWidth, Swizzled);
            #endif
                    Texture = new Texture();
                    Texture.TextureCacheKey = TextureCacheKey;
                    {
                        fixed (PixelFormatDecoder.OutputPixel* TexturePixelsPointer = DecodedTextureBuffer)
                        {
                            if (Swizzled)
                            {
                                fixed (byte* SwizzlingBufferPointer = SwizzlingBuffer)
                                {
                                    Marshal.Copy(new IntPtr(TexturePointer), SwizzlingBuffer, 0, TextureDataSize);
                                    PixelFormatDecoder.UnswizzleInline(TextureFormat, (void*)SwizzlingBufferPointer, BufferWidth, Height);
                                    PixelFormatDecoder.Decode(
                                        TextureFormat, (void*)SwizzlingBufferPointer, TexturePixelsPointer, BufferWidth, Height,
                                        ClutPointer, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask
                                    );
                                }
                            }
                            else
                            {
                                PixelFormatDecoder.Decode(
                                    TextureFormat, (void*)TexturePointer, TexturePixelsPointer, BufferWidth, Height,
                                    ClutPointer, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask
                                );
                            }

            #if DEBUG_TEXTURE_CACHE
                            var Bitmap = new Bitmap(BufferWidth, Height);
                            BitmapUtils.TransferChannelsDataInterleaved(
                                Bitmap.GetFullRectangle(),
                                Bitmap,
                                (byte*)TexturePixelsPointer,
                                BitmapUtils.Direction.FromDataToBitmap,
                                BitmapChannel.Red,
                                BitmapChannel.Green,
                                BitmapChannel.Blue,
                                BitmapChannel.Alpha
                            );
                            Bitmap.Save(TextureName + ".png");
            #endif

                            Texture.SetData(TexturePixelsPointer, BufferWidth, Height);
                        }
                    }
                    if (Cache.ContainsKey(Hash1))
                    {
                        Cache[Hash1].Dispose();
                    }
                    Cache[Hash1] = Texture;
                }
            }

            Texture.RecheckTimestamp = RecheckTimestamp;

            return Texture;
        }
Ejemplo n.º 2
0
        public static unsafe void TransferChannelsDataLinear(Rectangle Rectangle, Bitmap Bitmap, byte[] NewData, Direction Direction, params BitmapChannel[] Channels)
        {
            int WidthHeight = Bitmap.Width * Bitmap.Height;
            var FullRectangle = Bitmap.GetFullRectangle();
            if (!FullRectangle.Contains(Rectangle.Location)) throw(new InvalidProgramException());
            if (!FullRectangle.Contains(Rectangle.Location + Rectangle.Size - new Size(1, 1))) throw (new InvalidProgramException());

            int NumberOfChannels = 1;
            foreach (var Channel in Channels)
            {
                if (Channel != BitmapChannel.Indexed)
                {
                    NumberOfChannels = 4;
                    break;
                }
            }

            Bitmap.LockBitsUnlock((NumberOfChannels == 1) ? PixelFormat.Format8bppIndexed : PixelFormat.Format32bppArgb, (BitmapData) =>
            {
                byte* BitmapDataScan0 = (byte*)BitmapData.Scan0.ToPointer();
                int Width = Bitmap.Width;
                int Height = Bitmap.Height;
                int Stride = BitmapData.Stride;
                if (NumberOfChannels == 1)
                {
                    Stride = Width;
                }

                int RectangleTop = Rectangle.Top;
                int RectangleBottom = Rectangle.Bottom;
                int RectangleLeft = Rectangle.Left;
                int RectangleRight = Rectangle.Right;

                fixed (byte* OutputPtrStart = &NewData[0])
                {
                    byte* OutputPtr = OutputPtrStart;
                    foreach (var Channel in Channels)
                    {
                        for (int y = RectangleTop; y < RectangleBottom; y++)
                        {
                            byte* InputPtr = BitmapDataScan0 + Stride * y;
                            if (NumberOfChannels != 1)
                            {
                                InputPtr = InputPtr + (int)Channel;
                            }
                            InputPtr += NumberOfChannels * RectangleLeft;
                            for (int x = RectangleLeft; x < RectangleRight; x++)
                            {
                                if (Direction == Direction.FromBitmapToData)
                                {
                                    *OutputPtr = *InputPtr;
                                }
                                else
                                {
                                    *InputPtr  = * OutputPtr;
                                }
                                OutputPtr++;
                                InputPtr += NumberOfChannels;
                            }
                        }
                    }
                }
            });
        }
Ejemplo n.º 3
0
 public static unsafe void TransferChannelsDataLinear(Bitmap Bitmap, byte[] NewData, Direction Direction, params BitmapChannel[] Channels)
 {
     TransferChannelsDataLinear(Bitmap.GetFullRectangle(), Bitmap, NewData, Direction, Channels);
 }
Ejemplo n.º 4
0
        private void SaveFrameBuffer(GpuStateStruct* GpuState, string FileName)
        {
            var GlPixelFormat = GlPixelFormatList[(int)GuPixelFormats.RGBA_8888];
            int Width = (int)GpuState->DrawBufferState.Width;
            if (Width == 0) Width = 512;
            int Height = 272;
            int ScanWidth = PixelFormatDecoder.GetPixelsSize(GlPixelFormat.GuPixelFormat, Width);
            int PixelSize = PixelFormatDecoder.GetPixelsSize(GlPixelFormat.GuPixelFormat, 1);

            if (Width == 0) Width = 512;

            GL.PixelStore(PixelStoreParameter.PackAlignment, PixelSize);

            var FB = new Bitmap(Width, Height);
            var Data = new byte[Width * Height * 4];

            fixed (byte* DataPtr = Data)
            {
                GL.ReadPixels(0, 0, Width, Height, PixelFormat.Rgba, GlPixelFormat.OpenglPixelType, new IntPtr(DataPtr));

                BitmapUtils.TransferChannelsDataInterleaved(
                    FB.GetFullRectangle(),
                    FB,
                    DataPtr,
                    BitmapUtils.Direction.FromDataToBitmap,
                    BitmapChannel.Red,
                    BitmapChannel.Green,
                    BitmapChannel.Blue,
                    BitmapChannel.Alpha
                );
            }

            FB.Save(FileName);
        }
Ejemplo n.º 5
0
        public Texture Get(GpuStateStruct *GpuState)
        {
            var TextureMappingState = &GpuState->TextureMappingState;
            var ClutState = &TextureMappingState->ClutState;
            var TextureState = &TextureMappingState->TextureState;

            Texture Texture;
            //GC.Collect();
            bool Swizzled = TextureState->Swizzled;
            uint TextureAddress = TextureState->Mipmap0.Address;
            uint ClutAddress = ClutState->Address;
            var ClutFormat = ClutState->PixelFormat;
            var ClutStart = ClutState->Start;
            var ClutDataStart = PixelFormatDecoder.GetPixelsSize(ClutFormat, ClutStart);

            ulong Hash1 = TextureAddress | (ulong)((ClutAddress + ClutDataStart) << 32);
            bool Recheck = false;
            if (Cache.TryGetValue(Hash1, out Texture))
            {
                if (Texture.RecheckTimestamp != RecheckTimestamp)
                {
                    Recheck = true;
                }
            }
            else
            {
                Recheck = true;
            }

            if (Recheck)
            {
                //Console.Write(".");

                //Console.WriteLine("{0:X}", ClutAddress);
                var TexturePointer = (byte*)PspMemory.PspAddressToPointerSafe(TextureAddress);
                var ClutPointer = (byte *)PspMemory.PspAddressToPointerSafe(ClutAddress);
                var TextureFormat = TextureState->PixelFormat;
                //var Width = TextureState->Mipmap0.TextureWidth;
                int BufferWidth = TextureState->Mipmap0.BufferWidth;
                var Height = TextureState->Mipmap0.TextureHeight;
                var TextureDataSize = PixelFormatDecoder.GetPixelsSize(TextureFormat, BufferWidth * Height);
                if (ClutState->NumberOfColors > 256)
                {
                    ClutState->NumberOfColors = 256;
                }
                var ClutDataSize = PixelFormatDecoder.GetPixelsSize(ClutFormat, ClutState->NumberOfColors);
                var ClutCount = ClutState->NumberOfColors;
                var ClutShift = ClutState->Shift;
                var ClutMask = ClutState->Mask;

                //Console.WriteLine(TextureFormat);

                if (!PspMemory.IsAddressValid((uint)(TextureAddress + TextureDataSize - 1)))
                {
                    Console.Error.WriteLine("Invalid TEXTURE!");
                    return new Texture(OpenglGpuImpl);
                }

                if (TextureDataSize > 2048 * 2048 * 4)
                {
                    Console.Error.WriteLine("UPDATE_TEXTURE(TEX={0},CLUT={1}:{2}:{3}:{4}:0x{5:X},SIZE={6}x{7},{8},Swizzled={9})", TextureFormat, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, BufferWidth, Height, BufferWidth, Swizzled);
                    Console.Error.WriteLine("Invalid TEXTURE!");
                    return new Texture(OpenglGpuImpl);
                }

                //Console.WriteLine("TextureAddress=0x{0:X}, TextureDataSize=0x{1:X}", TextureAddress, TextureDataSize);

                TextureCacheKey TextureCacheKey = new TextureCacheKey()
                {
                    TextureAddress = TextureAddress,
                    TextureFormat = TextureFormat,
                    TextureHash = FastHash((uint*)TexturePointer, TextureDataSize),

                    ClutHash = FastHash((uint*)&(ClutPointer[ClutDataStart]), ClutDataSize),
                    ClutAddress = ClutAddress,
                    ClutFormat = ClutFormat,
                    ClutStart = ClutStart,
                    ClutShift = ClutShift,
                    ClutMask = ClutMask,
                    Swizzled = Swizzled,

                    ColorTestEnabled = GpuState->ColorTestState.Enabled,
                    ColorTestRef = GpuState->ColorTestState.Ref,
                    ColorTestMask = GpuState->ColorTestState.Mask,
                    ColorTestFunction = GpuState->ColorTestState.Function,
                };

                if (Texture == null || (!Texture.TextureCacheKey.Equals(TextureCacheKey)))
                {
                    string TextureName = "texture_" + TextureCacheKey.TextureHash + "_" + TextureCacheKey.ClutHash + "_" + TextureFormat + "_" + ClutFormat + "_" + BufferWidth + "x" + Height + "_" + Swizzled;
            #if DEBUG_TEXTURE_CACHE

                    Console.Error.WriteLine("UPDATE_TEXTURE(TEX={0},CLUT={1}:{2}:{3}:{4}:0x{5:X},SIZE={6}x{7},{8},Swizzled={9})", TextureFormat, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, BufferWidth, Height, BufferWidth, Swizzled);
            #endif
                    Texture = new Texture(OpenglGpuImpl);
                    Texture.TextureCacheKey = TextureCacheKey;
                    {
                        //int TextureWidth = Math.Max(BufferWidth, Height);
                        //int TextureHeight = Math.Max(BufferWidth, Height);
                        int TextureWidth = BufferWidth;
                        int TextureHeight = Height;
                        int TextureWidthHeight = TextureWidth * TextureHeight;

                        fixed (OutputPixel* TexturePixelsPointer = DecodedTextureBuffer)
                        {
                            if (Swizzled)
                            {
                                fixed (byte* SwizzlingBufferPointer = SwizzlingBuffer)
                                {
                                    Marshal.Copy(new IntPtr(TexturePointer), SwizzlingBuffer, 0, TextureDataSize);
                                    PixelFormatDecoder.UnswizzleInline(TextureFormat, (void*)SwizzlingBufferPointer, BufferWidth, Height);
                                    PixelFormatDecoder.Decode(
                                        TextureFormat, (void*)SwizzlingBufferPointer, TexturePixelsPointer, BufferWidth, Height,
                                        ClutPointer, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, StrideWidth: PixelFormatDecoder.GetPixelsSize(TextureFormat, TextureWidth)
                                    );
                                }
                            }
                            else
                            {
                                PixelFormatDecoder.Decode(
                                    TextureFormat, (void*)TexturePointer, TexturePixelsPointer, BufferWidth, Height,
                                    ClutPointer, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, StrideWidth: PixelFormatDecoder.GetPixelsSize(TextureFormat, TextureWidth)
                                );
                            }

                            if (TextureCacheKey.ColorTestEnabled)
                            {
                                byte EqualValue, NotEqualValue;

                                switch (TextureCacheKey.ColorTestFunction)
                                {
                                    case ColorTestFunctionEnum.GU_ALWAYS: EqualValue = 0xFF; NotEqualValue = 0xFF; break;
                                    case ColorTestFunctionEnum.GU_NEVER: EqualValue = 0x00; NotEqualValue = 0x00; break;
                                    case ColorTestFunctionEnum.GU_EQUAL: EqualValue = 0xFF; NotEqualValue = 0x00; break;
                                    case ColorTestFunctionEnum.GU_NOTEQUAL: EqualValue = 0x00; NotEqualValue = 0xFF; break;
                                    default: throw(new NotImplementedException());
                                }

                                ConsoleUtils.SaveRestoreConsoleState(() =>
                                {
                                    Console.BackgroundColor = ConsoleColor.Red;
                                    Console.ForegroundColor = ConsoleColor.Yellow;
                                    Console.Error.WriteLine("{0} : {1}, {2} : ref:{3} : mask:{4}", TextureCacheKey.ColorTestFunction, EqualValue, NotEqualValue, TextureCacheKey.ColorTestRef, TextureCacheKey.ColorTestMask);
                                });

                                for (int n = 0; n < TextureWidthHeight; n++)
                                {
                                    if ((TexturePixelsPointer[n] & TextureCacheKey.ColorTestMask).Equals((TextureCacheKey.ColorTestRef & TextureCacheKey.ColorTestMask)))
                                    {
                                        TexturePixelsPointer[n].A = EqualValue;
                                    }
                                    else
                                    {
                                        TexturePixelsPointer[n].A = NotEqualValue;
                                    }
                                    if (TexturePixelsPointer[n].A == 0)
                                    {
                                        //Console.Write("yup!");
                                    }
                                }
                            }

                            /*
                            var Bitmap = new Bitmap(BufferWidth, Height);
                            BitmapUtils.TransferChannelsDataInterleaved(
                                Bitmap.GetFullRectangle(),
                                Bitmap,
                                (byte*)TexturePixelsPointer,
                                BitmapUtils.Direction.FromDataToBitmap,
                                BitmapChannel.Red,
                                BitmapChannel.Green,
                                BitmapChannel.Blue,
                                BitmapChannel.Alpha
                            );
                            Bitmap.Save(TextureName + ".png");
                            */

            #if DEBUG_TEXTURE_CACHE
                            var Bitmap = new Bitmap(BufferWidth, Height);
                            BitmapUtils.TransferChannelsDataInterleaved(
                                Bitmap.GetFullRectangle(),
                                Bitmap,
                                (byte*)TexturePixelsPointer,
                                BitmapUtils.Direction.FromDataToBitmap,
                                BitmapChannel.Red,
                                BitmapChannel.Green,
                                BitmapChannel.Blue,
                                BitmapChannel.Alpha
                            );
                            Bitmap.Save(TextureName + ".png");
            #endif

                            var Result = Texture.SetData(TexturePixelsPointer, TextureWidth, TextureHeight);
            #if DEBUG_TEXTURE_CACHE
                            if (!Result || Texture.TextureId == 0)
                            {
                                var Bitmap2 = new Bitmap(BufferWidth, Height);
                                BitmapUtils.TransferChannelsDataInterleaved(
                                    Bitmap2.GetFullRectangle(),
                                    Bitmap2,
                                    (byte*)TexturePixelsPointer,
                                    BitmapUtils.Direction.FromDataToBitmap,
                                    BitmapChannel.Red,
                                    BitmapChannel.Green,
                                    BitmapChannel.Blue,
                                    BitmapChannel.Alpha
                                );
                                string TextureName2 = @"C:\projects\csharp\cspspemu\__invalid_texture_" + TextureCacheKey.TextureHash + "_" + TextureCacheKey.ClutHash + "_" + TextureFormat + "_" + ClutFormat + "_" + BufferWidth + "x" + Height;
                                Bitmap.Save(TextureName2 + ".png");
                            }
            #endif
                        }
                    }
                    if (Cache.ContainsKey(Hash1))
                    {
                        Cache[Hash1].Dispose();
                    }
                    Cache[Hash1] = Texture;
                }
            }

            Texture.RecheckTimestamp = RecheckTimestamp;

            return Texture;
        }
Ejemplo n.º 6
0
 public void Save(string File)
 {
     var Bitmap = new Bitmap(this.Width, this.Height);
     fixed (OutputPixel* DataPtr = Data)
     {
         BitmapUtils.TransferChannelsDataInterleaved(
             Bitmap.GetFullRectangle(),
             Bitmap,
             (byte*)DataPtr,
             BitmapUtils.Direction.FromDataToBitmap,
             BitmapChannel.Red,
             BitmapChannel.Green,
             BitmapChannel.Blue,
             BitmapChannel.Alpha
         );
     }
     Bitmap.Save(File);
 }