VI registers.
parent
55382b2c14
commit
83f573764b
|
@ -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\" />
|
||||
|
|
|
@ -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 & resamp (always fetch extra lines).</summary>
|
||||
AntiAliasAndResampleAlways = 0,
|
||||
/// <summary>AA & 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue