Mesen-SX/UI/Debugger/PpuViewer/frmPaletteViewer.cs
2019-03-16 16:38:28 -04:00

107 lines
2.6 KiB
C#

using Mesen.GUI.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public partial class frmPaletteViewer : BaseForm
{
private NotificationListener _notifListener;
private byte[] _cgRam;
private Bitmap _paletteImage;
public frmPaletteViewer()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(DesignMode) {
return;
}
_notifListener = new NotificationListener();
_notifListener.OnNotification += OnNotificationReceived;
_paletteImage = new Bitmap(256, 256, PixelFormat.Format32bppArgb);
picPalette.Image = _paletteImage;
ctrlScanlineCycleSelect.Initialize(241, 0);
RefreshData();
RefreshViewer();
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
_notifListener?.Dispose();
}
private void OnNotificationReceived(NotificationEventArgs e)
{
switch(e.NotificationType) {
case ConsoleNotificationType.ViewerRefresh:
if(e.Parameter.ToInt32() == ctrlScanlineCycleSelect.ViewerId) {
RefreshData();
this.BeginInvoke((Action)(() => {
this.RefreshViewer();
}));
}
break;
}
}
private void RefreshData()
{
_cgRam = DebugApi.GetMemoryState(SnesMemoryType.CGRam);
}
private void RefreshViewer()
{
Func<int, uint> to8Bit = (int color) => { return (uint)((color << 3) + (color >> 2)); };
Func<int, uint> toArgb = (int rgb555) => {
uint b = to8Bit(rgb555 >> 10);
uint g = to8Bit((rgb555 >> 5) & 0x1F);
uint r = to8Bit(rgb555 & 0x1F);
return (0xFF000000 | (r << 16) | (g << 8) | b);
};
UInt32[] argbPalette = new UInt32[256];
for(int i = 0; i < 256; i++) {
argbPalette[i] = toArgb(_cgRam[i * 2] | _cgRam[i * 2 + 1] << 8);
}
using(Graphics g = Graphics.FromImage(_paletteImage)) {
GCHandle handle = GCHandle.Alloc(argbPalette, GCHandleType.Pinned);
Bitmap source = new Bitmap(16, 16, 16 * 4, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
try {
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.SmoothingMode = SmoothingMode.None;
g.PixelOffsetMode = PixelOffsetMode.Half;
g.ScaleTransform(16, 16);
g.DrawImage(source, 0, 0);
} finally {
handle.Free();
}
}
picPalette.Invalidate();
}
}
}