private void GetTexVram(Action <TexturePair> Action) { if (TexVram == null) { TexVram = GLTexture.Create().SetFormat(TextureFormat.RGBA).SetSize(1, 1); } //Console.WriteLine(TexVram); TexVram.Bind(); if (BufferGraphics == null) { BufferGraphics = Graphics.FromImage(Buffer); //BufferGraphics.Clear(Color.Red); BufferGraphics.Clear(Color.Black); } //if (PspDisplayForm.Singleton.WindowState == FormWindowState.Minimized) //{ // return; //} // //if (!PspDisplayForm.Singleton.EnableRefreshing) //{ // return; //} if (IGuiWindowInfo.EnableRefreshing) { try { int Width = 512; int Height = 272; var FrameAddress = PspDisplay.CurrentInfo.FrameAddress; byte *FrameBuffer = null; byte *DepthBuffer = null; try { FrameBuffer = (byte *)Memory.PspAddressToPointerSafe( FrameAddress, PixelFormatDecoder.GetPixelsSize(PspDisplay.CurrentInfo.PixelFormat, Width * Height) ); } catch (Exception Exception) { Console.Error.WriteLine(Exception); } //Console.Error.WriteLine("FrameBuffer == 0x{0:X}!!", (long)FrameBuffer); if (FrameBuffer == null) { //Console.Error.WriteLine("FrameBuffer == null!!"); } //Console.WriteLine("{0:X}", Address); var Hash = PixelFormatDecoder.Hash( PspDisplay.CurrentInfo.PixelFormat, (void *)FrameBuffer, Width, Height ); if (Hash != LastHash) { LastHash = Hash; Buffer.LockBitsUnlock(System.Drawing.Imaging.PixelFormat.Format32bppArgb, (BitmapData) => { var Count = Width * Height; fixed(OutputPixel * BitmapDataDecodePtr = BitmapDataDecode) { var BitmapDataPtr = (BGRA *)BitmapData.Scan0.ToPointer(); //var LastRow = (FrameBuffer + 512 * 260 * 4 + 4 * 10); //Console.WriteLine("{0},{1},{2},{3}", LastRow[0], LastRow[1], LastRow[2], LastRow[3]); if (FrameBuffer == null) { if (OldFrameBuffer != null) { Console.Error.WriteLine("FrameBuffer == null"); } } else if (BitmapDataPtr == null) { Console.Error.WriteLine("BitmapDataPtr == null"); } else { PixelFormatDecoder.Decode( PspDisplay.CurrentInfo.PixelFormat, (void *)FrameBuffer, BitmapDataDecodePtr, Width, Height ); } // Converts the decoded data to Window's format. for (int n = 0; n < Count; n++) { BitmapDataPtr[n].R = BitmapDataDecodePtr[n].B; BitmapDataPtr[n].G = BitmapDataDecodePtr[n].G; BitmapDataPtr[n].B = BitmapDataDecodePtr[n].R; BitmapDataPtr[n].A = 0xFF; } OldFrameBuffer = FrameBuffer; GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, 512, 272, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, BitmapDataPtr); TextureVerticalFlip = true; } }); } //else { //Console.WriteLine("Display not updated!"); } } catch (Exception Exception) { Console.Error.WriteLine(Exception); } } Action(new TexturePair() { Color = TexVram, Depth = GLTexture.Wrap(0) }); return; }
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); }
protected override void OnRenderFrame(FrameEventArgs e) { GL.ClearColor(0f, 0f, 0f, 1f); GL.Clear(ClearBufferMask.ColorBufferBit); if (SimplifiedPspEmulator != null) { if (texture <= 0) { texture = GL.GenTexture(); } GL.BindTexture(TextureTarget.Texture2D, texture); CheckError("BindTexture"); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); CheckError("TexParameter"); var bitmap = SimplifiedPspEmulator.Display.TakePspScreenshot(); var pixelsArray = new OutputPixel[bitmap.Area]; fixed(OutputPixel *pixels = pixelsArray) { PixelFormatDecoder.Decode(bitmap.GuPixelFormat, bitmap.Address, pixels, bitmap.Width, bitmap.Height); /* * var data = new byte[512 * 272 * 4]; * for (int i = 0; i < 512 * 272 * 4; i++) * { * data[i] = 0x10; * //pixels[i] = OutputPixel.FromRgba(255, 128, 128, 255); * } * Console.WriteLine($"{bitmap.Width}, {bitmap.Height}, {pixels[0]}"); */ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bitmap.Width, bitmap.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, new IntPtr(pixels)); CheckError("TexImage2D"); GL.BindTexture(TextureTarget.Texture2D, 0); CheckError("BindTexture"); } GL.Viewport(0, 0, Width, Height); CheckError("Viewport"); GL.Enable(EnableCap.Texture2D); GL.MatrixMode(MatrixMode.Projection); CheckError("MatrixMode"); GL.LoadIdentity(); GL.Ortho(-1.0, 1.0, -1.0, 1.0, 0.0, 4.0); GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.BindTexture(TextureTarget.Texture2D, texture); CheckError("BindTexture"); GL.Begin(BeginMode.Quads); GL.TexCoord2(0.0f, 1.0f); GL.Vertex2(-1f, -1f); GL.TexCoord2(1.0f, 1.0f); GL.Vertex2(+1f, -1f); GL.TexCoord2(1.0f, 0.0f); GL.Vertex2(+1f, +1f); GL.TexCoord2(0.0f, 0.0f); GL.Vertex2(-1f, +1f); GL.End(); CheckError("End"); } //GL.BindTexture(TextureTarget.Texture2D, 0); SwapBuffers(); if (SimplifiedPspEmulator != null) { UpdateAnalogCounter(pressingAnalogLeftSet, ref pressingAnalogLeft); UpdateAnalogCounter(pressingAnalogUpSet, ref pressingAnalogUp); UpdateAnalogCounter(pressingAnalogDownSet, ref pressingAnalogDown); UpdateAnalogCounter(pressingAnalogRightSet, ref pressingAnalogRight); lx = pressingAnalogLeft != 0 ? -pressingAnalogLeft : pressingAnalogRight; ly = pressingAnalogUp != 0 ? -pressingAnalogUp : pressingAnalogDown; ctrlData.X = lx / 3f; ctrlData.Y = ly / 3f; ctrlData.TimeStamp = (uint)Emulator.InjectContext.GetInstance <PspRtc>().UnixTimeStampTS.Milliseconds; //Console.WriteLine($"controller.InsertSceCtrlData({ctrlData})"); Emulator.InjectContext.GetInstance <PspController>().InsertSceCtrlData(ctrlData); Emulator.InjectContext.GetInstance <PspDisplay>().TriggerVBlankEnd(); } }
public TTexture Get(GpuStateStruct GpuState) { var TextureMappingState = GpuState.TextureMappingState; var ClutState = TextureMappingState.ClutState; var TextureState = TextureMappingState.TextureState; TTexture 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 TextureFormat = TextureState.PixelFormat; //var Width = TextureState->Mipmap0.TextureWidth; int BufferWidth = TextureState.Mipmap0.BufferWidth; // FAKE! //BufferWidth = TextureState->Mipmap0.TextureWidth; 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); // INVALID TEXTURE if (!PspMemory.IsRangeValid(TextureAddress, TextureDataSize) || TextureDataSize > 2048 * 2048 * 4) { Console.Error.WriteLineColored(ConsoleColor.DarkRed, "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.WriteLineColored(ConsoleColor.DarkRed, "Invalid TEXTURE! TextureAddress=0x{0:X}, TextureDataSize={1}", TextureAddress, TextureDataSize); if (InvalidTexture == null) { InvalidTexture = new TTexture(); InvalidTexture.Init(GpuImpl); int InvalidTextureWidth = 2, InvalidTextureHeight = 2; int InvalidTextureSize = InvalidTextureWidth * InvalidTextureHeight; var Data = new OutputPixel[InvalidTextureSize]; fixed(OutputPixel *DataPtr = Data) { var Color1 = OutputPixel.FromRgba(0xFF, 0x00, 0x00, 0xFF); var Color2 = OutputPixel.FromRgba(0x00, 0x00, 0xFF, 0xFF); for (int n = 0; n < InvalidTextureSize; n++) { DataPtr[n] = (n & 1) != 0 ? Color1 : Color2; } InvalidTexture.SetData(Data, InvalidTextureWidth, InvalidTextureHeight); } } return(InvalidTexture); } //Console.WriteLine("TextureAddress=0x{0:X}, TextureDataSize=0x{1:X}", TextureAddress, TextureDataSize); byte *TexturePointer = null; byte *ClutPointer = null; try { TexturePointer = (byte *)PspMemory.PspAddressToPointerSafe(TextureAddress); ClutPointer = (byte *)PspMemory.PspAddressToPointerSafe(ClutAddress); } catch (PspMemory.InvalidAddressException InvalidAddressException) { throw InvalidAddressException; } TextureCacheKey TextureCacheKey = new TextureCacheKey() { TextureAddress = TextureAddress, TextureFormat = TextureFormat, TextureHash = FastHash(TexturePointer, TextureDataSize), ClutHash = FastHash(&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 TTexture(); Texture.Init(GpuImpl); Texture.TextureCacheKey = TextureCacheKey; //Texture.Hash = Hash1; { //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) { PointerUtils.Memcpy(SwizzlingBuffer, TexturePointer, 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.GuAlways: EqualValue = 0xFF; NotEqualValue = 0xFF; break; case ColorTestFunctionEnum.GuNever: EqualValue = 0x00; NotEqualValue = 0x00; break; case ColorTestFunctionEnum.GuEqual: EqualValue = 0xFF; NotEqualValue = 0x00; break; case ColorTestFunctionEnum.GuNotequal: 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 TextureInfo = new TextureHookInfo() { TextureCacheKey = TextureCacheKey, Data = DecodedTextureBuffer, Width = TextureWidth, Height = TextureHeight }; MessageBus.Dispatch(TextureInfo); var Result = Texture.SetData(TextureInfo.Data, TextureInfo.Width, TextureInfo.Height); } } if (Cache.ContainsKey(Hash1)) { Cache[Hash1].Dispose(); } Cache[Hash1] = Texture; } } Texture.RecheckTimestamp = RecheckTimestamp; return(Texture); }
protected override void OnPaintBackground(PaintEventArgs PaintEventArgs) { if (IGuiExternalInterface.IsInitialized()) { if (EnableRefreshing) { try { Buffer.LockBitsUnlock(PixelFormat.Format32bppArgb, (BitmapData) => { int Width = 512; int Height = 272; var Count = Width * Height; var BitmapDataDecode = new PixelFormatDecoder.OutputPixel[Count]; fixed(PixelFormatDecoder.OutputPixel * BitmapDataDecodePtr = BitmapDataDecode) { var BitmapDataPtr = (BGRA *)BitmapData.Scan0.ToPointer(); var Address = PspDisplay.CurrentInfo.Address; //var Address = Memory.FrameBufferSegment.Low; //Console.WriteLine("{0:X}", Address); var FrameBuffer = (byte *)Memory.PspAddressToPointer(Address); //var LastRow = (FrameBuffer + 512 * 260 * 4 + 4 * 10); //Console.WriteLine("{0},{1},{2},{3}", LastRow[0], LastRow[1], LastRow[2], LastRow[3]); if (FrameBuffer == null) { Console.Error.WriteLine("FrameBuffer == null"); } else if (BitmapDataPtr == null) { Console.Error.WriteLine("BitmapDataPtr == null"); } else { PixelFormatDecoder.Decode( PspDisplay.CurrentInfo.PixelFormat, (void *)FrameBuffer, BitmapDataDecodePtr, Width, Height ); } // Converts the decoded data to Window's format. for (int n = 0; n < Count; n++) { BitmapDataPtr[n].R = BitmapDataDecodePtr[n].R; BitmapDataPtr[n].G = BitmapDataDecodePtr[n].G; BitmapDataPtr[n].B = BitmapDataDecodePtr[n].B; BitmapDataPtr[n].A = 0xFF; } } }); } catch (Exception Exception) { Console.WriteLine(Exception); } } //Console.WriteLine(this.ClientRectangle); PaintEventArgs.Graphics.CompositingMode = CompositingMode.SourceCopy; PaintEventArgs.Graphics.CompositingQuality = CompositingQuality.HighSpeed; PaintEventArgs.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor; PaintEventArgs.Graphics.DrawImage( Buffer, new Rectangle( 0, menuStrip1.Height, 512 * DisplayScale, 272 * DisplayScale ) ); //PaintEventArgs.Graphics.DrawImageUnscaled(Buffer, new Point(0, menuStrip1.Height)); } else { var Buffer = new Bitmap(512, 272); var BufferGraphics = Graphics.FromImage(Buffer); BufferGraphics.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, Buffer.Width, Buffer.Height)); //BufferGraphics.DrawString("Initializing...", new Font("Arial", 10), new SolidBrush(Color.White), new PointF(8, 8)); PaintEventArgs.Graphics.DrawImage(Buffer, new Rectangle(0, menuStrip1.Height, 512 * DisplayScale, 272 * DisplayScale)); } }