diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs index 0a3c0da98a..d4a76bc936 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs @@ -585,6 +585,7 @@ namespace Ryujinx.Graphics.Gal.Shader bool AbsA = OpCode.Read(46); bool NegA = OpCode.Read(48); bool AbsB = OpCode.Read(49); + bool Sat = OpCode.Read(50); ShaderIrNode OperA = OpCode.Gpr8(), OperB; @@ -603,12 +604,13 @@ namespace Ryujinx.Graphics.Gal.Shader ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fadd, OperA, OperB); - Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op))); + Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), GetAluFsat(Op, Sat)))); } private static void EmitFmul(ShaderIrBlock Block, long OpCode, ShaderOper Oper) { bool NegB = OpCode.Read(48); + bool Sat = OpCode.Read(50); ShaderIrNode OperA = OpCode.Gpr8(), OperB; @@ -625,13 +627,14 @@ namespace Ryujinx.Graphics.Gal.Shader ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fmul, OperA, OperB); - Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op))); + Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), GetAluFsat(Op, Sat)))); } private static void EmitFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper) { bool NegB = OpCode.Read(48); bool NegC = OpCode.Read(49); + bool Sat = OpCode.Read(50); ShaderIrNode OperA = OpCode.Gpr8(), OperB, OperC; @@ -658,7 +661,7 @@ namespace Ryujinx.Graphics.Gal.Shader ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Ffma, OperA, OperB, OperC); - Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op))); + Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), GetAluFsat(Op, Sat)))); } private static void EmitIadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper) diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs index ebacd53ab4..d07bcd9171 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs @@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Gal.Shader { static class ShaderDecodeHelper { + private static readonly ShaderIrOperImmf ImmfZero = new ShaderIrOperImmf(0); + private static readonly ShaderIrOperImmf ImmfOne = new ShaderIrOperImmf(1); + public static ShaderIrNode GetAluFabsFneg(ShaderIrNode Node, bool Abs, bool Neg) { return GetAluFneg(GetAluFabs(Node, Abs), Neg); @@ -17,6 +20,11 @@ namespace Ryujinx.Graphics.Gal.Shader return Neg ? new ShaderIrOp(ShaderIrInst.Fneg, Node) : Node; } + public static ShaderIrNode GetAluFsat(ShaderIrNode Node, bool Sat) + { + return Sat ? new ShaderIrOp(ShaderIrInst.Fclamp, Node, ImmfZero, ImmfOne) : Node; + } + public static ShaderIrNode GetAluIabsIneg(ShaderIrNode Node, bool Abs, bool Neg) { return GetAluIneg(GetAluIabs(Node, Abs), Neg); diff --git a/Ryujinx.Graphics/Texture/ImageUtils.cs b/Ryujinx.Graphics/Texture/ImageUtils.cs index 1b043245ef..e1f370cda9 100644 --- a/Ryujinx.Graphics/Texture/ImageUtils.cs +++ b/Ryujinx.Graphics/Texture/ImageUtils.cs @@ -235,18 +235,23 @@ namespace Ryujinx.Graphics.Texture int BytesPerPixel = Desc.BytesPerPixel; - int OutOffs = 0; + //Note: Each row of the texture needs to be aligned to 4 bytes. + int Pitch = (Width * BytesPerPixel + 3) & ~3; - byte[] Data = new byte[Width * Height * BytesPerPixel]; + byte[] Data = new byte[Height * Pitch]; for (int Y = 0; Y < Height; Y++) - for (int X = 0; X < Width; X++) { - long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); + int OutOffs = Y * Pitch; - CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel); + for (int X = 0; X < Width; X++) + { + long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); - OutOffs += BytesPerPixel; + CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel); + + OutOffs += BytesPerPixel; + } } return Data;