add a crappy little PCE sound debugger and individual channel muting

This commit is contained in:
zeromus 2014-06-09 08:10:20 +00:00
parent 67cfb998da
commit 1edd4edb49
8 changed files with 1040 additions and 316 deletions

View File

@ -764,6 +764,12 @@
<Compile Include="tools\PCE\PCECDL.Designer.cs">
<DependentUpon>PCECDL.cs</DependentUpon>
</Compile>
<Compile Include="tools\PCE\PCESoundDebugger.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="tools\PCE\PCESoundDebugger.Designer.cs">
<DependentUpon>PCESoundDebugger.cs</DependentUpon>
</Compile>
<Compile Include="tools\PCE\PCETileViewer.cs">
<SubType>Form</SubType>
</Compile>
@ -1238,6 +1244,9 @@
<EmbeddedResource Include="tools\PCE\PCECDL.resx">
<DependentUpon>PCECDL.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="tools\PCE\PCESoundDebugger.resx">
<DependentUpon>PCESoundDebugger.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="tools\PCE\PCETileViewer.resx">
<DependentUpon>PCETileViewer.cs</DependentUpon>
</EmbeddedResource>

File diff suppressed because it is too large Load Diff

View File

@ -1185,6 +1185,12 @@ namespace BizHawk.Client.EmuHawk
GlobalWin.Tools.Load<PCETileViewer>();
}
private void PceSoundDebuggerToolStripMenuItem_Click(object sender, EventArgs e)
{
GlobalWin.Tools.Load<PCESoundDebugger>();
}
private void CodeDataLoggerMenuItem_Click(object sender, EventArgs e)
{
GlobalWin.Tools.Load<PCECDL>();

View File

@ -0,0 +1,283 @@
namespace BizHawk.Client.EmuHawk
{
partial class PCESoundDebugger
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("PSG 0");
System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("PSG 1");
System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("PSG 2");
System.Windows.Forms.ListViewItem listViewItem4 = new System.Windows.Forms.ListViewItem("PSG 3");
System.Windows.Forms.ListViewItem listViewItem5 = new System.Windows.Forms.ListViewItem("PSG 4");
System.Windows.Forms.ListViewItem listViewItem6 = new System.Windows.Forms.ListViewItem("PSG 5");
System.Windows.Forms.ListViewItem listViewItem7 = new System.Windows.Forms.ListViewItem(new string[] {
"0",
"-",
"-",
"-"}, -1);
System.Windows.Forms.ListViewItem listViewItem8 = new System.Windows.Forms.ListViewItem(new string[] {
"1",
"-",
"-",
"-"}, -1);
System.Windows.Forms.ListViewItem listViewItem9 = new System.Windows.Forms.ListViewItem(new string[] {
"2",
"-",
"-",
"-"}, -1);
System.Windows.Forms.ListViewItem listViewItem10 = new System.Windows.Forms.ListViewItem(new string[] {
"3",
"-",
"-",
"-"}, -1);
System.Windows.Forms.ListViewItem listViewItem11 = new System.Windows.Forms.ListViewItem(new string[] {
"4",
"-",
"-",
"-"}, -1);
System.Windows.Forms.ListViewItem listViewItem12 = new System.Windows.Forms.ListViewItem(new string[] {
"5",
"-",
"-",
"-"}, -1);
this.btnExport = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.lvPsgWaveforms = new System.Windows.Forms.ListView();
this.colName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colHitCount = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.btnReset = new System.Windows.Forms.Button();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.lvChEn = new System.Windows.Forms.ListView();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.lvChannels = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// btnExport
//
this.btnExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnExport.Location = new System.Drawing.Point(441, 311);
this.btnExport.Name = "btnExport";
this.btnExport.Size = new System.Drawing.Size(75, 23);
this.btnExport.TabIndex = 0;
this.btnExport.Text = "Export";
this.btnExport.UseVisualStyleBackColor = true;
this.btnExport.Click += new System.EventHandler(this.btnExport_Click);
//
// groupBox1
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.lvPsgWaveforms);
this.groupBox1.Controls.Add(this.btnReset);
this.groupBox1.Controls.Add(this.btnExport);
this.groupBox1.Location = new System.Drawing.Point(12, 187);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(603, 340);
this.groupBox1.TabIndex = 1;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "PSG Waveform Capture";
//
// lvPsgWaveforms
//
this.lvPsgWaveforms.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lvPsgWaveforms.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colName,
this.colHitCount});
this.lvPsgWaveforms.FullRowSelect = true;
this.lvPsgWaveforms.LabelEdit = true;
this.lvPsgWaveforms.Location = new System.Drawing.Point(7, 20);
this.lvPsgWaveforms.MultiSelect = false;
this.lvPsgWaveforms.Name = "lvPsgWaveforms";
this.lvPsgWaveforms.Size = new System.Drawing.Size(590, 285);
this.lvPsgWaveforms.TabIndex = 2;
this.lvPsgWaveforms.UseCompatibleStateImageBehavior = false;
this.lvPsgWaveforms.View = System.Windows.Forms.View.Details;
this.lvPsgWaveforms.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.lvPsgWaveforms_AfterLabelEdit);
this.lvPsgWaveforms.ItemActivate += new System.EventHandler(this.lvPsgWaveforms_ItemActivate);
this.lvPsgWaveforms.KeyDown += new System.Windows.Forms.KeyEventHandler(this.lvPsgWaveforms_KeyDown);
//
// colName
//
this.colName.Text = "Name";
this.colName.Width = 191;
//
// colHitCount
//
this.colHitCount.Text = "Hit Count";
this.colHitCount.Width = 79;
//
// btnReset
//
this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnReset.Location = new System.Drawing.Point(522, 311);
this.btnReset.Name = "btnReset";
this.btnReset.Size = new System.Drawing.Size(75, 23);
this.btnReset.TabIndex = 1;
this.btnReset.Text = "Reset";
this.btnReset.UseVisualStyleBackColor = true;
this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
//
// groupBox2
//
this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.groupBox2.Controls.Add(this.lvChEn);
this.groupBox2.Location = new System.Drawing.Point(621, 6);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(165, 175);
this.groupBox2.TabIndex = 2;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Channel Enable";
//
// lvChEn
//
this.lvChEn.CheckBoxes = true;
this.lvChEn.FullRowSelect = true;
listViewItem1.StateImageIndex = 0;
listViewItem2.StateImageIndex = 0;
listViewItem3.StateImageIndex = 0;
listViewItem4.StateImageIndex = 0;
listViewItem5.StateImageIndex = 0;
listViewItem6.StateImageIndex = 0;
this.lvChEn.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2,
listViewItem3,
listViewItem4,
listViewItem5,
listViewItem6});
this.lvChEn.Location = new System.Drawing.Point(7, 20);
this.lvChEn.Name = "lvChEn";
this.lvChEn.Size = new System.Drawing.Size(121, 127);
this.lvChEn.TabIndex = 0;
this.lvChEn.UseCompatibleStateImageBehavior = false;
this.lvChEn.View = System.Windows.Forms.View.List;
this.lvChEn.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.lvChEn_ItemChecked);
this.lvChEn.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.lvChEn_ItemSelectionChanged);
//
// groupBox3
//
this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox3.Controls.Add(this.lvChannels);
this.groupBox3.Location = new System.Drawing.Point(12, 4);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(603, 177);
this.groupBox3.TabIndex = 3;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "PSG Channels";
//
// lvChannels
//
this.lvChannels.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lvChannels.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader5,
this.columnHeader3,
this.columnHeader4,
this.columnHeader1});
this.lvChannels.Enabled = false;
this.lvChannels.FullRowSelect = true;
this.lvChannels.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem7,
listViewItem8,
listViewItem9,
listViewItem10,
listViewItem11,
listViewItem12});
this.lvChannels.LabelEdit = true;
this.lvChannels.Location = new System.Drawing.Point(6, 19);
this.lvChannels.MultiSelect = false;
this.lvChannels.Name = "lvChannels";
this.lvChannels.Size = new System.Drawing.Size(591, 152);
this.lvChannels.TabIndex = 3;
this.lvChannels.UseCompatibleStateImageBehavior = false;
this.lvChannels.View = System.Windows.Forms.View.Details;
//
// columnHeader1
//
this.columnHeader1.Text = "Status";
this.columnHeader1.Width = 259;
//
// columnHeader3
//
this.columnHeader3.Text = "Vol";
//
// columnHeader4
//
this.columnHeader4.Text = "Pitch";
//
// columnHeader5
//
this.columnHeader5.Text = "Channel";
//
// PCESoundDebugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(787, 535);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Name = "PCESoundDebugger";
this.Text = "PCESoundDebugger";
this.Load += new System.EventHandler(this.PCESoundDebugger_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.groupBox3.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnExport;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button btnReset;
private System.Windows.Forms.ListView lvPsgWaveforms;
private System.Windows.Forms.ColumnHeader colHitCount;
private System.Windows.Forms.ColumnHeader colName;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.ListView lvChEn;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.ListView lvChannels;
private System.Windows.Forms.ColumnHeader columnHeader5;
private System.Windows.Forms.ColumnHeader columnHeader3;
private System.Windows.Forms.ColumnHeader columnHeader4;
private System.Windows.Forms.ColumnHeader columnHeader1;
}
}

