This commit is contained in:
adelikat 2016-12-19 10:50:26 -06:00
commit 9c3e4cd411
42 changed files with 845 additions and 663 deletions

View File

@ -29,6 +29,7 @@
#include gamedb_msx1.txt
#include gamedb_msx2.txt
#include gamedb_vs.txt
#include gamedb_intv.txt
; ************ NES / Famicom ************

View File

@ -0,0 +1,29 @@
; NOTE: games not in this database will default to mapper 0
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: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

View File

@ -717,12 +717,14 @@
<Compile Include="RomStatusPicker.Designer.cs">
<DependentUpon>RomStatusPicker.cs</DependentUpon>
</Compile>
<Compile Include="Sound\Interfaces\IBufferedSoundProvider.cs" />
<Compile Include="Sound\Interfaces\ISoundOutput.cs" />
<Compile Include="Sound\Output\DirectSoundSoundOutput.cs" />
<Compile Include="Sound\Output\DummySoundOutput.cs" />
<Compile Include="Sound\Output\OpenALSoundOutput.cs" />
<Compile Include="Sound\Output\XAudio2SoundOutput.cs" />
<Compile Include="Sound\Sound.cs" />
<Compile Include="Sound\Utilities\BufferedAsync.cs" />
<Compile Include="Sound\Utilities\SoundOutputProvider.cs" />
<Compile Include="Throttle.cs" />
<Compile Include="ToolAttributes.cs" />

View File

@ -290,7 +290,7 @@ namespace BizHawk.Client.EmuHawk
var comm = CreateCoreComm();
CoreFileProvider.SyncCoreCommInputSignals(comm);
Emulator = new NullEmulator(comm, Global.Config.GetCoreSettings<NullEmulator>());
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); }
@ -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))
@ -1761,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);
}
@ -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 isFastForwardingOrRewinding = isFastForwarding || isRewinding;
if (isFastForwardingOrRewinding != _lastFastForwardingOrRewinding)
{
InitializeFpsData();
}
_lastFastForwardingOrRewinding = isFastForwardingOrRewinding;
// 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 (isFastForwardingOrRewinding)
{
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
@ -3636,7 +3655,7 @@ namespace BizHawk.Client.EmuHawk
var coreComm = CreateCoreComm();
CoreFileProvider.SyncCoreCommInputSignals(coreComm);
Emulator = new NullEmulator(coreComm, Global.Config.GetCoreSettings<NullEmulator>());
Global.ActiveController = new Controller(NullEmulator.NullController);
Global.ActiveController = new Controller(NullController.Instance.Definition);
Global.AutoFireController = Global.AutofireNullControls;
RewireSound();
RebootStatusBarIcon.Visible = false;

View File

@ -1,4 +1,6 @@
namespace BizHawk.Emulation.Common
using BizHawk.Emulation.Common;
namespace BizHawk.Client.EmuHawk
{
public interface IBufferedSoundProvider
{

View File

@ -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)
{

View File

@ -56,7 +56,6 @@ namespace BizHawk.Client.EmuHawk
if (_remainingSamples < 0)
{
_remainingSamples = 0;
_sound.OnUnderrun();
detectedUnderrun = true;
}
_lastWriteTime = currentWriteTime;

View File

@ -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;

View File

@ -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)

View File

@ -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)
@ -172,7 +153,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();

View File

@ -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.

View File

@ -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

View File

@ -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);
}

View File

@ -28,41 +28,41 @@
/// </summary>
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;

View File

@ -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
{

View File

@ -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)

View File

@ -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<string, byte[]>
/// <summary>
/// The base implementation of ICodeDataLog
/// </summary>
/// <seealso cref="ICodeDataLogger" />
/// <seealso cref="ICodeDataLog" />
public class CodeDataLog : Dictionary<string, byte[]>, ICodeDataLog
{
public CodeDataLog()
{
Active = true;
}
/// <summary>
@ -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);
}
}
/// <summary>
@ -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
/// <summary>
/// Pinned managed arrays
/// </summary>
Dictionary<string, GCHandle> Pins = new Dictionary<string, GCHandle>();
private readonly Dictionary<string, GCHandle> Pins = new Dictionary<string, GCHandle>();
/// <summary>
/// Whether the CDL is tracking a block with the given name
/// </summary>
public bool Has(string blockname) { return ContainsKey(blockname); }
public bool Has(string blockname)
{
return ContainsKey(blockname);
}
/// <summary>
/// This is just a hook, if needed, to readily suspend logging, without having to rewire the core
/// </summary>
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; }
/// <summary>
/// Tests whether the other CodeDataLog is structurally identical
/// </summary>
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<string, long> _Save(Stream s, bool forReal)
private Dictionary<string, long> _Save(Stream s, bool forReal)
{
var ret = new Dictionary<string, long>();
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++)

