Skip to content
Merged
2 changes: 1 addition & 1 deletion LibDmd.Test/Stubs/SourceGray2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SourceGray2 : IGray2Source, ITestSource<DmdFrame>

private readonly Subject<DmdFrame> _frames = new Subject<DmdFrame>();

public IObservable<DmdFrame> GetGray2Frames(bool dedupe) => _frames;
public IObservable<DmdFrame> GetGray2Frames(bool dedupe, bool skipIdentificationFrames) => _frames;

public void AddFrame(DmdFrame frame)
{
Expand Down
2 changes: 1 addition & 1 deletion LibDmd.Test/Stubs/SourceGray4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SourceGray4 : IGray4Source, ITestSource<DmdFrame>

private readonly Subject<DmdFrame> _frames = new Subject<DmdFrame>();

public IObservable<DmdFrame> GetGray4Frames(bool dedupe) => _frames;
public IObservable<DmdFrame> GetGray4Frames(bool dedupe, bool skipIdentificationFrames) => _frames;

public void AddFrame(DmdFrame frame)
{
Expand Down
14 changes: 14 additions & 0 deletions LibDmd/Common/FrameUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,20 @@ public static byte[] ConvertGrayToGray(byte[] srcFrame, params byte[] mapping)
}
}

public static byte[] ConvertGray8ToGray(byte[] srcFrame, int bitLength)
{
using (Profiler.Start("FrameUtil.ConvertGray8ToGray")) {
var numDestColors = Math.Pow(2, bitLength);
var factor = 256 / numDestColors;

var destFrame = new byte[srcFrame.Length];
for (var i = 0; i < destFrame.Length; i++) {
destFrame[i] = (byte)Math.Floor(srcFrame[i] / factor);
}
return destFrame;
}
}

public static byte[] NewPlane(Dimensions dim)
{
var count = dim.Width / 8 * dim.Height;
Expand Down
41 changes: 39 additions & 2 deletions LibDmd/DmdDevice/DmdDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
// sources
private readonly PassthroughGray2Source _passthroughGray2Source;
private readonly PassthroughGray4Source _passthroughGray4Source;
private readonly PassthroughGray8Source _passthroughGray8Source;
private readonly PassthroughRgb24Source _passthroughRgb24Source;
private readonly PassthroughAlphaNumericSource _passthroughAlphaNumericSource;

Expand Down Expand Up @@ -94,6 +95,7 @@
var currentFrameFormat = new BehaviorSubject<FrameFormat>(FrameFormat.Rgb24);
_passthroughGray2Source = new PassthroughGray2Source(currentFrameFormat, "DmdDevice 2-bit Source");
_passthroughGray4Source = new PassthroughGray4Source(currentFrameFormat, "DmdDevice 4-bit Source");
_passthroughGray8Source = new PassthroughGray8Source(currentFrameFormat, "DmdDevice 8-bit Source");
_passthroughRgb24Source = new PassthroughRgb24Source(currentFrameFormat, "DmdDevice RGB24 Source");
_passthroughAlphaNumericSource = new PassthroughAlphaNumericSource(currentFrameFormat);

Expand All @@ -116,7 +118,7 @@
}
#if !DEBUG
else {
SimpleConfigurator.ConfigureForTargetLogging(MemLogger, LogLevel.Debug);

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x86, Release)

'SimpleConfigurator.ConfigureForTargetLogging(Target, LogLevel)' is obsolete: 'Use LogManager.Setup().LoadConfiguration(c => c.ForLogger(minLevel).WriteTo(target)) instead. Marked obsolete on NLog 5.2'

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x86, Release)

'SimpleConfigurator' is obsolete: 'Use LogManager.Setup().LoadConfiguration() instead. Marked obsolete on NLog 5.2'

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x86, Release)

'SimpleConfigurator.ConfigureForTargetLogging(Target, LogLevel)' is obsolete: 'Use LogManager.Setup().LoadConfiguration(c => c.ForLogger(minLevel).WriteTo(target)) instead. Marked obsolete on NLog 5.2'

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x86, Release)

'SimpleConfigurator' is obsolete: 'Use LogManager.Setup().LoadConfiguration() instead. Marked obsolete on NLog 5.2'

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x64, Release)

'SimpleConfigurator.ConfigureForTargetLogging(Target, LogLevel)' is obsolete: 'Use LogManager.Setup().LoadConfiguration(c => c.ForLogger(minLevel).WriteTo(target)) instead. Marked obsolete on NLog 5.2'

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x64, Release)

'SimpleConfigurator' is obsolete: 'Use LogManager.Setup().LoadConfiguration() instead. Marked obsolete on NLog 5.2'

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x64, Release)

'SimpleConfigurator.ConfigureForTargetLogging(Target, LogLevel)' is obsolete: 'Use LogManager.Setup().LoadConfiguration(c => c.ForLogger(minLevel).WriteTo(target)) instead. Marked obsolete on NLog 5.2'

Check warning on line 121 in LibDmd/DmdDevice/DmdDevice.cs

View workflow job for this annotation

GitHub Actions / build-windows (x64, Release)

'SimpleConfigurator' is obsolete: 'Use LogManager.Setup().LoadConfiguration() instead. Marked obsolete on NLog 5.2'
}
#endif
}
Expand Down Expand Up @@ -242,7 +244,7 @@
public void SetColor(Color color)
{
Logger.Info("Setting color: {0}", color);
_color = color;
_color = Colors.OrangeRed;
}

/// <summary>
Expand Down Expand Up @@ -288,6 +290,31 @@
_passthroughGray4Source.NextFrame(frame);
}

/// <summary>
/// A new gray8 frame coming in from the DLL.
/// </summary>
///
/// <remarks>
/// Gray8 frames exist because PinMAME does some clever PWM simulation on some games which ends up in 8-bit shadings.
/// </remarks>
/// <param name="frame">New gray8 frame</param>
public void RenderGray8(DmdFrame frame, DmdFrame identifyFrame)
{
AnalyticsSetDmd();
if (!_isOpen) {
Init();
}
_passthroughGray8Source.NextFrame(frame);
switch (identifyFrame.BitLength) {
case 2:
_passthroughGray2Source.NextFrame(identifyFrame);
break;
case 4:
_passthroughGray4Source.NextFrame(identifyFrame);
break;
}
}

/// <summary>
/// A new RGB24 frame coming in from the DLL.
/// </summary>
Expand Down Expand Up @@ -329,7 +356,7 @@

_passthroughAlphaNumericSource.NextFrame(new AlphaNumericFrame(layout, segData, segDataExtended));

//Logger.Info("Alphanumeric: {0}", layout);
Logger.Info("Alphanumeric: {0}", layout);
switch (layout) {
case NumericalLayout.__2x16Alpha:
_passthroughGray2Source.NextFrame(_alphanumFrame.Update(AlphaNumeric.Render2x16Alpha(segData), 2));
Expand Down Expand Up @@ -769,6 +796,16 @@
FlipVertically = _config.Global.FlipVertically,
ScalerMode = _config.Global.ScalerMode
});

_graphs.Add(new RenderGraph(refs) {
Name = "8-bit Passthrough Graph",
Source = _passthroughGray8Source,
Destinations = renderers,
Resize = _config.Global.Resize,
FlipHorizontally = _config.Global.FlipHorizontally,
FlipVertically = _config.Global.FlipVertically,
ScalerMode = _config.Global.ScalerMode
});
}

// rgb24 graph
Expand Down
43 changes: 22 additions & 21 deletions LibDmd/DmdDevice/IDmdDevice.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
using System.Windows.Media;
using LibDmd.Frame;

namespace LibDmd.DmdDevice
{
public interface IDmdDevice
{
void Close();
void SetColorize(bool colorize);
void SetGameName(string gameName);
void SetColor(Color color);
void ConsoleData(byte data);
void Init();
void LoadPalette(uint palIndex);
void SetPalette(Color[] colors);
void RenderRgb24(DmdFrame frame);
void RenderGray4(DmdFrame frame);
void RenderGray2(DmdFrame frame);
void RenderAlphaNumeric(NumericalLayout numericalLayout, ushort[] readUInt16Array, ushort[] ushorts);
}
}
using System.Windows.Media;
using LibDmd.Frame;

namespace LibDmd.DmdDevice
{
public interface IDmdDevice
{
void Close();
void SetColorize(bool colorize);
void SetGameName(string gameName);
void SetColor(Color color);
void ConsoleData(byte data);
void Init();
void LoadPalette(uint palIndex);
void SetPalette(Color[] colors);
void RenderRgb24(DmdFrame frame);
void RenderGray8(DmdFrame frame, DmdFrame identifyFrame = null);
void RenderGray4(DmdFrame frame);
void RenderGray2(DmdFrame frame);
void RenderAlphaNumeric(NumericalLayout numericalLayout, ushort[] readUInt16Array, ushort[] ushorts);
}
}
29 changes: 28 additions & 1 deletion LibDmd/Frame/DmdFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public class DmdFrame : BaseFrame, ICloneable, IEqualityComparer<DmdFrame>
/// </summary>
public byte[] Data { get; protected set; }

/// <summary>
/// These frames are used for colorization and should never be rendered (if they exist, that means
/// there's a gray-8 frame to be rendered).
/// </summary>
public bool IsIdentifyFrame { get; protected set; }

