VI registers.

master
Nabile Rahmani 2018-06-16 13:59:56 +02:00
parent 55382b2c14
commit 83f573764b
9 changed files with 459 additions and 17 deletions

View File

@ -95,6 +95,12 @@
<Compile Include="CPU\VR4300\CP1\VR4300.FloatingPointUnit.ControlStatusRegister.cs" />
<Compile Include="CPU\VR4300\CP0\VR4300.SystemControlUnit.FunctOpCode.cs" />
<Compile Include="CPU\VR4300\VR4300.AccessSize.cs" />
<Compile Include="RCP\VI\RealityCoprocessor.VideoInterface.ControlRegister.cs" />
<Compile Include="RCP\VI\RealityCoprocessor.VideoInterface.TimingRegister.cs" />
<Compile Include="RCP\VI\RealityCoprocessor.VideoInterface.HorizontalSyncRegister.cs" />
<Compile Include="RCP\VI\RealityCoprocessor.VideoInterface.VerticalVideoRegister.cs" />
<Compile Include="RCP\VI\RealityCoprocessor.VideoInterface.VerticalBurstRegister.cs" />
<Compile Include="RCP\VI\RealityCoprocessor.VideoInterface.ScaleRegister.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="CPU\" />

View File

@ -0,0 +1,108 @@
using System;
using System.Collections.Specialized;
namespace DotN64.RCP
{
public partial class RealityCoprocessor
{
public partial class VideoInterface
{
public struct ControlRegister
{
#region Fields
private BitVector32 bits;
private static readonly BitVector32.Section type = BitVector32.CreateSection((1 << 2) - 1),
gammaDitherEnable = BitVector32.CreateSection(1, type),
gammaEnable = BitVector32.CreateSection(1, gammaDitherEnable),
divotEnable = BitVector32.CreateSection(1, gammaEnable),
reserved1 = BitVector32.CreateSection(1, divotEnable), // Always off.
serrate = BitVector32.CreateSection(1, reserved1),
reserved2 = BitVector32.CreateSection(1, serrate), // Diagnostics only.
antiAliasMode = BitVector32.CreateSection((1 << 2) - 1, reserved2);
#endregion
#region Properties
public PixelSize Type
{
get => (PixelSize)bits[type];
set => bits[type] = (byte)value;
}
/// <summary>
/// Normally on, unless "special effect".
/// </summary>
public bool GammaDitherEnable
{
get => Convert.ToBoolean(bits[gammaDitherEnable]);
set => bits[gammaDitherEnable] = Convert.ToInt32(value);
}
/// <summary>
/// Normally on, unless MPEG/JPEG.
/// </summary>
public bool GammaEnable
{
get => Convert.ToBoolean(bits[gammaEnable]);
set => bits[gammaEnable] = Convert.ToInt32(value);
}
/// <summary>
/// Normally on if antialiased, unless decal lines.
/// </summary>
public bool DivotEnable
{
get => Convert.ToBoolean(bits[divotEnable]);
set => bits[divotEnable] = Convert.ToInt32(value);
}
/// <summary>
/// Always on if interlaced, off if not.
/// </summary>
public bool Serrate
{
get => Convert.ToBoolean(bits[serrate]);
set => bits[serrate] = Convert.ToInt32(value);
}
public AntiAliasingMode AntiAliasMode
{
get => (AntiAliasingMode)bits[antiAliasMode];
set => bits[antiAliasMode] = (byte)value;
}
#endregion
#region Operators
public static implicit operator ControlRegister(ushort data) => new ControlRegister { bits = new BitVector32(data) };
public static implicit operator ushort(ControlRegister status) => (ushort)status.bits.Data;
#endregion
#region Enumerations
public enum PixelSize : byte
{
/// <summary>No data, no sync.</summary>
Blank = 0,
Reserved = 1,
/// <summary>"16" bit.</summary>
RGBA5553 = 2,
/// <summary>32 bit.</summary>
RGBA8888 = 3
}
public enum AntiAliasingMode : byte
{
/// <summary>AA &amp; resamp (always fetch extra lines).</summary>
AntiAliasAndResampleAlways = 0,
/// <summary>AA &amp; resamp (fetch extra lines if needed).</summary>
AntiAliasAndResampleIfNeeded = 1,
/// <summary>Resamp only (treat as all fully covered).</summary>
ResampleOnly = 2,
/// <summary>Neither (replicate pixels, no interpolate).</summary>
Neither = 3
}
#endregion
}
}
}
}

View File

@ -0,0 +1,46 @@
namespace DotN64.RCP
{
using static Helpers.BitHelper;
public partial class RealityCoprocessor
{
public partial class VideoInterface
{
public struct HorizontalSyncRegister
{
#region Fields
private uint data;
private const ushort TotalLineDurationShift = 0, TotalLineDurationSize = (1 << 12) - 1;
private const byte LeapPatternShift = 16, LeapPatternSize = (1 << 5) - 1;
#endregion
#region Properties
/// <summary>
/// Total duration of a line in 1/4 pixel.
/// </summary>
public ushort TotalLineDuration
{
get => (ushort)Get(data, TotalLineDurationShift, TotalLineDurationSize);
set => Set(ref data, TotalLineDurationShift, TotalLineDurationSize, value);
}
/// <summary>
/// A 5-bit leap pattern used for PAL only (h_sync_period).
/// </summary>
public byte LeapPattern
{
get => (byte)Get(data, LeapPatternShift, LeapPatternSize);
set => Set(ref data, LeapPatternShift, LeapPatternSize, value);
}
#endregion
#region Operators
public static implicit operator HorizontalSyncRegister(uint data) => new HorizontalSyncRegister { data = data };
public static implicit operator uint(HorizontalSyncRegister register) => register.data;
#endregion
}
}
}
}

View File

