From b0141c516ea5f8edeedef6d319938b4b15812329 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Thu, 15 Dec 2016 15:06:35 -0500 Subject: [PATCH 01/21] Multi-disk Bundler: Fix DPI scaling issues and improve control positioning. --- .../MultiDiskBundler/MultiDiskBundler.cs | 10 ++--- .../MultiDiskFileSelector.Designer.cs | 41 ++++++++++--------- .../MultiDiskBundler/MultiDiskFileSelector.cs | 14 ++----- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs index df6896401a..4ca6bfabda 100644 --- a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs +++ b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs @@ -120,26 +120,26 @@ namespace BizHawk.Client.EmuHawk private void AddButton_Click(object sender, EventArgs e) { - int start = 5 + (FileSelectorPanel.Controls.Count * 43); + int start = 3 + (FileSelectorPanel.Controls.Count * 43); var groupBox = new GroupBox { Text = "", - Location = new Point(5, start), - Size = new Size(435, 38), + Location = UIHelper.Scale(new Point(6, start)), + Size = new Size(FileSelectorPanel.ClientSize.Width - UIHelper.ScaleX(12), UIHelper.ScaleY(41)), Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top }; var mdf = new MultiDiskFileSelector { - Location = new Point(5, 8), + Location = UIHelper.Scale(new Point(7, 12)), + Width = groupBox.ClientSize.Width - UIHelper.ScaleX(13), Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top }; mdf.NameChanged += FileSelector_NameChanged; groupBox.Controls.Add(mdf); - //grpMulti.Controls.Add(mdf); FileSelectorPanel.Controls.Add(groupBox); } diff --git a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.Designer.cs b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.Designer.cs index 007a9a7478..2ca3b27b1c 100644 --- a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.Designer.cs @@ -28,41 +28,41 @@ /// private void InitializeComponent() { - this.button1 = new System.Windows.Forms.Button(); + this.BrowseButton = new System.Windows.Forms.Button(); this.PathBox = new System.Windows.Forms.TextBox(); this.UseCurrentRomButton = new System.Windows.Forms.Button(); this.SuspendLayout(); // - // button1 + // BrowseButton // - this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.button1.Location = new System.Drawing.Point(290, 3); - this.button1.Name = "button1"; - this.button1.Size = new System.Drawing.Size(60, 23); - this.button1.TabIndex = 2; - this.button1.Text = "Browse..."; - this.button1.UseVisualStyleBackColor = true; - this.button1.Click += new System.EventHandler(this.button1_Click); + this.BrowseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.BrowseButton.Location = new System.Drawing.Point(294, 0); + this.BrowseButton.Name = "BrowseButton"; + this.BrowseButton.Size = new System.Drawing.Size(66, 23); + this.BrowseButton.TabIndex = 2; + this.BrowseButton.Text = "Browse..."; + this.BrowseButton.UseVisualStyleBackColor = true; + this.BrowseButton.Click += new System.EventHandler(this.BrowseButton_Click); // // PathBox // this.PathBox.AllowDrop = true; this.PathBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.PathBox.Location = new System.Drawing.Point(3, 5); + this.PathBox.Location = new System.Drawing.Point(0, 1); this.PathBox.Name = "PathBox"; - this.PathBox.Size = new System.Drawing.Size(285, 20); + this.PathBox.Size = new System.Drawing.Size(288, 20); this.PathBox.TabIndex = 1; this.PathBox.TextChanged += new System.EventHandler(this.PathBox_TextChanged); - this.PathBox.DragDrop += new System.Windows.Forms.DragEventHandler(this.textBox1_DragDrop); - this.PathBox.DragEnter += new System.Windows.Forms.DragEventHandler(this.textBox1_DragEnter); + this.PathBox.DragDrop += new System.Windows.Forms.DragEventHandler(this.PathBox_DragDrop); + this.PathBox.DragEnter += new System.Windows.Forms.DragEventHandler(this.PathBox_DragEnter); // // UseCurrentRomButton // this.UseCurrentRomButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.UseCurrentRomButton.Location = new System.Drawing.Point(357, 3); + this.UseCurrentRomButton.Location = new System.Drawing.Point(364, 0); this.UseCurrentRomButton.Name = "UseCurrentRomButton"; - this.UseCurrentRomButton.Size = new System.Drawing.Size(62, 23); + this.UseCurrentRomButton.Size = new System.Drawing.Size(58, 23); this.UseCurrentRomButton.TabIndex = 3; this.UseCurrentRomButton.Text = "Current"; this.UseCurrentRomButton.UseVisualStyleBackColor = true; @@ -70,12 +70,13 @@ // // MultiDiskFileSelector // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.UseCurrentRomButton); - this.Controls.Add(this.button1); + this.Controls.Add(this.BrowseButton); this.Controls.Add(this.PathBox); this.Name = "MultiDiskFileSelector"; - this.Size = new System.Drawing.Size(425, 29); + this.Size = new System.Drawing.Size(422, 23); this.Load += new System.EventHandler(this.DualGBFileSelector_Load); this.ResumeLayout(false); this.PerformLayout(); @@ -84,7 +85,7 @@ #endregion - private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button BrowseButton; private System.Windows.Forms.TextBox PathBox; private System.Windows.Forms.Button UseCurrentRomButton; diff --git a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs index 14f9a83521..1e1e662283 100644 --- a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs +++ b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs @@ -1,15 +1,7 @@ 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 BizHawk.Client.Common; -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Nintendo.Gameboy; using BizHawk.Client.EmuHawk.WinFormExtensions; namespace BizHawk.Client.EmuHawk @@ -48,7 +40,7 @@ namespace BizHawk.Client.EmuHawk } } - private void textBox1_DragEnter(object sender, DragEventArgs e) + private void PathBox_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop) && ((string[])e.Data.GetData(DataFormats.FileDrop)).Length == 1) @@ -61,7 +53,7 @@ namespace BizHawk.Client.EmuHawk } } - private void textBox1_DragDrop(object sender, DragEventArgs e) + private void PathBox_DragDrop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { @@ -73,7 +65,7 @@ namespace BizHawk.Client.EmuHawk } } - private void button1_Click(object sender, EventArgs e) + private void BrowseButton_Click(object sender, EventArgs e) { using (var ofd = new OpenFileDialog { From cabf27f5d9ce77e4ec593e56b4d4b292539f507c Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Thu, 15 Dec 2016 19:25:09 -0500 Subject: [PATCH 02/21] Move a few files related to sound output from BizHawk.Emulation.Common to BizHawk.Client.EmuHawk. --- BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj | 2 ++ .../Sound}/Interfaces/IBufferedSoundProvider.cs | 4 +++- .../Sound/Utilities/BufferedAsync.cs | 4 +++- BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj | 2 -- 4 files changed, 8 insertions(+), 4 deletions(-) rename {BizHawk.Emulation.Common => BizHawk.Client.EmuHawk/Sound}/Interfaces/IBufferedSoundProvider.cs (79%) rename {BizHawk.Emulation.Common => BizHawk.Client.EmuHawk}/Sound/Utilities/BufferedAsync.cs (95%) diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj index 632a6603eb..3a0220059a 100644 --- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj +++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj @@ -717,12 +717,14 @@ RomStatusPicker.cs + + diff --git a/BizHawk.Emulation.Common/Interfaces/IBufferedSoundProvider.cs b/BizHawk.Client.EmuHawk/Sound/Interfaces/IBufferedSoundProvider.cs similarity index 79% rename from BizHawk.Emulation.Common/Interfaces/IBufferedSoundProvider.cs rename to BizHawk.Client.EmuHawk/Sound/Interfaces/IBufferedSoundProvider.cs index aec9efda87..f47c60b057 100644 --- a/BizHawk.Emulation.Common/Interfaces/IBufferedSoundProvider.cs +++ b/BizHawk.Client.EmuHawk/Sound/Interfaces/IBufferedSoundProvider.cs @@ -1,4 +1,6 @@ -namespace BizHawk.Emulation.Common +using BizHawk.Emulation.Common; + +namespace BizHawk.Client.EmuHawk { public interface IBufferedSoundProvider { diff --git a/BizHawk.Emulation.Common/Sound/Utilities/BufferedAsync.cs b/BizHawk.Client.EmuHawk/Sound/Utilities/BufferedAsync.cs similarity index 95% rename from BizHawk.Emulation.Common/Sound/Utilities/BufferedAsync.cs rename to BizHawk.Client.EmuHawk/Sound/Utilities/BufferedAsync.cs index aab88f280b..4b132e6b0c 100644 --- a/BizHawk.Emulation.Common/Sound/Utilities/BufferedAsync.cs +++ b/BizHawk.Client.EmuHawk/Sound/Utilities/BufferedAsync.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; -namespace BizHawk.Emulation.Common +using BizHawk.Emulation.Common; + +namespace BizHawk.Client.EmuHawk { // Generates SEMI-synchronous sound, or "buffered asynchronous" sound. diff --git a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj index d3045c5a35..ce06f98ac7 100644 --- a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj +++ b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj @@ -117,7 +117,6 @@ - @@ -145,7 +144,6 @@ - From c971fba7df0b2ba0739fefcd9eadb4f405eb44f0 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Thu, 15 Dec 2016 22:10:38 -0500 Subject: [PATCH 03/21] Prevent divide by zero. Would sometimes result in fSkipFrames being PositiveInfinity, which gets propagated to fSkipFramesError, resulting in the "while (fSkipFramesError <= -1.0f..." loop freezing. --- BizHawk.Client.EmuHawk/Throttle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BizHawk.Client.EmuHawk/Throttle.cs b/BizHawk.Client.EmuHawk/Throttle.cs index 8ae8117998..c528d02023 100644 --- a/BizHawk.Client.EmuHawk/Throttle.cs +++ b/BizHawk.Client.EmuHawk/Throttle.cs @@ -245,7 +245,7 @@ namespace BizHawk.Client.EmuHawk endticks = GetCurTime(); // calculate time since last frame - ulong diffticks = endticks - beginticks; + ulong diffticks = Math.Max(endticks - beginticks, 1); float diff = (float)diffticks / afsfreq; // calculate time since last frame not including throttle sleep time From 691632f1880efd98834d118e4859a59d3eb8b533 Mon Sep 17 00:00:00 2001 From: adelikat Date: Fri, 16 Dec 2016 08:50:05 -0600 Subject: [PATCH 04/21] More IAsyncSoundProvider and related classes to BizHawk.Emulation.Cores and make them internal, since they are implementation details, and they are deprecrated and not intended to be used in future cores. --- .../BizHawk.Emulation.Common.csproj | 2 - .../Sound/Utilities/Metaspu.cs | 58 --------- .../BizHawk.Emulation.Cores.csproj | 20 +-- .../Consoles/PC Engine/ADPCM.cs | 3 +- .../Consoles/Sega/SMS/SMS.ISoundProvider.cs | 3 +- .../Sound}/IAsyncSoundProvider.cs | 80 ++++++++++-- .../Sound}/SoundMixer.cs | 119 +++++++++--------- BizHawk.Emulation.Cores/Sound/YM2413.cs | 1 + BizHawk.Emulation.Cores/Sound/YM2612.cs | 2 + 9 files changed, 146 insertions(+), 142 deletions(-) rename {BizHawk.Emulation.Common/Interfaces => BizHawk.Emulation.Cores/Sound}/IAsyncSoundProvider.cs (51%) rename {BizHawk.Emulation.Common/Sound/Utilities => BizHawk.Emulation.Cores/Sound}/SoundMixer.cs (79%) diff --git a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj index ce06f98ac7..fd5a2c2852 100644 --- a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj +++ b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj @@ -126,7 +126,6 @@ - @@ -147,7 +146,6 @@ - diff --git a/BizHawk.Emulation.Common/Sound/Utilities/Metaspu.cs b/BizHawk.Emulation.Common/Sound/Utilities/Metaspu.cs index be230af925..e473b94d75 100644 --- a/BizHawk.Emulation.Common/Sound/Utilities/Metaspu.cs +++ b/BizHawk.Emulation.Common/Sound/Utilities/Metaspu.cs @@ -58,64 +58,6 @@ namespace BizHawk.Emulation.Common } } - // An async sound provider - // Sound refactor TODO: can this be combined with the other Metaspu? - public class MetaspuSoundProvider : ISoundProvider - { - public MetaspuSoundProvider(ESynchMethod method) - { - Buffer = Metaspu.metaspu_construct(method); - } - - public ISynchronizingAudioBuffer Buffer { get; set; } - private readonly short[] pullBuffer = new short[1470]; - - public MetaspuSoundProvider() - : this(ESynchMethod.ESynchMethod_V) - { - } - - public void PullSamples(IAsyncSoundProvider source) - { - Array.Clear(pullBuffer, 0, 1470); - source.GetSamples(pullBuffer); - Buffer.enqueue_samples(pullBuffer, 735); - } - - public bool CanProvideAsync - { - get { return true; } - } - - public SyncSoundMode SyncMode - { - get { return SyncSoundMode.Async; } - } - - public void SetSyncMode(SyncSoundMode mode) - { - if (mode != SyncSoundMode.Async) - { - throw new NotSupportedException("Only Async mode is supported."); - } - } - - public void GetSamplesSync(out short[] samples, out int nsamp) - { - throw new InvalidOperationException("Sync mode is not supported."); - } - - public void GetSamplesAsync(short[] samples) - { - Buffer.output_samples(samples, samples.Length / 2); - } - - public void DiscardSamples() - { - Buffer.clear(); - } - } - public interface ISynchronizingAudioBuffer { void enqueue_samples(short[] buf, int samples_provided); diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index f6c9f2d3d7..daaac6ad08 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -911,32 +911,32 @@ - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs - PCEngine.cs + PCEngine.cs @@ -1197,8 +1197,10 @@ + + diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs index 3bace6afb6..03ec7dba05 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs @@ -1,9 +1,8 @@ using System; -using System.IO; -using System.Globalization; using BizHawk.Common; using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Components; namespace BizHawk.Emulation.Cores.PCEngine { diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs index ba64537826..fd44ce7fe5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs @@ -1,5 +1,4 @@ -using System; -using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Components; namespace BizHawk.Emulation.Cores.Sega.MasterSystem { diff --git a/BizHawk.Emulation.Common/Interfaces/IAsyncSoundProvider.cs b/BizHawk.Emulation.Cores/Sound/IAsyncSoundProvider.cs similarity index 51% rename from BizHawk.Emulation.Common/Interfaces/IAsyncSoundProvider.cs rename to BizHawk.Emulation.Cores/Sound/IAsyncSoundProvider.cs index e06e30afb6..86aaca7e6e 100644 --- a/BizHawk.Emulation.Common/Interfaces/IAsyncSoundProvider.cs +++ b/BizHawk.Emulation.Cores/Sound/IAsyncSoundProvider.cs @@ -1,25 +1,26 @@ using System; +using BizHawk.Emulation.Common; -namespace BizHawk.Emulation.Common -{ - /// - /// This interface is for legacy sound implementations in some older cores - /// This needs to go away, but is provided here, for now - /// - public interface IAsyncSoundProvider +namespace BizHawk.Emulation.Cores.Components +{ + /// + /// This interface is for legacy sound implementations in some older cores + /// This needs to go away, but is provided here, for now + /// + internal interface IAsyncSoundProvider { void GetSamples(short[] samples); void DiscardSamples(); } /// - /// TODO: this is a shim for now + /// TODO: this is a shim for now, and needs to go away /// turns an IAsyncSoundPRovider into a full ISoundProvider /// This is used in cores that have an async only sound implementation - /// better is impleemnt a sync sound option in those cores without the need for + /// better is implement a sync sound option in those cores without the need for /// this class or an IAsyncSoundPRovider interface /// - public class FakeSyncSound : ISoundProvider + internal class FakeSyncSound : ISoundProvider { private readonly IAsyncSoundProvider source; private readonly int spf; @@ -75,4 +76,63 @@ namespace BizHawk.Emulation.Common SyncMode = mode; } } + + // An async sound provider + // This class needs to go away, it takes an IAsyncSoundProvider + // and is only used by legacy sound implementations + internal class MetaspuSoundProvider : ISoundProvider + { + public MetaspuSoundProvider(ESynchMethod method) + { + Buffer = Metaspu.metaspu_construct(method); + } + + public ISynchronizingAudioBuffer Buffer { get; set; } + private readonly short[] pullBuffer = new short[1470]; + + public MetaspuSoundProvider() + : this(ESynchMethod.ESynchMethod_V) + { + } + + public void PullSamples(IAsyncSoundProvider source) + { + Array.Clear(pullBuffer, 0, 1470); + source.GetSamples(pullBuffer); + Buffer.enqueue_samples(pullBuffer, 735); + } + + public bool CanProvideAsync + { + get { return true; } + } + + public SyncSoundMode SyncMode + { + get { return SyncSoundMode.Async; } + } + + public void SetSyncMode(SyncSoundMode mode) + { + if (mode != SyncSoundMode.Async) + { + throw new NotSupportedException("Only Async mode is supported."); + } + } + + public void GetSamplesSync(out short[] samples, out int nsamp) + { + throw new InvalidOperationException("Sync mode is not supported."); + } + + public void GetSamplesAsync(short[] samples) + { + Buffer.output_samples(samples, samples.Length / 2); + } + + public void DiscardSamples() + { + Buffer.clear(); + } + } } diff --git a/BizHawk.Emulation.Common/Sound/Utilities/SoundMixer.cs b/BizHawk.Emulation.Cores/Sound/SoundMixer.cs similarity index 79% rename from BizHawk.Emulation.Common/Sound/Utilities/SoundMixer.cs rename to BizHawk.Emulation.Cores/Sound/SoundMixer.cs index d4ab8b8e27..f370d977e9 100644 --- a/BizHawk.Emulation.Common/Sound/Utilities/SoundMixer.cs +++ b/BizHawk.Emulation.Cores/Sound/SoundMixer.cs @@ -1,59 +1,60 @@ -using System.Collections.Generic; - -namespace BizHawk.Emulation.Common -{ - /// - /// An interface that extends a sound provider to provide mixing capabilities through the SoundMixer class - /// - public interface IMixedSoundProvider : IAsyncSoundProvider - { - int MaxVolume { get; set; } - } - - // This is a straightforward class to mix/chain multiple ISoundProvider sources. - public sealed class SoundMixer : IAsyncSoundProvider - { - private readonly List SoundProviders; - - public SoundMixer(params IMixedSoundProvider[] soundProviders) - { - SoundProviders = new List(soundProviders); - } - - public void AddSource(IMixedSoundProvider source) - { - SoundProviders.Add(source); - } - - public void DisableSource(IMixedSoundProvider source) - { - SoundProviders.Remove(source); - } - - public void DiscardSamples() - { - foreach (var soundSource in SoundProviders) - { - soundSource.DiscardSamples(); - } - } - - public void GetSamples(short[] samples) - { - foreach (var soundSource in SoundProviders) - { - soundSource.GetSamples(samples); - } - } - - // Splits the volume space equally between available sources. - public void EqualizeVolumes() - { - int eachVolume = short.MaxValue / SoundProviders.Count; - foreach (var source in SoundProviders) - { - source.MaxVolume = eachVolume; - } - } - } -} +using System.Collections.Generic; + +namespace BizHawk.Emulation.Cores.Components +{ + // TODO: Sound mixer is a good concept, but it needs to be refactored to use an ISoundProvider, it perhaps can enforce only recieving providers in Async mode + /// + /// An interface that extends a sound provider to provide mixing capabilities through the SoundMixer class + /// + internal interface IMixedSoundProvider : IAsyncSoundProvider + { + int MaxVolume { get; set; } + } + + // This is a straightforward class to mix/chain multiple ISoundProvider sources. + internal sealed class SoundMixer : IAsyncSoundProvider + { + private readonly List SoundProviders; + + public SoundMixer(params IMixedSoundProvider[] soundProviders) + { + SoundProviders = new List(soundProviders); + } + + public void AddSource(IMixedSoundProvider source) + { + SoundProviders.Add(source); + } + + public void DisableSource(IMixedSoundProvider source) + { + SoundProviders.Remove(source); + } + + public void DiscardSamples() + { + foreach (var soundSource in SoundProviders) + { + soundSource.DiscardSamples(); + } + } + + public void GetSamples(short[] samples) + { + foreach (var soundSource in SoundProviders) + { + soundSource.GetSamples(samples); + } + } + + // Splits the volume space equally between available sources. + public void EqualizeVolumes() + { + int eachVolume = short.MaxValue / SoundProviders.Count; + foreach (var source in SoundProviders) + { + source.MaxVolume = eachVolume; + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Sound/YM2413.cs b/BizHawk.Emulation.Cores/Sound/YM2413.cs index 2aa41032bb..c902e88a4e 100644 --- a/BizHawk.Emulation.Cores/Sound/YM2413.cs +++ b/BizHawk.Emulation.Cores/Sound/YM2413.cs @@ -7,6 +7,7 @@ using System; using BizHawk.Common; +using BizHawk.Emulation.Cores.Components; namespace BizHawk.Emulation.Common.Components { diff --git a/BizHawk.Emulation.Cores/Sound/YM2612.cs b/BizHawk.Emulation.Cores/Sound/YM2612.cs index 3e96a49f83..a856524c57 100644 --- a/BizHawk.Emulation.Cores/Sound/YM2612.cs +++ b/BizHawk.Emulation.Cores/Sound/YM2612.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; +using BizHawk.Emulation.Cores.Components; + namespace BizHawk.Emulation.Common.Components { // ====================================================================== From eda79c2212f04b92df3ea98d37b2ceabcf32d599 Mon Sep 17 00:00:00 2001 From: adelikat Date: Fri, 16 Dec 2016 11:33:02 -0600 Subject: [PATCH 05/21] Make an interface for CodeDataLog, and move CodeDataLog to Base Implementations --- .../{ => Base Implementations}/CodeDataLog.cs | 76 ++++++++++++++----- .../BizHawk.Emulation.Common.csproj | 2 +- .../Interfaces/Services/ICodeDataLogger.cs | 57 +++++++++++++- .../CPUs/HuC6280/HuC6280_CDL.cs | 4 +- .../Nintendo/Gameboy/Gambatte.ICodeDataLog.cs | 8 +- .../Gameboy/GambatteLink.ICodeDataLog.cs | 38 +++++----- .../Nintendo/SNES/LibsnesApi_QUERY.cs | 2 +- .../Consoles/Nintendo/SNES/LibsnesCore.cs | 8 +- .../PC Engine/PCEngine.ICodeDataLogger.cs | 6 +- .../Consoles/Sega/SMS/SMS.ICodeDataLogger.cs | 8 +- .../Sega/gpgx/GPGX.ICodeDataLogger.cs | 8 +- .../Sega/gpgx64/GPGX.ICodeDataLogger.cs | 8 +- 12 files changed, 158 insertions(+), 67 deletions(-) rename BizHawk.Emulation.Common/{ => Base Implementations}/CodeDataLog.cs (79%) diff --git a/BizHawk.Emulation.Common/CodeDataLog.cs b/BizHawk.Emulation.Common/Base Implementations/CodeDataLog.cs similarity index 79% rename from BizHawk.Emulation.Common/CodeDataLog.cs rename to BizHawk.Emulation.Common/Base Implementations/CodeDataLog.cs index 972ff199a1..260c48b3e0 100644 --- a/BizHawk.Emulation.Common/CodeDataLog.cs +++ b/BizHawk.Emulation.Common/Base Implementations/CodeDataLog.cs @@ -1,17 +1,20 @@ using System; -using System.Runtime.InteropServices; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.IO; -using BizHawk.Emulation.Common; +using System.Runtime.InteropServices; namespace BizHawk.Emulation.Common { - public class CodeDataLog : Dictionary + /// + /// The base implementation of ICodeDataLog + /// + /// + /// + public class CodeDataLog : Dictionary, ICodeDataLog { public CodeDataLog() { + Active = true; } /// @@ -20,9 +23,14 @@ namespace BizHawk.Emulation.Common public void Pin() { if (Pins.Count != 0) + { throw new InvalidOperationException("incremental astrological examination"); + } + foreach (var kvp in this) + { Pins[kvp.Key] = GCHandle.Alloc(kvp.Value, GCHandleType.Pinned); + } } /// @@ -31,7 +39,10 @@ namespace BizHawk.Emulation.Common public void Unpin() { foreach (var pin in Pins.Values) + { pin.Free(); + } + Pins.Clear(); } @@ -46,49 +57,67 @@ namespace BizHawk.Emulation.Common /// /// Pinned managed arrays /// - Dictionary Pins = new Dictionary(); + private readonly Dictionary Pins = new Dictionary(); /// /// Whether the CDL is tracking a block with the given name /// - public bool Has(string blockname) { return ContainsKey(blockname); } + public bool Has(string blockname) + { + return ContainsKey(blockname); + } /// /// This is just a hook, if needed, to readily suspend logging, without having to rewire the core /// - public bool Active = true; + public bool Active { get; set; } - public string SubType; - public int SubVer; + public string SubType { get; set; } + public int SubVer { get; set; } /// /// Tests whether the other CodeDataLog is structurally identical /// - public bool Check(CodeDataLog other) + public bool Check(ICodeDataLog other) { if (SubType != other.SubType) + { return false; - if (SubVer != other.SubVer) - return false; + } - if (this.Count != other.Count) + if (SubVer != other.SubVer) + { return false; + } + + if (Count != other.Count) + { + return false; + } + foreach (var kvp in this) { if (!other.ContainsKey(kvp.Key)) + { return false; + } + var oval = other[kvp.Key]; if (oval.Length != kvp.Value.Length) + { return false; + } } return true; } - public void LogicalOrFrom(CodeDataLog other) + public void LogicalOrFrom(ICodeDataLog other) { - if (this.Count != other.Count) + if (Count != other.Count) + { throw new InvalidDataException("Dictionaries must have the same number of keys!"); + } foreach (var kvp in other) { @@ -96,17 +125,23 @@ namespace BizHawk.Emulation.Common byte[] todata = this[kvp.Key]; if (fromdata.Length != todata.Length) + { throw new InvalidDataException("Memory regions must be the same size!"); + } for (int i = 0; i < todata.Length; i++) + { todata[i] |= fromdata[i]; + } } } public void ClearData() { foreach (byte[] data in Values) + { Array.Clear(data, 0, data.Length); + } } public void Save(Stream s) @@ -114,7 +149,7 @@ namespace BizHawk.Emulation.Common _Save(s, true); } - Dictionary _Save(Stream s, bool forReal) + private Dictionary _Save(Stream s, bool forReal) { var ret = new Dictionary(); var w = new BinaryWriter(s); @@ -142,6 +177,7 @@ namespace BizHawk.Emulation.Common addr += kvp.Value.Length; } } + w.Flush(); return ret; } @@ -156,11 +192,17 @@ namespace BizHawk.Emulation.Common var br = new BinaryReader(s); string id = br.ReadString(); if (id == "BIZHAWK-CDL-1") + { SubType = "PCE"; + } else if (id == "BIZHAWK-CDL-2") + { SubType = br.ReadString().TrimEnd(' '); + } else + { throw new InvalidDataException("File is not a Bizhawk CDL file!"); + } int count = br.ReadInt32(); for (int i = 0; i < count; i++) diff --git a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj index fd5a2c2852..5c5b3ade3e 100644 --- a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj +++ b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj @@ -107,7 +107,7 @@ - + diff --git a/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs b/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs index 6fcd634156..a2d064c923 100644 --- a/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs +++ b/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs @@ -1,4 +1,6 @@ -using System.IO; +using System; +using System.IO; +using System.Collections.Generic; namespace BizHawk.Emulation.Common { @@ -11,17 +13,64 @@ namespace BizHawk.Emulation.Common /// /// Sets the CodeDataLog as current (and logging) on the core /// - void SetCDL(CodeDataLog cdl); + void SetCDL(ICodeDataLog cdl); /// /// Fills a new CodeDataLog with memory domain information suitable for the core /// - void NewCDL(CodeDataLog cdl); + void NewCDL(ICodeDataLog cdl); /// /// Disassembles the CodeDataLog to an output Stream. Can't be done without a core because there's no code to disassemble otherwise! /// This could be extended later to produce richer multi-file disassembly /// - void DisassembleCDL(Stream s, CodeDataLog cdl); + void DisassembleCDL(Stream s, ICodeDataLog cdl); + } + + /// + /// Defines a code/data log to be used with the code/data logger + /// + /// + public interface ICodeDataLog : IDictionary + { + /// + /// Pins the managed arrays. Not that we expect them to be allocated, but in case we do, seeing thish ere will remind us to check for the pin condition and abort + /// + void Pin(); + + /// + /// Unpins the managed arrays, to be paired with calls to Pin() + /// + void Unpin(); + + /// + /// Retrieves the pointer to a managed array + /// + IntPtr GetPin(string key); + + /// + /// Whether the CDL is tracking a block with the given name + /// + bool Has(string blockname); + + /// + /// This is just a hook, if needed, to readily suspend logging, without having to rewire the core + /// + bool Active { get; set; } + + string SubType { get; set; } + + int SubVer { get; set; } + + /// + /// Tests whether the other CodeDataLog is structurally identical + /// + bool Check(ICodeDataLog other); + + void LogicalOrFrom(ICodeDataLog other); + + void ClearData(); + + void Save(Stream s); } } diff --git a/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs b/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs index def9ecc065..9438733ba7 100644 --- a/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs +++ b/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs @@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280 { public partial class HuC6280 { - public void DisassembleCDL(Stream s, CodeDataLog cdl, IMemoryDomains mem) + public void DisassembleCDL(Stream s, ICodeDataLog cdl, IMemoryDomains mem) { var w = new StreamWriter(s); w.WriteLine("; Bizhawk CDL Disassembly"); @@ -78,7 +78,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280 public MemMapping[] Mappings; // = new MemMapping[256]; - public CodeDataLog CDL = null; + public ICodeDataLog CDL = null; [Flags] public enum CDLUsage : byte diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs index 1eaf4cbaf9..8625c95d3b 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { partial class Gameboy { - void ICodeDataLogger.SetCDL(CodeDataLog cdl) + void ICodeDataLogger.SetCDL(ICodeDataLog cdl) { CDL = cdl; if(cdl == null) @@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy LibGambatte.gambatte_setcdcallback(GambatteState, CDCallback); } - void ICodeDataLogger.NewCDL(CodeDataLog cdl) + void ICodeDataLogger.NewCDL(ICodeDataLog cdl) { cdl["ROM"] = new byte[MemoryDomains["ROM"].Size]; @@ -32,9 +32,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy } //not supported - void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl) { } + void ICodeDataLogger.DisassembleCDL(Stream s, ICodeDataLog cdl) { } - CodeDataLog CDL; + ICodeDataLog CDL; LibGambatte.CDCallback CDCallback; void CDCallbackProc(int addr, LibGambatte.CDLog_AddrType addrtype, LibGambatte.CDLog_Flags flags) { diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs index 0348165c76..7585653826 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs @@ -1,24 +1,24 @@ -using System; -using System.IO; -using System.Collections.Generic; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.Gameboy +using System; +using System.IO; +using System.Collections.Generic; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { - partial class GambatteLink - { - void ICodeDataLogger.SetCDL(CodeDataLog cdl) + partial class GambatteLink + { + void ICodeDataLogger.SetCDL(ICodeDataLog cdl) { - ((ICodeDataLogger)L).SetCDL(cdl); - } - - void ICodeDataLogger.NewCDL(CodeDataLog cdl) - { - ((ICodeDataLogger)L).NewCDL(cdl); + ((ICodeDataLogger)L).SetCDL(cdl); } - void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl) { ((ICodeDataLogger)L).DisassembleCDL(s, cdl); } - - } + void ICodeDataLogger.NewCDL(ICodeDataLog cdl) + { + ((ICodeDataLogger)L).NewCDL(cdl); + } + + void ICodeDataLogger.DisassembleCDL(Stream s, ICodeDataLog cdl) { ((ICodeDataLogger)L).DisassembleCDL(s, cdl); } + + } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs index bc92dbf1dd..f08f29b57e 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs @@ -204,7 +204,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES Marshal.Copy(temp, 0, new IntPtr(ptr), CpuRegs.SIZEOF); } - public void QUERY_set_cdl(CodeDataLog cdl) + public void QUERY_set_cdl(ICodeDataLog cdl) { WritePipeMessage(eMessage.eMessage_QUERY_set_cdl); if (cdl == null) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs index a2b3c47ff4..127ef65e68 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -174,9 +174,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES } } - CodeDataLog currCdl; + ICodeDataLog currCdl; - public void SetCDL(CodeDataLog cdl) + public void SetCDL(ICodeDataLog cdl) { if(currCdl != null) currCdl.Unpin(); currCdl = cdl; @@ -186,7 +186,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES api.QUERY_set_cdl(currCdl); } - public void NewCDL(CodeDataLog cdl) + public void NewCDL(ICodeDataLog cdl) { cdl["CARTROM"] = new byte[MemoryDomains["CARTROM"].Size]; @@ -200,7 +200,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES cdl.SubVer = 0; } - public void DisassembleCDL(Stream s, CodeDataLog cdl) + public void DisassembleCDL(Stream s, ICodeDataLog cdl) { //not supported yet } diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs index e46911343a..8161881024 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs @@ -8,12 +8,12 @@ namespace BizHawk.Emulation.Cores.PCEngine { public sealed partial class PCEngine : ICodeDataLogger { - public void SetCDL(CodeDataLog cdl) + public void SetCDL(ICodeDataLog cdl) { Cpu.CDL = cdl; } - public void NewCDL(CodeDataLog cdl) + public void NewCDL(ICodeDataLog cdl) { InitCDLMappings(); var mm = this.Cpu.Mappings; @@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Cores.PCEngine cdl.SubVer = 0; } - public void DisassembleCDL(Stream s, CodeDataLog cdl) + public void DisassembleCDL(Stream s, ICodeDataLog cdl) { Cpu.DisassembleCDL(s, cdl, _memoryDomains); } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs index 1b00f989e1..3c5d438faf 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs @@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { public sealed partial class SMS : ICodeDataLogger { - public void SetCDL(CodeDataLog cdl) + public void SetCDL(ICodeDataLog cdl) { CDL = cdl; if (cdl == null) @@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } } - public void NewCDL(CodeDataLog cdl) + public void NewCDL(ICodeDataLog cdl) { cdl["ROM"] = new byte[MemoryDomains["ROM"].Size]; cdl["Main RAM"] = new byte[MemoryDomains["Main RAM"].Size]; @@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } [FeatureNotImplemented] - public void DisassembleCDL(Stream s, CodeDataLog cdl) + public void DisassembleCDL(Stream s, ICodeDataLog cdl) { } @@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem private delegate CDLog_MapResults MapMemoryDelegate(ushort addr, bool write); private MapMemoryDelegate MapMemory; - private CodeDataLog CDL; + private ICodeDataLog CDL; private void RunCDL(ushort address, CDLog_Flags flags) { diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.ICodeDataLogger.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.ICodeDataLogger.cs index 63d4cfe903..0c154bece0 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.ICodeDataLogger.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.ICodeDataLogger.cs @@ -7,14 +7,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { public partial class GPGX : ICodeDataLogger { - public void SetCDL(CodeDataLog cdl) + public void SetCDL(ICodeDataLog cdl) { CDL = cdl; if (cdl == null) LibGPGX.gpgx_set_cd_callback(null); else LibGPGX.gpgx_set_cd_callback(CDCallback); } - public void NewCDL(CodeDataLog cdl) + public void NewCDL(ICodeDataLog cdl) { cdl["MD CART"] = new byte[MemoryDomains["MD CART"].Size]; cdl["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size]; @@ -29,9 +29,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx // TODO: we have Disassembling now // not supported - public void DisassembleCDL(Stream s, CodeDataLog cdl) { } + public void DisassembleCDL(Stream s, ICodeDataLog cdl) { } - private CodeDataLog CDL; + private ICodeDataLog CDL; private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags) { //TODO - hard reset makes CDL go nuts. diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs index 0d144b94cd..445a11ea62 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs @@ -7,14 +7,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 { public partial class GPGX : ICodeDataLogger { - public void SetCDL(CodeDataLog cdl) + public void SetCDL(ICodeDataLog cdl) { CDL = cdl; if (cdl == null) Core.gpgx_set_cd_callback(null); else Core.gpgx_set_cd_callback(CDCallback); } - public void NewCDL(CodeDataLog cdl) + public void NewCDL(ICodeDataLog cdl) { cdl["MD CART"] = new byte[MemoryDomains["MD CART"].Size]; cdl["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size]; @@ -29,9 +29,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 // TODO: we have Disassembling now // not supported - public void DisassembleCDL(Stream s, CodeDataLog cdl) { } + public void DisassembleCDL(Stream s, ICodeDataLog cdl) { } - private CodeDataLog CDL; + private ICodeDataLog CDL; private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags) { //TODO - hard reset makes CDL go nuts. From 7843664f688cfa517ad0088761ef2e1341245dd4 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Fri, 16 Dec 2016 16:01:21 -0500 Subject: [PATCH 06/21] Improve FPS smoothing to initialize with a real value instead of ramping up from zero. Re-initialize the FPS data after pausing or changing fast forward/rewind state to eliminate ramp-up and ramp-down in those cases. Only the initial behavior has changed; the FPS calculation/smoothing is otherwise mathematically identical. --- BizHawk.Client.EmuHawk/MainForm.cs | 111 +++++++++++++++++------------ 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 58befef60b..75b80b34a6 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -487,6 +487,8 @@ namespace BizHawk.Client.EmuHawk Activate(); BringToFront(); + InitializeFpsData(); + for (;;) { Input.Instance.Update(); @@ -584,6 +586,11 @@ namespace BizHawk.Client.EmuHawk private set { + if (_emulatorPaused && !value) // Unpausing + { + InitializeFpsData(); + } + _emulatorPaused = value; if (OnPauseChanged != null) { @@ -1358,15 +1365,16 @@ namespace BizHawk.Client.EmuHawk private bool _runloopFrameProgress; private long _frameAdvanceTimestamp; private long _frameRewindTimestamp; - private double _runloopLastFps; - private double _runloopDisplayFps; private bool _runloopFrameadvance; - private double _runloopUpdatesPerSecond = 12.0; - private double _runloopFpsSmoothing = 8.0; - private long _runloopSecond; - private bool _runloopLastFf; + private bool _lastFastForwardingOrRewinding; private bool _inResizeLoop; + private readonly double _fpsUpdatesPerSecond = 12.0; + private readonly double _fpsSmoothing = 8.0; + private double _lastFps; + private int _framesSinceLastFpsUpdate; + private long _timestampLastFpsUpdate; + private readonly Throttle _throttle; private bool _unthrottled; @@ -1416,7 +1424,7 @@ namespace BizHawk.Client.EmuHawk //we need to display FPS somewhere, in this case if (Global.Config.DispSpeedupFeatures == 0) { - str = str + string.Format("({0:0} fps) -", _runloopDisplayFps); + str = str + string.Format("({0:0} fps) -", _lastFps); } if (!string.IsNullOrEmpty(VersionInfo.CustomBuildString)) @@ -2757,8 +2765,13 @@ namespace BizHawk.Client.EmuHawk if (runFrame || force) { var isFastForwarding = Global.ClientControls["Fast Forward"] || IsTurboing; - var updateFpsString = _runloopLastFf != isFastForwarding; - _runloopLastFf = isFastForwarding; + var isFastFowardingOrRewinding = isFastForwarding || isRewinding; + + if (isFastFowardingOrRewinding != _lastFastForwardingOrRewinding) + { + InitializeFpsData(); + } + _lastFastForwardingOrRewinding = isFastFowardingOrRewinding; // client input-related duties GlobalWin.OSD.ClearGUIText(); @@ -2783,9 +2796,9 @@ namespace BizHawk.Client.EmuHawk GlobalWin.Tools.UpdateToolsBefore(); } - _runloopLastFps+= _runloopFpsSmoothing; + _framesSinceLastFpsUpdate++; - UpdateFpsDisplay(currentTimestamp, updateFpsString, isRewinding, isFastForwarding); + UpdateFpsDisplay(currentTimestamp, isRewinding, isFastForwarding); CaptureRewind(suppressCaptureRewind); @@ -2794,7 +2807,7 @@ namespace BizHawk.Client.EmuHawk { atten = Global.Config.SoundVolume / 100.0f; - if (isFastForwarding || IsTurboing || isRewinding) + if (isFastFowardingOrRewinding) { if (Global.Config.SoundEnabledRWFF) atten *= Global.Config.SoundVolumeRWFF / 100.0f; @@ -2884,46 +2897,52 @@ namespace BizHawk.Client.EmuHawk GlobalWin.Sound.UpdateSound(atten); } - private void UpdateFpsDisplay(long currentTimestamp, bool updateFpsString, bool isRewinding, bool isFastForwarding) + private void UpdateFpsDisplay(long currentTimestamp, bool isRewinding, bool isFastForwarding) { - var timeDiff = (currentTimestamp - _runloopSecond); - if ( timeDiff * _runloopUpdatesPerSecond >= Stopwatch.Frequency) + double elapsedSeconds = (currentTimestamp - _timestampLastFpsUpdate) / (double)Stopwatch.Frequency; + + if (elapsedSeconds < 1.0 / _fpsUpdatesPerSecond) { - _runloopLastFps = Stopwatch.Frequency * (_runloopLastFps / (Stopwatch.Frequency + timeDiff * _runloopFpsSmoothing)); - _runloopSecond = currentTimestamp; - _runloopDisplayFps = _runloopLastFps; - updateFpsString = true; + return; } - if (updateFpsString) + if (_lastFps == 0) // Initial calculation { - var fps_string = string.Format("{0:0} fps", _runloopDisplayFps); - if (isRewinding) - { - if (IsTurboing || isFastForwarding) - { - fps_string += " <<<<"; - } - else - { - fps_string += " <<"; - } - } - else if (IsTurboing) - { - fps_string += " >>>>"; - } - else if (isFastForwarding) - { - fps_string += " >>"; - } - - GlobalWin.OSD.FPS = fps_string; - - //need to refresh window caption in this case - if (Global.Config.DispSpeedupFeatures == 0) - SetWindowText(); + _lastFps = (_framesSinceLastFpsUpdate - 1) / elapsedSeconds; } + else + { + _lastFps = (_lastFps + (_framesSinceLastFpsUpdate * _fpsSmoothing)) / (1.0 + (elapsedSeconds * _fpsSmoothing)); + } + _framesSinceLastFpsUpdate = 0; + _timestampLastFpsUpdate = currentTimestamp; + + var fps_string = string.Format("{0:0} fps", _lastFps); + if (isRewinding) + { + fps_string += IsTurboing || isFastForwarding ? + " <<<<" : + " <<"; + } + else if (isFastForwarding) + { + fps_string += IsTurboing ? + " >>>>" : + " >>"; + } + + GlobalWin.OSD.FPS = fps_string; + + //need to refresh window caption in this case + if (Global.Config.DispSpeedupFeatures == 0) + SetWindowText(); + } + + private void InitializeFpsData() + { + _lastFps = 0; + _timestampLastFpsUpdate = Stopwatch.GetTimestamp(); + _framesSinceLastFpsUpdate = 0; } #endregion From 2b4267d2c985966c74715460e8e34a2c9f93a9c2 Mon Sep 17 00:00:00 2001 From: adelikat Date: Fri, 16 Dec 2016 15:47:19 -0600 Subject: [PATCH 07/21] nitpicky code refactorings on unimportant files, nothing to see here --- .../Base Implementations/NullEmulator.cs | 225 ++++++++++++------ BizHawk.Emulation.Cores/Calculator/TI83.cs | 15 +- 2 files changed, 156 insertions(+), 84 deletions(-) diff --git a/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs b/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs index 0b89fe25b8..36c2d3bc82 100644 --- a/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs +++ b/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; -using System.IO; -using BizHawk.Common; using System.ComponentModel; +using System.IO; + +using BizHawk.Common; namespace BizHawk.Emulation.Common { @@ -19,77 +20,107 @@ namespace BizHawk.Emulation.Common _settings = (NullEmulatorSettings)settings ?? new NullEmulatorSettings(); var d = DateTime.Now; - xmas = d.Month == 12 && d.Day >= 17 && d.Day <= 27; - if (xmas) - pleg = new Pleg(); + _xmas = d.Month == 12 && d.Day >= 17 && d.Day <= 27; + if (_xmas) + { + _pleg = new Pleg(); + } } + #region IEmulator + public IEmulatorServiceProvider ServiceProvider { get; private set; } - public string SystemId { get { return "NULL"; } } - public static readonly ControllerDefinition NullController = new ControllerDefinition { Name = "Null Controller" }; - - public string BoardName { get { return null; } } - - private bool frameBufferClear = true; - private readonly int[] frameBuffer = new int[256 * 192]; - private readonly Random rand = new Random(); - public CoreComm CoreComm { get; private set; } - - public void ResetCounters() + public ControllerDefinition ControllerDefinition { - Frame = 0; + get { return NullController; } } + public IController Controller { get; set; } + public void FrameAdvance(bool render, bool rendersound) { if (render == false) return; if (!_settings.SnowyDisplay) { - if (frameBufferClear) return; - frameBufferClear = true; - Array.Clear(frameBuffer, 0, 256 * 192); + if (_frameBufferClear) return; + _frameBufferClear = true; + Array.Clear(FrameBuffer, 0, 256 * 192); return; } - frameBufferClear = false; - if (xmas) + _frameBufferClear = false; + if (_xmas) { for (int i = 0; i < 256 * 192; i++) { - byte b = (byte)rand.Next(); - frameBuffer[i] = Colors.ARGB(b, (byte)(255 - b), 0, 255); + byte b = (byte)Rand.Next(); + FrameBuffer[i] = Colors.ARGB(b, (byte)(255 - b), 0, 255); } } else { - for (int i = 0; i < 256*192; i++) + for (int i = 0; i < 256 * 192; i++) { - frameBuffer[i] = Colors.Luminosity((byte) rand.Next()); + FrameBuffer[i] = Colors.Luminosity((byte)Rand.Next()); } } Frame++; } - public ControllerDefinition ControllerDefinition { get { return NullController; } } - public IController Controller { get; set; } public int Frame { get; set; } + + public string SystemId { get { return "NULL"; } } + public bool DeterministicEmulation { get { return true; } } - public int[] GetVideoBuffer() { return frameBuffer; } - public int VirtualWidth { get { return 256; } } - public int VirtualHeight { get { return 192; } } - public int BufferWidth { get { return 256; } } - public int BufferHeight { get { return 192; } } - public int BackgroundColor { get { return 0; } } + public void ResetCounters() + { + Frame = 0; + } + + public string BoardName { get { return null; } } + + public CoreComm CoreComm { get; private set; } public void Dispose() { } - private bool xmas; - private Pleg pleg; + #endregion - private short[] sampbuff = new short[735 * 2]; + #region IVideoProvider + + public int[] GetVideoBuffer() + { + return FrameBuffer; + } + + public int VirtualWidth + { + get { return 256; } + } + + public int VirtualHeight + { + get { return 192; } + } + + public int BufferWidth + { + get { return 256; } + } + + public int BufferHeight + { + get { return 192; } + } + + public int BackgroundColor + { + get { return 0; } + } + + #endregion #region ISoundProvider @@ -101,11 +132,16 @@ namespace BizHawk.Emulation.Common } nsamp = 735; - samples = sampbuff; + samples = SampleBuffer; if (!_settings.SnowyDisplay) + { return; - if (xmas) - pleg.Generate(samples); + } + + if (_xmas) + { + _pleg.Generate(samples); + } } public void DiscardSamples() @@ -120,9 +156,14 @@ namespace BizHawk.Emulation.Common } if (!_settings.SnowyDisplay) + { return; - if (xmas) - pleg.Generate(samples); + } + + if (_xmas) + { + _pleg.Generate(samples); + } } public bool CanProvideAsync @@ -139,23 +180,7 @@ namespace BizHawk.Emulation.Common #endregion - private NullEmulatorSettings _settings; - - public class NullEmulatorSettings - { - [DefaultValue(false)] - public bool SnowyDisplay { get; set; } - - public NullEmulatorSettings() - { - SettingsUtil.SetDefaultValues(this); - } - - public NullEmulatorSettings Clone() - { - return (NullEmulatorSettings)MemberwiseClone(); - } - } + #region ISettable public NullEmulatorSettings GetSettings() { @@ -177,14 +202,45 @@ namespace BizHawk.Emulation.Common { return false; } + + #endregion + + public static readonly ControllerDefinition NullController = new ControllerDefinition { Name = "Null Controller" }; + + private readonly int[] FrameBuffer = new int[256 * 192]; + private readonly short[] SampleBuffer = new short[735 * 2]; + private readonly Random Rand = new Random(); + + private bool _frameBufferClear = true; + + private bool _xmas; + private Pleg _pleg; + + private NullEmulatorSettings _settings; + + public class NullEmulatorSettings + { + [DefaultValue(false)] + public bool SnowyDisplay { get; set; } + + public NullEmulatorSettings() + { + SettingsUtil.SetDefaultValues(this); + } + + public NullEmulatorSettings Clone() + { + return (NullEmulatorSettings)MemberwiseClone(); + } + } } #region super tone generator - class Bell + internal class Bell { // ms ima adpcm - const string dataz = "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"; + private const string dataz = "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"; private static readonly int[] AdaptationTable = { 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 }; private static readonly int[] AdaptCoeff1 = { 256, 512, 0, 192, 240, 460, 392 }; @@ -201,7 +257,9 @@ namespace BizHawk.Emulation.Common gz.CopyTo(ms); data = ms.ToArray(); for (int i = 0; i < 3800; i++) // compenstate for sample start point + { Next(); + } } private int blockpredictor; @@ -258,22 +316,27 @@ namespace BizHawk.Emulation.Common delta >>= 8; if (delta < 16) delta = 16; } + samplectr++; if (samplectr == sampleloop) { samplectr = 0; idx = 0; } + return (short)ret; } } - class Pleg + internal class Pleg { - const string data = "H4sICI/2sVICAG91dDMudHh0AOxazdLbIAy8d6bvgkFImFsvufb936Yt3YyKvjBY5UvS6XDSxOZndyULy9H3ylLD1y8/baxHs/Lb5rNG2IT7zVKq9Msmrmf7Tb/st3qcP4ff7rdhb7itw04eXrVzsYWOTuXTt7yzl/OXvYHtDWwN+0cQi0IcqzJnxtchy9lDbo5rVODAAJvbdXWk1PiQooBiMBQPnxcOnYbhfkoCSgGUMmLxbgsoCSgdoCSgFEApwxZQArZ0uryWTp227DUBxVzDpbXLNUhlAVIGJELsZ6hb+kzACdePGqFqxPiE8QnjEualCcUZtb+mRKAUP0tlfyxHQAiIZUEsJ6gZYVXtTlVOiGWBmhk29qoS+zIQ6zQvJZ3rUHFtSwm9I++q5WJUS1At90mNAywhA/CqausZIPaPG/Jtgwhq6ug3qU5GdZMRMg+OmNR7IxfjjQwbDLXD5Q09Yta9QcfqKQfkz4Aw3fptrP0xNVfsCVu++j1S55KPJem01Yi2Bw/R27N2yxfj9znNI9TnESo1dikyT7J68aledNqi6vO1yjUI5RkQplu/mTWRf8u7LVTzZeXaaBRNeUxDTozimi8HRhuNqM/XJZOoiK5IeLJFOF5bEV3XSBGxeHiwjDSbaTXRBkhmuBUBU83T9IiK/wEPUmQOf3RIZxqxI2YVEQfDy7C3VZzJuWTqDuTkDzmW9PUT49KfXHIAlzD0s+qk6CJWx2ptFdzt9mqWsuYF6KT6aBoRAmWGK3MPMfEIkoHg2JIRPfajC39U1/K2TCeQ3SrqHi4V+YSK8VUq2hJoriKDd3So+NJYtBTUnvV4jaqq1omtCVYGsdi9RVmIyDdzqJoPNLdZ6O0q5MhzKh8LUAIFGQSIraFFA8VSg0QOagAJ+5xY1xpaBrGel2I9j2Nd63Kiv8u7tBDb5Mu7xaiYH6uovAcq0ttV5KIxvq6iMxb/HxV7CmpLPV6i6vhrGZdRHp5Us/SEPEwmD5eaXQEzycN5kIfZ5GHjDS7LediftAaxH/DN0r5riPWOLXld3xiI/unqWhgqnbCHieGzU8v9/YJK2wWrSqxHA0404bv+7yjpy1G7HwGBFAoiOIJw9PsABHVVHhBc+G8UJyAAYwv1lJASaZZAiPFbzCN6Pq7zKPq+pUWdtuy7oo9qp2YCNe59xGwe0RmWco1CWaDAfeKUA95KfXmA6+qlWKOpwieUZlTW/0NNSqH9DoAcAfmosUuYx2d5wf+MpP4ZYYbqAdBpoP5x73ExrRFHXwuKpSa+Z0R0mo+aFqsygKRrj9SerYqrZu1V3CRuqRbougPdId0qxLlfR6Psgam9PBxhT+wd+71zcKmeg05bVBWQboBkIF7Zq8xWxdXJ2iuZfILTSuil/SxIqSxDu+bX+RHOYjIxwUZTQIgeKoOuQ2Ac993tbsTdjbi7EXc34u5G3N2IuxtxdyPubsTdjbi7EXc34u5G3N2IuxtxdyPubsTdjbi7EXc34o927dAGAACEgeB27D8SEoVBleRmqGg+ORqRRqQRaUQakUakEWlEGjG1rmlEGpFGpBFpRBqRRqQRaUQakUakEWlEGpFGpBFpRBqRRqQRaUQakUakEWlEGpFGpBFpRBqRRqQRaUQakUb86OhoRBqRRqQRk+qaRqQRaUQakUakEWlEGpFGpBFvGnFXiHMetSzUwqZz46p5AAA="; - List Lines = new List(); - int LineIDX = 0; - Bell bell = new Bell(); + private const string data = "H4sICI/2sVICAG91dDMudHh0AOxazdLbIAy8d6bvgkFImFsvufb936Yt3YyKvjBY5UvS6XDSxOZndyULy9H3ylLD1y8/baxHs/Lb5rNG2IT7zVKq9Msmrmf7Tb/st3qcP4ff7rdhb7itw04eXrVzsYWOTuXTt7yzl/OXvYHtDWwN+0cQi0IcqzJnxtchy9lDbo5rVODAAJvbdXWk1PiQooBiMBQPnxcOnYbhfkoCSgGUMmLxbgsoCSgdoCSgFEApwxZQArZ0uryWTp227DUBxVzDpbXLNUhlAVIGJELsZ6hb+kzACdePGqFqxPiE8QnjEualCcUZtb+mRKAUP0tlfyxHQAiIZUEsJ6gZYVXtTlVOiGWBmhk29qoS+zIQ6zQvJZ3rUHFtSwm9I++q5WJUS1At90mNAywhA/CqausZIPaPG/Jtgwhq6ug3qU5GdZMRMg+OmNR7IxfjjQwbDLXD5Q09Yta9QcfqKQfkz4Aw3fptrP0xNVfsCVu++j1S55KPJem01Yi2Bw/R27N2yxfj9znNI9TnESo1dikyT7J68aledNqi6vO1yjUI5RkQplu/mTWRf8u7LVTzZeXaaBRNeUxDTozimi8HRhuNqM/XJZOoiK5IeLJFOF5bEV3XSBGxeHiwjDSbaTXRBkhmuBUBU83T9IiK/wEPUmQOf3RIZxqxI2YVEQfDy7C3VZzJuWTqDuTkDzmW9PUT49KfXHIAlzD0s+qk6CJWx2ptFdzt9mqWsuYF6KT6aBoRAmWGK3MPMfEIkoHg2JIRPfajC39U1/K2TCeQ3SrqHi4V+YSK8VUq2hJoriKDd3So+NJYtBTUnvV4jaqq1omtCVYGsdi9RVmIyDdzqJoPNLdZ6O0q5MhzKh8LUAIFGQSIraFFA8VSg0QOagAJ+5xY1xpaBrGel2I9j2Nd63Kiv8u7tBDb5Mu7xaiYH6uovAcq0ttV5KIxvq6iMxb/HxV7CmpLPV6i6vhrGZdRHp5Us/SEPEwmD5eaXQEzycN5kIfZ5GHjDS7LediftAaxH/DN0r5riPWOLXld3xiI/unqWhgqnbCHieGzU8v9/YJK2wWrSqxHA0404bv+7yjpy1G7HwGBFAoiOIJw9PsABHVVHhBc+G8UJyAAYwv1lJASaZZAiPFbzCN6Pq7zKPq+pUWdtuy7oo9qp2YCNe59xGwe0RmWco1CWaDAfeKUA95KfXmA6+qlWKOpwieUZlTW/0NNSqH9DoAcAfmosUuYx2d5wf+MpP4ZYYbqAdBpoP5x73ExrRFHXwuKpSa+Z0R0mo+aFqsygKRrj9SerYqrZu1V3CRuqRbougPdId0qxLlfR6Psgam9PBxhT+wd+71zcKmeg05bVBWQboBkIF7Zq8xWxdXJ2iuZfILTSuil/SxIqSxDu+bX+RHOYjIxwUZTQIgeKoOuQ2Ac993tbsTdjbi7EXc34u5G3N2IuxtxdyPubsTdjbi7EXc34u5G3N2IuxtxdyPubsTdjbi7EXc34o927dAGAACEgeB27D8SEoVBleRmqGg+ORqRRqQRaUQakUakEWlEGjG1rmlEGpFGpBFpRBqRRqQRaUQakUakEWlEGpFGpBFpRBqRRqQRaUQakUakEWlEGpFGpBFpRBqRRqQRaUQakUb86OhoRBqRRqQRk+qaRqQRaUQakUakEWlEGpFGpBFvGnFXiHMetSzUwqZz46p5AAA="; + private readonly List SinMen = new List(); + private readonly List Lines = new List(); + private readonly Bell Bell = new Bell(); + + private int LineIDX = 0; + private int deadtime = 0; public Pleg() { @@ -283,32 +346,36 @@ namespace BizHawk.Emulation.Common var tr = new StreamReader(gz); string line; while ((line = tr.ReadLine()) != null) + { Lines.Add(line); + } } - List SinMen = new List(); - - int deadtime = 0; - - void Off(int c, int n) + private void Off(int c, int n) { foreach (var s in SinMen) { if (s.c == c && s.n == n && !s.fading) + { s.fading = true; + } } } - void On(int c, int n) + + private void On(int c, int n) { if (c == 9) + { return; + } + var s = new SinMan(1500, n); s.c = c; s.n = n; SinMen.Add(s); } - short Next() + private short Next() { int ret = 0; for (int i = 0; i < SinMen.Count; i++) @@ -329,7 +396,7 @@ namespace BizHawk.Emulation.Common return (short)ret; } - string FetchNext() + private string FetchNext() { string ret = Lines[LineIDX]; LineIDX++; @@ -346,7 +413,7 @@ namespace BizHawk.Emulation.Common if (deadtime > 0) { short n = Next(); - n += bell.Next(); + n += Bell.Next(); dest[idx++] = n; dest[idx++] = n; deadtime--; @@ -367,7 +434,7 @@ namespace BizHawk.Emulation.Common } } - class SinMan + internal class SinMan { public int c; public int n; @@ -378,7 +445,10 @@ namespace BizHawk.Emulation.Common public bool fading = false; - public bool Done { get { return amp < 2.0; } } + public bool Done + { + get { return amp < 2.0; } + } static double GetFreq(int note) { @@ -401,7 +471,6 @@ namespace BizHawk.Emulation.Common this.amp = amp; this.freq = GetFreq(note); } - } #endregion diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.cs b/BizHawk.Emulation.Cores/Calculator/TI83.cs index 2a496c9ca6..eb9f86b9a3 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.cs @@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.Calculators if (game["initPC"]) { - startPC = ushort.Parse(game.OptionValue("initPC"), NumberStyles.HexNumber); + _startPC = ushort.Parse(game.OptionValue("initPC"), NumberStyles.HexNumber); } HardReset(); @@ -57,7 +57,7 @@ namespace BizHawk.Emulation.Cores.Calculators serviceProvider.Register(new Disassembler()); } - private ITraceable Tracer { get; set; } + private readonly ITraceable Tracer; // hardware private const ushort RamSizeMask = 0x7FFF; @@ -80,10 +80,10 @@ namespace BizHawk.Emulation.Cores.Calculators private int _frame; // configuration - private ushort startPC; + private ushort _startPC; // Link Cable - public TI83LinkPort LinkPort { get; set; } + public TI83LinkPort LinkPort { get; private set; } internal bool LinkActive; internal int LinkOutput, LinkInput; @@ -306,7 +306,6 @@ namespace BizHawk.Emulation.Cores.Calculators } return (byte)ret; - } private byte ReadDispData() @@ -384,9 +383,13 @@ namespace BizHawk.Emulation.Cores.Calculators private void WriteDispCtrl(byte value) { if (value <= 1) + { _displayMode = value; + } else if (value >= 4 && value <= 7) + { _displayMove = value - 4; + } else if ((value & 0xC0) == 0x40) { //hardware scroll @@ -434,7 +437,7 @@ namespace BizHawk.Emulation.Cores.Calculators _ram = new byte[0x8000]; for (int i = 0; i < 0x8000; i++) _ram[i] = 0xFF; - Cpu.RegisterPC = startPC; + Cpu.RegisterPC = _startPC; Cpu.IFF1 = false; Cpu.IFF2 = false; From 40be0dd0b3ad840603a38dbc63285fbf4aac0f45 Mon Sep 17 00:00:00 2001 From: adelikat Date: Fri, 16 Dec 2016 23:34:18 -0600 Subject: [PATCH 08/21] Refactor the way a Null ControllerDefinition is created --- BizHawk.Client.EmuHawk/MainForm.cs | 6 +++--- BizHawk.Client.MultiHawk/Mainform.cs | 4 ++-- .../Base Implementations/NullController.cs | 7 ++++++- .../Base Implementations/NullEmulator.cs | 4 +--- BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 75b80b34a6..2f46a8dd51 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -290,7 +290,7 @@ namespace BizHawk.Client.EmuHawk var comm = CreateCoreComm(); CoreFileProvider.SyncCoreCommInputSignals(comm); Emulator = new NullEmulator(comm, Global.Config.GetCoreSettings()); - Global.ActiveController = new Controller(NullEmulator.NullController); + Global.ActiveController = new Controller(NullController.Instance.Definition); Global.AutoFireController = Global.AutofireNullControls; Global.AutofireStickyXORAdapter.SetOnOffPatternFromConfig(); try { GlobalWin.Sound = new Sound(Handle); } @@ -1769,7 +1769,7 @@ namespace BizHawk.Client.EmuHawk } Global.ClientControls = controls; - Global.AutofireNullControls = new AutofireController(NullEmulator.NullController, Emulator); + Global.AutofireNullControls = new AutofireController(NullController.Instance.Definition, Emulator); } @@ -3655,7 +3655,7 @@ namespace BizHawk.Client.EmuHawk var coreComm = CreateCoreComm(); CoreFileProvider.SyncCoreCommInputSignals(coreComm); Emulator = new NullEmulator(coreComm, Global.Config.GetCoreSettings()); - Global.ActiveController = new Controller(NullEmulator.NullController); + Global.ActiveController = new Controller(NullController.Instance.Definition); Global.AutoFireController = Global.AutofireNullControls; RewireSound(); RebootStatusBarIcon.Visible = false; diff --git a/BizHawk.Client.MultiHawk/Mainform.cs b/BizHawk.Client.MultiHawk/Mainform.cs index ac66217f20..bbcacb5b29 100644 --- a/BizHawk.Client.MultiHawk/Mainform.cs +++ b/BizHawk.Client.MultiHawk/Mainform.cs @@ -84,7 +84,7 @@ namespace BizHawk.Client.MultiHawk // TODO //CoreFileProvider.SyncCoreCommInputSignals(); - Global.ActiveController = new Controller(NullEmulator.NullController); + Global.ActiveController = new Controller(NullController.Instance.Definition); Global.AutoFireController = Global.AutofireNullControls; Global.AutofireStickyXORAdapter.SetOnOffPatternFromConfig(); @@ -199,7 +199,7 @@ namespace BizHawk.Client.MultiHawk } Global.ClientControls = controls; - Global.AutofireNullControls = new AutofireController(NullEmulator.NullController, Emulator); + Global.AutofireNullControls = new AutofireController(NullController.Instance.Definition, Emulator); } private void OpenRomMenuItem_Click(object sender, EventArgs e) diff --git a/BizHawk.Emulation.Common/Base Implementations/NullController.cs b/BizHawk.Emulation.Common/Base Implementations/NullController.cs index 7491e14cd9..8ea8738bc4 100644 --- a/BizHawk.Emulation.Common/Base Implementations/NullController.cs +++ b/BizHawk.Emulation.Common/Base Implementations/NullController.cs @@ -7,9 +7,14 @@ /// public class NullController : IController { + private static readonly ControllerDefinition _definition = new ControllerDefinition + { + Name = "Null Controller" + }; + public ControllerDefinition Definition { - get { return null; } + get { return _definition; } } public bool this[string button] diff --git a/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs b/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs index 36c2d3bc82..15b7257425 100644 --- a/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs +++ b/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs @@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Common public ControllerDefinition ControllerDefinition { - get { return NullController; } + get { return NullController.Instance.Definition; } } public IController Controller { get; set; } @@ -205,8 +205,6 @@ namespace BizHawk.Emulation.Common #endregion - public static readonly ControllerDefinition NullController = new ControllerDefinition { Name = "Null Controller" }; - private readonly int[] FrameBuffer = new int[256 * 192]; private readonly short[] SampleBuffer = new short[735 * 2]; private readonly Random Rand = new Random(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs index 5b8dcaf782..15fbd3e03a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs @@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X public ControllerDefinition ControllerDefinition { - get { return NullEmulator.NullController; } + get { return NullController.Instance.Definition; } } public IController Controller { get; set; } From a2d366a20dd033e043bb289760610aba6dc6ec2c Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 12:10:58 -0500 Subject: [PATCH 09/21] Start intellivision gamedb --- Assets/gamedb/gamedb_intv.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Assets/gamedb/gamedb_intv.txt diff --git a/Assets/gamedb/gamedb_intv.txt b/Assets/gamedb/gamedb_intv.txt new file mode 100644 index 0000000000..f735166701 --- /dev/null +++ b/Assets/gamedb/gamedb_intv.txt @@ -0,0 +1,3 @@ +; NOTE: games not in this database will default to mapper 0 + +sha1:7E44A63186C66A80DF20DF26036F48E5A309256F Pac Man INTV board=5 \ No newline at end of file From 810267441133bf65411ee316010c1abad7934d16 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 12:11:44 -0500 Subject: [PATCH 10/21] Update gamedb.txt --- Assets/gamedb/gamedb.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Assets/gamedb/gamedb.txt b/Assets/gamedb/gamedb.txt index e3c679cbdd..aa654de9da 100644 --- a/Assets/gamedb/gamedb.txt +++ b/Assets/gamedb/gamedb.txt @@ -29,6 +29,7 @@ #include gamedb_msx1.txt #include gamedb_msx2.txt #include gamedb_vs.txt +#include gamedb_intv.txt ; ************ NES / Famicom ************ From 204647e065253159949776a077a045219bd6a483 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 12:13:32 -0500 Subject: [PATCH 11/21] intellivision add gamedb selection to cartridge start process of mapper selection --- .../Consoles/Intellivision/Cartridge.cs | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs index f0d739c8a3..fec3b56512 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs @@ -1,4 +1,7 @@ using BizHawk.Common; +using BizHawk.Common.BufferExtensions; +using BizHawk.Emulation.Common; +using System; namespace BizHawk.Emulation.Cores.Intellivision { @@ -6,17 +9,22 @@ namespace BizHawk.Emulation.Cores.Intellivision { private ushort[] Data = new ushort[56320]; + // There are 10 mappers Intellivision games use (not counting intellicart which is handled seperately) + // we will pick the mapper from the game DB and default to 0 + private int mapper = 0; + public void SyncState(Serializer ser) { ser.BeginSection("Cart"); - // TODO + ser.Sync("mapper", ref mapper); ser.EndSection(); } public int Parse(byte[] Rom) { + /* // TODO: Determine which loading method, if either, is correct. int index = 0; // Combine every two bytes into a word. @@ -28,9 +36,79 @@ namespace BizHawk.Emulation.Cores.Intellivision for (int index = 0; index < Rom.Length; index++) Data[index + 0x2C00] = Rom[index]; */ + + // Combine every two bytes into a word. + int index = 0; + + while (index + 1 < Rom.Length) + { + Data[(index / 2)] = (ushort)((Rom[index++] << 8) | Rom[index++]); + } + + // look up hash in gamedb to see what mapper to use + // if none found default is zero + string hash_sha1 = null; + string s_mapper = null; + hash_sha1 = "sha1:" + Rom.HashSHA1(16, Rom.Length - 16); + + var gi = Database.CheckDatabase(hash_sha1); + if (gi != null) + { + var dict = gi.GetOptionsDict(); + if (!dict.ContainsKey("board")) + throw new Exception("INTV gamedb entries must have a board identifier!"); + s_mapper = dict["board"]; + Console.WriteLine(mapper); + } + else + { + s_mapper = "0"; + } + + int.TryParse(s_mapper, out mapper); + return Rom.Length; } + public ushort? ReadCart(ushort addr) + { + switch (mapper) + { + case 0: + if (addr>=0x5000 && addr<0x6FFF) + { + return Data[addr-0x5000]; + } + else if (addr>=0xD000 && addr<0xDFFF) + { + return Data[addr - 0xB000]; + } + else if (addr>=0xF000 && addr<0xFFFF) + { + return Data[addr - 0xC000]; + } + break; + case 5: + if (addr >= 0x5000 && addr < 0x7FFF) + { + return Data[addr - 0x5000]; + } + else if (addr >= 0x9000 && addr < 0xBFFF) + { + return Data[addr - 0x6000]; + } + break; + } + + + return null; + } + + public bool WriteCart(ushort addr, ushort value) + { + return false; + } + /* public ushort? ReadCart(ushort addr) { // TODO: Check if address is RAM / ROM. @@ -153,6 +231,7 @@ namespace BizHawk.Emulation.Cores.Intellivision return null; } + public bool WriteCart(ushort addr, ushort value) { int dest; @@ -294,5 +373,6 @@ namespace BizHawk.Emulation.Cores.Intellivision } return false; } + */ } } From 5d0bc690851e65f3cb576db5b87e3fc99367ac4a Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 14:00:03 -0500 Subject: [PATCH 12/21] Intellivision finish cartridge mapping --- .../Consoles/Intellivision/Cartridge.cs | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs index fec3b56512..ee2dcca718 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs @@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Intellivision { private ushort[] Data = new ushort[56320]; + private ushort[] Cart_Ram = new ushort[0x400]; + // There are 10 mappers Intellivision games use (not counting intellicart which is handled seperately) // we will pick the mapper from the game DB and default to 0 private int mapper = 0; @@ -18,6 +20,7 @@ namespace BizHawk.Emulation.Cores.Intellivision ser.BeginSection("Cart"); ser.Sync("mapper", ref mapper); + ser.Sync("Cart_Ram", ref Cart_Ram, false); ser.EndSection(); } @@ -88,6 +91,63 @@ namespace BizHawk.Emulation.Cores.Intellivision return Data[addr - 0xC000]; } break; + + case 1: + if (addr >= 0x5000 && addr < 0x6FFF) + { + return Data[addr - 0x5000]; + } + else if (addr >= 0xD000 && addr < 0xFFFF) + { + return Data[addr - 0xB000]; + } + break; + + case 2: + if (addr >= 0x5000 && addr < 0x6FFF) + { + return Data[addr - 0x5000]; + } + else if (addr >= 0x9000 && addr < 0xBFFF) + { + return Data[addr - 0x7000]; + } + else if (addr >= 0xD000 && addr < 0xDFFF) + { + return Data[addr - 0x8000]; + } + break; + + case 3: + if (addr >= 0x5000 && addr < 0x6FFF) + { + return Data[addr - 0x5000]; + } + else if (addr >= 0x9000 && addr < 0xAFFF) + { + return Data[addr - 0x7000]; + } + else if (addr >= 0xD000 && addr < 0xDFFF) + { + return Data[addr - 0x9000]; + } + else if (addr >= 0xF000 && addr < 0xFFFF) + { + return Data[addr - 0xA000]; + } + break; + + case 4: + if (addr >= 0x5000 && addr < 0x6FFF) + { + return Data[addr - 0x5000]; + } + else if (addr >= 0xD000 && addr < 0xD3FF) + { + return Cart_Ram[addr - 0xD000]; + } + break; + case 5: if (addr >= 0x5000 && addr < 0x7FFF) { @@ -98,6 +158,54 @@ namespace BizHawk.Emulation.Cores.Intellivision return Data[addr - 0x6000]; } break; + + case 6: + if (addr >= 0x6000 && addr < 0x7FFF) + { + return Data[addr - 0x6000]; + } + break; + + case 7: + if (addr >= 0x4800 && addr < 0x67FF) + { + return Data[addr - 0x4800]; + } + break; + + case 8: + if (addr >= 0x5000 && addr < 0x5FFF) + { + return Data[addr - 0x5000]; + } + else if (addr >= 0x7000 && addr < 0x7FFF) + { + return Data[addr - 0x6000]; + } + break; + + case 9: + if (addr >= 0x5000 && addr < 0x6FFF) + { + return Data[addr - 0x5000]; + } + else if (addr >= 0x9000 && addr < 0xAFFF) + { + return Data[addr - 0x7000]; + } + else if (addr >= 0xD000 && addr < 0xDFFF) + { + return Data[addr - 0x9000]; + } + else if (addr >= 0xF000 && addr < 0xFFFF) + { + return Data[addr - 0xA000]; + } + else if (addr >= 0x8800 && addr < 0x8FFF) + { + return Cart_Ram[addr - 0x8800]; + } + break; } @@ -106,6 +214,23 @@ namespace BizHawk.Emulation.Cores.Intellivision public bool WriteCart(ushort addr, ushort value) { + switch (mapper) + { + case 4: + if (addr >= 0xD000 && addr < 0xD3FF) + { + Cart_Ram[addr - 0xD000] = value; + return true; + } + break; + case 9: + if (addr >= 0x8800 && addr < 0x8FFF) + { + Cart_Ram[addr - 0x8800] = value; + return true; + } + break; + } return false; } /* From 8ab8eb43b9e60f4c68a338a29da3e09a377585ce Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 18:23:30 -0500 Subject: [PATCH 13/21] Update Cartridge.cs --- BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs index ee2dcca718..1c5d95b43c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs @@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Intellivision { private ushort[] Data = new ushort[56320]; - private ushort[] Cart_Ram = new ushort[0x400]; + private ushort[] Cart_Ram = new ushort[0x800]; // There are 10 mappers Intellivision games use (not counting intellicart which is handled seperately) // we will pick the mapper from the game DB and default to 0 From 3789485d3b65c5ef7d52c14367c97d6665a9629e Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 18:24:12 -0500 Subject: [PATCH 14/21] Update intv game db --- Assets/gamedb/gamedb_intv.txt | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Assets/gamedb/gamedb_intv.txt b/Assets/gamedb/gamedb_intv.txt index f735166701..c8073b4bb5 100644 --- a/Assets/gamedb/gamedb_intv.txt +++ b/Assets/gamedb/gamedb_intv.txt @@ -1,3 +1,28 @@ ; NOTE: games not in this database will default to mapper 0 -sha1:7E44A63186C66A80DF20DF26036F48E5A309256F Pac Man INTV board=5 \ No newline at end of file +sha1:AAD9D2691F63A993B984143D8457FC4A86CFC472 Atlantis INTV board=7 +sha1:280A14898F1AB2C26209D3B28AD67054504C0856 Beauty and the Beast (1982) (Imagic) [!] INTV board=7 +sha1:A27144195AE123FA4FC9F9848B77B7B5208D5FFC Body Slam - Super Pro Wrestling (1988) (Intv Corp) INTV board=2 +sha1:C50B818CB1E5041BAD1087A03BF8B6E021579BC5 Centipede (1983) (Atarisoft) INTV board=6 +sha1:39BF9C38E1A9F0472A6254A4700FC0D2695E8A71 Championship Tennis (1985) (Mattel) INTV board=1 +sha1:059A73EC21E71985A6724974F864AE8A82041AA8 Commando (1987) (Mattel) INTV board=2 +sha1:E8E3DCB80ED8273D079DEF0793BEB1D6070C9A08 Congo Bongo (1983) (Sega) INTV board=5 +sha1:D41F0B32703A15A8406901905224205451D7B59C Defender (1983) (Atarisoft) INTV board=5 +sha1:E27310C6C26C07D9FF59E723AFFA8E48BEE7D820 Demon Attack (1982) (Imagic) [!] INTV board=7 +sha1:997846CEE15A81E51255CBE378379216B01DE0F2 Dig Dug (1987) (Intv Corp) INTV board=5 +sha1:C649D6A822062B3DD7151E27005979ACF1C6FDFD Diner (1987) (Intv Corp) INTV board=2 +sha1:B883C75D3ABCB9638E8ED3D4E11CFCC1322462A8 Game Factory (Prototype) (1983) (Mattel) [!] INTV board=9 +sha1:208147F393AF35ECE134D2CD056214E4A4DCCA5E Hover Force (1986) (Intv Corp) INTV board=2 +sha1:9800325E3C8A82BBEE66FE0402C9F76A5D996AB0 King of the Mountain (1982) (Mattel) INTV board=1 +sha1:8E28A7AD0DB9CB0E7D7DA008A16C0F8654810826 Land Battle (1982) (Mattel) INTV board=4 +sha1:18AE3B7BC158B7FFCDFCFA84AF86D16B1545769C Learning Fun I - Math Master Factor Fun (1987) (Intv Corp) INTV board=2 +sha1:A01DB79795CCB7F20B45D3C44791F52065600DEB Learning Fun II - Word Wizard Memory Fun (1987) (Intv Corp) INTV board=2 +sha1:13BDECAF48094920F257C8A25686EEC91C0ADADC Microsurgeon (1982) (Imagic) [!] INTV board=7 +sha1:350313B04570F0F30B8E6730C999B5DA8EE26ABE MTE201 Intellivision Test Cartridge (1978) (Mattel) INTV board=8 +sha1:68AC0AE38753D0F3EDC69E004954B0575DF85DD6 Pac-Man (1983) (Atarisoft) INTV board=5 +sha1:7E44A63186C66A80DF20DF26036F48E5A309256F Pac-Man (1983) (Intv Corp) INTV board=5 +sha1:30399A9B4AAA0B4E0D8C7987AEF56D0AB7AE4B09 Stadium Mud Buggies (1988) (Intv Corp) INTV board=2 +sha1:004ABB06C3C5A4641EAE488DD78858C10C9F0A42 Super Pro Decathlon (1988) (Intv Corp) INTV board=2 +sha1:6E1261F456070F3EBBE124B6DCEC2A31C5BCC0EE Super Pro Football (1986) (Intv Corp) INTV board=2 +sha1:57B8BFAD43CD7F0CC0E30029870CA6BA0454AE38 Tower of Doom (1986) (Intv Corp) INTV board=3 +sha1:307D7DF3EE36000D1BE8C1151EA6484245602C5D USCF Chess (1981) (Mattel) INTV board=4 \ No newline at end of file From d8c39235bfd72d78f2f4b632d39934efd2bc5bfb Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 18:32:36 -0500 Subject: [PATCH 15/21] Update gamedb_intv.txt --- Assets/gamedb/gamedb_intv.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/gamedb/gamedb_intv.txt b/Assets/gamedb/gamedb_intv.txt index c8073b4bb5..1aeadfe8cf 100644 --- a/Assets/gamedb/gamedb_intv.txt +++ b/Assets/gamedb/gamedb_intv.txt @@ -21,8 +21,9 @@ sha1:13BDECAF48094920F257C8A25686EEC91C0ADADC Microsurgeon (1982) (Imagic) [!] sha1:350313B04570F0F30B8E6730C999B5DA8EE26ABE MTE201 Intellivision Test Cartridge (1978) (Mattel) INTV board=8 sha1:68AC0AE38753D0F3EDC69E004954B0575DF85DD6 Pac-Man (1983) (Atarisoft) INTV board=5 sha1:7E44A63186C66A80DF20DF26036F48E5A309256F Pac-Man (1983) (Intv Corp) INTV board=5 +sha1:FB32AE847476A5BC7625100D85985E99A377CE39 Pole Position (1986) (Intv Corp) INTV board=2 sha1:30399A9B4AAA0B4E0D8C7987AEF56D0AB7AE4B09 Stadium Mud Buggies (1988) (Intv Corp) INTV board=2 sha1:004ABB06C3C5A4641EAE488DD78858C10C9F0A42 Super Pro Decathlon (1988) (Intv Corp) INTV board=2 sha1:6E1261F456070F3EBBE124B6DCEC2A31C5BCC0EE Super Pro Football (1986) (Intv Corp) INTV board=2 sha1:57B8BFAD43CD7F0CC0E30029870CA6BA0454AE38 Tower of Doom (1986) (Intv Corp) INTV board=3 -sha1:307D7DF3EE36000D1BE8C1151EA6484245602C5D USCF Chess (1981) (Mattel) INTV board=4 \ No newline at end of file +sha1:307D7DF3EE36000D1BE8C1151EA6484245602C5D USCF Chess (1981) (Mattel) INTV board=4 From 6bc9a027b3ef01bcd4b4e16f638a49c397d47fce Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 17 Dec 2016 22:09:23 -0500 Subject: [PATCH 16/21] Intellivision Bug fix to STIC --- BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs index 3a2529e501..9248d674f5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs @@ -286,7 +286,7 @@ namespace BizHawk.Emulation.Cores.Intellivision colors[0] = fg; colors[1] = (card >> 3) & 0x0007; colors[2] = (card >> 6) & 0x0007; - colors[3] = ((card >> 11) & 0x0004) | ((card >> 9) & 0x0003); + colors[3] = ((card >> 10) & 0x0004) | ((card >> 9) & 0x0003); for (int z=0;z<4;z++) { @@ -341,10 +341,10 @@ namespace BizHawk.Emulation.Cores.Intellivision // note that the collision field is attached to the lower right corner of the BG // so we add 8 to x and 16 to y here // also notice the extra condition attached to colored squares mode - if ((card_col * 8 + (7 - squares_col) + 8) < 167 && square_col[color]==1) + if ((card_col * 8 + squares_col + 8) < 167 && square_col[color]==1) { - Collision[card_col * 8 + (7 - squares_col) + 8, (card_row * 8 + squares_row) * 2 + 16] = 1 << 8; - Collision[card_col * 8 + (7 - squares_col) + 8, (card_row * 8 + squares_row) * 2 + 16 + 1] = 1 << 8; + Collision[card_col * 8 + squares_col + 8, (card_row * 8 + squares_row) * 2 + 16] = 1 << 8; + Collision[card_col * 8 + squares_col + 8, (card_row * 8 + squares_row) * 2 + 16 + 1] = 1 << 8; } } } From 970a9017d4934435239c37e86466311d65c379ae Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Sun, 18 Dec 2016 13:03:44 -0500 Subject: [PATCH 17/21] Fix typo in previous commit. --- BizHawk.Client.EmuHawk/MainForm.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 2f46a8dd51..6fd700c178 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -2765,13 +2765,13 @@ namespace BizHawk.Client.EmuHawk if (runFrame || force) { var isFastForwarding = Global.ClientControls["Fast Forward"] || IsTurboing; - var isFastFowardingOrRewinding = isFastForwarding || isRewinding; + var isFastForwardingOrRewinding = isFastForwarding || isRewinding; - if (isFastFowardingOrRewinding != _lastFastForwardingOrRewinding) + if (isFastForwardingOrRewinding != _lastFastForwardingOrRewinding) { InitializeFpsData(); } - _lastFastForwardingOrRewinding = isFastFowardingOrRewinding; + _lastFastForwardingOrRewinding = isFastForwardingOrRewinding; // client input-related duties GlobalWin.OSD.ClearGUIText(); @@ -2807,7 +2807,7 @@ namespace BizHawk.Client.EmuHawk { atten = Global.Config.SoundVolume / 100.0f; - if (isFastFowardingOrRewinding) + if (isFastForwardingOrRewinding) { if (Global.Config.SoundEnabledRWFF) atten *= Global.Config.SoundVolumeRWFF / 100.0f; From f2e9ca2ac93390dceedf6e4a731a9395719a7727 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Sun, 18 Dec 2016 15:23:23 -0500 Subject: [PATCH 18/21] Fix fast-forward when using audio throttle and XAudio2 or OpenAL. --- BizHawk.Client.EmuHawk/Sound/Sound.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/BizHawk.Client.EmuHawk/Sound/Sound.cs b/BizHawk.Client.EmuHawk/Sound/Sound.cs index 4c10058d60..0a3c3eef94 100644 --- a/BizHawk.Client.EmuHawk/Sound/Sound.cs +++ b/BizHawk.Client.EmuHawk/Sound/Sound.cs @@ -172,7 +172,12 @@ namespace BizHawk.Client.EmuHawk { _outputProvider.BaseSoundProvider.GetSamplesSync(out samples, out samplesProvided); - while (samplesNeeded < samplesProvided && !Global.DisableSecondaryThrottling) + if (Global.DisableSecondaryThrottling && samplesProvided > samplesNeeded) + { + return; + } + + while (samplesProvided > samplesNeeded) { Thread.Sleep((samplesProvided - samplesNeeded) / (SampleRate / 1000)); // Let the audio clock control sleep time samplesNeeded = _outputDevice.CalculateSamplesNeeded(); From 36daa01ad64c0656391ae7c79f2cda818dfc85f5 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Sun, 18 Dec 2016 20:45:38 -0500 Subject: [PATCH 19/21] Sound cleanup. In case you're curious, the "SilenceLeaveRoomForFrameCount" part ended up not mattering (and may have been slightly counterproductive) once SoundOutputProvider had the ability to be notified of underruns. It doesn't matter for BufferedAsync either. --- .../Sound/Output/DirectSoundSoundOutput.cs | 6 +-- .../Sound/Output/DummySoundOutput.cs | 1 - .../Sound/Output/OpenALSoundOutput.cs | 1 - .../Sound/Output/XAudio2SoundOutput.cs | 4 -- BizHawk.Client.EmuHawk/Sound/Sound.cs | 37 +++++-------------- 5 files changed, 10 insertions(+), 39 deletions(-) diff --git a/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs index 9bf155b9e7..ec1a19b549 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs @@ -129,11 +129,7 @@ namespace BizHawk.Client.EmuHawk int cursorDelta = CircularDistance(_lastWriteCursor, writeCursor, BufferSizeBytes); cursorDelta += BufferSizeBytes * (int)Math.Round((elapsedSeconds - (cursorDelta / (double)(Sound.SampleRate * Sound.BlockAlign))) / bufferSizeSeconds); _filledBufferSizeBytes -= cursorDelta; - if (_filledBufferSizeBytes < 0) - { - _sound.OnUnderrun(); - detectedUnderrun = true; - } + detectedUnderrun = _filledBufferSizeBytes < 0; } if (isInitializing || detectedUnderrun) { diff --git a/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs index fad2c2f618..d1632ced87 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs @@ -56,7 +56,6 @@ namespace BizHawk.Client.EmuHawk if (_remainingSamples < 0) { _remainingSamples = 0; - _sound.OnUnderrun(); detectedUnderrun = true; } _lastWriteTime = currentWriteTime; diff --git a/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs index 6fb3b98ea8..4a24bb4d82 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs @@ -81,7 +81,6 @@ namespace BizHawk.Client.EmuHawk bool detectedUnderrun = sourceState == ALSourceState.Stopped; if (detectedUnderrun) { - _sound.OnUnderrun(); // SampleOffset should reset to 0 when stopped; update the queued sample count to match UnqueueProcessedBuffers(); currentSamplesPlayed = 0; diff --git a/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs index dab844f113..b5e81f73e2 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs @@ -102,10 +102,6 @@ namespace BizHawk.Client.EmuHawk { bool isInitializing = _runningSamplesQueued == 0; bool detectedUnderrun = !isInitializing && _sourceVoice.State.BuffersQueued == 0; - if (detectedUnderrun) - { - _sound.OnUnderrun(); - } long samplesAwaitingPlayback = _runningSamplesQueued - _sourceVoice.State.SamplesPlayed; int samplesNeeded = (int)Math.Max(BufferSizeSamples - samplesAwaitingPlayback, 0); if (isInitializing || detectedUnderrun) diff --git a/BizHawk.Client.EmuHawk/Sound/Sound.cs b/BizHawk.Client.EmuHawk/Sound/Sound.cs index 0a3c3eef94..31174fb69b 100644 --- a/BizHawk.Client.EmuHawk/Sound/Sound.cs +++ b/BizHawk.Client.EmuHawk/Sound/Sound.cs @@ -109,40 +109,21 @@ namespace BizHawk.Client.EmuHawk public bool LogUnderruns { get; set; } - private bool InitializeBufferWithSilence - { - get { return true; } - } - - private bool RecoverFromUnderrunsWithSilence - { - get { return true; } - } - - private int SilenceLeaveRoomForFrameCount - { - get { return Global.Config.SoundThrottle ? 1 : 2; } // Why 2? I don't know, but it seems to work well with the clock throttle's behavior. - } - internal void HandleInitializationOrUnderrun(bool isUnderrun, ref int samplesNeeded) { - if ((!isUnderrun && InitializeBufferWithSilence) || (isUnderrun && RecoverFromUnderrunsWithSilence)) + // Fill device buffer with silence but leave enough room for one frame + int samplesPerFrame = (int)Math.Round(SampleRate / Global.Emulator.CoreComm.VsyncRate); + int silenceSamples = Math.Max(samplesNeeded - samplesPerFrame, 0); + _outputDevice.WriteSamples(new short[silenceSamples * 2], silenceSamples); + samplesNeeded -= silenceSamples; + + if (isUnderrun) { - int samplesPerFrame = (int)Math.Round(SampleRate / Global.Emulator.CoreComm.VsyncRate); - int silenceSamples = Math.Max(samplesNeeded - (SilenceLeaveRoomForFrameCount * samplesPerFrame), 0); - _outputDevice.WriteSamples(new short[silenceSamples * 2], silenceSamples); - samplesNeeded -= silenceSamples; + if (LogUnderruns) Console.WriteLine("Sound underrun detected!"); + _outputProvider.OnVolatility(); } } - internal void OnUnderrun() - { - if (!IsStarted) return; - - if (LogUnderruns) Console.WriteLine("Sound underrun detected!"); - _outputProvider.OnVolatility(); - } - public void UpdateSound(float atten) { if (!Global.Config.SoundEnabled || !IsStarted || _bufferedProvider == null || _disposed) From 97a8430f5d27347f6e7463563b243e248824c02b Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Mon, 19 Dec 2016 10:27:36 -0500 Subject: [PATCH 20/21] Intellivision implement STIC masking --- .../Consoles/Intellivision/STIC.cs | 93 ++++++++++++++++--- 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs index 9248d674f5..7ff187a385 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs @@ -56,6 +56,11 @@ namespace BizHawk.Emulation.Cores.Intellivision { Sr1 = true; Sr2 = true; + + for (int i=0;i<64;i++) + { + Register[i] = register_mask(i, 0); + } } public bool GetSr1() @@ -78,6 +83,54 @@ namespace BizHawk.Emulation.Cores.Intellivision Sst = value; } + // mask off appropriate STIC bits + private ushort register_mask(int reg, ushort value) + { + + if (reg < 8) + { + return (ushort)((value & 0x7FF) | 0x3800); + } + else if (reg < 16) + { + return (ushort)((value & 0xFFF) | 0x3000); + } + else if (reg < 24) + { + return (ushort)(value & 0x3FFF); + } + else if (reg < 32) + { + return (ushort)((value & 0x3FF) | 0x3C00); + } + else if (reg < 40) + { + return (ushort)(0x3FFF); + } + else if (reg < 45) + { + return (ushort)((value & 0xF) | 0x3FF0); + } + else if (reg < 48) + { + return (ushort)(0x3FFF); + } + else if (reg < 51) + { + if (reg==50) + { + return (ushort)((value & 0x3) | 0x3FFC); + } + else + return (ushort)((value & 0x7) | 0x3FF8); + } + else if (reg < 64) + { + return (ushort)(0x3FFF); + } + return value; + } + public ushort? ReadSTIC(ushort addr) { switch (addr & 0xF000) @@ -144,7 +197,10 @@ namespace BizHawk.Emulation.Cores.Intellivision { Fgbg = true; } - Register[addr] = value; + + //Console.WriteLine(value); + //Console.WriteLine(addr); + Register[addr] = register_mask(addr,value); return true; } else if (addr <= 0x007F) @@ -161,7 +217,7 @@ namespace BizHawk.Emulation.Cores.Intellivision { Fgbg = true; } - Register[addr - 0x4000] = value; + Register[addr - 0x4000] = register_mask(addr - 0x4000, value); return true; } break; @@ -173,7 +229,7 @@ namespace BizHawk.Emulation.Cores.Intellivision { Fgbg = true; } - Register[addr & 0x003F] = value; + Register[addr & 0x003F] = register_mask(addr & 0x003F, value); return true; } break; @@ -185,7 +241,7 @@ namespace BizHawk.Emulation.Cores.Intellivision { Fgbg = true; } - Register[addr - 0xC000] = value; + Register[addr - 0xC000] = register_mask(addr - 0xC000, value); return true; } break; @@ -413,8 +469,8 @@ namespace BizHawk.Emulation.Cores.Intellivision // there is a trick here in that we move the displayed area of the screen relative to the BG buffer // this is done using the delay registers - int x_delay = Register[0x30]; - int y_delay = Register[0x31]; + int x_delay = Register[0x30] & 0x7; + int y_delay = Register[0x31] & 0x7; int x_border = (Register[0x32] & 0x0001) * 8; int y_border = ((Register[0x32] >> 1) & 0x0001) * 8; @@ -484,8 +540,8 @@ namespace BizHawk.Emulation.Cores.Intellivision ushort attr; byte row; - int x_delay = Register[0x30]; - int y_delay = Register[0x31]; + int x_delay = Register[0x30] & 0x7; + int y_delay = Register[0x31] & 0x7; int cur_x, cur_y; @@ -515,6 +571,8 @@ namespace BizHawk.Emulation.Cores.Intellivision bool intr = x.Bit(8); ushort x_size = x.Bit(10) ? (ushort)2 : (ushort)1; + //Console.WriteLine(intr); + ushort y_size = (ushort)(ysiz2 * ysiz4); // setting yres implicitly uses an even card first if (yres>1) @@ -729,8 +787,8 @@ namespace BizHawk.Emulation.Cores.Intellivision // by now we have collision information for all 8 mobs and the BG // so we can store data in the collision registers here - int x_border = Register[0x32].Bit(0) ? 16 : 8; - int y_border = Register[0x32].Bit(1) ? 32 : 16; + int x_border = Register[0x32].Bit(0) ? 16-x_delay : 8-x_delay; + int y_border = Register[0x32].Bit(1) ? 32-y_delay*2 : 16-y_delay*2; int x_border_2 = Register[0x32].Bit(0) ? 8 : 0; int y_border_2 = Register[0x32].Bit(1) ? 16 : 0; @@ -740,11 +798,11 @@ namespace BizHawk.Emulation.Cores.Intellivision for (int j = 0; j < 210; j++) { // while we are here we can set collision detection bits for the border region - if (i= 208) + if ((j == y_border || j == y_border-1) || (j == (207-y_delay*2) || j == (207 - y_delay * 2+1))) { Collision[i, j] |= (1 << 9); } @@ -753,10 +811,10 @@ namespace BizHawk.Emulation.Cores.Intellivision if ((i-x_delay)>=0 && (i-x_delay)<159 && (j-y_delay*2)>=0 && (j-y_delay*2)<192) { if ((i-x_delay) < x_border_2) - FrameBuffer[(j - y_delay*2) * 159 + (i - x_delay)] = ColorToRGBA(Register[0x2C]); + FrameBuffer[(j - y_delay*2) * 159 + (i - x_delay)] = ColorToRGBA(Register[0x2C] & 0xF); if ((j - y_delay*2) < y_border_2) - FrameBuffer[(j - y_delay*2) * 159 + (i - x_delay)] = ColorToRGBA(Register[0x2C]); + FrameBuffer[(j - y_delay*2) * 159 + (i - x_delay)] = ColorToRGBA(Register[0x2C] & 0xF); } // the extra condition here is to ignore only border collsion bit set @@ -778,6 +836,13 @@ namespace BizHawk.Emulation.Cores.Intellivision } } + for (int z=0;z<8;z++) + { + //Console.WriteLine(z); + //Console.WriteLine(Register[z + 24]); + + } + } // end of Mobs function, we now have collision and graphics data for the mobs From 824112bc0d1a3acd2003e6626e47340532b79236 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Mon, 19 Dec 2016 10:58:22 -0500 Subject: [PATCH 21/21] Intellivision clean up Cartridge --- .../Consoles/Intellivision/Cartridge.cs | 280 ------------------ 1 file changed, 280 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs index 1c5d95b43c..24ab69b4bc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs @@ -27,19 +27,6 @@ namespace BizHawk.Emulation.Cores.Intellivision public int Parse(byte[] Rom) { - /* - // TODO: Determine which loading method, if either, is correct. - int index = 0; - // Combine every two bytes into a word. - while (index + 1 < Rom.Length) - { - Data[(index / 2) + 0x2C00] = (ushort)((Rom[index++] << 8) | Rom[index++]); - } - /* - for (int index = 0; index < Rom.Length; index++) - Data[index + 0x2C00] = Rom[index]; - */ - // Combine every two bytes into a word. int index = 0; @@ -61,7 +48,6 @@ namespace BizHawk.Emulation.Cores.Intellivision if (!dict.ContainsKey("board")) throw new Exception("INTV gamedb entries must have a board identifier!"); s_mapper = dict["board"]; - Console.WriteLine(mapper); } else { @@ -233,271 +219,5 @@ namespace BizHawk.Emulation.Cores.Intellivision } return false; } - /* - public ushort? ReadCart(ushort addr) - { - // TODO: Check if address is RAM / ROM. - int dest; - switch (addr & 0xF000) - { - case 0x0000: - dest = addr - 0x0400; - if (addr <= 0x03FF) - { - break; - } - else if (addr <= 0x04FF) - { - // OK on all but Intellivision 2. - return Data[dest]; - } - else if (addr <= 0x06FF) - { - return Data[dest]; - } - else if (addr <= 0x0CFF) - { - // OK if no Intellivoice. - return Data[dest]; - } - else - { - return Data[dest]; - } - case 0x2000: - dest = (addr - 0x2000) + 0x0C00; - // OK if no ECS. - return Data[dest]; - case 0x4000: - dest = (addr - 0x4000) + 0x1C00; - if (addr <= 0x47FF) - { - // OK if no ECS. - return Data[dest]; - } - else if (addr == 0x4800) - { - // return Data[dest]; - // For now, assume unmapped. TODO: Fix. - return null; - } - else - { - return Data[dest]; - } - case 0x5000: - case 0x6000: - dest = (addr - 0x5000) + 0x2C00; - if (addr <= 0x5014) - { - return Data[dest]; - } - else - { - return Data[dest]; - } - case 0x7000: - dest = (addr - 0x7000) + 0x4C00; - if (addr == 0x7000) - { - // OK if no ECS. - // return Data[dest]; - // For now, assume unmapped. TODO: Fix. - return null; - } - else if (addr <= 0x77FF) - { - // OK if no ECS. - return Data[dest]; - } - else - { - // OK if no ECS. - return Data[dest]; - } - case 0x8000: - dest = (addr - 0x8000) + 0x5C00; - // OK. Avoid STIC alias at $8000-$803F. - return Data[dest]; - case 0x9000: - case 0xA000: - case 0xB000: - dest = (addr - 0x9000) + 0x6C00; - if (addr <= 0xB7FF) - { - return Data[dest]; - } - else - { - return Data[dest]; - } - case 0xC000: - dest = (addr - 0xC000) + 0x9C00; - // OK. Avoid STIC alias at $C000-$C03F. - return Data[dest]; - case 0xD000: - dest = (addr - 0xD000) + 0xAC00; - return Data[dest]; - case 0xE000: - dest = (addr - 0xE000) + 0xBC00; - // OK if no ECS. - return Data[dest]; - case 0xF000: - dest = (addr - 0xF000) + 0xCC00; - if (addr <= 0xF7FF) - { - return Data[dest]; - } - else - { - return Data[dest]; - } - } - return null; - } - - - public bool WriteCart(ushort addr, ushort value) - { - int dest; - // TODO: Check if address is RAM / ROM. - switch (addr & 0xF000) - { - case 0x0000: - dest = addr - 0x0400; - if (addr <= 0x03FF) - { - break; - } - else if (addr <= 0x04FF) - { - // OK on all but Intellivision 2. - Data[dest] = value; - return true; - } - else if (addr <= 0x06FF) - { - Data[dest] = value; - return true; - } - else if (addr <= 0x0CFF) - { - // OK if no Intellivoice. - Data[dest] = value; - return true; - } - else - { - Data[dest] = value; - return true; - } - case 0x2000: - dest = (addr - 0x2000) + 0x0C00; - // OK if no ECS. - Data[dest] = value; - return true; - case 0x4000: - dest = (addr - 0x4000) + 0x1C00; - if (addr <= 0x47FF) - { - // OK if no ECS. - Data[dest] = value; - return true; - } - else if (addr == 0x4800) - { - // OK only if boot ROM at $7000. - Data[dest] = value; - return true; - } - else - { - Data[dest] = value; - return true; - } - case 0x5000: - case 0x6000: - dest = (addr - 0x5000) + 0x2C00; - if (addr <= 0x5014) - { - // OK only if boot ROM at $4800 or $7000. - Data[dest] = value; - return true; - } - else - { - Data[dest] = value; - return true; - } - case 0x7000: - dest = (addr - 0x7000) + 0x4C00; - if (addr == 0x7000) - { - // RAM at $7000 confuses EXEC boot sequence. - Data[dest] = value; - return true; - } - else if (addr <= 0x77FF) - { - // OK if no ECS. - Data[dest] = value; - return true; - } - else - { - // Do not map RAM here due to GRAM alias. - Data[dest] = value; - return true; - } - case 0x8000: - dest = (addr - 0x8000) + 0x5C00; - // OK. Avoid STIC alias at $8000-$803F. - Data[dest] = value; - return true; - case 0x9000: - case 0xA000: - case 0xB000: - dest = (addr - 0x9000) + 0x6C00; - if (addr <= 0xB7FF) - { - Data[dest] = value; - return true; - } - else - { - // Do not map RAM here due to GRAM alias. - Data[dest] = value; - return true; - } - case 0xC000: - dest = (addr - 0xC000) + 0x9C00; - // OK. Avoid STIC alias at $C000-$C03F. - Data[dest] = value; - return true; - case 0xD000: - Data[(addr & 0x0FFF) + 0xAC00] = value; - return true; - case 0xE000: - dest = (addr - 0xE000) + 0xBC00; - // OK if no ECS. - Data[dest] = value; - return true; - case 0xF000: - dest = (addr - 0xF000) + 0xCC00; - if (addr <= 0xF7FF) - { - Data[dest] = value; - return true; - } - else - { - // Do not map RAM here due to GRAM alias. - Data[dest] = value; - return true; - } - } - return false; - } - */ } }