View File

@ -7,9 +7,14 @@
/// <seealso cref="IController" />
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]

File diff suppressed because one or more lines are too long

View File

@ -107,7 +107,7 @@
<Compile Include="BinaryQuickSerializer.cs" />
<Compile Include="BizInvoke\BizInvoker.cs" />
<Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
<Compile Include="CodeDataLog.cs" />
<Compile Include="Base Implementations\CodeDataLog.cs" />
<Compile Include="CoreAttributes.cs" />
<Compile Include="CoreComms.cs" />
<Compile Include="Database\CRC32.cs" />
@ -117,7 +117,6 @@
<Compile Include="EmulationExceptions.cs" />
<Compile Include="Enums.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="Interfaces\IBufferedSoundProvider.cs" />
<Compile Include="Interfaces\IController.cs" />
<Compile Include="Interfaces\ICoreFileProvider.cs" />
<Compile Include="Interfaces\IEmulator.cs" />
@ -127,7 +126,6 @@
<Compile Include="Interfaces\IEmulatorServiceProvider.cs" />
<Compile Include="Interfaces\Services\ICreateGameDBEntries.cs" />
<Compile Include="Interfaces\Services\ISoundProvider.cs" />
<Compile Include="Interfaces\IAsyncSoundProvider.cs" />
<Compile Include="Interfaces\Services\ICodeDataLogger.cs" />
<Compile Include="Interfaces\Services\IDebuggable.cs" />
<Compile Include="Interfaces\Services\IDisassemblable.cs" />
@ -145,11 +143,9 @@
<Compile Include="ServiceAttributes.cs" />
<Compile Include="ServiceInjector.cs" />
<Compile Include="Sound\Utilities\BlipBuffer.cs" />
<Compile Include="Sound\Utilities\BufferedAsync.cs" />
<Compile Include="Sound\Utilities\DCFilter.cs" />
<Compile Include="Sound\Utilities\Equalizer.cs" />
<Compile Include="Sound\Utilities\Metaspu.cs" />
<Compile Include="Sound\Utilities\SoundMixer.cs" />
<Compile Include="Sound\Utilities\SpeexResampler.cs" />
<Compile Include="Sound\Utilities\Waves.cs" />
<Compile Include="SystemLookup.cs" />

View File

@ -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
/// <summary>
/// Sets the CodeDataLog as current (and logging) on the core
/// </summary>
void SetCDL(CodeDataLog cdl);
void SetCDL(ICodeDataLog cdl);
/// <summary>
/// Fills a new CodeDataLog with memory domain information suitable for the core
/// </summary>
void NewCDL(CodeDataLog cdl);
void NewCDL(ICodeDataLog cdl);
/// <summary>
/// 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
/// </summary>
void DisassembleCDL(Stream s, CodeDataLog cdl);
void DisassembleCDL(Stream s, ICodeDataLog cdl);
}
/// <summary>
/// Defines a code/data log to be used with the code/data logger
/// </summary>
/// <seealso cref="ICodeDataLogger" />
public interface ICodeDataLog : IDictionary<string, byte[]>
{
/// <summary>
/// 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
/// </summary>
void Pin();
/// <summary>
/// Unpins the managed arrays, to be paired with calls to Pin()
/// </summary>
void Unpin();
/// <summary>
/// Retrieves the pointer to a managed array
/// </summary>
IntPtr GetPin(string key);
/// <summary>
/// Whether the CDL is tracking a block with the given name
/// </summary>
bool Has(string blockname);
/// <summary>
/// This is just a hook, if needed, to readily suspend logging, without having to rewire the core
/// </summary>
bool Active { get; set; }
string SubType { get; set; }
int SubVer { get; set; }
/// <summary>
/// Tests whether the other CodeDataLog is structurally identical
/// </summary>
bool Check(ICodeDataLog other);
void LogicalOrFrom(ICodeDataLog other);
void ClearData();
void Save(Stream s);
}
}

View File

@ -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);

View File