@ -1,7 +1,7 @@
using System.Collections.Specialized;
namespace DotN64.RCP
namespace DotN64.RCP
{
using static Helpers.BitHelper;
public partial class RealityCoprocessor
{
public partial class VideoInterface
@ -9,11 +9,10 @@ namespace DotN64.RCP
public struct HorizontalVideoRegister
{
#region Fields
private BitVector32 bits;
private uint data;
private static readonly BitVector32.Section activeVideoEnd = BitVector32.CreateSection((1 << 10) - 1),
unknown1 = BitVector32.CreateSection((1 << 6) - 1, activeVideoEnd),
activeVideoStart = BitVector32.CreateSection((1 << 10) - 1, unknown1);
private const ushort ActiveVideoEndShift = 0, ActiveVideoEndSize = (1 << 10) - 1;
private const ushort ActiveVideoStartShift = 16, ActiveVideoStartSize = (1 << 10) - 1;
#endregion
#region Properties
@ -22,8 +21,8 @@ namespace DotN64.RCP
/// </summary>
public ushort ActiveVideoEnd
{
get => (ushort)bits[activeVideoEnd];
set => bits[activeVideoEnd] = value;
get => (ushort)Get(data, ActiveVideoEndShift, ActiveVideoEndSize);
set => Set(ref data, ActiveVideoEndShift, ActiveVideoEndSize, value);
}
/// <summary>
@ -31,15 +30,15 @@ namespace DotN64.RCP
/// </summary>
public ushort ActiveVideoStart
{
get => (ushort)bits[activeVideoStart];
set => bits[activeVideoStart] = value;
get => (ushort)Get(data, ActiveVideoStartShift, ActiveVideoStartSize);
set => Set(ref data, ActiveVideoStartShift, ActiveVideoStartSize, value);
}
#endregion
#region Operators
public static implicit operator HorizontalVideoRegister(uint data) => new HorizontalVideoRegister { bits = new BitVector32((int)data) };
public static implicit operator HorizontalVideoRegister(uint data) => new HorizontalVideoRegister { data = data };
public static implicit operator uint(HorizontalVideoRegister register) => (uint)register.bits.Data;
public static implicit operator uint(HorizontalVideoRegister register) => register.data;
#endregion
}
}

View File

@ -0,0 +1,46 @@
namespace DotN64.RCP
{
using static Helpers.BitHelper;
public partial class RealityCoprocessor
{
public partial class VideoInterface
{
public struct ScaleRegister
{
#region Fields
private uint data;
private const ushort ScaleUpFactorShift = 0, ScaleUpFactorSize = (1 << 12) - 1;
private const ushort SubpixelOffsetShift = 16, SubpixelOffsetSize = (1 << 12) - 1;
#endregion
#region Properties
/// <summary>
/// 1/scale up factor (2.10 format).
/// </summary>
public ushort ScaleUpFactor
{
get => (ushort)Get(data, ScaleUpFactorShift, ScaleUpFactorSize);
set => Set(ref data, ScaleUpFactorShift, ScaleUpFactorSize, value);
}
/// <summary>
/// Subpixel offset (2.10 format).
/// </summary>
public ushort SubpixelOffset
{
get => (ushort)Get(data, SubpixelOffsetShift, SubpixelOffsetSize);
set => Set(ref data, SubpixelOffsetShift, SubpixelOffsetSize, value);
}
#endregion
#region Operators
public static implicit operator ScaleRegister(uint data) => new ScaleRegister { data = data };
public static implicit operator uint(ScaleRegister register) => register.data;
#endregion
}
}
}
}

View File

@ -0,0 +1,66 @@
using System.Collections.Specialized;
namespace DotN64.RCP
{
public partial class RealityCoprocessor
{
public partial class VideoInterface
{
public struct TimingRegister
{
#region Fields
private BitVector32 bits;
private static readonly BitVector32.Section horizontalSyncWidth = BitVector32.CreateSection((1 << 8) - 1),
colorBurstWidth = BitVector32.CreateSection((1 << 8) - 1, horizontalSyncWidth),
verticalSyncWidth = BitVector32.CreateSection((1 << 4) - 1, colorBurstWidth),
colorBurstStart = BitVector32.CreateSection((1 << 10) - 1, verticalSyncWidth);
#endregion
#region Properties
/// <summary>
/// Horizontal sync width in pixels.
/// </summary>
public byte HorizontalSyncWidth
{
get => (byte)bits[horizontalSyncWidth];
set => bits[horizontalSyncWidth] = value;
}
/// <summary>
/// Color burst width in pixels.
/// </summary>
public byte ColorBurstWidth
{
get => (byte)bits[colorBurstWidth];
set => bits[colorBurstWidth] = value;
}
/// <summary>
/// Vertical sync width in half lines.
/// </summary>
public byte VerticalSyncWidth
{
get => (byte)bits[verticalSyncWidth];
set => bits[verticalSyncWidth] = value;
}
/// <summary>
/// Start of color burst in pixels from h-sync.
/// </summary>
public ushort ColorBurstStart
{
get => (ushort)bits[colorBurstStart];
set => bits[colorBurstStart] = value;
}
#endregion
#region Operators
public static implicit operator TimingRegister(uint data) => new TimingRegister { bits = new BitVector32((int)data) };
public static implicit operator uint(TimingRegister timing) => (uint)timing.bits.Data;
#endregion
}
}
}
}

View File

@ -0,0 +1,46 @@
namespace DotN64.RCP
{
using static Helpers.BitHelper;
public partial class RealityCoprocessor
{
public partial class VideoInterface
{
public struct VerticalBurstRegister
{
#region Fields
private uint data;
private const ushort ColorBurstEnableEndShift = 0, ColorBurstEnableEndSize = (1 << 10) - 1;
private const ushort ColorBurstEnableStartShift = 16, ColorBurstEnableStartSize = (1 << 10) - 1;
#endregion
#region Properties
/// <summary>
/// End of color burst enable in half-lines.
/// </summary>
public ushort ColorBurstEnableEnd
{
get => (ushort)Get(data, ColorBurstEnableEndShift, ColorBurstEnableEndSize);
set => Set(ref data, ColorBurstEnableEndShift, ColorBurstEnableEndSize, value);
}
/// <summary>
/// Start of color burst enable in half-lines.
/// </summary>
public ushort ColorBurstEnableStart
{
get => (ushort)Get(data, ColorBurstEnableStartShift, ColorBurstEnableStartSize);
set => Set(ref data, ColorBurstEnableStartShift, ColorBurstEnableStartSize, value);
}
#endregion
#region Operators
public static implicit operator VerticalBurstRegister(uint data) => new VerticalBurstRegister { data = data };
public static implicit operator uint(VerticalBurstRegister register) => register.data;
#endregion
}
}
}
}

View File

@ -0,0 +1,46 @@
namespace DotN64.RCP
{
using static Helpers.BitHelper;
public partial class RealityCoprocessor
{
public partial class VideoInterface
{
public struct VerticalVideoRegister
{
#region Fields
private uint data;
private const ushort ActiveVideoEndShift = 0, ActiveVideoEndSize = (1 << 10) - 1;
private const ushort ActiveVideoStartShift = 16, ActiveVideoStartSize = (1 << 10) - 1;
#endregion
#region Properties
/// <summary>
/// End of active video in screen half-lines.
/// </summary>
public ushort ActiveVideoEnd
{
get => (ushort)Get(data, ActiveVideoEndShift, ActiveVideoEndSize);
set => Set(ref data, ActiveVideoEndShift, ActiveVideoEndSize, value);
}
/// <summary>
/// Start of active video in screen half-lines.
/// </summary>
public ushort ActiveVideoStart
{
get => (ushort)Get(data, ActiveVideoStartShift, ActiveVideoStartSize);
set => Set(ref data, ActiveVideoStartShift, ActiveVideoStartSize, value);
}
#endregion
#region Operators
public static implicit operator VerticalVideoRegister(uint data) => new VerticalVideoRegister { data = data };
public static implicit operator uint(VerticalVideoRegister register) => register.data;
#endregion
}
}
}
}

View File

@ -16,6 +16,41 @@
/// Current half line, sampled once per line (the lsb of V_CURRENT is constant within a field, and in interlaced modes gives the field number - which is constant for non-interlaced modes).
/// </summary>
public ushort CurrentVerticalLine { get; set; }
public ControlRegister Control { get; set; }
/// <summary>
/// Frame buffer origin in bytes.
/// </summary>
public uint DRAMAddress { get; set; }
/// <summary>
/// Frame buffer line width in pixels.
/// </summary>
public ushort Width { get; set; }
public TimingRegister Timing { get; set; }
/// <summary>
/// Number of half-lines per field.
/// </summary>
public ushort VerticalSync { get; set; }
public HorizontalSyncRegister HorizontalSync { get; set; }
/// <summary>
/// [11:0] identical to h_sync_period.
/// [27:16] identical to h_sync_period.
/// </summary>
public uint HorizontalSyncLeap { get; set; }
public VerticalVideoRegister VerticalVideo { get; set; }
public VerticalBurstRegister VerticalBurst { get; set; }
public ScaleRegister HorizontalScale { get; set; }
public ScaleRegister VerticalScale { get; set; }
#endregion
#region Constructors
@ -24,14 +59,22 @@
{
MemoryMaps = new[]
{
new MappingEntry(0x04400000, 0x04400003) // VI status/control.
{
Write = (o, d) => Control = (ushort)d
},
new MappingEntry(0x04400004, 0x04400007) // VI origin.
{
Write = (o, d) => DRAMAddress = d & ((1 << 24) - 1)
},
new MappingEntry(0x04400008, 0x0440000B) // VI width.
{
Write = (o, d) => Width = (ushort)(d & ((1 << 12) - 1))
},
new MappingEntry(0x0440000C, 0x0440000F) // VI vertical intr.
{
Write = (o, d) => VerticalInterrupt = (ushort)(d & ((1 << 10) - 1))
},
new MappingEntry(0x04400024, 0x04400027) // VI horizontal video.
{
Write = (o, d) => HorizontalVideo = d
},
new MappingEntry(0x04400010, 0x04400013) // VI current vertical line.
{
Write = (o, d) =>
@ -39,6 +82,42 @@
CurrentVerticalLine = (ushort)(d & ((1 << 10) - 1));
rcp.MI.Interrupt &= ~MIPSInterface.Interrupts.VI;
}
},
new MappingEntry(0x04400014, 0x04400017) // VI video timing.
{
Write = (o, d) => Timing = d
},
new MappingEntry(0x04400018, 0x0440001B) // VI vertical sync.
{
Write = (o, d) => VerticalSync = (ushort)(d & ((1 << 10) - 1))
},
new MappingEntry(0x0440001C, 0x0440001F) // VI horizontal sync.
{
Write = (o, d) => HorizontalSync = d
},
new MappingEntry(0x04400020, 0x04400023) // VI horizontal sync leap.
{
Write = (o, d) => HorizontalSyncLeap = d
},
new MappingEntry(0x04400024, 0x04400027) // VI horizontal video.
{
Write = (o, d) => HorizontalVideo = d
},
new MappingEntry(0x04400028, 0x0440002B) // VI vertical video.
{
Write = (o, d) => VerticalVideo = d
},
new MappingEntry(0x0440002C, 0x0440002F) // VI vertical burst.
{
Write = (o, d) => VerticalBurst = d
},
new MappingEntry(0x04400030, 0x04400033) // VI x-scale.
{
Write = (o, d) => HorizontalScale = d
},
new MappingEntry(0x04400034, 0x04400037) // VI y-scale.
{
Write = (o, d) => VerticalScale = d
}
};
}