/// <summary>
/// The bit length of each pixel.
/// </summary>
Expand Down Expand Up @@ -132,6 +138,7 @@ public DmdFrame Update(DmdFrame frame)
Dimensions = frame.Dimensions;
Data = frame.Data;
BitLength = frame.BitLength;
IsIdentifyFrame = false;

#if DEBUG
AssertData();
Expand All @@ -143,18 +150,20 @@ public DmdFrame Update(byte[] data, int bitLength)
{
Data = data;
BitLength = bitLength;
IsIdentifyFrame = false;

#if DEBUG
AssertData();
#endif
return this;
}

public DmdFrame Update(Dimensions dim, byte[] data, int bitLength)
public DmdFrame Update(Dimensions dim, byte[] data, int bitLength, bool isIdentifyFrame = false)
{
Dimensions = dim;
Data = data;
BitLength = bitLength;
IsIdentifyFrame = isIdentifyFrame;

#if DEBUG
AssertData();
Expand All @@ -166,6 +175,7 @@ public DmdFrame Update(Dimensions dim, byte[] data)
{
Dimensions = dim;
Data = data;
IsIdentifyFrame = false;

#if DEBUG
AssertData();
Expand Down Expand Up @@ -248,6 +258,8 @@ public DmdFrame ConvertToGray2()
return Update(FrameUtil.ConvertGrayToGray(Data, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3), 2);
case 6:
return Update(FrameUtil.ConvertGrayToGray(Data, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3), 2);
case 8:
return Update(FrameUtil.ConvertGray8ToGray(Data, 2), 2);
case 16:
return Update(ImageUtil.ConvertRgb565ToGray(Dimensions, Data, 4), 2);
case 24:
Expand Down Expand Up @@ -275,6 +287,8 @@ public DmdFrame ConvertToGray4()
throw new ArgumentException("Frame is already gray4.");
case 6:
return Update(FrameUtil.ConvertGrayToGray(Data, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x6, 0x6, 0x6, 0x6, 0x7, 0x7, 0x7, 0x7, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0xa, 0xa, 0xa, 0xa, 0xb, 0xb, 0xb, 0xb, 0xc, 0xc, 0xc, 0xc, 0xd, 0xd, 0xd, 0xd, 0xe, 0xe, 0xe, 0xe, 0xf, 0xf, 0xf, 0xf), 4);
case 8:
return Update(FrameUtil.ConvertGray8ToGray(Data, 4), 4);
case 16:
return Update(ImageUtil.ConvertRgb565ToGray(Dimensions, Data, 16), 4);
case 24:
Expand Down Expand Up @@ -383,6 +397,19 @@ public DmdFrame ConvertRgb565ToRgb24()
}
}

public ColoredFrame ConvertGray8ToColoredGray6(Color[] palette)
{
using (Profiler.Start("DmdFrame.ConvertGray8ToColoredGray")) {

#if DEBUG
if (BitLength != 8) {
throw new ArgumentException("Cannot convert non-Gray8 frame to Colored Gray 6.");
}
#endif
return new ColoredFrame(Dimensions, FrameUtil.ConvertGray8ToGray(Data, 6), palette);
}
}

public DmdFrame ConvertRgb24ToRgb565()
{
using (Profiler.Start("DmdFrame.ConvertRgb24ToRgb565")) {
Expand Down
2 changes: 1 addition & 1 deletion LibDmd/Input/FileSystem/DumpSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public DumpSource(string filename)
}
}