@ -911,32 +911,32 @@
<Compile Include="Consoles\PC Engine\MemoryMap.Populous.cs" />
<Compile Include="Consoles\PC Engine\PCEngine.ArcadeCard.cs" />
<Compile Include="Consoles\PC Engine\PCEngine.ICodeDataLogger.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IDebuggable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IDriveLight.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IEmulator.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IInputPollable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IMemoryDomains.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.Input.cs" />
<Compile Include="Consoles\PC Engine\PCEngine.ISaveRam.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.ISettable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IStatable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.TurboCD.cs" />
<Compile Include="Consoles\PC Engine\ScsiCDBus.cs" />
@ -1197,8 +1197,10 @@
<Compile Include="Consoles\Sega\Genesis\MemoryMap.Z80.cs" />
<Compile Include="Sound\CDAudio.cs" />
<Compile Include="Sound\HuC6280PSG.cs" />
<Compile Include="Sound\IAsyncSoundProvider.cs" />
<Compile Include="Sound\MMC5Audio.cs" />
<Compile Include="Sound\SN76489.cs" />
<Compile Include="Sound\SoundMixer.cs" />
<Compile Include="Sound\Sunsoft5BAudio.cs" />
<Compile Include="Sound\VRC6Alt.cs" />
<Compile Include="Sound\YM2413.cs" />

View File

@ -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

View File