View File

@ -0,0 +1,287 @@
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.Common;
using BizHawk.Client.Common;
using BizHawk.Emulation.Cores.Nintendo.SNES;
using BizHawk.Emulation.Cores.PCEngine;
using BizHawk.Emulation.Common.Components;
using ICSharpCode.SharpZipLib.Zip;
namespace BizHawk.Client.EmuHawk
{
public partial class PCESoundDebugger : Form, IToolForm
{
public PCESoundDebugger()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
byte[] waveformTemp = new byte[32 * 2];
protected override void OnShown(EventArgs e)
{
for (int i = 0; i < lvChEn.Items.Count; i++)
lvChEn.Items[i].Checked = true;
}
public void UpdateValues()
{
var pce = Global.Emulator as PCEngine;
if (pce == null)
return;
foreach(var entry in PSGEntries)
{
entry.wasactive = entry.active;
entry.active = false;
}
bool sync = false;
lvPsgWaveforms.BeginUpdate();
lvChannels.BeginUpdate();
for(int i=0;i<6;i++)
{
var ch = pce.PSG.Channels[i];
//these conditions mean a sample isnt playing
if (!ch.Enabled)
{
lvChannels.Items[i].SubItems[1].Text = "-";
lvChannels.Items[i].SubItems[2].Text = "-";
lvChannels.Items[i].SubItems[3].Text = "(disabled)";
goto DEAD;
}
if (ch.DDA)
{
lvChannels.Items[i].SubItems[1].Text = "-";
lvChannels.Items[i].SubItems[2].Text = "-";
lvChannels.Items[i].SubItems[3].Text = "(DDA)";
goto DEAD;
}
lvChannels.Items[i].SubItems[1].Text = ch.Volume.ToString();
lvChannels.Items[i].SubItems[2].Text = ch.Frequency.ToString();
if (ch.NoiseChannel)
{
lvChannels.Items[i].SubItems[3].Text = "(noise)";
goto DEAD;
}
if (ch.Volume == 0) goto DEAD;
lvChannels.Items[i].SubItems[3].Text = "-";
//ok, a sample is playing. copy out the waveform
short[] waveform = (short[])ch.Wave.Clone();
//hash it
var ms = new MemoryStream(waveformTemp);
var bw = new BinaryWriter(ms);
foreach (var s in waveform)
bw.Write(s);
bw.Flush();
string md5 = Util.Hash_MD5(waveformTemp);
if (!PSGEntryTable.ContainsKey(md5))
{
var entry = new PSGEntry()
{
hash = md5,
name = md5,
waveform = waveform,
active = true,
hitcount = 1,
index = PSGEntries.Count
};
PSGEntries.Add(entry);
PSGEntryTable[md5] = entry;
sync = true;
LastSamples[i] = entry;
}
else
{
PSGEntry entry = PSGEntryTable[md5];
entry.active = true;
//are we playing the same sample as before?
if (LastSamples[i] == entry) { }
else
//if (!entry.wasactive)
{
LastSamples[i] = entry;
entry.hitcount++;
if (entry.index < lvPsgWaveforms.Items.Count)
lvPsgWaveforms.Items[entry.index].SubItems[1].Text = entry.hitcount.ToString();
else
sync = true;
}
}
lvChannels.Items[i].SubItems[3].Text = PSGEntryTable[md5].name;
continue;
DEAD:
LastSamples[i] = null;
}
if (sync)
SyncLists();
lvPsgWaveforms.EndUpdate();
lvChannels.EndUpdate();
}
class PSGEntry
{
public int index;
public bool active, wasactive;
public int hitcount;
public string hash;
public string name;
public short[] waveform;
}
PSGEntry[] LastSamples = new PSGEntry[8];
List<PSGEntry> PSGEntries = new List<PSGEntry>();
Dictionary<string, PSGEntry> PSGEntryTable = new Dictionary<string, PSGEntry>();
public void Restart()
{
}
public bool AskSave()
{
return true;
}
public bool UpdateBefore
{
get { return false; }
}
//32*16 samples, 16bit, mono, 8khz (but we'll change the sample rate)
static readonly byte[] emptyWav = new byte[] {
0x52, 0x49, 0x46, 0x46, 0x24, 0x04, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xE0, 0x2E, 0x00, 0x00, 0xC0, 0x5D, 0x00, 0x00,
0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x04, 0x00, 0x00,
} ;
private void btnExport_Click(object sender, EventArgs e)
{
string tmpf = Path.GetTempFileName() + ".zip";
using (var stream = new FileStream(tmpf,FileMode.Create,FileAccess.Write,FileShare.Read))
{
var zip = new ZipOutputStream(stream)
{
IsStreamOwner = false,
UseZip64 = UseZip64.Off
};
foreach (var entry in PSGEntries)
{
var ze = new ZipEntry(entry.name + ".wav") { CompressionMethod = CompressionMethod.Deflated };
zip.PutNextEntry(ze);
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
bw.Write(emptyWav, 0, emptyWav.Length);
ms.Position = 0x18; //samplerate and avgbytespersecond
bw.Write(20000);
bw.Write(20000 * 2);
bw.Flush();
ms.Position = 0x2C;
for (int i = 0; i < 32; i++)
for(int j=0;j<16;j++)
bw.Write(entry.waveform[i]);
bw.Flush();
var buf = ms.GetBuffer();
zip.Write(buf, 0, (int)ms.Length);
zip.Flush();
zip.CloseEntry();
}
zip.Close();
stream.Flush();
}
System.Diagnostics.Process.Start(tmpf);
}
class ZipDataSource : IStaticDataSource
{
public ZipDataSource(byte[] data) { this.data = data; }
byte[] data;
public Stream GetSource() { return new MemoryStream(data); }
}
private void btnReset_Click(object sender, EventArgs e)
{
PSGEntryTable.Clear();
PSGEntries.Clear();
for (int i = 0; i < 8; i++) LastSamples[i] = null;
SyncLists();
}
void SyncLists()
{
lvPsgWaveforms.Items.Clear();
foreach (var entry in PSGEntries)
{
var lvi = new ListViewItem(entry.name);
lvi.SubItems.Add(entry.hitcount.ToString());
lvPsgWaveforms.Items.Add(lvi);
}
}
private void lvPsgWaveforms_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F2 && lvPsgWaveforms.SelectedItems.Count>0)
{
lvPsgWaveforms.SelectedItems[0].BeginEdit();
}
}
private void lvPsgWaveforms_ItemActivate(object sender, EventArgs e)
{
}
private void lvPsgWaveforms_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
var entry = PSGEntries[e.Item];
entry.name = e.Label;
}
private void lvChEn_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
}
private void lvChEn_ItemChecked(object sender, ItemCheckedEventArgs e)
{
var pce = Global.Emulator as PCEngine;
if (pce == null)
return;
for (int i = 0; i < 6; i++)
pce.PSG.UserMute[i] = !lvChEn.Items[i].Checked;
}
private void PCESoundDebugger_Load(object sender, EventArgs e)
{
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -3,6 +3,7 @@
namespace BizHawk.Emulation.Common
{
//TODO - why am I here? put me alongside hash_md5 and such in a non-emulation-related class
public static class CRC32
{
// Lookup table for speed.

View File

@ -28,6 +28,8 @@ namespace BizHawk.Emulation.Common.Components
public PSGChannel[] Channels = new PSGChannel[8];
public bool[] UserMute = new bool[8];
public byte VoiceLatch;
private byte WaveTableWriteOffset;
@ -99,7 +101,10 @@ namespace BizHawk.Emulation.Common.Components
Channels[VoiceLatch].Enabled = (value & 0x80) != 0;
Channels[VoiceLatch].DDA = (value & 0x40) != 0;
if (Channels[VoiceLatch].Enabled == false && Channels[VoiceLatch].DDA)
{
//for the soudn debugger, this might be a useful indication that a new note has begun.. but not for sure
WaveTableWriteOffset = 0;
}
break;
case 5: // Panning
Channels[VoiceLatch].Panning = value;
@ -157,7 +162,10 @@ namespace BizHawk.Emulation.Common.Components
void MixSamples(short[] samples, int start, int len)
{
for (int i = 0; i < 6; i++)
{
if (UserMute[i]) continue;
MixChannel(samples, start, len, Channels[i]);
}
}
void MixChannel(short[] samples, int start, int len, PSGChannel channel)