public IObservable<DmdFrame> GetGray2Frames(bool dedupe)
public IObservable<DmdFrame> GetGray2Frames(bool dedupe, bool skipIdentificationFrames)
{
const Int32 bufferSize = 128;
_gameName.OnNext(Path.GetFileNameWithoutExtension(_filename).TrimEnd('-'));
Expand Down
4 changes: 2 additions & 2 deletions LibDmd/Input/FileSystem/ImageSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ImageSourceGray2 : ImageSource, IGray2Source
{
readonly DmdFrame _dmdFrame = new DmdFrame();

public IObservable<DmdFrame> GetGray2Frames(bool dedupe) => _frames;
public IObservable<DmdFrame> GetGray2Frames(bool dedupe, bool skipIdentificationFrames) => _frames;

private readonly BehaviorSubject<DmdFrame> _frames;

Expand All @@ -27,7 +27,7 @@ public class ImageSourceGray4 : ImageSource, IGray4Source
{
DmdFrame _dmdFrame = new DmdFrame();

public IObservable<DmdFrame> GetGray4Frames(bool dedupe) => _frames;
public IObservable<DmdFrame> GetGray4Frames(bool dedupe, bool skipIdentificationFrames) => _frames;

private readonly BehaviorSubject<DmdFrame> _frames;

Expand Down
4 changes: 2 additions & 2 deletions LibDmd/Input/FileSystem/PassthroughSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ public PassthroughSource(string name)
Name = name;
}

public IObservable<DmdFrame> GetGray2Frames(bool dedupe)
public IObservable<DmdFrame> GetGray2Frames(bool dedupe, bool skipIdentificationFrames)
{
return FramesGray2;
}

public IObservable<DmdFrame> GetGray4Frames(bool dedupe)
public IObservable<DmdFrame> GetGray4Frames(bool dedupe, bool skipIdentificationFrames)
{
return FramesGray4;
}
Expand Down
2 changes: 1 addition & 1 deletion LibDmd/Input/FutureDmd/FutureDmdSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public FutureDmdSink(double framesPerSecond)
Thread.Sleep(250);
}

public IObservable<DmdFrame> GetGray4Frames(bool dedupe)
public IObservable<DmdFrame> GetGray4Frames(bool dedupe, bool skipIdentificationFrames)
{
return _framesGray4;
}
Expand Down
3 changes: 2 additions & 1 deletion LibDmd/Input/IGray2Source.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public interface IGray2Source : ISource
/// between 0 and 3 for every pixel.
/// </summary>
/// <param name="dedupe"></param>
/// <param name="skipIdentificationFrames"></param>
/// <remarks>When disposed, frame production must stop.</remarks>
IObservable<DmdFrame> GetGray2Frames(bool dedupe);
IObservable<DmdFrame> GetGray2Frames(bool dedupe, bool skipIdentificationFrames);
}
}
3 changes: 2 additions & 1 deletion LibDmd/Input/IGray4Source.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public interface IGray4Source : ISource
/// between 0 and 15 for every pixel.
/// </summary>
/// <param name="dedupe"></param>
/// <param name="skipIdentificationFrames"></param>
/// <remarks>When disposed, frame production must stop.</remarks>
IObservable<DmdFrame> GetGray4Frames(bool dedupe);
IObservable<DmdFrame> GetGray4Frames(bool dedupe, bool skipIdentificationFrames);
}
}
22 changes: 22 additions & 0 deletions LibDmd/Input/IGray8Source.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using LibDmd.Frame;

namespace LibDmd.Input
{

/// <summary>
/// A source that is able to deliver 8-bit grayscale frames without conversion.
/// </summary>
public interface IGray8Source : ISource
{
/// <summary>
/// Returns an observable that produces a sequence of 8-bit frames.
///
/// The returned byte array contains Width * Height bytes, with values
/// between 0 and 255 for every pixel.
/// </summary>
/// <param name="dedupe"></param>
/// <remarks>When disposed, frame production must stop.</remarks>
IObservable<DmdFrame> GetGray8Frames(bool dedupe);
}
}
2 changes: 1 addition & 1 deletion LibDmd/Input/Network/WebsocketGray2Source.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class WebsocketGray2Source : AbstractSource, IGray2Source

public readonly Subject<DmdFrame> FramesGray2 = new Subject<DmdFrame>();

public IObservable<DmdFrame> GetGray2Frames(bool dedupe)
public IObservable<DmdFrame> GetGray2Frames(bool dedupe, bool skipIdentificationFrames)
{
return FramesGray2;
}
Expand Down
2 changes: 1 addition & 1 deletion LibDmd/Input/Network/WebsocketGray4Source .cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class WebsocketGray4Source : AbstractSource, IGray4Source

public readonly Subject<DmdFrame> FramesGray4 = new Subject<DmdFrame>();

public IObservable<DmdFrame> GetGray4Frames(bool dedupe)
public IObservable<DmdFrame> GetGray4Frames(bool dedupe, bool skipIdentificationFrames)
{
return FramesGray4;
}
Expand Down
5 changes: 4 additions & 1 deletion LibDmd/Input/Passthrough/PassthroughGray2Source.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using LibDmd.Frame;
using NLog;
Expand Down Expand Up @@ -50,7 +51,9 @@ public void NextFrame(DmdFrame frame)
_framesGray2Deduped.OnNext(frame);
}

public IObservable<DmdFrame> GetGray2Frames(bool dedupe) => dedupe ? _framesGray2Deduped : _framesGray2Duped;
public IObservable<DmdFrame> GetGray2Frames(bool dedupe, bool skipIdentificationFrames) => dedupe
? (skipIdentificationFrames ? _framesGray2Deduped.Where(f => !f.IsIdentifyFrame) : _framesGray2Deduped)
: (skipIdentificationFrames ? _framesGray2Duped.Where(f => !f.IsIdentifyFrame) : _framesGray2Duped);

public void NextGameName(string gameName) => _gameName.OnNext(gameName);

Expand Down
Loading
Loading