Beispiel #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;
        }
Beispiel #2
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;
        }