@ -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<IDisassemblable>(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;

View File

@ -1,4 +1,7 @@
using BizHawk.Common;
using BizHawk.Common.BufferExtensions;
using BizHawk.Emulation.Common;
using System;
namespace BizHawk.Emulation.Cores.Intellivision
{
@ -6,291 +9,213 @@ namespace BizHawk.Emulation.Cores.Intellivision
{
private ushort[] Data = new ushort[56320];
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
private int mapper = 0;
public void SyncState(Serializer ser)
{
ser.BeginSection("Cart");
// TODO
ser.Sync("mapper", ref mapper);
ser.Sync("Cart_Ram", ref Cart_Ram, false);
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.
int index = 0;
while (index + 1 < Rom.Length)
{
Data[(index / 2) + 0x2C00] = (ushort)((Rom[index++] << 8) | Rom[index++]);
Data[(index / 2)] = (ushort)((Rom[index++] << 8) | Rom[index++]);
}
/*
for (int index = 0; index < Rom.Length; index++)
Data[index + 0x2C00] = 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"];
}
else
{
s_mapper = "0";
}
int.TryParse(s_mapper, out mapper);
return Rom.Length;
}
public ushort? ReadCart(ushort addr)
{
// TODO: Check if address is RAM / ROM.
int dest;
switch (addr & 0xF000)
switch (mapper)
{
case 0x0000:
dest = addr - 0x0400;
if (addr <= 0x03FF)
case 0:
if (addr>=0x5000 && addr<0x6FFF)
{
break;
return Data[addr-0x5000];
}
else if (addr <= 0x04FF)
else if (addr>=0xD000 && addr<0xDFFF)
{
// OK on all but Intellivision 2.
return Data[dest];
return Data[addr - 0xB000];
}
else if (addr <= 0x06FF)
else if (addr>=0xF000 && addr<0xFFFF)
{
return Data[dest];
return Data[addr - 0xC000];
}
else if (addr <= 0x0CFF)
break;
case 1:
if (addr >= 0x5000 && addr < 0x6FFF)
{
// OK if no Intellivoice.
return Data[dest];
return Data[addr - 0x5000];
}
else
else if (addr >= 0xD000 && addr < 0xFFFF)
{
return Data[dest];
return Data[addr - 0xB000];
}
case 0x2000:
dest = (addr - 0x2000) + 0x0C00;
// OK if no ECS.
return Data[dest];
case 0x4000:
dest = (addr - 0x4000) + 0x1C00;
if (addr <= 0x47FF)
break;
case 2:
if (addr >= 0x5000 && addr < 0x6FFF)
{
// OK if no ECS.
return Data[dest];
return Data[addr - 0x5000];
}
else if (addr == 0x4800)
else if (addr >= 0x9000 && addr < 0xBFFF)
{
// return Data[dest];
// For now, assume unmapped. TODO: Fix.
return null;
return Data[addr - 0x7000];
}
else
else if (addr >= 0xD000 && addr < 0xDFFF)
{
return Data[dest];
return Data[addr - 0x8000];
}
case 0x5000:
case 0x6000:
dest = (addr - 0x5000) + 0x2C00;
if (addr <= 0x5014)
break;
case 3:
if (addr >= 0x5000 && addr < 0x6FFF)
{
return Data[dest];
return Data[addr - 0x5000];
}
else
else if (addr >= 0x9000 && addr < 0xAFFF)
{
return Data[dest];
return Data[addr - 0x7000];
}
case 0x7000:
dest = (addr - 0x7000) + 0x4C00;
if (addr == 0x7000)
else if (addr >= 0xD000 && addr < 0xDFFF)
{
// OK if no ECS.
// return Data[dest];
// For now, assume unmapped. TODO: Fix.
return null;
return Data[addr - 0x9000];
}
else if (addr <= 0x77FF)
else if (addr >= 0xF000 && addr < 0xFFFF)
{
// OK if no ECS.
return Data[dest];
return Data[addr - 0xA000];
}
else
break;
case 4:
if (addr >= 0x5000 && addr < 0x6FFF)
{
// OK if no ECS.
return Data[dest];
return Data[addr - 0x5000];
}
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)
else if (addr >= 0xD000 && addr < 0xD3FF)
{
return Data[dest];
return Cart_Ram[addr - 0xD000];
}
else
break;
case 5:
if (addr >= 0x5000 && addr < 0x7FFF)
{
return Data[dest];
return Data[addr - 0x5000];
}
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)
else if (addr >= 0x9000 && addr < 0xBFFF)
{
return Data[dest];
return Data[addr - 0x6000];
}
else
break;
case 6:
if (addr >= 0x6000 && addr < 0x7FFF)
{
return Data[dest];
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;
}
return null;
}
public bool WriteCart(ushort addr, ushort value)
{
int dest;
// TODO: Check if address is RAM / ROM.
switch (addr & 0xF000)
switch (mapper)
{
case 0x0000:
dest = addr - 0x0400;
if (addr <= 0x03FF)
case 4:
if (addr >= 0xD000 && addr < 0xD3FF)
{
break;
}
else if (addr <= 0x04FF)
{
// OK on all but Intellivision 2.
Data[dest] = value;
Cart_Ram[addr - 0xD000] = value;
return true;
}
else if (addr <= 0x06FF)
break;
case 9:
if (addr >= 0x8800 && addr < 0x8FFF)
{
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;
Cart_Ram[addr - 0x8800] = value;
return true;
}
break;
}
return false;
}

View File

@ -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;
@ -286,7 +342,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 +397,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;
}
}
}
@ -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<x_border || i==166)
if (i == x_border || i == (165-x_delay))
{
Collision[i, j] |= (1 << 9);
}
if (j < y_border || j >= 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

View File

@ -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)
{

View File

@ -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); }
}
}

View File

@ -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)

View File

@ -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
}

View File

@ -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; }

View File

@ -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
{

View File

@ -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);
}

View File

@ -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)
{

View File

@ -1,5 +1,4 @@
using System;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components;
namespace BizHawk.Emulation.Cores.Sega.MasterSystem
{

View File

@ -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.

View File

@ -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.

View File

@ -1,25 +1,26 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Common
{
/// <summary>
/// This interface is for legacy sound implementations in some older cores
/// This needs to go away, but is provided here, for now
/// </summary>
public interface IAsyncSoundProvider
namespace BizHawk.Emulation.Cores.Components
{
/// <summary>
/// This interface is for legacy sound implementations in some older cores
/// This needs to go away, but is provided here, for now
/// </summary>
internal interface IAsyncSoundProvider
{
void GetSamples(short[] samples);
void DiscardSamples();
}
/// <summary>
/// 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
/// </summary>
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();
}
}
}

View File

@ -1,59 +1,60 @@
using System.Collections.Generic;
namespace BizHawk.Emulation.Common
{
/// <summary>
/// An interface that extends a sound provider to provide mixing capabilities through the SoundMixer class
/// </summary>
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<IMixedSoundProvider> SoundProviders;
public SoundMixer(params IMixedSoundProvider[] soundProviders)
{
SoundProviders = new List<IMixedSoundProvider>(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
/// <summary>
/// An interface that extends a sound provider to provide mixing capabilities through the SoundMixer class
/// </summary>
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<IMixedSoundProvider> SoundProviders;
public SoundMixer(params IMixedSoundProvider[] soundProviders)
{
SoundProviders = new List<IMixedSoundProvider>(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;
}
}
}
}

View File

@ -7,6 +7,7 @@
using System;
using BizHawk.Common;
using BizHawk.Emulation.Cores.Components;
namespace BizHawk.Emulation.Common.Components
{

View File

@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using BizHawk.Emulation.Cores.Components;
namespace BizHawk.Emulation.Common.Components
{
// ======================================================================