This commit is contained in:
adelikat 2019-12-31 10:17:55 -06:00
parent 094ae65e06
commit 64ea9afee5
29 changed files with 575 additions and 779 deletions

View File

@ -19,11 +19,7 @@ namespace BizHawk.Client.EmuHawk
/// </summary>
public int Frameskip
{
get
{
return _frameskip;
}
get => _frameskip;
private set
{
if (value < 0)
@ -46,11 +42,7 @@ namespace BizHawk.Client.EmuHawk
/// </summary>
public int FrameDelay
{
get
{
return _framedelay;
}
get => _framedelay;
private set
{
if (value < -1)
@ -81,10 +73,10 @@ namespace BizHawk.Client.EmuHawk
{
}
private GifToken(int frameskip, int framedelay)
private GifToken(int frameskip, int frameDelay)
{
Frameskip = frameskip;
FrameDelay = framedelay;
FrameDelay = frameDelay;
}
}
@ -92,9 +84,9 @@ namespace BizHawk.Client.EmuHawk
public void SetVideoCodecToken(IDisposable token)
{
if (token is GifToken)
if (token is GifToken gifToken)
{
_token = (GifToken)token;
_token = gifToken;
CalcDelay();
}
else
@ -169,35 +161,31 @@ namespace BizHawk.Client.EmuHawk
return; // skip this frame
}
using (var bmp = new Bitmap(source.BufferWidth, source.BufferHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
using var bmp = new Bitmap(source.BufferWidth, source.BufferHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Runtime.InteropServices.Marshal.Copy(source.GetVideoBuffer(), 0, data.Scan0, bmp.Width * bmp.Height);
bmp.UnlockBits(data);
using var qBmp = new OctreeQuantizer(255, 8).Quantize(bmp);
MemoryStream ms = new MemoryStream();
qBmp.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
byte[] b = ms.GetBuffer();
if (!firstdone)
{
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Runtime.InteropServices.Marshal.Copy(source.GetVideoBuffer(), 0, data.Scan0, bmp.Width * bmp.Height);
bmp.UnlockBits(data);
using (var qBmp = new OctreeQuantizer(255, 8).Quantize(bmp))
{
MemoryStream ms = new MemoryStream();
qBmp.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
byte[] b = ms.GetBuffer();
if (!firstdone)
{
firstdone = true;
b[10] = (byte)(b[10] & 0x78); // no global color table
f.Write(b, 0, 13);
f.Write(GifAnimation, 0, GifAnimation.Length);
}
b[785] = Delay[0];
b[786] = Delay[1];
b[798] = (byte)(b[798] | 0x87);
f.Write(b, 781, 18);
f.Write(b, 13, 768);
f.Write(b, 799, (int)(ms.Length - 800));
lastbyte = b[ms.Length - 1];
}
firstdone = true;
b[10] = (byte)(b[10] & 0x78); // no global color table
f.Write(b, 0, 13);
f.Write(GifAnimation, 0, GifAnimation.Length);
}
b[785] = Delay[0];
b[786] = Delay[1];
b[798] = (byte)(b[798] | 0x87);
f.Write(b, 781, 18);
f.Write(b, 13, 768);
f.Write(b, 799, (int)(ms.Length - 800));
lastbyte = b[ms.Length - 1];
}
public void AddSamples(short[] samples)

View File

@ -2,6 +2,7 @@
using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.WinFormExtensions;
namespace BizHawk.Client.EmuHawk
{
@ -14,23 +15,23 @@ namespace BizHawk.Client.EmuHawk
public static GifWriter.GifToken DoTokenForm(IWin32Window parent)
{
using (var dlg = new GifWriterForm())
using var dlg = new GifWriterForm
{
dlg.numericUpDown1.Value = Global.Config.GifWriterFrameskip;
dlg.numericUpDown2.Value = Global.Config.GifWriterDelay;
dlg.NumericUpDown2_ValueChanged(null, null);
numericUpDown1 = { Value = Global.Config.GifWriterFrameskip },
numericUpDown2 = { Value = Global.Config.GifWriterDelay }
};
dlg.NumericUpDown2_ValueChanged(null, null);
var result = dlg.ShowDialog(parent);
if (result == DialogResult.OK)
{
Global.Config.GifWriterFrameskip = (int)dlg.numericUpDown1.Value;
Global.Config.GifWriterDelay = (int)dlg.numericUpDown2.Value;
var result = dlg.ShowDialog(parent);
if (result.IsOk())
{
Global.Config.GifWriterFrameskip = (int)dlg.numericUpDown1.Value;
Global.Config.GifWriterDelay = (int)dlg.numericUpDown2.Value;
return GifWriter.GifToken.LoadFromConfig();
}
return null;
return GifWriter.GifToken.LoadFromConfig();
}
return null;
}
private void NumericUpDown2_ValueChanged(object sender, EventArgs e)

View File

@ -22,351 +22,348 @@ using System.Drawing.Imaging;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// Summary description for Class1.
/// </summary>
internal unsafe abstract class Quantizer
{
/// <summary>
/// Flag used to indicate whether a single pass or two passes are needed for quantization.
/// </summary>
private bool _singlePass;
protected bool highquality;
public bool HighQuality
{
get
{
return highquality;
}
internal abstract unsafe class Quantizer
{
/// <summary>
/// Flag used to indicate whether a single pass or two passes are needed for quantization.
/// </summary>
private bool _singlePass;
set
{
highquality = value;
}
}
protected bool highquality;
public bool HighQuality
{
get
{
return highquality;
}
protected int ditherLevel;
public int DitherLevel
{
get
{
return this.ditherLevel;
}
set
{
highquality = value;
}
}
set
{
this.ditherLevel = value;
}
}
protected int ditherLevel;
public int DitherLevel
{
get
{
return ditherLevel;
}
/// <summary>
/// Construct the quantizer
/// </summary>
/// <param name="singlePass">If true, the quantization only needs to loop through the source pixels once</param>
/// <remarks>
/// If you construct this class with a true value for singlePass, then the code will, when quantizing your image,
/// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage'
/// and then 'QuantizeImage'.
/// </remarks>
public Quantizer(bool singlePass)
{
_singlePass = singlePass;
}
set
{
ditherLevel = value;
}
}
/// <summary>
/// Quantize an image and return the resulting output bitmap
/// </summary>
/// <param name="source">The image to quantize</param>
/// <returns>A quantized version of the image</returns>
public Bitmap Quantize(Image source)
{
// Get the size of the source image
int height = source.Height;
int width = source.Width;
/// <summary>
/// Construct the quantizer
/// </summary>
/// <param name="singlePass">If true, the quantization only needs to loop through the source pixels once</param>
/// <remarks>
/// If you construct this class with a true value for singlePass, then the code will, when quantizing your image,
/// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage'
/// and then 'QuantizeImage'.
/// </remarks>
public Quantizer(bool singlePass)
{
_singlePass = singlePass;
}
// And construct a rectangle from these dimensions
Rectangle bounds = new Rectangle(0, 0, width, height);
/// <summary>
/// Quantize an image and return the resulting output bitmap
/// </summary>
/// <param name="source">The image to quantize</param>
/// <returns>A quantized version of the image</returns>
public Bitmap Quantize(Image source)
{
// Get the size of the source image
int height = source.Height;
int width = source.Width;
// First off take a 32bpp copy of the image
Bitmap copy;
if (source is Bitmap && source.PixelFormat == PixelFormat.Format32bppArgb)
{
copy = (Bitmap)source;
}
else
{
copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
// And construct a rectangle from these dimensions
Rectangle bounds = new Rectangle(0, 0, width, height);
// Now lock the bitmap into memory
using (Graphics g = Graphics.FromImage(copy))
{
g.PageUnit = GraphicsUnit.Pixel;
// First off take a 32bpp copy of the image
Bitmap copy;
// Draw the source image onto the copy bitmap,
// which will effect a widening as appropriate.
g.DrawImage(source, 0, 0, bounds.Width, bounds.Height);
}
}
if (source is Bitmap && source.PixelFormat == PixelFormat.Format32bppArgb)
{
copy = (Bitmap)source;
}
else
{
copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
// And construct an 8bpp version
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
// Now lock the bitmap into memory
using (Graphics g = Graphics.FromImage(copy))
{
g.PageUnit = GraphicsUnit.Pixel;
// Define a pointer to the bitmap data
BitmapData sourceData = null;
// Draw the source image onto the copy bitmap,
// which will effect a widening as appropriate.
g.DrawImage(source, 0, 0, bounds.Width, bounds.Height);
}
}
try
{
// Get the source image bits and lock into memory
sourceData = copy.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
// And construct an 8bpp version
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
// Call the FirstPass function if not a single pass algorithm.
// For something like an octree quantizer, this will run through
// all image pixels, build a data structure, and create a palette.
if (!_singlePass)
{
FirstPass(sourceData, width, height);
}
// Define a pointer to the bitmap data
BitmapData sourceData = null;
// Then set the color palette on the output bitmap. I'm passing in the current palette
// as there's no way to construct a new, empty palette.
output.Palette = this.GetPalette(output.Palette);
try
{
// Get the source image bits and lock into memory
sourceData = copy.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
// Then call the second pass which actually does the conversion
SecondPass(sourceData, output, width, height, bounds);
}
// Call the FirstPass function if not a single pass algorithm.
// For something like an octree quantizer, this will run through
// all image pixels, build a data structure, and create a palette.
if (!_singlePass)
{
FirstPass(sourceData, width, height);
}
finally
{
// Ensure that the bits are unlocked
copy.UnlockBits(sourceData);
}
// Then set the color palette on the output bitmap. I'm passing in the current palette
// as there's no way to construct a new, empty palette.
output.Palette = this.GetPalette(output.Palette);
if (copy != source)
{
copy.Dispose();
}
// Then call the second pass which actually does the conversion
SecondPass(sourceData, output, width, height, bounds);
}
// Last but not least, return the output bitmap
return output;
}
finally
{
// Ensure that the bits are unlocked
copy.UnlockBits(sourceData);
}
/// <summary>
/// Execute the first pass through the pixels in the image
/// </summary>
/// <param name="sourceData">The source data</param>
/// <param name="width">The width in pixels of the image</param>
/// <param name="height">The height in pixels of the image</param>
protected virtual void FirstPass(BitmapData sourceData, int width, int height)
{
// Define the source data pointers. The source row is a byte to
// keep addition of the stride value easier (as this is in bytes)
byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer();
int* pSourcePixel;
if (copy != source)
{
copy.Dispose();
}
// Loop through each row
for (int row = 0; row < height; row++)
{
// Set the source pixel to the first pixel in this row
pSourcePixel = (Int32*)pSourceRow;
// Last but not least, return the output bitmap
return output;
}
// And loop through each column
for (int col = 0; col < width; col++, pSourcePixel++)
{
InitialQuantizePixel(*pSourcePixel);
}
/// <summary>
/// Execute the first pass through the pixels in the image
/// </summary>
/// <param name="sourceData">The source data</param>
/// <param name="width">The width in pixels of the image</param>
/// <param name="height">The height in pixels of the image</param>
protected virtual void FirstPass(BitmapData sourceData, int width, int height)
{
// Define the source data pointers. The source row is a byte to
// keep addition of the stride value easier (as this is in bytes)
byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer();
int* pSourcePixel;
// Add the stride to the source row
pSourceRow += sourceData.Stride;
// Loop through each row
for (int row = 0; row < height; row++)
{
// Set the source pixel to the first pixel in this row
pSourcePixel = (Int32*)pSourceRow;
}
}
// And loop through each column
for (int col = 0; col < width; col++, pSourcePixel++)
{
InitialQuantizePixel(*pSourcePixel);
}
int ClampToByte(int val)
{
if (val < 0) return 0;
else if (val > 255) return 255;
else return val;
}
// Add the stride to the source row
pSourceRow += sourceData.Stride;
/// <summary>
/// Execute a second pass through the bitmap
/// </summary>
/// <param name="sourceData">The source bitmap, locked into memory</param>
/// <param name="output">The output bitmap</param>
/// <param name="width">The width in pixels of the image</param>
/// <param name="height">The height in pixels of the image</param>
/// <param name="bounds">The bounding rectangle</param>
protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds)
{
BitmapData outputData = null;
Color[] pallete = output.Palette.Entries;
int weight = ditherLevel;
}
}
try
{
// Lock the output bitmap into memory
outputData = output.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
int ClampToByte(int val)
{
if (val < 0) return 0;
else if (val > 255) return 255;
else return val;
}
// Define the source data pointers. The source row is a byte to
// keep addition of the stride value easier (as this is in bytes)
byte* pSourceRow = (byte *)sourceData.Scan0.ToPointer();
Int32* pSourcePixel = (Int32 *)pSourceRow;
/// <summary>
/// Execute a second pass through the bitmap
/// </summary>
/// <param name="sourceData">The source bitmap, locked into memory</param>
/// <param name="output">The output bitmap</param>
/// <param name="width">The width in pixels of the image</param>
/// <param name="height">The height in pixels of the image</param>
/// <param name="bounds">The bounding rectangle</param>
protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds)
{
BitmapData outputData = null;
Color[] pallete = output.Palette.Entries;
int weight = ditherLevel;
// Now define the destination data pointers
byte* pDestinationRow = (byte *)outputData.Scan0.ToPointer();
byte* pDestinationPixel = pDestinationRow;
try
{
// Lock the output bitmap into memory
outputData = output.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
int[] errorThisRowR = new int[width + 1];
int[] errorThisRowG = new int[width + 1];
int[] errorThisRowB = new int[width + 1];
// Define the source data pointers. The source row is a byte to
// keep addition of the stride value easier (as this is in bytes)
byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer();
Int32* pSourcePixel = (Int32*)pSourceRow;
for (int row = 0; row < height; row++)
{
int[] errorNextRowR = new int[width + 1];
int[] errorNextRowG = new int[width + 1];
int[] errorNextRowB = new int[width + 1];
// Now define the destination data pointers
byte* pDestinationRow = (byte*)outputData.Scan0.ToPointer();
byte* pDestinationPixel = pDestinationRow;
int ptrInc;
int[] errorThisRowR = new int[width + 1];
int[] errorThisRowG = new int[width + 1];
int[] errorThisRowB = new int[width + 1];
if ((row & 1) == 0)
{
pSourcePixel = (Int32*)pSourceRow;
pDestinationPixel = pDestinationRow;
ptrInc = +1;
}
else
{
pSourcePixel = (Int32*)pSourceRow + width - 1;
pDestinationPixel = pDestinationRow + width - 1;
ptrInc = -1;
}
for (int row = 0; row < height; row++)
{
int[] errorNextRowR = new int[width + 1];
int[] errorNextRowG = new int[width + 1];
int[] errorNextRowB = new int[width + 1];
// Loop through each pixel on this scan line
for (int col = 0; col < width; ++col)
{
// Quantize the pixel
int srcPixel = *pSourcePixel;
int ptrInc;
int srcR = srcPixel & 0xFF; //not
int srcG = (srcPixel>>8) & 0xFF; //a
int srcB = (srcPixel>>16) & 0xFF; //mistake
int srcA = (srcPixel >> 24) & 0xFF;
if ((row & 1) == 0)
{
pSourcePixel = (Int32*)pSourceRow;
pDestinationPixel = pDestinationRow;
ptrInc = +1;
}
else
{
pSourcePixel = (Int32*)pSourceRow + width - 1;
pDestinationPixel = pDestinationRow + width - 1;
ptrInc = -1;
}
int targetB = ClampToByte(srcB - ((errorThisRowB[col] * weight) / 8));
int targetG = ClampToByte(srcG - ((errorThisRowG[col] * weight) / 8));
int targetR = ClampToByte(srcR - ((errorThisRowR[col] * weight) / 8));
int targetA = srcA;
// Loop through each pixel on this scan line
for (int col = 0; col < width; ++col)
{
// Quantize the pixel
int srcPixel = *pSourcePixel;
int target = (targetA<<24)|(targetB<<16)|(targetG<<8)|targetR;
int srcR = srcPixel & 0xFF; //not
int srcG = (srcPixel >> 8) & 0xFF; //a
int srcB = (srcPixel >> 16) & 0xFF; //mistake
int srcA = (srcPixel >> 24) & 0xFF;
byte pixelValue = QuantizePixel(target);
*pDestinationPixel = pixelValue;
int targetB = ClampToByte(srcB - ((errorThisRowB[col] * weight) / 8));
int targetG = ClampToByte(srcG - ((errorThisRowG[col] * weight) / 8));
int targetR = ClampToByte(srcR - ((errorThisRowR[col] * weight) / 8));
int targetA = srcA;
int actual = pallete[pixelValue].ToArgb();
int target = (targetA << 24) | (targetB << 16) | (targetG << 8) | targetR;
int actualR = actual & 0xFF;
int actualG = (actual >> 8) & 0xFF;
int actualB = (actual >> 16) & 0xFF;
int errorR = actualR - targetR;
int errorG = actualG - targetG;
int errorB = actualB - targetB;
byte pixelValue = QuantizePixel(target);
*pDestinationPixel = pixelValue;
// Floyd-Steinberg Error Diffusion:
// a) 7/16 error goes to x+1
// b) 5/16 error goes to y+1
// c) 3/16 error goes to x-1,y+1
// d) 1/16 error goes to x+1,y+1
int actual = pallete[pixelValue].ToArgb();
const int a = 7;
const int b = 5;
const int c = 3;
int actualR = actual & 0xFF;
int actualG = (actual >> 8) & 0xFF;
int actualB = (actual >> 16) & 0xFF;
int errorR = actualR - targetR;
int errorG = actualG - targetG;
int errorB = actualB - targetB;
int errorRa = (errorR * a) / 16;
int errorRb = (errorR * b) / 16;
int errorRc = (errorR * c) / 16;
int errorRd = errorR - errorRa - errorRb - errorRc;
// Floyd-Steinberg Error Diffusion:
// a) 7/16 error goes to x+1
// b) 5/16 error goes to y+1
// c) 3/16 error goes to x-1,y+1
// d) 1/16 error goes to x+1,y+1
int errorGa = (errorG * a) / 16;
int errorGb = (errorG * b) / 16;
int errorGc = (errorG * c) / 16;
int errorGd = errorG - errorGa - errorGb - errorGc;
const int a = 7;
const int b = 5;
const int c = 3;
int errorBa = (errorB * a) / 16;
int errorBb = (errorB * b) / 16;
int errorBc = (errorB * c) / 16;
int errorBd = errorB - errorBa - errorBb - errorBc;
int errorRa = (errorR * a) / 16;
int errorRb = (errorR * b) / 16;
int errorRc = (errorR * c) / 16;
int errorRd = errorR - errorRa - errorRb - errorRc;
errorThisRowR[col + 1] += errorRa;
errorThisRowG[col + 1] += errorGa;
errorThisRowB[col + 1] += errorBa;
int errorGa = (errorG * a) / 16;
int errorGb = (errorG * b) / 16;
int errorGc = (errorG * c) / 16;
int errorGd = errorG - errorGa - errorGb - errorGc;
errorNextRowR[width - col] += errorRb;
errorNextRowG[width - col] += errorGb;
errorNextRowB[width - col] += errorBb;
int errorBa = (errorB * a) / 16;
int errorBb = (errorB * b) / 16;
int errorBc = (errorB * c) / 16;
int errorBd = errorB - errorBa - errorBb - errorBc;
if (col != 0)
{
errorNextRowR[width - (col - 1)] += errorRc;
errorNextRowG[width - (col - 1)] += errorGc;
errorNextRowB[width - (col - 1)] += errorBc;
}
errorThisRowR[col + 1] += errorRa;
errorThisRowG[col + 1] += errorGa;
errorThisRowB[col + 1] += errorBa;
errorNextRowR[width - (col + 1)] += errorRd;
errorNextRowG[width - (col + 1)] += errorGd;
errorNextRowB[width - (col + 1)] += errorBd;
errorNextRowR[width - col] += errorRb;
errorNextRowG[width - col] += errorGb;
errorNextRowB[width - col] += errorBb;
unchecked
{
pSourcePixel += ptrInc;
pDestinationPixel += ptrInc;
}
}
if (col != 0)
{
errorNextRowR[width - (col - 1)] += errorRc;
errorNextRowG[width - (col - 1)] += errorGc;
errorNextRowB[width - (col - 1)] += errorBc;
}
// Add the stride to the source row
pSourceRow += sourceData.Stride;
errorNextRowR[width - (col + 1)] += errorRd;
errorNextRowG[width - (col + 1)] += errorGd;
errorNextRowB[width - (col + 1)] += errorBd;
// And to the destination row
pDestinationRow += outputData.Stride;
unchecked
{
pSourcePixel += ptrInc;
pDestinationPixel += ptrInc;
}
}
errorThisRowB = errorNextRowB;
errorThisRowG = errorNextRowG;
errorThisRowR = errorNextRowR;
}
}
finally
{
// Ensure that I unlock the output bits
output.UnlockBits(outputData);
}
}
// Add the stride to the source row
pSourceRow += sourceData.Stride;
/// <summary>
/// Override this to process the pixel in the first pass of the algorithm
/// </summary>
/// <param name="pixel">The pixel to quantize</param>
/// <remarks>
/// This function need only be overridden if your quantize algorithm needs two passes,
/// such as an Octree quantizer.
/// </remarks>
protected virtual void InitialQuantizePixel(int pixel)
{
}
// And to the destination row
pDestinationRow += outputData.Stride;
/// <summary>
/// Override this to process the pixel in the second pass of the algorithm
/// </summary>
/// <param name="pixel">The pixel to quantize</param>
/// <returns>The quantized value</returns>
protected abstract byte QuantizePixel(int pixel);
errorThisRowB = errorNextRowB;
errorThisRowG = errorNextRowG;
errorThisRowR = errorNextRowR;
}
}
/// <summary>
/// Retrieve the palette for the quantized image
/// </summary>
/// <param name="original">Any old palette, this is overrwritten</param>
/// <returns>The new color palette</returns>
protected abstract ColorPalette GetPalette(ColorPalette original);
}
finally
{
// Ensure that I unlock the output bits
output.UnlockBits(outputData);
}
}
/// <summary>
/// Override this to process the pixel in the first pass of the algorithm
/// </summary>
/// <param name="pixel">The pixel to quantize</param>
/// <remarks>
/// This function need only be overridden if your quantize algorithm needs two passes,
/// such as an Octree quantizer.
/// </remarks>
protected virtual void InitialQuantizePixel(int pixel)
{
}
/// <summary>
/// Override this to process the pixel in the second pass of the algorithm
/// </summary>
/// <param name="pixel">The pixel to quantize</param>
/// <returns>The quantized value</returns>
protected abstract byte QuantizePixel(int pixel);
/// <summary>
/// Retrieve the palette for the quantized image
/// </summary>
/// <param name="original">Any old palette, this is overrwritten</param>
/// <returns>The new color palette</returns>
protected abstract ColorPalette GetPalette(ColorPalette original);
}
}

View File

@ -52,18 +52,16 @@ namespace BizHawk.Client.EmuHawk
public void AddFrame(IVideoProvider source)
{
using (var bb = new BitmapBuffer(source.BufferWidth, source.BufferHeight, source.GetVideoBuffer()))
{
string subpath = GetAndCreatePathForFrameNum(mCurrFrame);
string path = $"{subpath}.png";
bb.ToSysdrawingBitmap().Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
using var bb = new BitmapBuffer(source.BufferWidth, source.BufferHeight, source.GetVideoBuffer());
string subPath = GetAndCreatePathForFrameNum(mCurrFrame);
string path = $"{subPath}.png";
bb.ToSysdrawingBitmap().Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
public void AddSamples(short[] samples)
{
string subpath = GetAndCreatePathForFrameNum(mCurrFrame);
string path = $"{subpath}.wav";
string subPath = GetAndCreatePathForFrameNum(mCurrFrame);
string path = $"{subPath}.wav";
WavWriterV wwv = new WavWriterV();
wwv.SetAudioParameters(paramSampleRate, paramChannels, paramBits);
wwv.OpenFile(path);
@ -107,7 +105,7 @@ namespace BizHawk.Client.EmuHawk
paramBits = bits;
}
public void SetMetaData(string gameName, string authors, UInt64 lengthMS, UInt64 rerecords)
public void SetMetaData(string gameName, string authors, ulong lengthMS, ulong rerecords)
{
// not needed
}
@ -146,9 +144,9 @@ namespace BizHawk.Client.EmuHawk
private string GetAndCreatePathForFrameNum(int index)
{
string subpath = GetPathFragmentForFrameNum(index);
string subPath = GetPathFragmentForFrameNum(index);
string path = mFramesDirectory;
path = Path.Combine(path, subpath);
path = Path.Combine(path, subPath);
string fpath = $"{path}.nothing";
Directory.CreateDirectory(Path.GetDirectoryName(fpath));
return path;

View File

@ -18,9 +18,9 @@ namespace BizHawk.Client.EmuHawk
private void GetPaths(int index, out string png, out string wav)
{
string subpath = SynclessRecorder.GetPathFragmentForFrameNum(index);
string subPath = SynclessRecorder.GetPathFragmentForFrameNum(index);
string path = mFramesDirectory;
path = Path.Combine(path, subpath);
path = Path.Combine(path, subPath);
png = $"{path}.png";
wav = $"{path}.wav";
}
@ -64,8 +64,7 @@ namespace BizHawk.Client.EmuHawk
int frame = 1; // hacky! skip frame 0, because we have a problem with dumping that frame somehow
for (;;)
{
string wav, png;
GetPaths(frame, out png, out wav);
GetPaths(frame, out var png, out var wav);
if (!File.Exists(png) || !File.Exists(wav))
{
break;
@ -115,37 +114,35 @@ namespace BizHawk.Client.EmuHawk
return;
}
using (var avw = new AviWriter())
using var avw = new AviWriter();
avw.SetAudioParameters(44100, 2, 16); // hacky
avw.SetMovieParameters(60, 1); // hacky
avw.SetVideoParameters(width, height);
var token = avw.AcquireVideoCodecToken(this);
avw.SetVideoCodecToken(token);
avw.OpenFile(sfd.FileName);
foreach (var fi in mFrameInfos)
{
avw.SetAudioParameters(44100, 2, 16); // hacky
avw.SetMovieParameters(60, 1); // hacky
avw.SetVideoParameters(width, height);
var token = avw.AcquireVideoCodecToken(this);
avw.SetVideoCodecToken(token);
avw.OpenFile(sfd.FileName);
foreach (var fi in mFrameInfos)
using (var bb = new BitmapBuffer(fi.pngPath, new BitmapLoadOptions()))
{
using (var bb = new BitmapBuffer(fi.pngPath, new BitmapLoadOptions()))
{
var bbvp = new BitmapBufferVideoProvider(bb);
avw.AddFrame(bbvp);
}
// offset = 44 dec
var wavBytes = File.ReadAllBytes(fi.wavPath);
var ms = new MemoryStream(wavBytes) { Position = 44 };
var br = new BinaryReader(ms);
var sampledata = new List<short>();
while (br.BaseStream.Position != br.BaseStream.Length)
{
sampledata.Add(br.ReadInt16());
}
avw.AddSamples(sampledata.ToArray());
var bbvp = new BitmapBufferVideoProvider(bb);
avw.AddFrame(bbvp);
}
avw.CloseFile();
// offset = 44 dec
var wavBytes = File.ReadAllBytes(fi.wavPath);
var ms = new MemoryStream(wavBytes) { Position = 44 };
var br = new BinaryReader(ms);
var sampledata = new List<short>();
while (br.BaseStream.Position != br.BaseStream.Length)
{
sampledata.Add(br.ReadInt16());
}
avw.AddSamples(sampledata.ToArray());
}
avw.CloseFile();
}
}
}

View File

@ -92,7 +92,6 @@
this.Controls.Add(this.CoreNameLabel);
this.Name = "BizBoxInfoControl";
this.Size = new System.Drawing.Size(359, 25);
this.Load += new System.EventHandler(this.BizBoxInfoControl_Load);
this.ResumeLayout(false);
this.PerformLayout();

View File

@ -1,19 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.EmuHawk
{
public partial class BizBoxInfoControl : UserControl
{
private string url = "";
private readonly string _url = "";
public BizBoxInfoControl(CoreAttribute attributes)
{
@ -39,19 +31,14 @@ namespace BizHawk.Client.EmuHawk
{
CoreUrlLink.Visible = true;
CoreUrlLink.Text = attributes.PortedVersion;
url = attributes.PortedUrl;
_url = attributes.PortedUrl;
}
}
private void BizBoxInfoControl_Load(object sender, EventArgs e)
{
}
private void CoreUrlLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
CoreUrlLink.LinkVisited = true;
System.Diagnostics.Process.Start(url);
System.Diagnostics.Process.Start(_url);
}
}
}

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using BizHawk.Common;

View File

@ -25,8 +25,7 @@ namespace BizHawk.Client.EmuHawk
public void ActivateThreaded()
{
ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
threadPaint = new Thread(PaintProc);
threadPaint.IsBackground = true;
threadPaint = new Thread(PaintProc) { IsBackground = true };
threadPaint.Start();
}
@ -62,27 +61,25 @@ namespace BizHawk.Client.EmuHawk
{
if (bmp != null)
{
using (Graphics g = CreateGraphics())
using Graphics g = CreateGraphics();
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighSpeed;
if (ScaleImage)
{
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighSpeed;
if (ScaleImage)
g.PixelOffsetMode = PixelOffsetMode.Half;
g.DrawImage(bmp, 0, 0, Width, Height);
}
else
{
using (var sb = new SolidBrush(Color.Black))
{
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.PixelOffsetMode = PixelOffsetMode.Half;
g.DrawImage(bmp, 0, 0, Width, Height);
}
else
{
using (var sb = new SolidBrush(Color.Black))
{
g.FillRectangle(sb, bmp.Width, 0, Width - bmp.Width, Height);
g.FillRectangle(sb, 0, bmp.Height, bmp.Width, Height - bmp.Height);
}
g.DrawImageUnscaled(bmp, 0, 0);
g.FillRectangle(sb, bmp.Width, 0, Width - bmp.Width, Height);
g.FillRectangle(sb, 0, bmp.Height, bmp.Width, Height - bmp.Height);
}
g.DrawImageUnscaled(bmp, 0, 0);
}
}
@ -153,7 +150,6 @@ namespace BizHawk.Client.EmuHawk
protected override void OnPaintBackground(PaintEventArgs pevent)
{
}

View File

@ -1,11 +1,8 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BizHawk.Common;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
{
@ -15,9 +12,9 @@ namespace BizHawk.Client.EmuHawk
/// </summary>
public unsafe class DisplaySurface : IDisposable
{
Bitmap bmp;
BitmapData bmpdata;
int[] pixels;
private Bitmap bmp;
private BitmapData bmpdata;
private int[] pixels;
public unsafe void Clear()
{
@ -42,8 +39,8 @@ namespace BizHawk.Client.EmuHawk
public unsafe void ToBitmap(bool copy=true)
{
if (isBitmap) return;
isBitmap = true;
if (_isBitmap) return;
_isBitmap = true;
if (bmp == null)
{
@ -67,13 +64,12 @@ namespace BizHawk.Client.EmuHawk
}
public bool IsBitmap { get { return isBitmap; } }
bool isBitmap = false;
bool _isBitmap;
public unsafe void FromBitmap(bool copy=true)
{
if (!isBitmap) return;
isBitmap = false;
if (!_isBitmap) return;
_isBitmap = false;
if (copy)
{
@ -91,21 +87,6 @@ namespace BizHawk.Client.EmuHawk
}
}
public static DisplaySurface DisplaySurfaceWrappingBitmap(Bitmap bmp)
{
DisplaySurface ret = new DisplaySurface();
ret.Width = bmp.Width;
ret.Height = bmp.Height;
ret.bmp = bmp;
ret.isBitmap = true;
return ret;
}
private DisplaySurface()
{
}
public DisplaySurface(int width, int height)
{
//can't create a bitmap with zero dimensions, so for now, just bump it up to one
@ -119,10 +100,8 @@ namespace BizHawk.Client.EmuHawk
LockPixels();
}
public int* PixelPtr { get { return (int*)ptr; } }
public IntPtr PixelIntPtr { get { return new IntPtr(ptr); } }
public int Stride { get { return Width*4; } }
public int OffsetOf(int x, int y) { return y * Stride + x*4; }
public int* PixelPtr => (int*)ptr;
public int Stride => Width * 4;
void* ptr;
GCHandle handle;
@ -133,52 +112,20 @@ namespace BizHawk.Client.EmuHawk
ptr = handle.AddrOfPinnedObject().ToPointer();
}
void UnlockPixels()
private void UnlockPixels()
{
if(handle.IsAllocated) handle.Free();
}
/// <summary>
/// returns a new surface
/// </summary>
public DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1)
{
int new_width = Width + xpad0 + xpad1;
int new_height = Height + ypad0 + ypad1;
DisplaySurface ret = new DisplaySurface(new_width, new_height);
int* dptr = ret.PixelPtr;
int* sptr = PixelPtr;
int dstride = ret.Stride / 4;
int sstride = Stride / 4;
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
{
dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x];
}
return ret;
}
public int Width { get; private set; }
public int Height { get; private set; }
public int Width { get; }
public int Height { get; }
public void Dispose()
{
if (bmp != null)
bmp.Dispose();
bmp?.Dispose();
bmp = null;
UnlockPixels();
}
//public unsafe int[] ToIntArray() { }
public void AcceptIntArray(int[] newpixels)
{
FromBitmap(false);
UnlockPixels();
pixels = newpixels;
LockPixels();
}
}
}

View File

@ -1,19 +1,10 @@
using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using BizHawk.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.Filters;
using BizHawk.Bizware.BizwareGL;
using BizHawk.Bizware.BizwareGL.Drivers.OpenTK;
using OpenTK;
using OpenTK.Graphics;
namespace BizHawk.Client.EmuHawk.FilterManager
{
@ -24,8 +15,8 @@ namespace BizHawk.Client.EmuHawk.FilterManager
public class SurfaceFormat
{
public SurfaceFormat(Size size) { this.Size = size; }
public Size Size { get; private set; }
public SurfaceFormat(Size size) { Size = size; }
public Size Size { get; }
}
public class SurfaceState
@ -33,9 +24,10 @@ namespace BizHawk.Client.EmuHawk.FilterManager
public SurfaceState() { }
public SurfaceState(SurfaceFormat surfaceFormat, SurfaceDisposition surfaceDisposition = SurfaceDisposition.Unspecified)
{
this.SurfaceFormat = surfaceFormat;
this.SurfaceDisposition = surfaceDisposition;
SurfaceFormat = surfaceFormat;
SurfaceDisposition = surfaceDisposition;
}
public SurfaceFormat SurfaceFormat;
public SurfaceDisposition SurfaceDisposition;
}
@ -47,16 +39,16 @@ namespace BizHawk.Client.EmuHawk.FilterManager
public class FilterProgram
{
private readonly Dictionary<string, BaseFilter> FilterNameIndex = new Dictionary<string, BaseFilter>();
public List<BaseFilter> Filters = new List<BaseFilter>();
Dictionary<string, BaseFilter> FilterNameIndex = new Dictionary<string, BaseFilter>();
public List<ProgramStep> Program = new List<ProgramStep>();
public BaseFilter this[string name]
{
get
{
BaseFilter ret;
FilterNameIndex.TryGetValue(name, out ret);
FilterNameIndex.TryGetValue(name, out var ret);
return ret;
}
}
@ -79,7 +71,7 @@ namespace BizHawk.Client.EmuHawk.FilterManager
{
return RenderTargetProvider.Get(new Size(width, height));
}
public void AddFilter(BaseFilter filter, string name = "")
{
Filters.Add(filter);
@ -128,10 +120,11 @@ namespace BizHawk.Client.EmuHawk.FilterManager
{
public ProgramStep(ProgramStepType type, object args, string comment = null)
{
this.Type = type;
this.Args = args;
this.Comment = comment;
Type = type;
Args = args;
Comment = comment;
}
public ProgramStepType Type;
public object Args;
public string Comment;
@ -218,9 +211,11 @@ namespace BizHawk.Client.EmuHawk.FilterManager
{
if (currState == null)
{
currState = new SurfaceState();
currState.SurfaceFormat = iosi.SurfaceFormat;
currState.SurfaceDisposition = iosi.SurfaceDisposition;
currState = new SurfaceState
{
SurfaceFormat = iosi.SurfaceFormat,
SurfaceDisposition = iosi.SurfaceDisposition
};
}
else
{

View File

@ -1,19 +1,10 @@
using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using BizHawk.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.FilterManager;
using BizHawk.Bizware.BizwareGL;
using BizHawk.Bizware.BizwareGL.Drivers.OpenTK;
using OpenTK;
using OpenTK.Graphics;
//Here's how to make a filter:
//1. Reset your state entirely in Initialize().
@ -37,7 +28,7 @@ namespace BizHawk.Client.EmuHawk.Filters
public virtual Size PresizeOutput(string channel, Size size) { return size; }
public virtual void SetInputFormat(string channel, SurfaceState state) { } //TODO - why a different param order than DeclareOutput?
public Dictionary<string, object> Parameters = new Dictionary<string, object>();
public bool IsNOP { get { return _IsNop; } protected set { _IsNop = value; } }
public bool IsNOP { get => _IsNop; protected set => _IsNop = value; }
private Boolean _IsNop = false;
//runtime signals
@ -111,10 +102,10 @@ namespace BizHawk.Client.EmuHawk.Filters
return iosi;
}
List<IOSurfaceInfo> IOSurfaceInfos = new List<IOSurfaceInfo>();
private readonly List<IOSurfaceInfo> IOSurfaceInfos = new List<IOSurfaceInfo>();
IOSurfaceInfo FindIOSurfaceInfo(string channel, SurfaceDirection direction)
private IOSurfaceInfo FindIOSurfaceInfo(string channel, SurfaceDirection direction)
{
foreach (var iosi in IOSurfaceInfos)
if (iosi.Channel == channel && iosi.SurfaceDirection == direction)
@ -135,5 +126,4 @@ namespace BizHawk.Client.EmuHawk.Filters
Input, Output
}
}
}

View File

@ -1,20 +1,9 @@
using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using BizHawk.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk;
using BizHawk.Client.EmuHawk.FilterManager;
using BizHawk.Bizware.BizwareGL;
using BizHawk.Bizware.BizwareGL.Drivers.OpenTK;
using OpenTK;
using OpenTK.Graphics;
namespace BizHawk.Client.EmuHawk.Filters
{
@ -486,8 +475,7 @@ namespace BizHawk.Client.EmuHawk.Filters
public override void Run()
{
if (RenderCallback == null) return;
RenderCallback();
RenderCallback?.Invoke();
}
}
}

View File

@ -1,20 +1,7 @@
using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using BizHawk.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk;
using BizHawk.Client.EmuHawk.FilterManager;
using BizHawk.Bizware.BizwareGL;
using BizHawk.Bizware.BizwareGL.Drivers.OpenTK;
using OpenTK;
using OpenTK.Graphics;
namespace BizHawk.Client.EmuHawk.Filters
{
@ -22,10 +9,10 @@ namespace BizHawk.Client.EmuHawk.Filters
{
public SourceImage(Size size)
{
this.Size = size;
Size = size;
}
Size Size;
private readonly Size Size;
public Texture2d Texture;

View File

@ -1,11 +1,4 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BizHawk.Common;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
{
@ -13,11 +6,11 @@ namespace BizHawk.Client.EmuHawk
/// encapsulates thread-safe concept of pending/current display surfaces, reusing buffers where matching
/// sizes are available and keeping them cleaned up when they dont seem like theyll need to be used anymore
/// </summary>
class SwappableDisplaySurfaceSet
public class SwappableDisplaySurfaceSet
{
DisplaySurface Pending, Current;
bool IsPending;
Queue<DisplaySurface> ReleasedSurfaces = new Queue<DisplaySurface>();
private DisplaySurface Pending, Current;
private bool IsPending;
private readonly Queue<DisplaySurface> ReleasedSurfaces = new Queue<DisplaySurface>();
/// <summary>
/// retrieves a surface with the specified size, reusing an old buffer if available and clearing if requested
@ -78,5 +71,4 @@ namespace BizHawk.Client.EmuHawk
return Current;
}
}
}

View File

@ -1,17 +1,12 @@
using System;
using System.Collections.Generic;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// Recycles a pair of temporary textures (in case double-buffering helps any) to contain a BitmapBuffer's or DisplaySurface's contents, as long as the dimensions match.
/// When the dimensions dont match, a new one will be allocated
/// When the dimensions don't match, a new one will be allocated
/// </summary>
public class TextureFrugalizer : IDisposable
{
@ -24,59 +19,56 @@ namespace BizHawk.Client.EmuHawk
public void Dispose()
{
foreach (var ct in CurrentTextures)
if(ct != null)
ct.Dispose();
{
ct?.Dispose();
}
ResetList();
}
void ResetList()
{
CurrentTextures = new List<Texture2d>();
CurrentTextures.Add(null);
CurrentTextures.Add(null);
CurrentTextures = new List<Texture2d> { null, null };
}
IGL GL;
List<Texture2d> CurrentTextures;
private readonly IGL GL;
private List<Texture2d> CurrentTextures;
public Texture2d Get(DisplaySurface ds)
{
using (var bb = new BitmapBuffer(ds.PeekBitmap(), new BitmapLoadOptions()))
{
return Get(bb);
}
using var bb = new BitmapBuffer(ds.PeekBitmap(), new BitmapLoadOptions());
return Get(bb);
}
public Texture2d Get(BitmapBuffer bb)
{
//get the current entry
Texture2d CurrentTexture = CurrentTextures[0];
Texture2d currentTexture = CurrentTextures[0];
//TODO - its a bit cruddy here that we dont respect the current texture HasAlpha condition (in fact, theres no such concept)
//we might need to deal with that in the future to fix some bugs.
// TODO - its a bit cruddy here that we dont respect the current texture HasAlpha condition (in fact, there's no such concept)
// we might need to deal with that in the future to fix some bugs.
//check if its rotten and needs recreating
if (CurrentTexture == null || CurrentTexture.IntWidth != bb.Width || CurrentTexture.IntHeight != bb.Height)
if (currentTexture == null || currentTexture.IntWidth != bb.Width || currentTexture.IntHeight != bb.Height)
{
//needs recreating. be sure to kill the old one...
if (CurrentTexture != null)
CurrentTexture.Dispose();
currentTexture?.Dispose();
//and make a new one
CurrentTexture = GL.LoadTexture(bb);
currentTexture = GL.LoadTexture(bb);
}
else
{
//its good! just load in the data
GL.LoadTextureData(CurrentTexture, bb);
GL.LoadTextureData(currentTexture, bb);
}
//now shuffle the buffers
CurrentTextures[0] = CurrentTextures[1];
CurrentTextures[1] = CurrentTexture;
CurrentTextures[1] = currentTexture;
//deterministic state, i guess
CurrentTexture.SetFilterNearest();
currentTexture.SetFilterNearest();
return CurrentTexture;
return currentTexture;
}
}
}

View File

@ -1,27 +1,23 @@
using System.Collections.Generic;
using System.IO;
using System;
using System.Threading;
using System.IO.Pipes;
using SlimDX;
using SlimDX.DirectInput;
//this is not a very safe or pretty protocol, I'm not proud of it
// this is not a very safe or pretty protocol, I'm not proud of it
namespace BizHawk.Client.EmuHawk
{
public static class IPCKeyInput
{
public static void Initialize()
{
var t = new Thread(IPCThread);
t.IsBackground = true;
var t = new Thread(IPCThread) { IsBackground = true };
t.Start();
}
static List<KeyInput.KeyEvent> PendingEventList = new List<KeyInput.KeyEvent>();
static List<KeyInput.KeyEvent> EventList = new List<KeyInput.KeyEvent>();
private static readonly List<KeyInput.KeyEvent> PendingEventList = new List<KeyInput.KeyEvent>();
private static readonly List<KeyInput.KeyEvent> EventList = new List<KeyInput.KeyEvent>();
static void IPCThread()
{
@ -30,24 +26,22 @@ namespace BizHawk.Client.EmuHawk
for (; ; )
{
using (NamedPipeServerStream pipe = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1024, 1024))
using var pipe = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1024, 1024);
try
{
try
pipe.WaitForConnection();
BinaryReader br = new BinaryReader(pipe);
for (; ; )
{
pipe.WaitForConnection();
BinaryReader br = new BinaryReader(pipe);
for (; ; )
{
int e = br.ReadInt32();
bool pressed = (e & 0x80000000) != 0;
lock (PendingEventList)
PendingEventList.Add(new KeyInput.KeyEvent { Key = (Key)(e & 0x7FFFFFFF), Pressed = pressed });
}
int e = br.ReadInt32();
bool pressed = (e & 0x80000000) != 0;
lock (PendingEventList)
PendingEventList.Add(new KeyInput.KeyEvent { Key = (Key)(e & 0x7FFFFFFF), Pressed = pressed });
}
catch { }
}
catch { }
}
}

View File

@ -1683,11 +1683,9 @@ namespace BizHawk.Client.EmuHawk
// why do we silently truncate\pad here instead of warning\erroring?
sram = new byte[oldRam.Length];
using (var reader = new BinaryReader(
new FileStream(PathManager.SaveRamPath(Game), FileMode.Open, FileAccess.Read)))
{
reader.Read(sram, 0, sram.Length);
}
using var reader = new BinaryReader(
new FileStream(PathManager.SaveRamPath(Game), FileMode.Open, FileAccess.Read));
reader.Read(sram, 0, sram.Length);
}
Emulator.AsSaveRam().StoreSaveRam(sram);

View File

@ -1,15 +1,9 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores;
using BizHawk.Emulation.Cores.Libretro;
using BizHawk.Client.Common;
@ -19,35 +13,29 @@ namespace BizHawk.Client.EmuHawk
{
public partial class OpenAdvancedChooser : Form
{
MainForm mainForm;
private readonly MainForm _mainForm;
public AdvancedRomLoaderType Result;
public string SuggestedExtensionFilter;
public OpenAdvancedChooser(MainForm mainForm)
{
this.mainForm = mainForm;
_mainForm = mainForm;
InitializeComponent();
RefreshLibretroCore(true);
}
private void btnOK_Click(object sender, EventArgs e)
{
DialogResult = System.Windows.Forms.DialogResult.OK;
Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
DialogResult = System.Windows.Forms.DialogResult.Cancel;
DialogResult = DialogResult.Cancel;
Close();
}
private void btnSetLibretroCore_Click(object sender, EventArgs e)
{
if(mainForm.RunLibretroCoreChooser())
if(_mainForm.RunLibretroCoreChooser())
RefreshLibretroCore(false);
}
@ -73,26 +61,24 @@ namespace BizHawk.Client.EmuHawk
////LibRetroEmulator should be able to survive having this stub corecomm
//NEW COMMENTS:
//nope, we need to navigate to the dll path. this was a bad idea anyway. so many dlls get loaded, something to resolve them is needed
var coreComm = new BizHawk.Emulation.Common.CoreComm(null, null);
var coreComm = new CoreComm(null, null);
CoreFileProvider.SyncCoreCommInputSignals(coreComm);
using (var retro = new LibretroCore(coreComm, core))
{
btnLibretroLaunchGame.Enabled = true;
if (retro.Description.SupportsNoGame)
btnLibretroLaunchNoGame.Enabled = true;
using var retro = new LibretroCore(coreComm, core);
btnLibretroLaunchGame.Enabled = true;
if (retro.Description.SupportsNoGame)
btnLibretroLaunchNoGame.Enabled = true;
//print descriptive information
var descr = retro.Description;
CurrentDescription = descr;
Console.WriteLine($"core name: {descr.LibraryName} version {descr.LibraryVersion}");
Console.WriteLine($"extensions: {descr.ValidExtensions}");
Console.WriteLine($"{nameof(descr.NeedsRomAsPath)}: {descr.NeedsRomAsPath}");
Console.WriteLine($"{nameof(descr.NeedsArchives)}: {descr.NeedsArchives}");
Console.WriteLine($"{nameof(descr.SupportsNoGame)}: {descr.SupportsNoGame}");
//print descriptive information
var descr = retro.Description;
CurrentDescription = descr;
Console.WriteLine($"core name: {descr.LibraryName} version {descr.LibraryVersion}");
Console.WriteLine($"extensions: {descr.ValidExtensions}");
Console.WriteLine($"{nameof(descr.NeedsRomAsPath)}: {descr.NeedsRomAsPath}");
Console.WriteLine($"{nameof(descr.NeedsArchives)}: {descr.NeedsArchives}");
Console.WriteLine($"{nameof(descr.SupportsNoGame)}: {descr.SupportsNoGame}");
foreach (var v in descr.Variables.Values)
Console.WriteLine(v);
}
foreach (var v in descr.Variables.Values)
Console.WriteLine(v);
}
catch (Exception ex)
{
@ -111,8 +97,7 @@ namespace BizHawk.Client.EmuHawk
sw.Write("*.{0};",ext);
var filter = sw.ToString();
filter = filter.Substring(0,filter.Length-1); //remove last semicolon
List<string> args = new List<string>();
args.Add("Rom Files");
var args = new List<string> { "Rom Files" };
if (!CurrentDescription.NeedsArchives)
filter += ";%ARCH%";
args.Add(filter);

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BizHawk.Emulation.Common;

View File

@ -47,12 +47,10 @@ namespace BizHawk.Client.EmuHawk
public static IEnumerable<string> GetDeviceNames()
{
using (XAudio2 device = new XAudio2())
{
return Enumerable.Range(0, device.DeviceCount)
.Select(n => device.GetDeviceDetails(n).DisplayName)
.ToList(); // enumerate before local var device is disposed
}
using XAudio2 device = new XAudio2();
return Enumerable.Range(0, device.DeviceCount)
.Select(n => device.GetDeviceDetails(n).DisplayName)
.ToList(); // enumerate before local var device is disposed
}
private int BufferSizeSamples { get; set; }
@ -126,8 +124,8 @@ namespace BizHawk.Client.EmuHawk
private class BufferPool : IDisposable
{
private List<BufferPoolItem> _availableItems = new List<BufferPoolItem>();
private Queue<BufferPoolItem> _obtainedItems = new Queue<BufferPoolItem>();
private readonly List<BufferPoolItem> _availableItems = new List<BufferPoolItem>();
private readonly Queue<BufferPoolItem> _obtainedItems = new Queue<BufferPoolItem>();
public void Dispose()
{

View File

@ -40,10 +40,8 @@ namespace BizHawk.Client.EmuHawk
private static SizeF GetCurrentAutoScaleSize(AutoScaleMode autoScaleMode)
{
using (var form = new Form { AutoScaleMode = autoScaleMode })
{
return form.CurrentAutoScaleDimensions;
}
using var form = new Form { AutoScaleMode = autoScaleMode };
return form.CurrentAutoScaleDimensions;
}
}
}

View File

@ -2,7 +2,6 @@
using System.Windows.Forms;
using BizHawk.Emulation.Cores.Nintendo.SNES;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.WinFormExtensions;
namespace BizHawk.Client.EmuHawk

View File

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.IEmulatorExtensions;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
{
@ -18,13 +14,10 @@ namespace BizHawk.Client.EmuHawk
[RequiredService]
private IMemoryDomains MemoryDomains { get; set; }
private IMemoryCallbackSystem MemoryCallbacks { get { return Debuggable.MemoryCallbacks; } }
private IMemoryCallbackSystem MemoryCallbacks => Debuggable.MemoryCallbacks;
private RegisterValue PCRegister
{
get { return Debuggable.GetCpuFlagsAndRegisters()[Disassembler.PCRegisterName]; }
}
private RegisterValue PCRegister => Debuggable.GetCpuFlagsAndRegisters()[Disassembler.PCRegisterName];
#region Implementation checking
@ -161,15 +154,8 @@ namespace BizHawk.Client.EmuHawk
EngageDebugger();
}
public bool AskSaveChanges()
{
// TODO
return true;
}
public bool AskSaveChanges() => true;
public bool UpdateBefore
{
get { return false; }
}
public bool UpdateBefore => false;
}
}

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

View File

@ -194,7 +194,6 @@
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Music Ripper";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.NESMusicRipper_FormClosed);
this.Load += new System.EventHandler(this.NESMusicRipper_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);

View File

@ -12,7 +12,7 @@ namespace BizHawk.Client.EmuHawk
public partial class NESMusicRipper : Form, IToolFormAutoConfig
{
[RequiredService]
private NES nes { get; set; }
private NES Nes { get; set; }
public NESMusicRipper()
{
@ -20,7 +20,7 @@ namespace BizHawk.Client.EmuHawk
SyncContents();
}
public bool AskSaveChanges() { return true; }
public bool AskSaveChanges() => true;
public bool UpdateBefore => true;
public void Restart()
@ -113,8 +113,10 @@ namespace BizHawk.Client.EmuHawk
{
Filter = "XRNS (*.xrns)|*.xrns"
};
if (sfd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
if (sfd.ShowDialog() != DialogResult.OK)
{
return;
}
//configuration:
var outPath = sfd.FileName;
@ -127,13 +129,11 @@ namespace BizHawk.Client.EmuHawk
var zfTemplate = new ICSharpCode.SharpZipLib.Zip.ZipFile(templatePath);
{
int zfSongXmlIndex = zfTemplate.FindEntry("Song.xml", true);
using (var zis = zfTemplate.GetInputStream(zfTemplate.GetEntry("Song.xml")))
{
byte[] buffer = new byte[4096]; // 4K is optimum
ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(zis, msSongXml, buffer);
}
using var zis = zfTemplate.GetInputStream(zfTemplate.GetEntry("Song.xml"));
byte[] buffer = new byte[4096]; // 4K is optimum
ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(zis, msSongXml, buffer);
}
XElement templateRoot = XElement.Parse(System.Text.Encoding.UTF8.GetString(msSongXml.ToArray()));
var templateRoot = XElement.Parse(System.Text.Encoding.UTF8.GetString(msSongXml.ToArray()));
//get the pattern pool, and whack the child nodes
var xPatterns = templateRoot.XPathSelectElement("//Patterns");
@ -424,7 +424,7 @@ namespace BizHawk.Client.EmuHawk
//fpulse = fCPU/(16*(t+1)) (where fCPU is 1.789773 MHz for NTSC, 1.662607 MHz for PAL, and 1.773448 MHz for Dendy)
//ftriangle = fCPU/(32*(tval + 1))
var apu = nes.apu;
var apu = Nes.apu;
//evaluate the pitches
int pulse0_period = apu.pulse[0].timer_reload_value;
@ -475,16 +475,16 @@ namespace BizHawk.Client.EmuHawk
if(IsRunning)
{
SyncContents();
nes.apu.DebugCallback = null;
nes.apu.DebugCallbackDivider = 0;
Nes.apu.DebugCallback = null;
Nes.apu.DebugCallbackDivider = 0;
IsRunning = false;
btnControl.Text = "Start";
}
else
{
Log.Clear();
nes.apu.DebugCallback = DebugCallback;
nes.apu.DebugCallbackDivider = int.Parse(txtDivider.Text);
Nes.apu.DebugCallback = DebugCallback;
Nes.apu.DebugCallbackDivider = int.Parse(txtDivider.Text);
IsRunning = true;
btnControl.Text = "Stop";
}
@ -497,15 +497,10 @@ namespace BizHawk.Client.EmuHawk
private void NESMusicRipper_FormClosed(object sender, FormClosedEventArgs e)
{
var apu = nes.apu;
var apu = Nes.apu;
apu.DebugCallbackDivider = 0;
apu.DebugCallbackTimer = 0;
apu.DebugCallback = null;
}
private void NESMusicRipper_Load(object sender, EventArgs e)
{
}
}
}

View File

@ -19,7 +19,7 @@ namespace BizHawk.Client.EmuHawk
get => _x;
set
{
_x = RangeX.Constrain(value);
_x = _rangeX.Constrain(value);
SetAnalog();
}
}
@ -29,7 +29,7 @@ namespace BizHawk.Client.EmuHawk
get => _y;
set
{
_y = RangeY.Constrain(value);
_y = _rangeY.Constrain(value);
SetAnalog();
}
}
@ -42,13 +42,13 @@ namespace BizHawk.Client.EmuHawk
private IController _previous;
private sbyte UserRangePercentageX = 100;
private sbyte UserRangePercentageY = 100;
private sbyte _userRangePercentageX = 100;
private sbyte _userRangePercentageY = 100;
public void SetUserRange(decimal rx, decimal ry)
{
UserRangePercentageX = (sbyte) rx;
UserRangePercentageY = (sbyte) ry;
_userRangePercentageX = (sbyte) rx;
_userRangePercentageY = (sbyte) ry;
Rerange();
Refresh();
@ -56,42 +56,42 @@ namespace BizHawk.Client.EmuHawk
public void SetRangeX(float[] range)
{
ActualRangeX.Min = (int) range[0];
ActualRangeX.Max = (int) range[2];
_actualRangeX.Min = (int) range[0];
_actualRangeX.Max = (int) range[2];
Rerange();
}
public void SetRangeY(float[] range)
{
ActualRangeY.Min = (int) range[0];
ActualRangeY.Max = (int) range[2];
_actualRangeY.Min = (int) range[0];
_actualRangeY.Max = (int) range[2];
Rerange();
}
private readonly MutableIntRange RangeX = new MutableIntRange(-128, 127);
private readonly MutableIntRange RangeY = new MutableIntRange(-128, 127);
private readonly MutableIntRange ActualRangeX = new MutableIntRange(-128, 127);
private readonly MutableIntRange ActualRangeY = new MutableIntRange(-128, 127);
private readonly MutableIntRange _rangeX = new MutableIntRange(-128, 127);
private readonly MutableIntRange _rangeY = new MutableIntRange(-128, 127);
private readonly MutableIntRange _actualRangeX = new MutableIntRange(-128, 127);
private readonly MutableIntRange _actualRangeY = new MutableIntRange(-128, 127);
private bool ReverseX;
private bool ReverseY;
private bool _reverseX;
private bool _reverseY;
private void Rerange()
{
ReverseX = UserRangePercentageX < 0;
ReverseY = UserRangePercentageY < 0;
_reverseX = _userRangePercentageX < 0;
_reverseY = _userRangePercentageY < 0;
var midX = (ActualRangeX.Min + ActualRangeX.Max) / 2.0;
var halfRangeX = (ReverseX ? -1 : 1) * (ActualRangeX.Max - ActualRangeX.Min) * UserRangePercentageX / 200.0;
RangeX.Min = (int) (midX - halfRangeX);
RangeX.Max = (int) (midX + halfRangeX);
var midX = (_actualRangeX.Min + _actualRangeX.Max) / 2.0;
var halfRangeX = (_reverseX ? -1 : 1) * (_actualRangeX.Max - _actualRangeX.Min) * _userRangePercentageX / 200.0;
_rangeX.Min = (int) (midX - halfRangeX);
_rangeX.Max = (int) (midX + halfRangeX);
var midY = (ActualRangeY.Min + ActualRangeY.Max) / 2.0;
var halfRangeY = (ReverseY ? -1 : 1) * (ActualRangeY.Max - ActualRangeY.Min) * UserRangePercentageY / 200.0;
RangeY.Min = (int) (midY - halfRangeY);
RangeY.Max = (int) (midY + halfRangeY);
var midY = (_actualRangeY.Min + _actualRangeY.Max) / 2.0;
var halfRangeY = (_reverseY ? -1 : 1) * (_actualRangeY.Max - _actualRangeY.Min) * _userRangePercentageY / 200.0;
_rangeY.Min = (int) (midY - halfRangeY);
_rangeY.Max = (int) (midY + halfRangeY);
// re-constrain after changing ranges
X = X;
@ -108,12 +108,12 @@ namespace BizHawk.Client.EmuHawk
/// <remarks>
/// min + (max - i) == max - (i - min) == min + max - i
/// </remarks>
private int MaybeReversedInX(int i) => ReverseX ? RangeX.Min + RangeX.Max - i : i;
private int MaybeReversedInX(int i) => _reverseX ? _rangeX.Min + _rangeX.Max - i : i;
/// <inheritdoc cref="MaybeReversedInX"/>
private int MaybeReversedInY(int i) => ReverseY ? RangeY.Min + RangeY.Max - i : i;
private int MaybeReversedInY(int i) => _reverseY ? _rangeY.Min + _rangeY.Max - i : i;
private int PixelSizeX => (int)(RangeX.GetCount() * ScaleX);
private int PixelSizeY => (int)(RangeY.GetCount() * ScaleY);
private int PixelSizeX => (int)(_rangeX.GetCount() * ScaleX);
private int PixelSizeY => (int)(_rangeY.GetCount() * ScaleY);
private int PixelMinX => (Size.Width - PixelSizeX) / 2;
private int PixelMinY => (Size.Height - PixelSizeY) / 2;
private int PixelMidX => PixelMinX + PixelSizeX / 2;
@ -122,23 +122,23 @@ namespace BizHawk.Client.EmuHawk
private int PixelMaxY => PixelMinY + PixelSizeY - 1;
private int RealToGfxX(int val) =>
PixelMinX + ((MaybeReversedInX(RangeX.Constrain(val)) - RangeX.Min) * ScaleX).RoundToInt();
PixelMinX + ((MaybeReversedInX(_rangeX.Constrain(val)) - _rangeX.Min) * ScaleX).RoundToInt();
private int RealToGfxY(int val) =>
PixelMinY + ((MaybeReversedInY(RangeY.Constrain(val)) - RangeY.Min) * ScaleY).RoundToInt();
PixelMinY + ((MaybeReversedInY(_rangeY.Constrain(val)) - _rangeY.Min) * ScaleY).RoundToInt();
private int GfxToRealX(int val) =>
MaybeReversedInX(RangeX.Constrain(RangeX.Min + ((val - PixelMinX) / ScaleX).RoundToInt()));
MaybeReversedInX(_rangeX.Constrain(_rangeX.Min + ((val - PixelMinX) / ScaleX).RoundToInt()));
private int GfxToRealY(int val) =>
MaybeReversedInY(RangeY.Constrain(RangeY.Min + ((val - PixelMinY) / ScaleY).RoundToInt()));
MaybeReversedInY(_rangeY.Constrain(_rangeY.Min + ((val - PixelMinY) / ScaleY).RoundToInt()));
private readonly Pen BlackPen = new Pen(Brushes.Black);
private readonly Pen BluePen = new Pen(Brushes.Blue, 2);
private readonly Pen GrayPen = new Pen(Brushes.Gray, 2);
private readonly Pen _blackPen = new Pen(Brushes.Black);
private readonly Pen _bluePen = new Pen(Brushes.Blue, 2);
private readonly Pen _grayPen = new Pen(Brushes.Gray, 2);
private readonly Bitmap Dot = new Bitmap(7, 7);
private readonly Bitmap GrayDot = new Bitmap(7, 7);
private readonly Bitmap _dot = new Bitmap(7, 7);
private readonly Bitmap _grayDot = new Bitmap(7, 7);
public Action ClearCallback { private get; set; }
@ -160,22 +160,18 @@ namespace BizHawk.Client.EmuHawk
BorderStyle = BorderStyle.Fixed3D;
// Draw the dot into a bitmap
using (var g = Graphics.FromImage(Dot))
{
g.Clear(Color.Transparent);
var redBrush = Brushes.Red;
g.FillRectangle(redBrush, 2, 0, 3, 7);
g.FillRectangle(redBrush, 1, 1, 5, 5);
g.FillRectangle(redBrush, 0, 2, 7, 3);
}
using var g = Graphics.FromImage(_dot);
g.Clear(Color.Transparent);
var redBrush = Brushes.Red;
g.FillRectangle(redBrush, 2, 0, 3, 7);
g.FillRectangle(redBrush, 1, 1, 5, 5);
g.FillRectangle(redBrush, 0, 2, 7, 3);
using (var gg = Graphics.FromImage(GrayDot))
{
gg.Clear(Color.Transparent);
gg.FillRectangle(Brushes.Gray, 2, 0, 3, 7);
gg.FillRectangle(Brushes.Gray, 1, 1, 5, 5);
gg.FillRectangle(Brushes.Gray, 0, 2, 7, 3);
}
using var gg = Graphics.FromImage(_grayDot);
gg.Clear(Color.Transparent);
gg.FillRectangle(Brushes.Gray, 2, 0, 3, 7);
gg.FillRectangle(Brushes.Gray, 1, 1, 5, 5);
gg.FillRectangle(Brushes.Gray, 0, 2, 7, 3);
}
private void SetAnalog()
@ -194,24 +190,24 @@ namespace BizHawk.Client.EmuHawk
e.Graphics.FillRectangle(Brushes.LightGray, PixelMinX, PixelMinY, PixelMaxX - PixelMinX, PixelMaxY - PixelMinY);
e.Graphics.FillEllipse(ReadOnly ? Brushes.Beige : Brushes.White, PixelMinX, PixelMinY, PixelMaxX - PixelMinX - 2, PixelMaxY - PixelMinY - 3);
e.Graphics.DrawEllipse(BlackPen, PixelMinX, PixelMinY, PixelMaxX - PixelMinX - 2, PixelMaxY - PixelMinY - 3);
e.Graphics.DrawLine(BlackPen, PixelMidX, 0, PixelMidX, PixelMaxY);
e.Graphics.DrawLine(BlackPen, 0, PixelMidY, PixelMaxX, PixelMidY);
e.Graphics.DrawEllipse(_blackPen, PixelMinX, PixelMinY, PixelMaxX - PixelMinX - 2, PixelMaxY - PixelMinY - 3);
e.Graphics.DrawLine(_blackPen, PixelMidX, 0, PixelMidX, PixelMaxY);
e.Graphics.DrawLine(_blackPen, 0, PixelMidY, PixelMaxX, PixelMidY);
// Previous frame
if (_previous != null)
{
var pX = (int)_previous.GetFloat(XName);
var pY = (int)_previous.GetFloat(YName);
e.Graphics.DrawLine(GrayPen, PixelMidX, PixelMidY, RealToGfxX(pX), RealToGfxY(pY));
e.Graphics.DrawImage(GrayDot, RealToGfxX(pX) - 3, RealToGfxY(RangeY.Max) - RealToGfxY(pY) - 3);
e.Graphics.DrawLine(_grayPen, PixelMidX, PixelMidY, RealToGfxX(pX), RealToGfxY(pY));
e.Graphics.DrawImage(_grayDot, RealToGfxX(pX) - 3, RealToGfxY(_rangeY.Max) - RealToGfxY(pY) - 3);
}
// Line
if (HasValue)
{
e.Graphics.DrawLine(BluePen, PixelMidX, PixelMidY, RealToGfxX(X), RealToGfxY(Y));
e.Graphics.DrawImage(ReadOnly ? GrayDot : Dot, RealToGfxX(X) - 3, RealToGfxY(Y) - 3);
e.Graphics.DrawLine(_bluePen, PixelMidX, PixelMidY, RealToGfxX(X), RealToGfxY(Y));
e.Graphics.DrawImage(ReadOnly ? _grayDot : _dot, RealToGfxX(X) - 3, RealToGfxY(Y) - 3);
}
}
}

View File

@ -319,6 +319,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=preload/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prereqs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=prescale/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Quantizer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quickload/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quicknes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quicksave/@EntryIndexedValue">True</s:Boolean>
@ -379,6 +380,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Virtualpad/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=vram/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Vsync/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Waterbox/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Winform/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=winforms/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=WSWAN/@EntryIndexedValue">True</s:Boolean>